yp87 / leaf2mqtt

Pull in data from the Nissan Connect platform for the LEAF and publish over MQTT
GNU General Public License v3.0
42 stars 39 forks source link

Not always publishing battery information #31

Closed wtadler closed 2 years ago

wtadler commented 2 years ago

The package is not always publishing battery status, even though I can tell from my logs that Nissan is reporting it. Do a search for batteryRemainingAmount to see that Nissan is indeed reporting it, but that it's not being published via MQTT along with the other info.

#5      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#6      startUpdateLoop (file:///app/src/leaf_2_mqtt.dart:111)
<asynchronous suspension>
#7      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#8      main (file:///app/src/leaf_2_mqtt.dart:69)
<asynchronous suspension>
FINER: 2022-05-20 06:00:16.303470: LeafSession: Force a login before retrying failed execution.
$ Invoking NissanConnect (NA) API: auth/authenticationForAAS
$ Params: {authenticate: {userid: [XXX], password: [XXX], brand-s: N, language-s: EN, country: US}}
$ Headers: {Content-Type: application/json, Api-Key: [XXX], User-Agent-Key: [XXX], User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; Android SDK built for x86 Build/LMY48X)}
$ Result: {vehicles: [{pinAndPassword: null, batteryRecords: null, interiorTempRecords: null, [............]}
FINEST: 2022-05-20 06:00:19.270605: LeafSession: Executing
$ Invoking NissanConnect (NA) API: battery/vehicles/[XXX]/getChargingStatusRequest
$ Params: null
$ Headers: {Content-Type: application/json, Api-Key: [........]}
$ JSON decoding failed!
FINE: 2022-05-20 06:00:23.291332: LeafSession: NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []()
FINER: 2022-05-20 06:00:23.291607: LeafSession: #0      new NissanConnectBattery (package:dartnissanconnectna/src/nissanconnect_battery.dart:28)
#1      NissanConnectVehicle.requestBatteryStatus (package:dartnissanconnectna/src/nissanconnect_vehicle.dart:36)
<asynchronous suspension>
#2      NissanConnectNAVehicleWrapper.fetchBatteryStatus (file:///app/src/leaf/nissan_connect_na_wrapper.dart:71)
<asynchronous suspension>
#3      LeafSession._executeWithRetry (file:///app/src/leaf/leaf_session.dart:153)
<asynchronous suspension>
#4      LeafSession.executeWithRetry (file:///app/src/leaf/leaf_session.dart:129)
<asynchronous suspension>
#5      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#6      startUpdateLoop (file:///app/src/leaf_2_mqtt.dart:111)
<asynchronous suspension>
#7      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#8      main (file:///app/src/leaf_2_mqtt.dart:69)
<asynchronous suspension>
FINE: 2022-05-20 06:00:23.291824: LeafSession: Exception: Execution failed.
FINER: 2022-05-20 06:00:23.291978: LeafSession: #0      LeafSession._executeWithRetry (file:///app/src/leaf/leaf_session.dart:161)
<asynchronous suspension>
#1      LeafSession.executeWithRetry (file:///app/src/leaf/leaf_session.dart:129)
<asynchronous suspension>
#2      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#3      startUpdateLoop (file:///app/src/leaf_2_mqtt.dart:111)
<asynchronous suspension>
#4      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#5      main (file:///app/src/leaf_2_mqtt.dart:69)
<asynchronous suspension>
WARNING: 2022-05-20 06:00:23.293555: main: Could not execute request.
FINEST: 2022-05-20 06:00:23.293978: MqttClientWrapper: Publishing message lastErrorDateTimeUtc 2022-05-20T10:00:23.293955Z
FINEST: 2022-05-20 06:00:23.294841: MqttClientWrapper: Publishing message {vin}/lastErrorDateTimeUtc 2022-05-20T10:00:23.293955Z
$ Result: {displayMessage: Vehicle Location details not available, sandsNotificationEvent: null}
FINE: 2022-05-20 06:01:03.106315: LeafSession: NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []("sandsNotificationEvent")
FINER: 2022-05-20 06:01:03.106510: LeafSession: #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:38)
#1      _objectNoSuchMethod (dart:core-patch/object_patch.dart:85)
#2      new NissanConnectLocation (package:dartnissanconnectna/src/nissanconnect_location.dart:6)
#3      NissanConnectVehicle.requestLocation (package:dartnissanconnectna/src/nissanconnect_vehicle.dart:137)
<asynchronous suspension>
#4      NissanConnectNAVehicleWrapper.fetchLocation (file:///app/src/leaf/nissan_connect_na_wrapper.dart:110)
<asynchronous suspension>
#5      LeafSession._executeWithRetry (file:///app/src/leaf/leaf_session.dart:153)
<asynchronous suspension>
#6      LeafSession.executeWithRetry (file:///app/src/leaf/leaf_session.dart:129)
<asynchronous suspension>
#7      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#8      startUpdateLoop (file:///app/src/leaf_2_mqtt.dart:111)
<asynchronous suspension>
#9      Future.wait.<anonymous closure> (dart:async/future.dart:521)
<asynchronous suspension>
#10     main (file:///app/src/leaf_2_mqtt.dart:69)
<asynchronous suspension>
FINER: 2022-05-20 06:01:03.106549: LeafSession: Force a login before retrying failed execution.
$ Invoking NissanConnect (NA) API: auth/authenticationForAAS
$ Params: {authenticate: {userid: [XXX], password: [XXX], brand-s: N, language-s: EN, country: US}}
$ Headers: {Content-Type: application/json, Api-Key: [XXX], User-Agent-Key: [XXX], User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; Android SDK built for x86 Build/LMY48X)}
$ Result: {vehicles: [{pinAndPassword: null, batteryRecords: {operationResult: START, lastUpdatedDateAndTime: 2022-05-20T10:00:35Z, batteryStatus: {batteryChargingStatus: NO, batteryCapacity: 100, batteryRemainingAmount: 59, soc: {value: 59}}, pluginState: NOT_CONNECTED, cruisingRangeAcOn: 210000.0, cruisingRangeAcOff: 226000.0, timeRequired: {hourRequiredToFull: 22, minutesRequiredToFull: 30}, timeRequired200: {hourRequiredToFull: 9, minutesRequiredToFull: 0}, timeRequired200_6kW: {hourRequiredToFull: 5, minutesRequiredToFull: 30}, notificationDateAndTime: null}, interiorTempRecords: [............]}
FINEST: 2022-05-20 06:01:06.552224: LeafSession: Executing
$ Invoking NissanConnect (NA) API: vehicleLocator/vehicles/[XXX]/refreshVehicleLocator
$ Params: {acquiredDataUpperLimit: 1, searchPeriod: 20220420,20220520, serviceName: MyCarFinderResult}
$ Headers: {Content-Type: application/json, Api-Key: [..................]}
$ Result: {displayMessage: null, sandsNotificationEvent: {sandsNotificationEvent: {body: {location: {latitudeDMS: [..........]}}}}
FINEST: 2022-05-20 06:01:22.152073: main: publishStates {location/latitude: [XXX], location/longitude: [XXX], location/lastReceivedDateTimeUtc: 2022-05-20T10:01:22.151714Z, location/json: {"latitude":"[XXX]","longitude":"[XXX]","lastReceivedDateTimeUtc":"2022-05-20T10:01:22.151714Z"}, [XXX]/location/latitude: [XXX], [XXX]/location/longitude: [XXX], [XXX]/location/lastReceivedDateTimeUtc: 2022-05-20T10:01:22.151714Z, [XXX]/location/json: {"latitude":"[XXX]","longitude":"[XXX]","lastReceivedDateTimeUtc":"2022-05-20T10:01:22.151714Z"}}
FINEST: 2022-05-20 06:01:22.152374: MqttClientWrapper: Publishing message location/latitude [XXX]
FINEST: 2022-05-20 06:01:22.153577: MqttClientWrapper: Publishing message location/longitude [XXX]
FINEST: 2022-05-20 06:01:22.155689: MqttClientWrapper: Publishing message location/lastReceivedDateTimeUtc 2022-05-20T10:01:22.151714Z
FINEST: 2022-05-20 06:01:22.156022: MqttClientWrapper: Publishing message location/json {"latitude":"[XXX]","longitude":"[XXX]","lastReceivedDateTimeUtc":"2022-05-20T10:01:22.151714Z"}
FINEST: 2022-05-20 06:01:22.156268: MqttClientWrapper: Publishing message [XXX]/location/latitude [XXX]
FINEST: 2022-05-20 06:01:22.156476: MqttClientWrapper: Publishing message [XXX]/location/longitude [XXX]
FINEST: 2022-05-20 06:01:22.159221: MqttClientWrapper: Publishing message [XXX]/location/lastReceivedDateTimeUtc 2022-05-20T10:01:22.151714Z
FINEST: 2022-05-20 06:01:22.159496: MqttClientWrapper: Publishing message [XXX]/location/json {"latitude":"[XXX]","longitude":"[XXX]","lastReceivedDateTimeUtc":"2022-05-20T10:01:22.151714Z"}
yp87 commented 2 years ago

Hello!

The batteryRemainingAmount is coming from the login response. The library I use does not expose that value when doing a login. Also, I don't think there is a way to know if the value would be recent or very old.

To get the battery status, you have to publish the command update to the leaf/{vin}/command/battery topic. In your logs, it looks like it was done, but the library received an error from the Nissan server. I recommend setting the variable COMMAND_ATTEMPTS to 5 to let leaf2mqtt retry up to 5 times in this case.

A more reliable way to get the current battery % would be to follow the logic in the readme (Recommended Battery Status Update Script). It uses the lastReceivedDateTimeUtc and lastUpdatedDateTimeUtc to know if the value is recent enough and will retry when it is not.

I will close this now, reopen it if you still have issues.

wtadler commented 2 years ago

Hm, it seems that simply retrying the update command only helps on rare occasion. Every once in a while it will work, and will publish the battery state of charge via MQTT. But far more often, when I do the update command, I get no battery update, but a log just like the above: In Result it lists a batteryRemainingAmount that I know is up to date because I just drove the car and checked. The data even includes lastUpdatedDateAndTime to know if the value is recent—and it usually is.

Is there any way to modify the library to publish these two values? Even appending their names with _login_response or something like that would be a big improvement, if it's important to separate the two ways this info can make it in. It's just odd to get published battery updates only rarely when I know the library is indeed receiving updated values. (It is very reliable about publishing cabin temp and location.)

yp87 commented 2 years ago

Hello @wtadler,

I tested it and those values are the same values as the one that are shown when you open the app before you click the refresh button. These values will be the values that was fetch from the car during the latest refresh (when you click the refresh button or call the update command). A login does not provoke a communication with the car, it must be a clear manual operation since it wakes the car and can deplete the car's 12v battery. So if there was no prior refresh done, the login values will be stale (Just checked, and they are 10 hours behind in my case even if the car was driven twice up to now)

Also, the library that is used by the leaf2mqtt service does not expose those values.

When you use the app, do you notice sometime you have to click refresh more than once to get the real latest values? In my case it happens often and it is the same behavior with the update command of leaf2mqtt. That is why in the readme you see an example on how to create a script in home assistant that will retry the update command multiple time up to a given limit and stop when it knows the values are good.