LoRaWAN OTAA join failing on TTN AU915 — JoinRequest visible in gateway traffic but device live data is empty
Asked by stale_biscuit_03 ·
Got a LilyGO T3S3 (ESP32-S3 + SX1262 onboard) and I'm trying to get it joining TTN on AU915. Been at this for most of yesterday and this morning and I'm going in circles.
Setup:
- MCCI LMIC 4.1.1 via Arduino IDE
lmic_project_config.hhasCFG_au915andCFG_sx1262_radiodefined- Device registered on TTN Australia 1 cluster, OTAA, LoRaWAN 1.0.3, frequency plan set to "Australia 915–928 MHz, FSB 2"
LMIC_selectSubBand(1)called insetup()afterLMIC_reset()
Here's the part I can't figure out: I can actually see the JoinRequest arriving in the TTN gateway live data panel. It's on 917.4 MHz, SF9, RSSI around –97 dBm. So the radio is definitely transmitting and the gateway is hearing it.
But the device live data tab is completely empty. No JoinRequest event, no
JoinAccept, nothing. Serial on the T3S3 just shows EV_JOINING every few
minutes as LMIC retries.
Key arrays (sanitised, but byte order is exactly as copied from TTN):
// All zeros — standard MCCI LMIC convention for TTN
static const u1_t PROGMEM APPEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Copied from the TTN end device overview page
static const u1_t PROGMEM DEVEUI[8] = { 0x70, 0xB3, 0xD5, 0x7E, 0xD0, 0x04, 0x2A, 0x8C };
// AppKey generated by TTN
static const u1_t PROGMEM APPKEY[16] = { 0x4A, 0x23, 0x96, 0xF1, 0x0B, 0x87, 0xE5, 0xD3,
0xC7, 0x5E, 0x9A, 0x12, 0x34, 0x56, 0x78, 0x9A };
Setup:
void setup() {
Serial.begin(115200);
os_init();
LMIC_reset();
LMIC_selectSubBand(1);
do_send(&sendjob);
}
The sub-band selection seems to be working — the gateway is hearing the JoinRequest fine. But it's like TTN doesn't know the device exists. Is there something about how gateway live data vs device live data works that explains this?
3 Replies
Your DEVEUI array is in the wrong byte order — that's the entire problem.
MCCI LMIC expects DEVEUI (and APPEUI) in LSB order: least significant byte
first, which is the byte-reversed version of how TTN displays them in the
console. So if your registered DevEUI is 70:B3:D5:7E:D0:04:2A:8C, the array
must be:
// LSB order — bytes reversed from the TTN console display
static const u1_t PROGMEM DEVEUI[8] = { 0x8C, 0x2A, 0x04, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
What you have now puts the bytes in MSB order. LMIC transmits the DEVEUI
starting from index 7 (last byte first), so the DevEUI the gateway decodes
from your JoinRequest is 8C:2A:04:D0:7E:D5:B3:70 — the reversed value.
TTN's network server looks that up, finds no matching registration, and silently
discards the frame without sending a JoinAccept.
That's exactly why you see the JoinRequest in gateway live data (gateways forward every frame they receive regardless of whether the network server recognises the device) but nothing in device live data (which only shows frames that the network server successfully attributed to a registered device).
Fix: In the TTN end device overview, look at the copy buttons next to DevEUI and JoinEUI — there are two: MSB and LSB. Use the LSB button for both DEVEUI and APPEUI. APPKEY is different: LoRaWAN always uses MSB order for the AppKey, so the default copy gives you what LMIC expects. That one is fine as-is.
After reflashing, check the gateway traffic details panel for your next JoinRequest. Some TTN gateways surface the decoded DevEUI in the packet metadata — if it matches your registered DevEUI exactly (not reversed), the next attempt will produce a JoinAccept.
One AU915-specific timing note: the OTAA receive window is 5 seconds after each JoinRequest (JOIN_ACCEPT_DELAY1 per the LoRa Alliance Regional Parameters RP002-1.0.3). LMIC handles the window automatically, but don't power-cycle or reset the device in the first few seconds after a join attempt while debugging — you'd miss the window every time. The longer delay also applies to RX2 at 6 seconds; regular data uplink windows are a separate 1-second delay.
Full AU915 sub-band table and the MCCI LMIC byte order requirement are both in the TTN AU915 setup guide — the LSB/MSB distinction is easy to miss the first time through.
Byte order answer is correct. Worth adding a diagnostic framework for the next time this category of failure appears.
The gateway-vs-device live data split cleanly separates two different OTAA failure modes:
JoinRequest in gateway traffic but absent from device live data — the gateway received and forwarded the frame, but the network server couldn't match it to any registered device. The on-air DevEUI doesn't match the registered DevEUI. Cause is almost always a byte order error in DEVEUI or APPEUI. This is what you had.
JoinRequest appears in device live data, but no JoinAccept follows — TTN matched the device correctly and sent a JoinAccept, but the device either couldn't decrypt it (AppKey mismatch) or missed both the RX1 and RX2 receive windows entirely. The latter usually means a clock or timing problem on a custom board rather than a dev board.
Knowing which mode you're in before starting to change things saves a lot of time. When the gateway traffic shows a JoinRequest, always expand the packet details and check the decoded DevEUI — it's your ground truth for what LMIC is actually putting on air.
Your LMIC_selectSubBand(1) position looks correct: after LMIC_reset() and
before do_send(). Calling it before LMIC_reset() would be undone by the
reset. For the AU915 channel table and sub-band 2 frequencies, the
LoRaWAN AU915 TTN setup guide
is the reference.
That fixed it. Switched to the LSB copy button for DEVEUI, reflashed, and it joined on the first attempt.
Went back to look at the gateway traffic details panel more carefully and I
could see 8C:2A:04:D0:7E:D5:B3:70 in the decoded DevEUI field — the
reversed bytes were there the whole time. Should have known to look for that
earlier.
Thanks for the gateway vs device live data explanation too — that's a useful mental model for debugging this stuff going forward.