manuelbl / ttn-esp32

The Things Network device library for ESP32 (ESP-IDF) and SX127x based devices
MIT License
303 stars 64 forks source link

Feature request: Keep session during deep sleep. #5

Closed jpmeijers closed 3 years ago

jpmeijers commented 5 years ago

When an ESP32 goes into deep sleep, the main memory is cleared. The programs starts from the beginning when the device wakes up.

Using ttn-esp32, at startup a join procedure is done. Say I have a device that only wakes up very seldomly. This device should only join once (in the factory/during initial programming), or periodically (±once a month). Therefore the state of the LoRaWAN session should be kept during sleep, and updated when a transmission is made.

Possible solution:

  1. After a successful join save the session (AppSessionKey, NetworkSessionKey, UplinkFrameCounter, DownlinkFrameCounter) in RTC memory (or in Flash).
  2. At startup check if there is a valid session stored in RTC memory. If there is a valid session, do not do the provisioning/joining and use the existing session.
  3. If we do not have a session stored, do a join and save the session.
  4. When sending a message, update the frame counters of this session.
  5. When receiving a message, update the frame counters of this session.

Nr 4 and 5 should already be done by LMIC, but it is in volatile memory. If we can move the variables that are use by LMIC for the session keys and frame counters to non-volatile memory it will already solve most of this. Then we just need a way to query the current session to see if we need to join or not. LMIC already has a way to do this too - it only joins when the first message is sent, and never joins when a session is hardcoded (ABP mode).

manuelbl commented 5 years ago

This feature is already on my wish list. I recently stumbled upon this LMIC modification that seems to have implemented this. It saves and restores all relevant LMIC data into RTC RAM.

jpmeijers commented 5 years ago

O wow, that looks great. Thanks for linking me to that library.

ngraziano commented 5 years ago

@jpmeijers I think saving only the Uplink and Downlink frame counter is not enough to be more generic (OTAA, ADR send some parameter to the device). The easiest way I think is to save all LMIC structure in RTC memory after a successful send and after init overwrite all the struct with the saved one. (In my version pointed by @manuelbl I save item by item but it is not saving a lot of byte of RTC memory). The other thing which is important is the time overflow (os_getTime), the calculation of band availability can introduce problem and generate unwanted wait.

Beliwars commented 4 years ago

Hello @ngraziano did you correct the time overflow issue on your modified version of LMIC? I haven't found how to modify the millis running on ESP32.

ngraziano commented 4 years ago

Hello @Beliwars For os_getTime I use the RTC to get the value but it may overflow the same way than other LMIC version because I also use an uint32, so the I never sleep more than 1 hour and I do not have problems. (overflow is every 9,5 hours if my maths are correct).

manuelbl commented 3 years ago

In order to go to deep sleep and still be a good network citizen, a lot of parameters have to be saved and restored. Currently, the underlying MCCI LMIC library does not support it even though there are discussions about implementing it. The feature would be a huge win for many applications.

I will implement it in this library if the MCCI LMIC implements it or if I find another suitable library that could be used instead of MCCI LMIC.

For now, I'm going to close this issue.