as far as I know it will be implemented in V3
This should be supported in V2 too, and should work in the Arduino library since July 2017, given the example log (and its explanation) in the pull request that added the feature.
If you’re really not seeing the request going out, then I’d say it doesn’t even matter which backend you’re using. But why are you expecting an empty payload? The linkCheck
command is delegated to the RN2483 module by using mac set linkchk
, which is documented as:
When the time interval expires, the next application packet that will be sent to the server will include also a link check MAC command.
So, I feel it will not be sending standalone packets just for the link check. So, are you sure one of the regular uplinks does not include the MAC command?
If you actually do see the MAC command: are you sure you can receive downlinks? (Like: are you using OTAA?) And anything in the gateway’s Traffic page in TTN Console?
Thank you for your quick response!
First of all, the zero-payload of the uplink was nonsense of course. I referred to the LoRaWANv1.1 spec where it reads:
With the LinkCheckReq command, an end-device may validate its connectivity with the
network. The command has no payload.
The command has no payload, but not the whole message. I should read more carefully.
So, are you sure one of the regular uplinks does not include the MAC command?
No, now I am actually not sure.
are you sure you can receive downlinks? (Like: are you using OTAA?)
I use OTAA (with Brocaar right now). I get uplinks, but no downlinks. Do I need to schedule downlinks by myself with an application or will the network server respond by itself with a downlink just containing the LinkCheckAns command?
Now, I am using TTN again and I also scheduled some downlinks (with nonsense-payload) to carry the LinkCheckAns piggy-back, but the following uplinks do not contain valid values for demod_margin and num_gateways.
The LoRaWANv1.1 spec just says:
When a LinkCheckReq is received by the Network Server via one or multiple gateways, it
responds with a LinkCheckAns command.
???
If OTAA works, then you do get downlinks, as the OTAA Join Accept is a downlink too. So, you’re sure downlinks work. Also, for LinkCheckAns you do not need to schedule a downlink yourself, I think.
To make sure your uplinks include the LinkCheckReq command, paste a raw packet from the gateway into an online decoder and then show us the values for FCtrl
and FOpts
(or show us a full packet here). While testing, make sure to use a very small value (I’d say: 1 second) in ttn.linkCheck
, to increase the chances that a LinkCheckReq is requested.
Also, I’ve no idea if the Brocaar version supports it. TTN should.
You are aware TTN has not implemented v1.1? (Yet)
For TTN I get something like this:
Assuming hex-encoded packet
1240001C09E3FF000CDE
Message Type = Join Request
PHYPayload = 1240001C09E3FF000CDE
( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
MHDR = 12
MACPayload = 40001C09E3
MIC = FF000CDE (from packet) INVALID (tried MSB 0000-FFFF)
= AF291AA5 (expected, assuming 32 bits frame counter with MSB 0000)
( MACPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] )
AppEUI = 0C00FFE3091C0040
DevEUI = DE
DevNonce =
With Brocaar, I get the following
uplinks brocaar.txt (5.8 KB)
FOpts is always null.
You are aware TTN has not implemented v1.1? (Yet)
No, I wasn’t. Nevertheless, the link check should still work, I guess. Brocaar will negotiate the max. supported minor version of LoRaWAN with the TTN node during the OTAA anyway.
You’re showing the Join Request. Instead, you’ll want to look at the uplinks after the device has joined.
I did look at a normal uplink. I don’t know why it tells me it is a join request.
Another trial way after successful join:
Assuming hex-encoded packet
1240002509B8FF000CDE
Message Type = Join Request
PHYPayload = 1240002509B8FF000CDE
( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
MHDR = 12
MACPayload = 40002509B8
MIC = FF000CDE (from packet) INVALID (tried MSB 0000-FFFF)
= 3DEF4FEF (expected, assuming 32 bits frame counter with MSB 0000)
( MACPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] )
AppEUI = 0C00FFB809250040
DevEUI = DE
DevNonce =
Ah, you’re pasting the application payload into that decoder. You should use the full LoRaWAN packet from the gateway. (Like from the gateway’s Traffic page in TTN Console.)
Indeed, so no LinkCheckReq.
Did you minimize the time in ttn.linkCheck(1)
?
(Note that you’re missing some values of the frame counter; jumping from 37, 39 to 47, but maybe you received all?)
uint16_t interval = 1;
ttn.linkCheck(interval);
He had his chance.
I did some random selection of frames. I received all frames of course.
isn’t a linkcheck a kind of downlink message /ack and will there be fair use limitations ? @htdvisser
I don’t know about any.
Nothing changed since 2016 (Questions regarding the TTN fair access policy - #4 by htdvisser):
Everything counts. Each uplink counts towards the total uplink, and each downlink (including ACKs) counts towards the total downlink.
Like Hylke confirmed it is subject to the Fair Access Policy. But as that is not enforced yet, your tests should not be affected by that. (Also, so far I think the problem is that the device is not even asking for the link check.)
Ah, finally unpacked my The Things Node to test it myself
It seems you need to call ttn.linkCheck(interval)
after you’ve joined. So, this works for me:
ttn.join(appEui, appKey);
// Set the time interval in seconds for the link check process to be triggered;
// 0 will disable the link check process. When the time interval expires, the
// next application packet that will be sent to the server will include also a
// link check MAC command in the LoRaWAN FOpts field.
uint16_t interval = 1;
ttn.linkCheck(interval);
Of course, interval = 1
is just for testing.
This yields, e.g., 40DA22012601080002020A3B48DAB7EFC8B9A7461D249E being:
( FHDR = DevAddr[4] | FCtrl[1] | FCnt[2] | FOpts[0..15] )
DevAddr = 260122DA (Big Endian)
FCtrl = 01
FCnt = 0008 (Big Endian)
FOpts = 02
Here, FCtrl
indicates that there’s 1 byte in FOpts
:
And that one byte is a LinkCheckReq:
The response is, e.g., 60DA2201260307000210016C6E99E6, or:
( FHDR = DevAddr[4] | FCtrl[1] | FCnt[2] | FOpts[0..15] )
DevAddr = 260122DA (Big Endian)
FCtrl = 03
FCnt = 0007 (Big Endian)
FOpts = 021001
Here, the 0x02 in 021001
decodes to LinkCheckAns, along with:
So, 0x10 = margin = 16 dB, and 0x01 = gateway count = 1.
Enjoy
That is correct. The LinkCheckAnswer will come directly in the network reply in RX1 or RX2.
Ahaaaa … Thank you all very much for your great support, and in particular I want to thank you Arjan, for providing the solution!
Now it also works for me.
Could someone add a hint to the API documentation, because this does not seem that obvious to me?