[LoRaWAN] Add methods to allow user-provided sleep function

This commit is contained in:
jgromes 2025-02-01 10:40:59 +01:00
parent 4deec953e8
commit 27eece8f8a
3 changed files with 39 additions and 2 deletions

View file

@ -377,6 +377,7 @@ getLastToA KEYWORD2
dutyCycleInterval KEYWORD2 dutyCycleInterval KEYWORD2
timeUntilUplink KEYWORD2 timeUntilUplink KEYWORD2
getMaxPayloadLen KEYWORD2 getMaxPayloadLen KEYWORD2
setSleepFunction KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)

View file

@ -1377,7 +1377,7 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
if(waitLen > this->scanGuard) { if(waitLen > this->scanGuard) {
waitLen -= this->scanGuard; waitLen -= this->scanGuard;
} }
mod->hal->delay(waitLen); this->sleepDelay(waitLen);
// open Rx window by starting receive with specified timeout // open Rx window by starting receive with specified timeout
// TODO remove default arguments // TODO remove default arguments
@ -1387,7 +1387,7 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opening Rx%d window (%d ms timeout)... <-- Rx Delay end ", window, (int)(timeoutHost / 1000 + scanGuard / 2)); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opening Rx%d window (%d ms timeout)... <-- Rx Delay end ", window, (int)(timeoutHost / 1000 + scanGuard / 2));
// wait for the timeout to complete (and a small additional delay) // wait for the timeout to complete (and a small additional delay)
mod->hal->delay(timeoutHost / 1000 + this->scanGuard / 2); this->sleepDelay(timeoutHost / 1000 + this->scanGuard / 2);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", window); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", window);
// if the IRQ bit for Rx Timeout is not set, something is received, so stop the windows // if the IRQ bit for Rx Timeout is not set, something is received, so stop the windows
@ -3310,6 +3310,10 @@ uint8_t LoRaWANNode::getMaxPayloadLen() {
return(curLen - 13 - this->fOptsUpLen); return(curLen - 13 - this->fOptsUpLen);
} }
void LoRaWANNode::setSleepFunction(SleepCb_t cb) {
this->sleepCb = cb;
}
int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) { int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) {
int16_t state = this->phyLayer->standby(); int16_t state = this->phyLayer->standby();
if(state != RADIOLIB_ERR_NONE) { if(state != RADIOLIB_ERR_NONE) {
@ -3434,6 +3438,18 @@ void LoRaWANNode::processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_
} }
} }
void LoRaWANNode::sleepDelay(RadioLibTime_t ms) {
// if the user did not provide sleep callback, or the duration is short, just call delay
if((this->sleepCb == nullptr) || (ms <= RADIOLIB_LORAWAN_DELAY_SLEEP_THRESHOLD)) {
Module* mod = this->phyLayer->getMod();
mod->hal->delay(ms);
return;
}
// otherwise, call the user-provided callback
this->sleepCb(ms);
}
int16_t LoRaWANNode::checkBufferCommon(const uint8_t *buffer, uint16_t size) { int16_t LoRaWANNode::checkBufferCommon(const uint8_t *buffer, uint16_t size) {
// check if there are actually values in the buffer // check if there are actually values in the buffer
size_t i = 0; size_t i = 0;

View file

@ -210,6 +210,9 @@
#define RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE (250) #define RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE (250)
// threshold at which sleeping via user callback enabled, in ms
#define RADIOLIB_LORAWAN_DELAY_SLEEP_THRESHOLD (50)
/*! /*!
\struct LoRaWANMacCommand_t \struct LoRaWANMacCommand_t
\brief MAC command specification structure. \brief MAC command specification structure.
@ -832,6 +835,18 @@ class LoRaWANNode {
*/ */
uint8_t getMaxPayloadLen(); uint8_t getMaxPayloadLen();
/*! \brief Callback to a user-provided sleep function. */
typedef void (*SleepCb_t)(RadioLibTime_t ms);
/*!
\brief Set custom delay/sleep function callback. If set, LoRaWAN node will call
this function to wait for periods of time longer than RADIOLIB_LORAWAN_DELAY_SLEEP_THRESHOLD.
This can be used to lower the power consumption by putting the host microcontroller to sleep.
NOTE: Since this method will call a user-provided function, it is up to the user to ensure
that the time duration spent in that sleep function is accurate to at least 1 ms!
*/
void setSleepFunction(SleepCb_t cb);
/*! /*!
\brief TS009 Protocol Specification Verification switch \brief TS009 Protocol Specification Verification switch
(allows FPort 224 and cuts off uplink payload instead of rejecting if maximum length exceeded). (allows FPort 224 and cuts off uplink payload instead of rejecting if maximum length exceeded).
@ -973,6 +988,8 @@ class LoRaWANNode {
// allow port 226 for devices implementing TS011 // allow port 226 for devices implementing TS011
bool TS011 = false; bool TS011 = false;
SleepCb_t sleepCb = nullptr;
// this will reset the device credentials, so the device starts completely new // this will reset the device credentials, so the device starts completely new
void clearNonces(); void clearNonces();
@ -1102,6 +1119,9 @@ class LoRaWANNode {
// function to encrypt and decrypt payloads (regular uplink/downlink) // function to encrypt and decrypt payloads (regular uplink/downlink)
void processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fCnt, uint8_t dir, uint8_t ctrId, bool counter); void processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fCnt, uint8_t dir, uint8_t ctrId, bool counter);
// function that allows sleeping via user-provided callback
void sleepDelay(RadioLibTime_t ms);
// 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum // 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum
static uint16_t checkSum16(const uint8_t *key, uint16_t keyLen); static uint16_t checkSum16(const uint8_t *key, uint16_t keyLen);