Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LoRaWAN] Major rework #1204

Merged
merged 24 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a9699d4
[LoRaWAN] Major rework
StevenCellist Sep 2, 2024
7299e45
[LoRaWAN] Some CI fixes, add retransmission timeout
StevenCellist Sep 2, 2024
c9b95d1
[LoRaWAN] CI fixes
StevenCellist Sep 2, 2024
1ca988d
[LoRaWAN] Add missing initializers
StevenCellist Sep 3, 2024
f2e26dd
[LoRaWAN] Return Rx window number, fix casing
StevenCellist Sep 4, 2024
ecd2996
[LoRaWAN] Un-static functions to fix overriding
StevenCellist Sep 4, 2024
8119a60
[LoRaWAN] Integrate feedback, fix session save/restore
StevenCellist Sep 7, 2024
c0ba1e9
[LoRaWAN] Add const
StevenCellist Sep 7, 2024
efc0671
[LoRaWAN] Do not accept invalid Rx2 datarate
StevenCellist Sep 7, 2024
9e42efc
[LoRaWAN] Integrate feedback
StevenCellist Sep 7, 2024
147e0c1
[LoRaWAN] Fix retransmission, ADR backoff, setDatarate; reject out-of…
StevenCellist Sep 9, 2024
2697c8b
Update keywords.txt
StevenCellist Sep 9, 2024
0e77f5d
[LoRaWAN] Fix initial datarate, misc cleanup
StevenCellist Sep 9, 2024
56dea8a
[LoRaWAN] Update examples
StevenCellist Sep 9, 2024
6b1baa5
[LoRaWAN] Update README
StevenCellist Sep 9, 2024
32322a8
[LoRaWAN] Reject oversized downlinks
StevenCellist Sep 9, 2024
8ec39c9
[LoRaWAN] Remove VLAs
StevenCellist Sep 9, 2024
6b20345
[LoRaWAN] CI fixes
StevenCellist Sep 9, 2024
740b570
[LoRaWAN] More CI
StevenCellist Sep 9, 2024
925ec00
[LoRaWAN] Fix getMaxPayloadLen
StevenCellist Sep 10, 2024
2dae730
[LoRaWAN] Rename some status codes
StevenCellist Sep 10, 2024
b92e387
Merge branch 'master' into lorawan-rework
jgromes Sep 10, 2024
f420516
[CI] Skip LoRaWAN on XMega48
jgromes Sep 10, 2024
ec99974
[CI] Skip FW update for LR11x0
jgromes Sep 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions examples/LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
After your device is registered, you can run this example.
The device will join the network and start uploading data.

LoRaWAN v1.1 requires the use of persistent storage.
LoRaWAN v1.0.4/v1.1 requires the use of persistent storage.
As this example does not use persistent storage, running this
examples REQUIRES you to check "Resets frame counters"
on your LoRaWAN dashboard. Refer to the notes or the
network's documentation on how to do this.
To comply with LoRaWAN v1.1's persistent storage, refer to
To comply with LoRaWAN's persistent storage, refer to
https://github.com/radiolib-org/radiolib-persistence

For default module settings, see the wiki page
Expand Down Expand Up @@ -66,8 +66,20 @@ void loop() {

// Perform an uplink
int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
debug(state < RADIOLIB_ERR_NONE, F("Error in sendReceive"), state, false);

// Check if a downlink was received
// (state 0 = no downlink, state 1/2 = downlink in window Rx1/Rx2)
if(state > 0) {
Serial.println(F("Received a downlink"));
} else {
Serial.println(F("No downlink received"));
}

Serial.print(F("Next uplink in "));
Serial.print(uplinkIntervalSeconds);
Serial.println(F(" seconds\n"));

// Wait until next uplink - observing legal & TTN FUP constraints
delay(uplinkIntervalSeconds * 1000UL);
delay(uplinkIntervalSeconds * 1000UL); // delay needs milli-seconds
}
4 changes: 2 additions & 2 deletions examples/LoRaWAN/LoRaWAN_ABP/configABP.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ String stateDecode(const int16_t result) {
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
case RADIOLIB_LORAWAN_NO_DOWNLINK:
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
case RADIOLIB_LORAWAN_NO_JOIN_ACCEPT:
return "RADIOLIB_LORAWAN_NO_JOIN_ACCEPT";
case RADIOLIB_LORAWAN_SESSION_RESTORED:
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
case RADIOLIB_LORAWAN_NEW_SESSION:
Expand Down
52 changes: 27 additions & 25 deletions examples/LoRaWAN/LoRaWAN_Reference/LoRaWAN_Reference.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
Also, most of the possible and available functions are
shown here for reference.

LoRaWAN v1.1 requires the use of EEPROM (persistent storage).
LoRaWAN v1.0.4/v1.1 requires the use of EEPROM (persistent storage).
Running this examples REQUIRES you to check "Resets DevNonces"
on your LoRaWAN dashboard. Refer to the notes or the
network's documentation on how to do this.
To comply with LoRaWAN v1.1's persistent storage, refer to
To comply with LoRaWAN's persistent storage, refer to
https://github.com/radiolib-org/radiolib-persistence

For default module settings, see the wiki page
Expand Down Expand Up @@ -59,11 +59,11 @@ void setup() {
Serial.print("[LoRaWAN] DevAddr: ");
Serial.println((unsigned long)node.getDevAddr(), HEX);

// Disable the ADR algorithm (on by default which is preferable)
node.setADR(false);
// Enable the ADR algorithm (on by default which is preferable)
node.setADR(true);

// Set a fixed datarate
node.setDatarate(4);
// Set a datarate to start off with
node.setDatarate(5);

// Manages uplink intervals to the TTN Fair Use Policy
node.setDutyCycle(true, 1250);
Expand Down Expand Up @@ -105,25 +105,28 @@ void loop() {
LoRaWANEvent_t uplinkDetails;
LoRaWANEvent_t downlinkDetails;

uint8_t Port = 10;
uint8_t fPort = 10;

// Retrieve the last uplink frame counter
uint32_t fcntUp = node.getFCntUp();
uint32_t fCntUp = node.getFCntUp();

// Send a confirmed uplink every 64th frame
// Send a confirmed uplink on the second uplink
// and also request the LinkCheck and DeviceTime MAC commands
if(fcntUp % 64 == 0) {
Serial.println(F("[LoRaWAN] Requesting LinkCheck and DeviceTime"));
Serial.println(F("Sending uplink"));
if(fCntUp == 1) {
Serial.println(F("and requesting LinkCheck and DeviceTime"));
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_LINK_CHECK);
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_DEVICE_TIME);
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize, true, &uplinkDetails, &downlinkDetails);
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), fPort, downlinkPayload, &downlinkSize, true, &uplinkDetails, &downlinkDetails);
} else {
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize);
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), fPort, downlinkPayload, &downlinkSize, false, &uplinkDetails, &downlinkDetails);
}
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
debug(state < RADIOLIB_ERR_NONE, F("Error in sendReceive"), state, false);

// Check if downlink was received
if(state != RADIOLIB_LORAWAN_NO_DOWNLINK) {
// Check if a downlink was received
// (state 0 = no downlink, state 1/2 = downlink in window Rx1/Rx2)
if(state > 0) {
Serial.println(F("Received a downlink"));
// Did we get a downlink with data for us
if(downlinkSize > 0) {
Serial.println(F("Downlink data: "));
Expand All @@ -142,11 +145,6 @@ void loop() {
Serial.print(radio.getSNR());
Serial.println(F(" dB"));

// print frequency error
Serial.print(F("[LoRaWAN] Frequency error:\t"));
Serial.print(radio.getFrequencyError());
Serial.println(F(" Hz"));

// print extra information about the event
Serial.println(F("[LoRaWAN] Event information:"));
Serial.print(F("[LoRaWAN] Confirmed:\t"));
Expand All @@ -158,13 +156,15 @@ void loop() {
Serial.print(F("[LoRaWAN] Frequency:\t"));
Serial.print(downlinkDetails.freq, 3);
Serial.println(F(" MHz"));
Serial.print(F("[LoRaWAN] Output power:\t"));
Serial.print(downlinkDetails.power);
Serial.println(F(" dBm"));
Serial.print(F("[LoRaWAN] Frame count:\t"));
Serial.println(downlinkDetails.fCnt);
Serial.print(F("[LoRaWAN] Port:\t\t"));
Serial.println(downlinkDetails.fPort);
Serial.print(F("[LoRaWAN] Time-on-air: \t"));
Serial.print(node.getLastToA());
Serial.println(F(" ms"));
Serial.print(F("[LoRaWAN] Rx window: \t"));
Serial.println(state);

uint8_t margin = 0;
uint8_t gwCnt = 0;
Expand All @@ -184,6 +184,8 @@ void loop() {
Serial.println(fracSecond);
}

} else {
Serial.println(F("[LoRaWAN] No downlink received"));
}

// wait before sending another packet
Expand All @@ -193,7 +195,7 @@ void loop() {

Serial.print(F("[LoRaWAN] Next uplink in "));
Serial.print(delayMs/1000);
Serial.println(F("s"));
Serial.println(F(" seconds\n"));

delay(delayMs);
}
4 changes: 2 additions & 2 deletions examples/LoRaWAN/LoRaWAN_Reference/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ String stateDecode(const int16_t result) {
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
case RADIOLIB_LORAWAN_NO_DOWNLINK:
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
case RADIOLIB_LORAWAN_NO_JOIN_ACCEPT:
return "RADIOLIB_LORAWAN_NO_JOIN_ACCEPT";
case RADIOLIB_LORAWAN_SESSION_RESTORED:
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
case RADIOLIB_LORAWAN_NEW_SESSION:
Expand Down
19 changes: 15 additions & 4 deletions examples/LoRaWAN/LoRaWAN_Starter/LoRaWAN_Starter.ino
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/*
RadioLib LoRaWAN Starter Example

! Please refer to the included notes to get started !

This example joins a LoRaWAN network and will send
uplink packets. Before you start, you will have to
register your device at https://www.thethingsnetwork.org/
Expand Down Expand Up @@ -35,7 +37,8 @@ void setup() {
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);

// Setup the OTAA session information
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
debug(state != RADIOLIB_ERR_NONE, F("Initialise node failed"), state, true);

Serial.println(F("Join ('login') the LoRaWAN Network"));
state = node.activateOTAA();
Expand All @@ -60,11 +63,19 @@ void loop() {

// Perform an uplink
int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
debug(state < RADIOLIB_ERR_NONE, F("Error in sendReceive"), state, false);

// Check if a downlink was received
// (state 0 = no downlink, state 1/2 = downlink in window Rx1/Rx2)
if(state > 0) {
Serial.println(F("Received a downlink"));
} else {
Serial.println(F("No downlink received"));
}

Serial.print(F("Uplink complete, next in "));
Serial.print(F("Next uplink in "));
Serial.print(uplinkIntervalSeconds);
Serial.println(F(" seconds"));
Serial.println(F(" seconds\n"));

// Wait until next uplink - observing legal & TTN FUP constraints
delay(uplinkIntervalSeconds * 1000UL); // delay needs milli-seconds
Expand Down
4 changes: 2 additions & 2 deletions examples/LoRaWAN/LoRaWAN_Starter/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ String stateDecode(const int16_t result) {
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
case RADIOLIB_LORAWAN_NO_DOWNLINK:
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
case RADIOLIB_LORAWAN_NO_JOIN_ACCEPT:
return "RADIOLIB_LORAWAN_NO_JOIN_ACCEPT";
case RADIOLIB_LORAWAN_SESSION_RESTORED:
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
case RADIOLIB_LORAWAN_NEW_SESSION:
Expand Down
25 changes: 21 additions & 4 deletions examples/LoRaWAN/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
# LoRaWAN examples
RadioLib LoRaWAN v1.1 examples.
RadioLib LoRaWAN examples.

* [LoRaWAN_Starter](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Starter): this is the recommended entry point for new users. Please read the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) that come with this example to learn more about LoRaWAN and how to use it in RadioLib!
* [LoRaWAN_Reference](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Reference): this sketch showcases most of the available API for LoRaWAN in RadioLib. Be frightened by the possibilities! It is recommended you have read all the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) for the Starter sketch first, as well as the [Learn section on The Things Network](https://www.thethingsnetwork.org/docs/lorawan/)!
* [LoRaWAN_ABP](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_ABP): if you wish to use ABP instead of OTAA (but why?), this example shows how you can do this using RadioLib.

---
## LoRaWAN versions & regional parameters
RadioLib implements both LoRaWAN v1.1 and v1.0.4. Confusingly, v1.0.4 is newer than v1.1, but v1.1 includes more security checks and as such **LoRaWAN v1.1 is preferred**.
The catch is in the Regional Parameters: as v1.0.4 is newer, it is more up to date regarding local laws & regulations. Therefore, RadioLib implements 1.0.4 as baseline and 1.1 as fallback, but **Regional Parameters v1.0.4 is preferred**.
_Note: the CN500 band is implemented as specified in RP v1.1, as the RP v1.0.4 version is much too complex._

To activate a LoRaWAN v1.1 session, supply all the required keys:
```cpp
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey);
```

To activate a LoRaWAN v1.0.4 session, set the keys that are not available to `NULL`:
```cpp
node.beginOTAA(joinEUI, devEUI, NULL, appKey);
node.beginABP(devAddr, NULL, NULL, nwkSEncKey, appSKey);
```

The device doesn't need to know the Regional Parameters version - that is of importance on the console.

## LoRaWAN persistence
> [!WARNING]
> These examples do not fully comply with LoRaWAN v1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
> These examples do not actually comply with LoRaWAN v1.0.4/v1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:

## RadioLib persistence
In [this repository](https://github.com/radiolib-org/radiolib-persistence), examples are provided that do comply with the required persistence of certain parameters for LoRaWAN v1.1. Examples are (or will become) available for some of the most popular platforms. **These examples assume you have successfully used the Starter sketch and understood (most of) the accompanying notes!**
Currently, examples are available for the following platforms:

Expand Down
34 changes: 17 additions & 17 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -320,38 +320,38 @@ checkDataRate KEYWORD2
setModem KEYWORD2

# LoRaWAN
clearSession KEYWORD2
getBufferNonces KEYWORD2
setBufferNonces KEYWORD2
clearSession KEYWORD2
getBufferSession KEYWORD2
setBufferSession KEYWORD2
beginOTAA KEYWORD2
activateOTAA KEYWORD2
beginABP KEYWORD2
activateOTAA KEYWORD2
activateABP KEYWORD2
isActivated KEYWORD2
setRx2Dr KEYWORD2
sendMacCommandReq KEYWORD2
uplink KEYWORD2
downlink KEYWORD2
sendReceive KEYWORD2
sendMacCommandReq KEYWORD2
getMacLinkCheckAns KEYWORD2
getMacDeviceTimeAns KEYWORD2
setDatarate KEYWORD2
setTxPower KEYWORD2
setRx2Dr KEYWORD2
setADR KEYWORD2
setDutyCycle KEYWORD2
setDwellTime KEYWORD2
setCSMA KEYWORD2
setDeviceStatus KEYWORD2
scheduleTransmission KEYWORD2
getFCntUp KEYWORD2
getNFCntDown KEYWORD2
getAFCntDown KEYWORD2
resetFCntDown KEYWORD2
setDatarate KEYWORD2
setADR KEYWORD2
setDutyCycle KEYWORD2
dutyCycleInterval KEYWORD2
timeUntilUplink KEYWORD2
setDwellTime KEYWORD2
maxPayloadDwellTime KEYWORD2
setTxPower KEYWORD2
getMacLinkCheckAns KEYWORD2
getMacDeviceTimeAns KEYWORD2
getDevAddr KEYWORD2
getLastToA KEYWORD2
dutyCycleInterval KEYWORD2
timeUntilUplink KEYWORD2
maxUplinkLen KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down Expand Up @@ -465,7 +465,7 @@ RADIOLIB_ERR_N_FCNT_DOWN_INVALID LITERAL1
RADIOLIB_ERR_A_FCNT_DOWN_INVALID LITERAL1
RADIOLIB_ERR_DWELL_TIME_EXCEEDED LITERAL1
RADIOLIB_ERR_CHECKSUM_MISMATCH LITERAL1
RADIOLIB_LORAWAN_NO_DOWNLINK LITERAL1
RADIOLIB_LORAWAN_NO_JOIN_ACCEPT LITERAL1
RADIOLIB_LORAWAN_SESSION_RESTORED LITERAL1
RADIOLIB_LORAWAN_NEW_SESSION LITERAL1
RADIOLIB_LORAWAN_NONCES_DISCARDED LITERAL1
Expand Down
4 changes: 2 additions & 2 deletions src/TypeDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,9 @@
#define RADIOLIB_ERR_CHECKSUM_MISMATCH (-1115)

/*!
\brief No downlink was received - most likely none was sent from the server.
\brief No JoinAccept was received - check your keys, or otherwise likely a range issue!
*/
#define RADIOLIB_LORAWAN_NO_DOWNLINK (-1116)
#define RADIOLIB_LORAWAN_NO_JOIN_ACCEPT (-1116)
StevenCellist marked this conversation as resolved.
Show resolved Hide resolved

/*!
\brief The LoRaWAN session was successfully re-activated.
Expand Down
Loading
Loading