For the sake of completeness:
…actually: maybe not. If the difference between the device’s uplink counter and the zero value in TTN exceeded the maximum difference between two subsequent received values (MAX_FCNT_GAP
or 16,384), then maybe TTN cannot recover from that.
Or even if the code knows the counter has been reset and hence simply knows it can accept anything, then if the node’s uplink counter exceeds 65,536 (or maybe twice that value; 131,072) then it might not be able to find the matching MSB. In LoRaWAN 1.0.x, the value of FCnt
only holds the 16 least-significant bits (LSB) of the actual frame counter. But for a 32 bits frame counter still all 32 bits are used when calculating the MIC. So, the server needs to guess or try the other 16 bits when validating the MIC. The server can use its own internal counters for a best guess. And due to the maximum allowed gap between the last known value and current value, the server needs to try, and will try, only one additional value for the MSB. And that will fail after resetting the counters, if the node’s uplink counter is large.
Even though you also already disabled the frame counter checks, TTN would then still be unable to find a matching MIC. I’ve tested by changing a NwkSKey of an ABP node in TTN Console. This also automatically reset the frame counters ; even just changing “Frame Counter Checks” or its description will also reset the counters! (Bug 746.) So even after restoring the correct NwkSKey TTN was still unable to find a matching MIC. In the trace part of the Gateway Traffic this showed the exact same thing that we saw for my earlier success and your failure. So, indeed: TTN will not report if it cannot match the MIC.
So: do you know the last 32 bits uplink counter value? If not, you can use a Node.js script to brute-force the MSB and determine the full 32 bits counter:
/*
* Brute-forces finding a LoRaWAN uplink counter's 16 most-significant bits.
* This needs:
* npm install lora-packet
*/
const lorapacket = require('lora-packet');
const nwkSKey = new Buffer('7A47...', 'hex');
const uplink = new Buffer('4053...', 'hex');
const packet = lorapacket.fromWire(uplink);
console.log(packet.toString());
const msb = new Buffer(2);
for (let i = 0; i <= 0xFFFF; i++) {
console.log(`Trying: ${i}`);
msb.writeUInt16LE(i, 0);
if (lorapacket.verifyMIC(packet, nwkSKey, null, msb)) {
console.log(`Found MSB: 0x${('0000' + i.toString(16)).substr(-4)}`);
console.log(`32 bits FCnt: ${i << 16 | packet.getFCnt()}`);
break;
}
}
Meanwhile I’ve also enhanced the online decoder to brute-force the FCnt’s MSB. So, the online decoder will also give you the 32 bits FCnt if it can find a valid MIC, even though only 16 bits are given in the LoRaWAN packet.
Indeed, the following fixed my ABP node again:
ttnctl devices set my-device --fcnt-up 123456
…and then there is hope!
Although I’ve no idea how to determine the last known downlink counter… So I guess ADR is now no longer working for that node, until it’s made to do a new OTAA Join.