mcci-catena / arduino-lmic

LoraWAN-MAC-in-C library, adapted to run under the Arduino environment
https://forum.mcci.io/c/device-software/arduino-lmic/
MIT License
636 stars 207 forks source link

Requirements for restarting as "ABP" from previous OTAA #582

Closed bertrik closed 4 years ago

bertrik commented 4 years ago

I've written a firmware for an ESP32+SX1272 board. It does an OTAA once, then remembers the session keys in (simulated) EEPROM. On next boot/powerup, it starts in "ABP" mode with parameters from the OTAA done on an earlier boot. They were saved using LMIC_getSessionKeys() during JOIN and restored using LMIC_setSession() on later bootup/powerup.

What I see now is that basically every uplink from my node triggers a downlink from the network (TheThingsNetwork) on port 0. I'm sending only unconfirmed messages. I can't really know what the network is sending (console doesn't show me), but I assume it is ADR. My node is sending as SF12BW initially.

What could be the cause of these numerous downlink messages from the network? Am I doing the resume-from-previous-OTAA correctly? In some of the ABP examples I can see that the downlink data rate being set: https://github.com/mcci-catena/arduino-lmic/blob/master/examples/ttn-abp/ttn-abp.ino#L290 LMIC.dn2Dr = DR_SF9; Should I be doing that too?

I'm using LMIC tagged as v3.2.0 with platformio. The network is TheThingsNetwork, eu region. Board is a heltec wifi lora 32, radio chip is sx1272 as far as I know.

My code is at https://github.com/bertrik/LoraWanPmSensor/blob/master/Esp32PmSensor/Esp32PmSensor.ino

terrillmoore commented 4 years ago

Yes, the network is trying to get you to reduce your SF because you’re coming in loud and clear.

You should save the SF (and the channel map) across reboots – the network also sends you a complete channel map at join, and you should honor that. Also, TTN changes the RX2 SF and other things. Unfortunately, I don’t have a list of everything you need to save. My suggestion is to look at the compliance sketch, which prints out all downlinks, and do the same in your script to see what they’re sending after original join, and make sure you retain that info. It’s not a huge amount of data.

There may be other parameters that need to be set, but this is why you’re getting downlinks.

--Terry

bertrik commented 4 years ago

Sorry, I feel a bit stuck in the middle.

On one hand there is TheThingsNetwork recommending OTAA in their "best practice" guide: https://www.thethingsnetwork.org/docs/devices/bestpractices.html Use OTAA to join and do this only once (during manufacture for example) then remember the device address (and session keys). No word about other parameters. On the other hand, the stack you're maintaining is the best LoRaWAN software stack I know of, but it does not currently implement the ability for restoring other essential parameters besides the network id, session keys and device address.

Would be nice to get some more support from TTN for this library, to back up their recommendations. Also would be nice to be to know for sure what the TTN is trying to send on port 0.

Anyway, TTN is probably sending ADR commands and apparently they're not heard by the node. My first try will be to follow your suggestion and see what changes TTN makes to the standard parameters in the JOIN response.

JackGruber commented 4 years ago

@bertrik it's not perfect, but works for me: https://jackgruber.github.io/2020-04-13-ESP32-DeepSleep-and-LoraWAN-OTAA-join/

terrillmoore commented 4 years ago

@bertrik thanks for the kind words. This is all about resources. The LMIC originally had no concept of living through a power failure, and the database has never been sorted into "things that must be persisted" and "things that are transient". It's been on my list for a while, but functional changes have taken priority. The current development thread is adding secure element support; this also has an effect on "what must be persisted" because some SE's want to store the frame counters, etc., for us. My current recommendation "for best results", if you're using the bare LMIC, is to rejoin on reboot. Otherwise, you have to sort through the parameters on your own, and you'll have to synch up again if we finally get around to fixing it. We need to add class C, multicast, and updates for the 1.0.4 regional parameters... get class B working.. fix configuration so that it's not as confusing when taking out class B... improve logging... add SX1262 support... add 2.4 GHz LoRaWAN support... there's a lot to do.

MCCI's solution for your specific problem has been to wrap this in other libraries (arduino-lorawan and catena-arduino-platform), but those are more and more MCCI-specific. However, you can look at them for reference. There are known problems in those wrappers, too, but we're using them in production right now, so they're not terrible.

Bear in mind that although you can access LMIC.whatever, that doesn't mean that those are "permanent API elements". The only things you can really rely on long term are the things accessed via function calls. So it's a good idea to put all the stuff that accesses LMIC.whatever inside function calls, so you can quickly change them (or #if them based on the LMIC version).

bertrik commented 4 years ago

Thanks for the pointers, that exlains a lot. As a first step, I've saved the downlink SF, this alone seems to make a huge difference. The node is now able to hear the ADR from the network. I can see that the node starts at SF12, gets a downlink (with ADR) and I see the following uplinks already using a much more appropriate SF.