If you call LMIC_startJoining() the device will try to join from SF7 to SF12 and then after EV_JOIN_FAILED it will redo the join loop. However this only takes a couple of hours and will send quite a lot of uplinks while on SF7/8.
To save battery I would like to control the interval of join requests to maybe once an hour or so until it successfully joins. Is there any parameters in the library that I could change?
If you mean the LoRaWAN specification version, then the latest LMIC supports 1.0.3 which is much much much better for interaction with TTS in terms of MAC commands, which would be germane to this situation.
Um, if you mean it’s not going to be used on TTN, this would make it off topic for this forum.
The most important detail you’ve left out is where the gateway is in all of this. Is the device trying to join when there are no gateways in the area, if so, why would anyone deploy one in such an area.
If there is a functioning gateway in the area, what does it think is going on - is it hearing the join request and is the network server issuing accepts?
Or are these some contrived tests for a notional real world situation?
If you can give me a bit more context to the situation and the relevance to TTN, there are ways and means of taking control over LMIC.
Imagine a person deploying a lot of meters in a building. Then someone else activates/provisions these meters later on via TTN. The time in between could take several weeks, so I still want the devices to send requests until a gateway accepts.
Other than the fact that devices join the Network through a gateway (rather than joining the gateway) yes that’s sensible.
A join request isn’t substantially heavier in weight than many typical data packets, so if sent at a comparably long interval it won’t really cost more battery or airtime than typical measurement usage.
There is a counter-argument for joining devices before deploying them in that then the packets sent while waiting for connection at least have value immediately when reported in rather than only once a join accept makes it back to the gateway. But there’s also the concern that many implementations are rigged to eventually abandon a joined session in which they receive no response, so if it could be weeks to months it would be hard to know what to set for a giveup threshold.
If you do try the join requests until accepted, you’ll have to keep in mind that formally speaking, there are only 65536 possible join requests that a device can ever send, because the device nonce in the join request is supposed to be unique. That’s a bit over seven year’s worth of attempts at once per hour, or less at more frequent attempts. However, there’s also a pretty good chance that if the device is still trying to join 8 months later, none of the previous attempts were ever seen and recorded as used by a network. So chances are that a wraparound scheme would work fine, and at whatever point a join accept is first finally received, there are probably thousands of never received (if perhaps previously sent) nonce stretching forward [modulo wrapping] from that point.
Also, within a join session, transmitted frame counts wrap at 16 bits, to disambiguate wrapper there’s a smaller limit on how far the frame count can legally skip forward (16384 if I recall). So in actuality, a sensor that’s joined and then transmits for a long time without being received may actually run into trouble four times faster than one that’s deployed still trying to join. And worse, there is absolutely no way for a node to tell if the lack of any response from the network is because there is still no gateway in range, or because its transmit frame count has illicitly advanced too far during the period between initial join at the factory and when there finally became a gateway deployed in position to receive its transmissions, such that even though its transmissions are now being received, they are being rejected for having an illegal (wrapping-ambiguous) frame count.
Of course you can also make devices with mylar pull ribbons that get yanked out to activate the battery. That means someone on site has to visit them when the system is ready to go live, but it also means you don’t burn any battery (beyond self-discharge aging) until that time.
Not sure if such interval option is already in place and usable.
The simplest and very logical alternative would be to have an option to not automatically retry the whole (SF7-SF12) join process after ‘join failed’.
And then ‘manually’ call ‘start joining’ again at a moment/interval you prefer.
Whether that option is currently available/accessible in the LMIC library I don’t know, but it should probably be straightforward to implement.
It will still be better though to first provide the complete infrastructure (e.g. working gateways, provisioning) before powering/activating (the LoRaWAN part of) those metering devices.
The maximum number of join request is describe in the LoRaWan specification in chapter 7 Retransmissions back-off:
36s of Airtime in the first hour
36s in the 10 next hours
8.7s every 24 hours
For now in mcci lmic you can’t control the interval of send of join request, you have to wait for the EV_JOIN_FAIL and then add a wait to reduce the number of join request.
Thanks for the specification info. So basically, not resetting LMIC and not calling LMIC_startJoining() after EV_JOIN_FAILED, would keep the device at sending a join request on SF12 about 4 times every 24h “for ever”?
So what would be the best solution to decrease this rate to send a SF12 join request e.g. once a day instead of 4?
Then of course it is best to provision devices before activation, however these situation can still occur in some cases and I want to handle those cases.
Sorry I wasn’t clear. Now, the back-off is not working in lmic and it will continue to send join request as fast as it is allowed by region settings. Lmic do not respect specification on this point, this is a bug.
@descartes is right you can try different hack to reduce join number when you receive the EV_JOIN_FAILED (maybe reset lmic and sleep for 24h)
Resetting LMiC would be a serious mistake, as that would break the accounting that it does do of channel usage, etc and probably not cause a sound behaviour with join nonces, either.
You should figure out how to work the more relaxed join into the actual program logic, rather than hack it at cross purposes to the design.
For one thing, keep in mind that LMiC itself doesn’t know how to low power sleep or wake up from it, if you do so in or perhaps better after noting the join failure callback you have absolute control over the soonest anything else can happen, though you typically also need to give LMiC a sense of how much time has actually passed and a sound sense of when something should next happen - people who get that wrong tend to find that LMiC ends up waiting even longer after each wakeup until it believes that it’s time to do something.