From 4cd658f5b5d51b26cd0225f0a09edb1068c65b0e Mon Sep 17 00:00:00 2001 From: StevenCellist Date: Thu, 28 Aug 2025 09:06:03 +0200 Subject: [PATCH] [LoRaWAN] Fixes for network package --- src/protocols/LoRaWAN/LoRaWAN.cpp | 25 ++++++++++++------------- src/protocols/LoRaWAN/LoRaWAN.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index 440d7f48..0a0bffeb 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -164,7 +164,7 @@ int16_t LoRaWANNode::sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fP return(state); } - // handle Rx1 and Rx2 windows - returns window > 0 if a downlink is received + // handle Rx windows - returns window > 0 if a downlink is received state = this->receiveDownlink(); // RETRANSMIT_TIMEOUT is 2s +/- 1s (RP v1.0.4) @@ -930,7 +930,7 @@ int16_t LoRaWANNode::activateOTAA(LoRaWANJoinEvent_t *joinEvent) { this->rxDelays[1] = RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_1_MS; this->rxDelays[2] = RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_2_MS; - // handle Rx1 and Rx2 windows - returns window > 0 if a downlink is received + // handle Rx windows - returns window > 0 if a downlink is received state = this->receiveDownlink(); if(state < RADIOLIB_ERR_NONE) { return(state); @@ -1786,9 +1786,11 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, uint8_t window, L // LoRaWAN v1.0.4 only: A Class B/C downlink SHALL NOT transport any MAC command. // (...) it SHALL silently discard the entire frame. // However, we also enforce this for LoRaWAN v1.1 (TTS does not allow this anyway). - if(fPort == RADIOLIB_LORAWAN_FPORT_MAC_COMMAND && window < RADIOLIB_LORAWAN_RX_BC) { - // payload consists of all MAC commands (or is empty) - ok = true; + if(fPort == RADIOLIB_LORAWAN_FPORT_MAC_COMMAND) { + if(this->lwClass == RADIOLIB_LORAWAN_CLASS_A || window < RADIOLIB_LORAWAN_RX_BC) { + // payload consists of all MAC commands (or is empty) + ok = true; + } } if(fPort >= RADIOLIB_LORAWAN_FPORT_PAYLOAD_MIN && fPort <= RADIOLIB_LORAWAN_FPORT_PAYLOAD_MAX) { ok = true; @@ -1833,7 +1835,7 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, uint8_t window, L // LoRaWAN v1.0.4 only: A Class B/C downlink SHALL NOT transport any MAC command. // (...) it SHALL silently discard the entire frame. // However, we also enforce this for LoRaWAN v1.1 (TTS does not allow this anyway). - if(fOptsLen > 0 && window == RADIOLIB_LORAWAN_RX_BC) { + if(fOptsLen > 0 && this->lwClass != RADIOLIB_LORAWAN_CLASS_A && window == RADIOLIB_LORAWAN_RX_BC) { #if !RADIOLIB_STATIC_ONLY delete[] downlinkMsg; #endif @@ -2126,10 +2128,11 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, uint8_t window, L processAES(&downlinkMsg[RADIOLIB_LORAWAN_FRAME_PAYLOAD_POS(fOptsLen)], payLen, encKey, data, addr, devFCnt32, RADIOLIB_LORAWAN_DOWNLINK, 0x00, true); *len = payLen; - // however, if this frame belongs to a package, redirect instead and 'hide' contents from the user + // however, if this frame belongs to an application package, + // redirect instead and 'hide' contents from the user // just to be sure that it doesn't get re-interpreted... for(int id = 0; id < RADIOLIB_LORAWAN_NUM_SUPPORTED_PACKAGES; id++) { - if(this->packages[id].enabled && fPort == this->packages[id].packFPort) { + if(this->packages[id].enabled && this->packages[id].isAppPack && fPort == this->packages[id].packFPort) { this->packages[id].callback(data, *len); memset(data, 0, *len); *len = 0; @@ -3629,18 +3632,14 @@ int16_t LoRaWANNode::addAppPackage(uint8_t packageId, PackageCb_t callback, uint return(RADIOLIB_ERR_NONE); } -int16_t LoRaWANNode::addNwkPackage(uint8_t packageId, PackageCb_t callback) { +int16_t LoRaWANNode::addNwkPackage(uint8_t packageId) { if(packageId >= RADIOLIB_LORAWAN_NUM_SUPPORTED_PACKAGES) { return(RADIOLIB_ERR_INVALID_MODE); } if(PackageTable[packageId].isAppPack == true) { return(RADIOLIB_ERR_INVALID_MODE); } - if(callback == NULL) { - return(RADIOLIB_ERR_NULL_POINTER); - } this->packages[packageId] = PackageTable[packageId]; - this->packages[packageId].callback = callback; this->packages[packageId].enabled = true; return(RADIOLIB_ERR_NONE); } diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index f13ed747..69ab67ca 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -1081,9 +1081,12 @@ class LoRaWANNode { LoRaWANChannel_t channels[4] = { RADIOLIB_LORAWAN_CHANNEL_NONE, RADIOLIB_LORAWAN_CHANNEL_NONE, RADIOLIB_LORAWAN_CHANNEL_NONE, RADIOLIB_LORAWAN_CHANNEL_NONE }; - // delays between the uplink and Rx1/2 windows - // the first field is meaningless, but is used for offsetting for Rx windows 1 and 2 - RadioLibTime_t rxDelays[3] = { 0, RADIOLIB_LORAWAN_RECEIVE_DELAY_1_MS, RADIOLIB_LORAWAN_RECEIVE_DELAY_2_MS }; + // delays between the uplink and Rx windows + // the first field is meaningless, but is used for offsetting the Rx windows + RadioLibTime_t rxDelays[4] = { 0, + RADIOLIB_LORAWAN_RECEIVE_DELAY_1_MS, + RADIOLIB_LORAWAN_RECEIVE_DELAY_2_MS, + 0 }; // offset between Tx and Rx1 (such that Rx1 has equal or lower DR) uint8_t rx1DrOffset = 0; @@ -1149,14 +1152,14 @@ class LoRaWANNode { int16_t receiveClassC(RadioLibTime_t timeout = 0); // open a series of Class A (and C) downlinks - int16_t receiveDownlink(); + virtual int16_t receiveDownlink(); // extract downlink payload and process MAC commands int16_t parseDownlink(uint8_t* data, size_t* len, uint8_t window, LoRaWANEvent_t* event = NULL); // add a LoRaWAN package that runs through the network layer // (not available to users, they are only allowed to add application packages) - int16_t addNwkPackage(uint8_t packageId, PackageCb_t callback); + int16_t addNwkPackage(uint8_t packageId); // execute mac command, return the number of processed bytes for sequential processing bool execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn);