Device Activation
Before a LoRaWAN device can exchange data with the server, it has to be activated. ONS supports two methods: OTAA, where the device joins the network by itself using the LoRaWAN 1.0.x procedure with one root key, AppKey, and ABP, where the address and session keys are set in advance both in the device and on the server. This page covers what the server does with a join request (Join Request), how to check the result and why a device may fail to join. Device fields in the web interface are described in the Nodes section, registration through the WebSocket API in the create_device_req command.
What to register on the server
| What | OTAA | ABP |
|---|---|---|
| DevEUI | Required. Unique among active devices. The server finds the device by it at join, in either byte order | Required. Unique among active devices |
| AppKey | Required. Exactly as in the device: the server derives the session keys and encrypts the Join Accept with it. If it does not match, the device cannot accept the Join Accept and will not join | The server does not use it; the create_device_req command requires it for ABP too |
| DevAddr | Not needed: the server issues a new address at every join | The address from the device firmware. Unique among active devices |
| NwkSKey, AppSKey | Not needed: the server derives them at join | The keys from the device firmware |
Frequency plan ("Region" field, region) | As in the device firmware: the server picks the Join Accept frequencies from it | As in the device firmware |
| Class | As in the device firmware, see Device classes | As in the device firmware |
| "On/Off" | On | On |
The server does not compare the JoinEUI (AppEUI) from the Join Request with anything: it does not have to match the AppEUI of the ONS application.
The server does not find a switched-off or deleted device at join, and its DevEUI gets banned for 1 hour, see Join anti-storm.
How an OTAA join goes
- Anti-storm check. The server does not process a Join Request from a banned device, see Join anti-storm.
- Reception. One or more gateways hear the Join Request. The first copy opens a record for that DevEUI. Copies that arrive within 2 seconds of it are merged with it: the server adds the gateway to the list and switches the Join Accept to that gateway if the copy was received with a higher RSSI than the first one. After 2 seconds the server closes the record, and a Join Request that arrives later is handled as a new attempt.
- Device lookup. The server looks for a switched-on, active device by DevEUI. If it finds none, there is no Join Accept and the DevEUI gets the not-found ban.
- AppKey. The server derives the session keys and encrypts the Join Accept with the AppKey from the device settings. If the AppKey in the settings does not match the key in the device, the device cannot accept the Join Accept.
- New address and keys. The server issues a new DevAddr to the device and derives new NwkSKey and AppSKey. The address and keys are written to the device settings and to the join history.
- Sending the Join Accept. 2 seconds after the first copy, the server sends the Join Accept through one gateway for the RX1 window, 5 seconds after the Join Request, or the RX2 window, 6 seconds after it. Details are in the next section.
- Frame counters. The uplink and downlink FCnt are reset to 0.
- Radio parameters. The server sends the parameters from the "Radio parameters" panel to the device with MAC commands after the join, see Radio parameters and the MAC command log.
The server builds the new DevAddr from the NwkID, the lower 7 bits of the NetID, and 25 random bits. The NetID is set by the --netid start parameter of the LWServer and LWAuthorizator components: the first puts the NetID into the Join Accept, the second builds the DevAddr, so in an on-premises installation set it the same in both. The default is 000021; with it, addresses fall in the range 0x42000000–0x43FFFFFF.
Join Accept: contents and timing
The Join Accept is encrypted with the AppKey and contains:
| Field | Value |
|---|---|
| AppNonce | 3 random bytes |
| NetID | The value of the --netid parameter of the LWServer component, 000021 by default |
| DevAddr | The new device address |
| DLSettings | RX1 DR offset is 0 in every frequency plan; the RX2 data rate comes from the device's frequency plan |
| RXDelay | 1 second in every frequency plan |
| CFList | Up to 5 optional uplink channels from the device's frequency plan; in the US915 and AU915 plans — the mask of the plan enabled channels |
The parameters from the "Radio parameters" panel (RX2 data rate and frequency, RX1 DR offset and delay, extra channels) are not sent in the Join Accept. After the join the session starts from the frequency plan parameters and the CFList channels, and the server then brings the device to the configured values with MAC commands.
How the server picks the window, frequency and data rate:
- Time. The frame is not sent immediately but at a set moment by the gateway counter: the moment this gateway received the Join Request plus 5 seconds for RX1 or plus 6 seconds for RX2. These delays are the same in every frequency plan.
- Window is set by the device's "Rx window" field (
rx_window), RX1 by default. The server treats the legacy value 0 as RX2. - RX1. The frequency is the downlink channel that matches the Join Request frequency and data rate in the device's frequency plan; if nothing matches, channel 0. The data rate comes from the plan's RX1 table with offset 0: in every plan except US915 and AU915 it is the Join Request's data rate; in the US915 and AU915 plans it is the matching downlink data rate (DR8–DR13).
- RX2. The frequency and data rate of the device's frequency plan, for example: KZ865-868 (code 6) — 866.7 MHz, DR0; RU (code 2) — 869.1 MHz, DR0; EU863-870 (code 7) — 869.525 MHz, DR0.
- Late for RX1. If the server estimates that the frame will miss RX1 (the time since the Join Request was received plus half the RTT to the gateway plus 0.15 seconds is more than 5 seconds), it moves the transmission to the RX2 moment and logs
JOIN_ACCEPT_RX_FALLBACK. The server does not change the frame's frequency and data rate in this case: they stay those of RX1. - Gateway. The Join Accept goes only through the chosen gateway. If the server does not know the gateway's address (the gateway has not sent PULL_DATA), the frame is not sent.
- No repeat. The Join Accept is sent once: the server does not repeat it in the other window.
Channels, the RX1 and RX2 windows and data rates of all 38 plans are in Frequency plans; a short table with the RX2 window is in Region codes.
Session keys and frame counters
The server derives the keys with the LoRaWAN 1.0.x scheme:
| Value | How it is computed |
|---|---|
| Join Request MIC | AES-CMAC(AppKey, MHDR | AppEUI | DevEUI | DevNonce) |
| NwkSKey | AES-ECB(AppKey, 0x01 | AppNonce | NetID | DevNonce | zero padding) |
| AppSKey | AES-ECB(AppKey, 0x02 | AppNonce | NetID | DevNonce | zero padding) |
The server writes the new keys and DevAddr to the device settings and to the join history. For an OTAA device the "Network Session Key" and "Application Session Key" fields of the card are read-only.
How the server checks an uplink:
- The frame MIC is checked with the NwkSKey. A frame with a bad MIC is dropped and does not appear in the device data.
- FRMPayload is decrypted with the AppSKey when FPort is above 0 and with the NwkSKey when FPort = 0.
- The server merges copies of a frame with the same FCnt (reception by several gateways and device retransmissions) into one frame.
The uplink and downlink FCnt are reset to 0 at every join, both in server memory and in the "Seq up" and "Seq down" fields.
FCnt limit. The server checks the MIC only for FCnt values whose upper 16 bits are 0 or 1. An uplink with an FCnt above 131071 (0x1FFFF) fails the MIC check and is dropped. An OTAA device's counter is reset at every join. An ABP device that does not reset its counter stops being accepted once its FCnt exceeds 131071.
Server restart. The session survives a server restart and the loss of its cache. If a DevAddr is in neither memory nor Redis, the server looks up a switched-on, active device with this DevAddr in the database, in either byte order, and gets back the keys, the frame counters and the MAC session state. An OTAA device does not need to rejoin after a server restart. Frames with a DevAddr that is not in the database are dropped for 300 seconds without querying the database; then the server asks again.
ABP specifics
- There is no join. The server serves the device from its first uplink using the DevAddr, NwkSKey and AppSKey from the database.
- On the first uplink, while "Seq up" is 0, the session starts from the frequency plan parameters without optional channels. The server sends the channels later with the NewChannelReq MAC command.
- Keys saved in the web interface are used by the server at once. When a device picks up changes made through the WebSocket API is described on the
update_device_reqpage. - The
join_request_timefield of therealtime_datamessage is alwaysnullfor an ABP device. - The FCnt limit applies: once FCnt exceeds 131071, the server stops accepting uplinks until the counter in the device is reset.
Join anti-storm
The server bans from joining devices that send Join Requests too often or that are not in the database.
| Ban | When | Default duration |
|---|---|---|
| Rate | A Join Request would be the 20th within 600 seconds | 1 hour |
| Not found | A Join Request from a DevEUI the database did not return: the device is not registered, switched off or deleted | 1 hour |
- The server does not process a banned device's Join Request: there is no JR row in the device data and no record in the join history.
- Creating the device clears the not-found ban — in the web interface, by import, through the REST API or with the
create_device_reqcommand. Editing the device, including switching it back on, does not clear the ban. - A device marked "Test device" is exempt from both the rate ban and the not-found ban. Only staff users and the superuser can set the mark, see LoRaWAN node parameters. The exemption lasts one day by default and is renewed at every successful join and every save of the device. A switched-off or deleted device does not get the exemption.
In an on-premises ONS installation the numbers are changed with server start parameters: --jr_limit is the limit, --jr_ban_timeout and --jr_notfound_ban_timeout are the ban durations in seconds, --jr_exempt_ttl is the test device exemption period in seconds. The 600-second window has no parameter.
How to check that a device joined
- The "Last join" column of the node list shows the time of the last join. The tooltip shows the status: MIC OK, MIC ERROR or LATE JOIN ACCEPT; a red cell means the status is not MIC OK. This column does not show whether the device accepted the Join Accept; the first uplink does (item 3). The time is updated as soon as the server finds the device by DevEUI, and on every join history record, whatever its status.
- The "Data" table on the Monitoring tab. A JR row (uplink, the data is the DevNonce) appears on the first copy of the Join Request, before the server prepares the Join Accept, so it is there even when no Join Accept is sent. The server writes a JR row only for a device that exists in the database. A JA row (downlink, the data is the AppNonce) appears after the Join Accept is sent.
- The first uplink after JA with the new DevAddr shows that the device received the Join Accept.
The status in the "Last join" column only says that the server accepted the Join Request. If the Join Accept is lost, the device has to send a new Join Request.
Why a device does not join
| What you see | Cause | What to do |
|---|---|---|
| No JR rows on the Monitoring tab | No gateway heard the Join Request, the device is banned, or it is not in the database: not registered or deleted | Check that a gateway connected to the server is near the device. Check the DevEUI. A ban expires after 1 hour; creating the device also clears the not-found ban |
| Status LATE JOIN ACCEPT | The server did not find the device in the database within 2 seconds, and the Join Accept was not sent | Wait for the device's next attempt. In an on-premises installation check the database load |
| JR present, no JA | The server does not know the chosen gateway's address: the gateway has not sent PULL_DATA. Or the device has the AS923-1 plan (code 10): in the current version the server does not send a Join Accept to such a device | Check the gateway's connection to the server. For an AS923-1 device select AS923-2 (code 11) or AS923-4 (code 13) in the "Region" field, see Frequency plans |
| JR present, no uplinks from the new DevAddr | The AppKey in the settings does not match the key in the device, the frequency plan ("Region") does not match the firmware, or the Join Accept was lost | Enter the AppKey from the device as is and wait for the next Join Request. Fix "Region". After a lost Join Accept the device has to repeat the Join Request |
| The device was switched off and back on and does not join | The switched-off device's Join Request got the not-found ban for 1 hour; switching it on does not clear the ban | Wait up to 1 hour or mark it as "Test device" |
| ABP: no uplinks in the data | Wrong DevAddr or NwkSKey, so the frame fails the MIC; FCnt above 131071; the device is switched off or deleted | Check the DevAddr and keys against the firmware and save the device in the web interface; reset the frame counter in the device; switch the device on |
| ABP: uplinks present, data not decrypted | Wrong AppSKey | Check the AppSKey against the firmware |
Server log
In an on-premises ONS installation the course of a join is visible in the log of the LWServer component. The LWAuthorizator component looks up the device in the database.
| Log entry | What it means |
|---|---|
JOIN_ACCEPT_SENT | The Join Accept was handed to the gateway. The entry shows the gateway, window, frequency and data rate |
JOIN_ACCEPT_TIMEOUT | 2 seconds after the first copy the Join Accept is not ready: LWAuthorizator did not answer |
JOIN_ACCEPT_NOT_FOUND | The device was not found in the database: not registered, switched off or deleted. The DevEUI gets the not-found ban |
JOIN_ACCEPT_LATE | The LWAuthorizator answer came after the 2 seconds allowed. The join history gets the LATE JOIN ACCEPT status |
JOIN_ACCEPT_NO_GATEWAY | The chosen gateway's address is unknown; the Join Accept was not sent |
JOIN_ACCEPT_RX_FALLBACK | The server could not make it to RX1 and moved the transmission to the RX2 moment |
DevEui: <EUI> banned, skip join | The Join Request was dropped because of a ban |
DevEui: <EUI> banned (rate|not_found) for Ns | The ban reason (rate or not found) and how many seconds it has left |
MIC ERROR for: <DevAddr> | An uplink with a bad MIC was dropped |
Good to know
- If the Monitoring tab shows JR and JA rows but no uplink arrives from the new DevAddr, first check the AppKey against the key in the device.
- If the Join Accept is lost, the device has to send a new Join Request.
- An uplink with an FCnt above 131071 fails the MIC check.
- The server does not handle the LoRaWAN 1.1 Rejoin-request.
- The Join Accept carries only the frequency plan parameters; the device gets the "Radio parameters" after the join with MAC commands.
- A device that was switched off and back on may wait up to 1 hour for the ban to expire.
See also
- Nodes — OTAA and ABP fields, "Test device", the "Last join" column.
- Create device — registering an OTAA or ABP device through the WebSocket API.
- Change device settings — when OTAA and ABP devices pick up new settings and keys.
- Frequency plans — channels, the RX1 and RX2 windows and data rates of all 38 plans.
- Device classes — when a device listens and receives downlinks.