From 594d8cbba11add408844950f6f726bc31c9138b8 Mon Sep 17 00:00:00 2001 From: StevenCellist Date: Mon, 27 Nov 2023 12:39:14 +0100 Subject: [PATCH 1/4] [LoRaWAN] Move TX power logic to function --- src/protocols/LoRaWAN/LoRaWAN.cpp | 50 +++++++++++++++++-------------- src/protocols/LoRaWAN/LoRaWAN.h | 11 +++++-- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index af930be9..a8f1fd2b 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -698,6 +698,8 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf this->isMACPayload = false; } + int16_t state = RADIOLIB_ERR_NONE; + // check if there are some MAC commands to piggyback (only when piggybacking onto a application-frame) uint8_t foptsLen = 0; size_t foptsBufSize = 0; @@ -722,18 +724,16 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf if((this->fcntUp - this->adrFcnt) >= adrLimit) { adrAckReq = true; } + // if we hit the Limit + Delay, try one of three, in order: + // set TxPower to max, set DR to min, enable all defined channels if ((this->fcntUp - this->adrFcnt) == (adrLimit + adrDelay)) { - // try one of three, in order: set TxPower to max, set DR to min, enable all defined channels // set the maximum power supported by both the module and the band - int8_t pwr = this->band->powerMax; - int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER; - while(state == RADIOLIB_ERR_INVALID_OUTPUT_POWER) { - // go from the highest power in band and lower it until we hit one supported by the module - state = this->phyLayer->setOutputPower(pwr--); - } + int8_t pwrPrev = this->txPwrCur; + state = this->setTxPower(this->band->powerMax); RADIOLIB_ASSERT(state); - if(pwr == this->txPwrCur) { + + if(this->txPwrCur == pwrPrev) { // failed to increase Tx power, so try to decrease the datarate if(this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK] > this->currentChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK].drMin) { @@ -750,8 +750,6 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf } } - } else { - this->txPwrCur = pwr; } // we tried something to improve the range, so increase the ADR frame counter by 'ADR delay' @@ -760,7 +758,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf // configure for uplink this->selectChannels(); - int16_t state = this->configureChannel(RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK); + state = this->configureChannel(RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK); RADIOLIB_ASSERT(state); // build the uplink message @@ -1366,15 +1364,8 @@ bool LoRaWANNode::verifyMIC(uint8_t* msg, size_t len, uint8_t* key) { int16_t LoRaWANNode::setPhyProperties() { // set the physical layer configuration - - // set the maximum power supported by both the module and the band - int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER; - while(state == RADIOLIB_ERR_INVALID_OUTPUT_POWER) { - // go from the highest power in band and lower it until we hit one supported by the module - state = this->phyLayer->setOutputPower(this->txPwrCur--); - } + int16_t state = this->setTxPower(this->txPwrCur); RADIOLIB_ASSERT(state); - this->txPwrCur++; uint8_t syncWord[3] = { 0 }; uint8_t syncWordLen = 0; @@ -1688,6 +1679,19 @@ void LoRaWANNode::setADR(bool enable) { this->adrEnabled = enable; } +int16_t LoRaWANNode::setTxPower(int8_t txPower) { + int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER; + while(state == RADIOLIB_ERR_INVALID_OUTPUT_POWER) { + // go from the highest power and lower it until we hit one supported by the module + state = this->phyLayer->setOutputPower(txPower--); + } + if(state == RADIOLIB_ERR_NONE) { + txPower++; + this->txPwrCur = txPower; + } + return(state); +} + int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) { uint8_t dataRateBand = this->band->dataRates[dr]; @@ -1838,13 +1842,15 @@ size_t LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd) { uint8_t pwrAck = 0; if(txPower == 0x0F) { pwrAck = 1; + } else { int8_t pwr = this->band->powerMax - 2*txPower; - if(this->phyLayer->setOutputPower(pwr) == RADIOLIB_ERR_NONE) { - RADIOLIB_DEBUG_PRINTLN("ADR set pwr = %d", pwr); + int16_t state = this->setTxPower(pwr); + // only acknowledge if the requested datarate was succesfully configured + if((state == RADIOLIB_ERR_NONE) && (this->txPwrCur == pwr)) { pwrAck = 1; } - this->txPwrCur = pwr; + } uint8_t chMaskAck = 1; diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index da1a4356..6e4523d0 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -532,11 +532,18 @@ class LoRaWANNode { int16_t setDatarate(uint8_t drUp); /*! - \brief Toggle ADR to on or off - \param enable Whether to disable ADR or not + \brief Toggle ADR to on or off. + \param enable Whether to disable ADR or not. */ void setADR(bool enable = true); + /*! + \brief Configure TX power of the radio module. + \param txPower Output power during TX mode to be set in dBm. + \returns \ref status_codes + */ + int16_t setTxPower(int8_t txPower); + /*! \brief Select a single subband (8 channels) for fixed bands such as US915. Only available before joining a network. From 3d6db1b79a387d6111b4b1e7827cea1d3a8cd3ab Mon Sep 17 00:00:00 2001 From: StevenCellist Date: Mon, 27 Nov 2023 15:41:41 +0100 Subject: [PATCH 2/4] Update keywords --- keywords.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/keywords.txt b/keywords.txt index 1a19ea40..24369e17 100644 --- a/keywords.txt +++ b/keywords.txt @@ -300,6 +300,7 @@ sendReceive KEYWORD2 setDeviceStatus KEYWORD2 setDatarate KEYWORD2 setADR KEYWORD2 +setTxPower KEYWORD2 selectSubband KEYWORD2 setCSMA KEYWORD2 From 4703f58b7f4509a7bf59975dcac17be8808e6259 Mon Sep 17 00:00:00 2001 From: StevenCellist Date: Mon, 27 Nov 2023 16:20:06 +0100 Subject: [PATCH 3/4] [LoRaWAN] Add datarate into event structure --- .../LoRaWAN_End_Device_Reference.ino | 2 ++ src/protocols/LoRaWAN/LoRaWAN.cpp | 2 ++ src/protocols/LoRaWAN/LoRaWAN.h | 3 +++ 3 files changed, 7 insertions(+) diff --git a/examples/LoRaWAN/LoRaWAN_End_Device_Reference/LoRaWAN_End_Device_Reference.ino b/examples/LoRaWAN/LoRaWAN_End_Device_Reference/LoRaWAN_End_Device_Reference.ino index c31752e7..bf70f139 100644 --- a/examples/LoRaWAN/LoRaWAN_End_Device_Reference/LoRaWAN_End_Device_Reference.ino +++ b/examples/LoRaWAN/LoRaWAN_End_Device_Reference/LoRaWAN_End_Device_Reference.ino @@ -214,6 +214,8 @@ void loop() { Serial.println(event.confirmed); Serial.print(F("[LoRaWAN] Confirming:\t")); Serial.println(event.confirming); + Serial.print(F("[LoRaWAN] Datarate:\t")); + Serial.print(event.datarate); Serial.print(F("[LoRaWAN] Frequency:\t")); Serial.print(event.freq, 3); Serial.println(F(" MHz")); diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index a8f1fd2b..99c93549 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -904,6 +904,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf event->dir = RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK; event->confirmed = isConfirmed; event->confirming = isConfirmingDown; + event->datarate = this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK]; event->freq = currentChannels[event->dir].freq; event->power = this->txPwrCur; event->fcnt = this->fcntUp; @@ -1262,6 +1263,7 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event) event->dir = RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK; event->confirmed = isConfirmedDown; event->confirming = isConfirmingUp; + event->datarate = this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK]; event->freq = currentChannels[event->dir].freq; event->power = this->txPwrCur; event->fcnt = isAppDownlink ? this->aFcntDown : this->nFcntDown; diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index 6e4523d0..30ff2512 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -325,6 +325,9 @@ struct LoRaWANEvent_t { /*! \brief Whether the event is confirming a previous request (e.g., server downlink reply to confirmed uplink sent by user application)*/ bool confirming; + + /*! \brief Datarate */ + uint8_t datarate; /*! \brief Frequency in MHz */ float freq; From 62276e070bcc4baac09236f2ecd7409eaf51728d Mon Sep 17 00:00:00 2001 From: StevenCellist Date: Sat, 9 Dec 2023 10:28:13 +0100 Subject: [PATCH 4/4] [LoRaWAN] Expose downlink framecounters --- keywords.txt | 3 +++ src/protocols/LoRaWAN/LoRaWAN.cpp | 8 ++++++++ src/protocols/LoRaWAN/LoRaWAN.h | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/keywords.txt b/keywords.txt index 24369e17..6394b32a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -298,6 +298,9 @@ uplink KEYWORD2 downlink KEYWORD2 sendReceive KEYWORD2 setDeviceStatus KEYWORD2 +getFcntUp KEYWORD2 +getNFcntDown KEYWORD2 +getAFcntDown KEYWORD2 setDatarate KEYWORD2 setADR KEYWORD2 setTxPower KEYWORD2 diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index 99c93549..a9370da5 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -1335,6 +1335,14 @@ uint32_t LoRaWANNode::getFcntUp() { return(this->fcntUp); } +uint32_t LoRaWANNode::getNFcntDown() { + return(this->nFcntDown); +} + +uint32_t LoRaWANNode::getAFcntDown() { + return(this->aFcntDown); +} + uint32_t LoRaWANNode::generateMIC(uint8_t* msg, size_t len, uint8_t* key) { if((msg == NULL) || (len == 0)) { return(0); diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index 30ff2512..f8e1365f 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -527,6 +527,12 @@ class LoRaWANNode { /*! \brief Returns the last uplink's frame counter */ uint32_t getFcntUp(); + /*! \brief Returns the last network downlink's frame counter */ + uint32_t getNFcntDown(); + + /*! \brief Returns the last application downlink's frame counter */ + uint32_t getAFcntDown(); + /*! \brief Set uplink datarate. This should not be used when ADR is enabled. \param dr Datarate to use for uplinks.