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] Improve persistence behaviour, add dwell time error, clear up debug output #980

Merged
merged 18 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion examples/LoRaWAN/LoRaWAN_End_Device/LoRaWAN_End_Device.ino
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void loop() {
Serial.println(state);
}

// on EEPROM enabled boards, you can save the current session
// on EEPROM enabled boards, you should save the current session
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep
node.saveSession();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void loop() {
Serial.println(state);
}

// on EEPROM enabled boards, you can save the current session
// on EEPROM enabled boards, you should save the current session
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep
node.saveSession();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ void loop() {

uint8_t margin = 0;
uint8_t gwCnt = 0;
if(node.getMacLinkCheckAns(&margin, &gwCnt)) {
if(node.getMacLinkCheckAns(&margin, &gwCnt) == RADIOLIB_ERR_NONE) {
Serial.print(F("[LoRaWAN] LinkCheck margin:\t"));
Serial.println(margin);
Serial.print(F("[LoRaWAN] LinkCheck count:\t"));
Expand All @@ -268,10 +268,10 @@ void loop() {

uint32_t networkTime = 0;
uint8_t fracSecond = 0;
if(node.getMacDeviceTimeAns(&networkTime, &fracSecond, true)) {
if(node.getMacDeviceTimeAns(&networkTime, &fracSecond, true) == RADIOLIB_ERR_NONE) {
Serial.print(F("[LoRaWAN] DeviceTime Unix:\t"));
Serial.println(networkTime);
Serial.print(F("[LoRaWAN] LinkCheck second:\t1/"));
Serial.print(F("[LoRaWAN] DeviceTime second:\t1/"));
Serial.println(fracSecond);
}

Expand All @@ -283,11 +283,9 @@ void loop() {
Serial.println(state);
}

// on EEPROM enabled boards, you can save the current session
// on EEPROM enabled boards, you should save the current session
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep
/*
node.saveSession();
*/
node.saveSession();

// wait before sending another packet
uint32_t minimumDelay = 60000; // try to send once every minute
Expand Down
4 changes: 3 additions & 1 deletion src/ArduinoHal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ void ArduinoHal::writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len
EEPROM.init();
#endif
for(size_t i = 0; i < len; i++) {
EEPROM.write(addr + i, buff[i]);
if(EEPROM.read(addr + i) != buff[i]) { // only write if value is new
EEPROM.write(addr + i, buff[i]);
}
}
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
EEPROM.commit();
Expand Down
2 changes: 1 addition & 1 deletion src/Hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ enum RADIOLIB_EEPROM_PARAMS {
};

static const uint32_t RadioLibPersistentParamTable[] = {
0x00, // RADIOLIB_EEPROM_LORAWAN_TABLE_VERSION_ID
0x00, // RADIOLIB_EEPROM_TABLE_VERSION_ID
0x02, // RADIOLIB_EEPROM_LORAWAN_CLASS_ID
0x03, // RADIOLIB_EEPROM_LORAWAN_MODE_ID
0x05, // RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID
Expand Down
5 changes: 5 additions & 0 deletions src/TypeDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,11 @@
*/
#define RADIOLIB_ERR_A_FCNT_DOWN_INVALID (-1114)

/*!
\brief Uplink payload length at this datarate exceeds the active dwell time limitations.
*/
#define RADIOLIB_ERR_DWELL_TIME_EXCEEDED (-1115)

/*!
\}
*/
Expand Down
317 changes: 200 additions & 117 deletions src/protocols/LoRaWAN/LoRaWAN.cpp

Large diffs are not rendered by default.

69 changes: 54 additions & 15 deletions src/protocols/LoRaWAN/LoRaWAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@
#define RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP (0x0F)
#define RADIOLIB_LORAWAN_MAC_PROPRIETARY (0x80)

// maximum allowed dwell time on bands that implement dwell time limitations
#define RADIOLIB_LORAWAN_DWELL_TIME (400)

// unused LoRaWAN version
#define RADIOLIB_LORAWAN_VERSION_NONE (0xFF)

// unused frame counter value
#define RADIOLIB_LORAWAN_FCNT_NONE (0xFFFFFFFF)

Expand All @@ -188,10 +194,7 @@
// the maximum number of simultaneously available channels
#define RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS (16)

// maximum allowed dwell time on bands that implement dwell time limitations
#define RADIOLIB_LORAWAN_DWELL_TIME (400)

// Maximum MAC command sizes
// maximum MAC command sizes
#define RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_DOWN (5)
#define RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_UP (2)
#define RADIOLIB_LORAWAN_MAX_NUM_ADR_COMMANDS (8)
Expand Down Expand Up @@ -530,6 +533,14 @@ class LoRaWANNode {
*/
int16_t downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event = NULL);

/*!
\brief Wait for downlink, simplified to allow for simpler sendReceive
\param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes
*/
int16_t downlink(LoRaWANEvent_t* event = NULL);

#if defined(RADIOLIB_BUILD_ARDUINO)
/*!
\brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window.
Expand Down Expand Up @@ -577,25 +588,49 @@ class LoRaWANNode {
*/
int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);

/*!
\brief Send a message to the server and wait for a downlink but don't bother the user with downlink contents
\param dataUp Data to send.
\param lenUp Length of the data.
\param port Port number to send the message to.
\param isConfirmed Whether to send a confirmed uplink or not.
\param eventUp Pointer to a structure to store extra information about the uplink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\param eventDown Pointer to a structure to store extra information about the downlink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes
*/
int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port = 1, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);

/*!
\brief Set device status.
\param battLevel Battery level to set. 0 for external power source, 1 for lowest battery,
254 for highest battery, 255 for unable to measure.
*/
void setDeviceStatus(uint8_t battLevel);

/*! \brief Returns the last uplink's frame counter */
/*!
\brief Returns the last uplink's frame counter;
also 0 if no uplink occured yet.
*/
uint32_t getFcntUp();

/*! \brief Returns the last network downlink's frame counter */
/*!
\brief Returns the last network downlink's frame counter;
also 0 if no network downlink occured yet.
*/
uint32_t getNFcntDown();

/*! \brief Returns the last application downlink's frame counter */
/*!
\brief Returns the last application downlink's frame counter;
also 0 if no application downlink occured yet.
*/
uint32_t getAFcntDown();

/*! \brief Reset the downlink frame counters (application and network)
/*!
\brief Reset the downlink frame counters (application and network)
This is unsafe and can possibly allow replay attacks using downlinks.
It mainly exists as part of the TS008 Specification Verification protocol.
It mainly exists as part of the TS009 Specification Verification protocol.
*/
void resetFcntDown();

Expand Down Expand Up @@ -798,22 +833,26 @@ class LoRaWANNode {
bool isMACPayload = false;

// save the selected sub-band in case this must be restored in ADR control
int8_t subBand = -1;
uint8_t subBand = 0;

#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
/*!
\brief Save the current uplink frame counter.
Note that the usable frame counter width is 'only' 30 bits for highly efficient wear-levelling.
\returns \ref status_codes
*/
int16_t saveFcntUp();
void saveFcntUp();

/*!
\brief Restore frame counter for uplinks from persistent storage.
Note that the usable frame counter width is 'only' 30 bits for highly efficient wear-levelling.
\returns \ref status_codes
*/
int16_t restoreFcntUp();
void restoreFcntUp();

// set all keys to zero
void clearSession();

// test if saved keys are non-zero
bool isValidSession();
#endif

// wait for, open and listen during Rx1 and Rx2 windows; only performs listening
Expand Down Expand Up @@ -859,7 +898,7 @@ class LoRaWANNode {

// delete a specific MAC command from queue, indicated by the command ID
// if a payload pointer is supplied, this returns the payload of the MAC command
int16_t deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* queue, uint8_t payload[5] = NULL);
int16_t deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* queue, uint8_t* payload = NULL);

// execute mac command, return the number of processed bytes for sequential processing
bool execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom = true);
Expand Down
Loading