Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting state save/restore to work? NetSaveSessionInfo/NetSaveSessionState/NetGetSessionState/GetAbpProvisioningInfo/GetProvisioningStyle #189

Open
ObviousInRetrospect opened this issue Apr 3, 2022 · 2 comments

Comments

@ObviousInRetrospect
Copy link

I'm not having much luck getting session save/restore to work.

Multiple examples show that you need to implement NetSaveSessionInfo/NetSaveSessionState/NetGetSessionState.

Based on issue #165 I also added GetAbpProvisioningInfo. When that wasn't actually being called I overrode GetProvisioningStyle to check for a saved session and return ProvisioningStyle::kABP.

At the moment I am using EEPROM as a placeholder. I know it will have endurance problems and once I get it working will switch to storing it in sram on a 2nd mcu acting as an i2c slave (that also acts as a watchdog).

The SessionState gets stored starting at EEPROM address 0. The SessionInfo gets stored starting at EEPROM address sizeof(SessionState):

bool
cMyLoRaWAN::GetOtaaProvisioningInfo(
    OtaaProvisioningInfo *pInfo
    ) {
    Serial.println("GetOtaaProvisioningInfo");
    memcpy(pInfo->DevEUI, DEVEUI,8);
    memcpy(pInfo->AppEUI, APPEUI,8);
    memcpy(pInfo->AppKey, APPKEY,16);
    return true;
}
bool cMyLoRaWAN::GetAbpProvisioningInfo(
                        Arduino_LoRaWAN::AbpProvisioningInfo *pInfo
                        ){
    SessionInfo si;
    SessionState ss;
    Serial.println("GetAbpProvisioningInfo:");
    Serial.print("Loading SessionInfo:");
    uint8_t * pb = (uint8_t *) &si;
    for(int i=0; i<sizeof(SessionInfo); i++){
      pb[i]=EEPROM.read(sizeof(SessionState)+i);
      printHex2(pb[i]);
    }
    Serial.println("");
    if(si.Header.Tag != kSessionInfoTag_V2){
      Serial.print("SessionInfo from EEPROM has tag: ");
      Serial.print(si.Header.Tag);
      Serial.println(" aborting restore.");
      return(false);      
    }
    this->NetGetSessionState(ss);
    if(ss.Header.Tag != kSessionStateTag_V1){
      Serial.print("SessionState from EEPROM has tag: ");
      Serial.print(si.Header.Tag);
      Serial.println(" aborting restore.");
      return(false);      
    }
    pInfo->NetID = si.V2.NetID;
    pInfo->DevAddr = si.V2.DevAddr;
    memcpy(pInfo->NwkSKey, si.V2.NwkSKey, 16);
    memcpy(pInfo->AppSKey, si.V2.AppSKey, 16);    
    pInfo->FCntUp=ss.V1.FCntUp;
    pInfo->FCntDown=ss.V1.FCntDown;
    return true;
}
void
cMyLoRaWAN::NetSaveSessionInfo(
    const SessionInfo &Info,
    const uint8_t *pExtraInfo,
    size_t nExtraInfo
    ) {
    // save Info somewhere.
    const uint8_t * pb = (uint8_t *) (&Info);   
    Serial.print("NSSI: "); 
    for(int i=0; i<sizeof(SessionInfo); i++){
      EEPROM.write(sizeof(SessionState)+i, pb[i]);
      printHex2(pb[i]);
    }
    Serial.print(" exI: "); 
    for(int i=0; i<nExtraInfo; i++){
      EEPROM.write(sizeof(SessionState)+sizeof(SessionInfo)+i, pExtraInfo[i]);
      printHex2(pExtraInfo[i]);
    }
    Serial.println();
    EEPROM.commit();
    Serial.print("Saved SI ");
    Serial.print(sizeof(SessionInfo) + nExtraInfo);
    Serial.println(" Bytes.");
}
void
cMyLoRaWAN::NetSaveSessionState(const SessionState &State) {
    // save State somwwhere. Note that it's often the same;
    // often only the frame counters change.
    Serial.print("NSSS: ");
    const uint8_t * pb = (uint8_t *) (&State);    
    for(int i=0; i<sizeof(SessionState); i++){
      EEPROM.write(i, pb[i]);
      printHex2(pb[i]);
    }
    Serial.println("");
    Serial.print("Saved SS ");
    Serial.print(sizeof(SessionState));
    Serial.println(" Bytes.");
    EEPROM.commit();
}
Arduino_LoRaWAN::ProvisioningStyle cMyLoRaWAN::GetProvisioningStyle(void){
  uint8_t tag = EEPROM.read(sizeof(SessionState)+0);
  if(tag == kSessionInfoTag_V2){
    Serial.println("Have a SessionInfo, ABP");    
    return Arduino_LoRaWAN::ProvisioningStyle::kABP;
  }
  Serial.println("No SessionInfo, OTAA");
  return Arduino_LoRaWAN::ProvisioningStyle::kOTAA;
}
bool
cMyLoRaWAN::NetGetSessionState(SessionState &State) {
  Serial.print("NGSS: ");
    // either fetch SessionState from somewhere and return true or...
    uint8_t * pb = (uint8_t *) (&State); 
    for(int i=0; i<sizeof(SessionState); i++){
      pb[i]=EEPROM.read(i);
      printHex2(pb[i]);
    }
    Serial.println("");
    return true;
}

Here is the output from the first boot with the EEPROM cleared:

eeprom cleared
BOOTING....
NGSS: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
No SessionInfo, OTAA
No SessionInfo, OTAA
Packet queued
NSSS: 01D802000000000000000000000000004D19FBFFA0700837A0700837000080FF14000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
NSSI: 02340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 exI: 
Saved SI 52 Bytes.
NSSS: 01D8020000000000000000000000000062FCFAFFA0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
331357: EV_JOINING
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
NSSI: 023400004865320026000048F22C117AD48428A5691BCF974A225B60AE076996F3F9DB1ADE315B7B5D647075301DFB3F00000000 exI: 
Saved SI 52 Bytes.
NSSS: 01D8020000000000000000000000000029B8F5FFA0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
682414: EV_JOINED
netid: 3302728
devaddr: 48000026
AppSKey: AE-07-69-96-F3-F9-DB-1A-DE-31-5B-7B-5D-64-70-75
NwkSKey: F2-2C-11-7A-D4-84-28-A5-69-1B-CF-97-4A-22-5B-60
NSSS: 01D802000000000000000000000000006B95F5FFA0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
686013: EV_TXCOMPLETE (includes waiting for RX windows)
5302 ms: TX: ch=8 rps=0x04 (SF10 BW125 CR 4/5 Crc IH=0)
Packet queued
NSSS: 01D80201010000000100000000000000127A0000A0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
NSSS: 01D8020101000000010000000000000078630000A0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
4523406: EV_TXCOMPLETE (includes waiting for RX windows)
NSSS: 01D80201020000000100000000000000117A0000A0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
4687540: EV_TXCOMPLETE (includes waiting for RX windows)
70977 ms: TX: ch=13 rps=0x03 (SF9 BW125 CR 4/5 Crc IH=0)
72727 ms: TX: ch=15 rps=0x03 (SF9 BW125 CR 4/5 Crc IH=0)

Here is the reboot,

01234BOOTING....
NGSS: 01D80201020000000100000000000000117A0000A0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Have a SessionInfo, ABP
Have a SessionInfo, ABP
GetAbpProvisioningInfo:
Loading SessionInfo:023400004865320026000048F22C117AD48428A5691BCF974A225B60AE076996F3F9DB1ADE315B7B5D647075301DFB3F00000000
NGSS: 01D80201020000000100000000000000117A0000A0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet queued
NSSS: 01D802000000000000000000000000005A0CFBFFA0700837A0700837000080FF14000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
NSSI: 02340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 exI: 
Saved SI 52 Bytes.
NSSS: 01D802000000000000000000000000009DE3FAFFA0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
337701: EV_JOINING
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
GetOtaaProvisioningInfo
NSSI: 023400004865320027000048CE118DD36177D3F1517C03781D38C79098B2F48C0DD0B9D80183B7C84E1707AB901EFB3FD702FC3F exI: 
Saved SI 52 Bytes.
NSSS: 01D80200000000000000000000000000ED93F5FFA0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
685906: EV_JOINED
netid: 3302728
devaddr: 48000027
AppSKey: 98-B2-F4-8C-0D-D0-B9-D8-01-83-B7-C8-4E-17-07-AB
NwkSKey: CE-11-8D-D3-61-77-D3-F1-51-7C-03-78-1D-38-C7-90
NSSS: 01D80200000000000000000000000000C887F5FFA0700837A0700837000080FF15000000080100000A000000011600FF000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Saved SS 216 Bytes.
689500: EV_TXCOMPLETE (includes waiting for RX windows)
5404 ms: TX: ch=8 rps=0x04 (SF10 BW125 CR 4/5 Crc IH=0)

You can see it does a rejoin and gets a new AppSKey/NwkSKey

What am I doing wrong? Any chance a fixed version of this could be added as an example?

@ObviousInRetrospect
Copy link
Author

Is there any other information that would be helpful? Thanks.

@ObviousInRetrospect
Copy link
Author

in case anyone else is stuck on this:

while I still can't get the convoluted NetGetSessionState flow to work, the underlying arduino-lmic library has a far simpler to use set of functions that work fine.

The following example code works (and will wear out eeprom if used as below)


typedef struct{
  uint32_t seqnoUp;
  uint32_t netid;
  devaddr_t devaddr;
  uint8_t nwkKey[16];
  uint8_t artKey[16];
} eep_sstate_t;

void store_joininfo(u4_t netid, devaddr_t devaddr, uint8_t *nwkKey, uint8_t *artKey){
  eep_sstate_t st;
  st.seqnoUp=LMIC_getSeqnoUp();
  st.netid=netid;
  st.devaddr=devaddr;
  memcpy(st.nwkKey,nwkKey,16);
  memcpy(st.artKey,artKey,16);
  uint8_t *r = (uint8_t*)&st;
  for(int i=0; i<sizeof(eep_sstate_t); i++){
    EEPROM.write(i,r[i]);
  }
  EEPROM.commit();
}

bool eep_rejoin(){
  eep_sstate_t st;
  uint8_t *r = (uint8_t*)&st;
  for(int i=0; i<sizeof(eep_sstate_t); i++){
    r[i]=EEPROM.read(i);
  }
  if(st.netid == 0xFFFFFFFF || st.netid == 0x0){
    Serial.println("no session in EEPROM");
    return false;
  }
  LMIC_reset();
  LMIC_setSession(st.netid, st.devaddr, st.nwkKey, st.artKey);
  LMIC_setSeqnoUp(st.seqnoUp);
  return(true);
}

and then in onEvent:


and then in onEvent:

case EV_JOINED:
...
    store_joininfo(netid,devaddr,nwkKey,artKey);

case EV_TXCOMPLETE:
...
            uint32_t su = LMIC_getSeqnoUp();
            uint8_t *sup = (uint8_t*)&su;
            EEPROM.write(0,sup[0]);
            EEPROM.write(1,sup[1]);
            EEPROM.write(2,sup[2]);
            EEPROM.write(3,sup[3]);
            EEPROM.commit();

and finally call eep_rejoin(); at startup.

Also, the state this way is 44 bytes instead of far more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant