Feeling my way around the pycarwings2 interface with a test script and having good success with it now and have learnt a few things.
For use in a persistent script you only need to call the initial login methods once:
Code:
s = pycarwings2.Session(username, password, region)
leaf = s.get_leaf()
Assuming that initial login succeeds (wait and try again later if not) from then on you can call the other functions over a long period of time without worrying about the login timing out as pycarwings2 automatically handles logging back in for you if the session has timed out. (Which seems to take around 10-15 minutes, not sure exactly how long) I've tried leaving my script paused for a couple of hours before telling it to poll again without explicitly logging in and I can see pycarwings2 automatically logging me back in.
Although the initial login does ping the car for an update automatically, (which you will get after a minimum of about 30 seconds) to affirmatively get the latest data every time you are best to use
resultkey = leaf.request_update()
which triggers a poll of the car, then wait a minimum of 30 seconds before checking the result with
response = leaf.get_status_from_update(resultkey)
this function will just return None if there is no response from the car yet, in which case wait a while longer in a while loop (I wait another 20 seconds) then call the function again and see if you have a response - I will probably retry every 20 seconds for a maximum of 4 retries after which point I'll assume polling the car has failed and wait until my next scheduled polling period. (Which is going to be dynamic based on current state of charge, but probably in the order of 10 minutes)
Using leaf_request_update() and get_status_from_update() together is very reliably getting me up to date data in a timely fashion when I am periodically polling - from what I've seen it takes a minimum of about 25 seconds for the Nissan servers to ping the car, wake the ECU's in the car and retrieve the the data from the car for it to be available, hence always waiting at least 30 seconds to avoid unnecessary repeat polls to the API as it usually succeeds the first time if you wait 30 seconds. Sometimes it's taking as long as about 40-50 seconds and no doubt if the car was in an area with a poor mobile data connection it could take quite a bit longer so up to a total of about 2 minutes seems reasonable to wait before giving up, especially if the cars are using 2G as I've heard is the case.
The data and time that the data was received from the car (which seems to be accurate) is also available in the response, so you could do a sanity check to make sure that data was no more than 2-3 minutes old - in my testing it has never been more than one minute old when using leaf_request_update() together with leaf_get_status_from_update().
Once you have positive confirmation that the car has been polled and up to date data is available you can get battery SoC and charging status with
leaf_info = leaf.get_latest_battery_status()
The
is_charging
state is useful as well because this is True when the car is actually charging, but false if the car is plugged in doing timed climate control but not simultaneously charging.
So for example if you detect the car is plugged in and activates the EVSE, and current SoC was already above your target, you could terminate the charging session immediately by switching off the EVSE, but only if
is_charging
is True, because if it is false, it is just going to be timed/remote climate control, not actually charging, in this case you don't want to switch off the EVSE or you will stop the climate control from working.
Anyway slowly working on this script and testing it out - I think this is going to work very well, and I will of course code in failsafe where if I can't poll the API at all I just revert to switching off at a preset time as the Shelly does now with its 3:13 am switch off schedule.
And even if that failed for some reason the result of the compete failure of the script to work would simply be that the car charged to 100%! The timers built into the car and the Shelly enable/start charging, the script I'm writing will only stop the charging at the right time... if the script is not running or working properly the car will just continue charging to 100%.