Strategy for LoRaWAN with deepsleep 2



  • Re: Strategy for LoRaWAN with deepsleep It is important that lopy when it wakes up from deepsleep has the opportunity to "remember" to join. Does anyone have any suggestion?



  • @jmarcelino said in Strategy for LoRaWAN with deepsleep 2:

    You mean after each deep sleep?

    Yes.

    On the latest firmware you can now call lora.nvram_save() before entering to deep sleep to save the counters and lora.nvram_restore() on restart, after initialising the LoRa object and before sending your data.

    Oh, I totally missed that in the release notes! :) Thanks, that should solve that issue!



  • @dbrgn
    You mean after each deep sleep?

    On the latest firmware you can now call lora.nvram_save() before entering to deep sleep to save the counters and lora.nvram_restore() on restart, after initialising the LoRa object and before sending your data.



  • I stumbled over this topic again, this time while using ABP with relaxed frame counters on TTN.

    I have a node that sends a measurement every X seconds. Since ABP does not remember the frame counter, it will always be 1.

    Now if I send a downlink from TTN to the device, that will be delivered once the device sends the next uplink. That uplink has the frame counter 1.

    Now if another uplink is sent with the frame counter 1, the network server thinks that it is a retry message and will send the downlink again. We're now stuck in a kind of downlink loop.

    I'd like to note that a device that does not remember the ABP frame counter is not LoRaWAN-compliant:

    screenshot 1

    screenshot 2

    And since the stack is not accessible from Python (in order to restore the frame counter), it's not possible to create a LoRaWAN compliant node at the moment with stock firmware, right?

    Any ideas how to deal with that situation?

    @daniel are there plans to fix this in the near future? Or are there workarounds?



  • @jmarcelino said in Strategy for LoRaWAN with deepsleep 2:

    So again it should be up to the application to decide if/when it should restore these.
    That said - while I have concerns about doing it automatically - I'd like the ability to get and set frame counters and session keys when and how I wish from my application. It would be a good feature.

    Yes exactly, I wouldn't necessarily expect you to store those keys automatically, but an API for that would be great. My approach would probably be to join via OTAA once per day. In that case, if the keys would expire immediately after the join then only 1 day worth of data would be lost.

    use ABP, relaxed counters and run your own encryption to prevent replay attacks

    What technique would you suggest for that? It probably still requires some kind of counter in the packet.



  • @dbrgn said in Strategy for LoRaWAN with deepsleep 2:

    Isn't it pretty simple? If you have a way to pre-flash every device with its own key, use ABP. If not, use OTAA. When using ABP, store the frame counter when going to sleep and restore after wakeup.

    Well, as far as I understand it's not really that simple.

    It's not enough to just store the frame counter at every sleep and restore it at wake, if your LoPy crashes for any reason - which still happens regularly - or if it runs out power the counter would still be incorrect and your network enforcing frame counters will still reject packets until things get matched up again.

    Ideally you want to store the frame counter with each send/receive (remember there are two counters), but that takes us to flash reliability and read/write cycles so you'd have to do some wear levelling algorithm - or maybe not store all frame counters, but again that depends a lot on what the application expects.

    For OTAA I have questions about key validity. LoRaWAN is still evolving and I don't believe that currently any set of OTAA keys (there are two, NwkSKey and AppSKey) will last forever, especially the NwkSKey - they are called session keys for a reason. So again it should be up to the application to decide if/when it should restore these.

    That said - while I have concerns about doing it automatically - I'd like the ability to get and set frame counters and session keys when and how I wish from my application. It would be a good feature.

    In what part of the source code would that need to be added?

    There's a few but modlora.c would be a starting point

    As far as real world LoRaWAN my own approach is to be paranoid: don't assume anything from network - use ABP, relaxed counters and run your own encryption to prevent replay attacks



  • To continue the discussion from here:

    Some modules like the RN2483 do support it, some others like the RM186 don't. IMHO LoRaWan doesn't offer a clear, best-practice, strategy for doing this.

    Isn't it pretty simple? If you have a way to pre-flash every device with its own key, use ABP. If not, use OTAA. When using ABP, store the frame counter when going to sleep and restore after wakeup.

    The issue with OTAA joins on every wake up is not just battery lifetime, but also gateway airtime. Downlinks are expensive, LoRaWAN does not scale if every node that wakes up every 10 minutes must do a join procedure, blocking all other communications during the downlink transmission.

    Just wondering, are there already "real world" deployments out there with LoPy devices? What do these use, ABP with relaxed frame counter? I can't imagine getting useful battery life with an OTAA join before every transmission.

    And if you have ABP with relaxed frame counters, replay attacks are trivial, right? Basically every SDR software has a "record and replay" feature that could be used to re-send old transmissions.

    With the LoPy you could of course add the functionally to the firmware since the source code is available .

    In what part of the source code would that need to be added?



  • @jmarcelino Excuse for unformatted code. Yes, it's my main.py



  • @_peter
    (in the future please put code between two
    ```
    ```
    lines otherwise the formatting gets all wrong, see this for more formatting tips)

    Is this your main.py file?



  • @Camot
    I tried with relaxed frame counter in ABP mode but it does not work. Send the data once and then nothing.
    Below the code on lopy:

    from network import LoRa
    import socket
    import binascii
    import struct
    
    # Initialize LoRa in LORAWAN mode.
    lora = LoRa(mode=LoRa.LORAWAN)
    
    # create an ABP authentication params
    dev_addr = struct.unpack(">l", binascii.unhexlify('07 11 7d e5'.replace(' ','')))[0]
    nwk_swkey = binascii.unhexlify('1b a9 32 60 6e e0 9d 0d 41 6a 51 af 98 6e ec 5b'.replace(' ',''))
    app_swkey = binascii.unhexlify('9a 28 99 2c 03 79 78 2a 3d 93 f5 c6 df b4 af e4'.replace(' ',''))
    
    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))
    
    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    
    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
    
    # make the socket blocking
    # (waits for the data to be sent and for the 2 receive windows to expire)
    s.setblocking(True)
    print('send')
    # send some data
    s.send(bytes([0x01, 0x02, 0x03]))
    
    # make the socket non-blocking
    # (because if there's no data received it will block forever...)
    s.setblocking(False)
    
    # get any data received (if any...)
    data = s.recv(64)
    print(data)
    machine.deepsleep(60000)
    


  • @jmarcelino OK, that's reasonable. I see that as an exception case rather than normal operation. Also, the basic idea is to increase battery life and minimize airtime usage, so even if I rejoined every 10 message intervals, that's still a 10X reduction of "join overhead". The "right" interval of re-joins will be up to the application, of course, but it's hopefully somewhat less frequently than "every time" and much more than "once". I wonder if TTN (and other networks) generally provide a way for the application to know that a message was received from a known device with invalid keys?



  • @Eric24
    Well TTN not long ago 'expired' all OTAA keys when they moved servers to production, the expectation was that OTAA nodes would pick up the new keys automatically. From what I understand this expectation is still in place at TTN and other networks.

    Also keep in mind there is a valid window for LoRaWAN frame counters - maxFCntGap = 16384 in the TTN source - for example if a node sends 16384 packets that for some reason (out of range, gateway down..) don't get picked up by TTN there will be a mismatch and TTN won't accept further data from the node - so you may want to reset those counters occasionally via rejoin.



  • @jmarcelino I did some additional research on the topic of expiring keys, and based on this post at TTN (https://www.thethingsnetwork.org/forum/t/otaa-node-sleep-mode/5188/7) and a review of the LoRaWAN specs, it appears that the server will never expire the keys after a join (the node can re-join if it wants new keys or if the message counter rolls over or is about to roll over). Although I have found mentions of session key expiration, so at least that concept is "out there". Do you have specific experience with networks/servers that expire the OTAA session keys?

    Bottom line, if the keys aren't expired by the server, then the idea of reusing the keys without re-joining is pretty straightforward (pending the ability to "set" the keys from some non-volatile memory).



  • @jmarcelino Question about the ATECC508A that you mentioned (as it relates to LoRaWAN, not "my own" authentication system): Does it support AES-128? I can't find any mention of anything other than AES-256, which makes it useless for working with LoRaWAN keys, etc. I was looking at the ATAES132A for this purpose. Any experience or thoughts on this?



  • Anyone knows what approach thingamagogs like this use? I guess ABP and pre-generated random keys, but I didn't find any details: http://ecubelabs.com/integrated-waste-management/ultrasonic-fill-level-sensor/



  • @jmarcelino Hmmm. I suppose so, if you have control of the network (although some would argue that this would be less secure). But I was also thinking about public networks where you don't have control, but could have specific knowledge of key lifetimes. Of course there's no technical problem with re-joining on every transmission, but it's definitely not optimal. It makes me wonder if a lot of LoRaWAN implementations are actually doing just that, because it's easier to implement?



  • @Eric24 ]
    If you have some control of the network some good advice I've heard - but not implemented personally yet - is to forget OTAA, run ADP with frame counters relaxed and implement your own authentication system using for example a crypto chip like the ATECC508A



  • @jmarcelino Right--ability to set keys will be needed. Regarding not knowing if they keys are valid, just thinking out loud...if you have some knowledge (or control) of the server behavior, you could know how long until the keys expire; let's say they last for 24 hours; given that, maybe the device (using the RTC) transmits without re-join for up to 23 hours (or so) and then re-joins on the next interval. Any flaw in that logic? Of course my objective here is to maximize battery life, and for a device that reports every 5 minutes, all that re-joining will add up.



  • @Eric24
    That's not possible yet because you have to tell the LoRa stack: "here reuse these keys I stored somewhere to connect" and that's not possible yet. Of course all the source code is out there so if anyone wants to have a go don't let me stop you. That's a functionality me and I'm sure many others will need for larger deployments so, even if Pycom doesn't get around to doing it, it'll come at some point.

    The other problem - but that's more an issue with LoRa and similar protocols - is it's not possible to know if the keys generated for an OTAA session are still valid without actually getting a response from the network, something you get for "free" with a fresh join. So always doing a join is safer. It's a balancing act.



  • @papasmurph It seems that the issue is not so much about whether it's possible to re-join, but the additional "on time" and radio power budget required to do so. Ideally, a LoRaWAN device should join very infrequently, sleep most of the time, and minimize its "on time" and radio usage (i.e. no re-joining) as much as possible. And that's not only a battery-life issue, but can also become a duty-cycle or simply system capacity issue at scale.

    Ultimately, I think storing the information needed to wake-up and transmit without re-joining is a necessity (especially for battery-powered devices). How that information is stored is another matter (the RTC NVRAM would be ideal, as soon as it's supported). But the question your comment brings up is what to do about the "joined" flag? If it's always necessary to re-join after deep sleep, that would be a significant issue. Has anyone else been able to "force" a joined state after deep sleep?


Log in to reply
 

Looks like your connection to Pycom Forum was lost, please wait while we try to reconnect.