diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index 5bef7005..337a5f1e 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -42,28 +42,32 @@ int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t fPort, String& strDown, } #endif -int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { - int16_t state = RADIOLIB_ERR_UNKNOWN; +int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { + // build a temporary buffer + // LoRaWAN downlinks can have 250 bytes at most with 1 extra byte for NULL + size_t lenDown = 0; + uint8_t dataDown[251]; + return(this->sendReceive((uint8_t*)strUp, strlen(strUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown)); +} + +int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { + return(this->sendReceive((uint8_t*)strUp, strlen(strUp), fPort, dataDown, lenDown, isConfirmed, eventUp, eventDown)); +} + +int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { // build a temporary buffer // LoRaWAN downlinks can have 250 bytes at most with 1 extra byte for NULL size_t lenDown = 0; uint8_t dataDown[251]; - state = this->sendReceive(dataUp, lenUp, fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown); - - return(state); -} - -int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { - int16_t state = RADIOLIB_ERR_UNKNOWN; - - state = this->sendReceive((uint8_t*)strUp, strlen(strUp), fPort, dataDown, lenDown, isConfirmed, eventUp, eventDown); - - return(state); + return(this->sendReceive(dataUp, lenUp, fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown)); } int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { + if(!dataUp || !dataDown || !lenDown) { + return(RADIOLIB_ERR_NULL_POINTER); + } int16_t state = RADIOLIB_ERR_UNKNOWN; Module* mod = this->phyLayer->getMod(); @@ -139,7 +143,7 @@ int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, u #if !RADIOLIB_STATIC_ONLY delete[] uplinkMsg; #endif - RADIOLIB_ASSERT(state); + return(state); } // handle Rx1 and Rx2 windows - returns window > 0 if a downlink is received @@ -187,7 +191,7 @@ int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, u #if !RADIOLIB_STATIC_ONLY delete[] uplinkMsg; #endif - RADIOLIB_ASSERT(state); + return(state); } uint8_t rxWindow = state; @@ -360,20 +364,14 @@ void LoRaWANNode::createSession(uint16_t lwMode, uint8_t initialDr) { cid = RADIOLIB_LORAWAN_MAC_DUTY_CYCLE; this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - uint8_t maxDCyclePower; + uint8_t maxDCyclePower = 0; switch(this->band->dutyCycle) { - case(0): - maxDCyclePower = 0; - break; case(3600): maxDCyclePower = 10; break; case(36000): maxDCyclePower = 7; break; - default: - maxDCyclePower = 0; - break; } cOcts[0] = maxDCyclePower; (void)execMacCommand(cid, cOcts, cLen); @@ -445,7 +443,8 @@ uint8_t* LoRaWANNode::getBufferSession() { LoRaWANNode::hton(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_AVAILABLE_CHANNELS], chMask); // save the current uplink MAC command queue - memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL], this->fOptsUp, RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN); + memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_MAC_QUEUE], this->fOptsUp, RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN); + memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_LEN], &this->fOptsUpLen, 1); // generate the signature of the Session buffer, and store it in the last two bytes of the Session buffer uint16_t signature = LoRaWANNode::checkSum16(this->bufferSession, RADIOLIB_LORAWAN_SESSION_BUF_SIZE - 2); @@ -467,7 +466,8 @@ int16_t LoRaWANNode::setBufferSession(uint8_t* persistentBuffer) { uint16_t signatureNonces = LoRaWANNode::ntoh(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_SIGNATURE]); uint16_t signatureInSession = LoRaWANNode::ntoh(&persistentBuffer[RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE]); if(signatureNonces != signatureInSession) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("The supplied session buffer does not match the Nonces buffer"); + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("The Session buffer (%04x) does not match the Nonces buffer (%04x)", + signatureInSession, signatureNonces); return(RADIOLIB_LORAWAN_SESSION_DISCARDED); } @@ -540,47 +540,36 @@ int16_t LoRaWANNode::setBufferSession(uint8_t* persistentBuffer) { } } + // restore the MAC state - ADR needs special care, the rest is straight default cid = RADIOLIB_LORAWAN_MAC_LINK_ADR; cLen = 14; // special internal ADR command memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_LINK_ADR], cLen); (void)execMacCommand(cid, cOcts, cLen); - cid = RADIOLIB_LORAWAN_MAC_DUTY_CYCLE; - (void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_DUTY_CYCLE], cLen); - (void)execMacCommand(cid, cOcts, cLen); + uint8_t cids[6] = { + RADIOLIB_LORAWAN_MAC_DUTY_CYCLE, RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP, + RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP, RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP, + RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP, RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP + }; + uint16_t locs[6] = { + RADIOLIB_LORAWAN_SESSION_DUTY_CYCLE, RADIOLIB_LORAWAN_SESSION_RX_PARAM_SETUP, + RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP, RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP, + RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP, RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP + }; - cid = RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP; - (void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_RX_PARAM_SETUP], cLen); - (void)execMacCommand(cid, cOcts, cLen); - - cid = RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP; - (void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP], cLen); - (void)execMacCommand(cid, cOcts, cLen); - - cid = RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP; - (void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP], cLen); - (void)execMacCommand(cid, cOcts, cLen); - - cid = RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP; - (void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP], cLen); - (void)execMacCommand(cid, cOcts, cLen); - - cid = RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP; - (void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK); - memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP], cLen); - (void)execMacCommand(cid, cOcts, cLen); + for(uint8_t i = 0; i < 6; i++) { + (void)this->getMacLen(cids[i], &cLen, RADIOLIB_LORAWAN_DOWNLINK); + memcpy(cOcts, &this->bufferSession[locs[i]], cLen); + (void)execMacCommand(cids[i], cOcts, cLen); + } // set the available channels uint16_t chMask = LoRaWANNode::ntoh(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_AVAILABLE_CHANNELS]); this->setAvailableChannels(chMask); // copy uplink MAC command queue back in place - memcpy(this->fOptsUp, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL], RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN); + memcpy(this->fOptsUp, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_MAC_QUEUE], RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN); + memcpy(&this->fOptsUpLen, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_LEN], 1); // as both the Nonces and session are restored, revert to active session this->bufferNonces[RADIOLIB_LORAWAN_NONCES_ACTIVE] = (uint8_t)true; @@ -588,7 +577,10 @@ int16_t LoRaWANNode::setBufferSession(uint8_t* persistentBuffer) { return(state); } -void LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey) { +int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey) { + if(!appKey) { + return(RADIOLIB_ERR_NULL_POINTER); + } // clear all the device credentials in case there were any this->clearNonces(); @@ -610,9 +602,14 @@ void LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, this->lwMode = RADIOLIB_LORAWAN_MODE_OTAA; this->lwClass = RADIOLIB_LORAWAN_CLASS_A; + + return(RADIOLIB_ERR_NONE); } -void LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey) { +int16_t LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey) { + if(!nwkSEncKey || !appSKey) { + return(RADIOLIB_ERR_NULL_POINTER); + } // clear all the device credentials in case there were any this->clearNonces(); @@ -637,6 +634,8 @@ void LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIn this->lwMode = RADIOLIB_LORAWAN_MODE_ABP; this->lwClass = RADIOLIB_LORAWAN_CLASS_A; + + return(RADIOLIB_ERR_NONE); } void LoRaWANNode::composeJoinRequest(uint8_t* out) { @@ -936,7 +935,7 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) // handle Rx1 and Rx2 windows - returns RADIOLIB_ERR_NONE if a downlink is received state = receiveCommon(RADIOLIB_LORAWAN_DOWNLINK, this->channels, this->rxDelays, 2, this->rxDelayStart); if(state < RADIOLIB_ERR_NONE) { - RADIOLIB_ASSERT(state); + return(state); } // process JoinAccept message @@ -1315,7 +1314,7 @@ static void LoRaWANNodeOnDownlinkAction(void) { downlinkAction = true; } -int16_t LoRaWANNode::receiveCommon(uint8_t dir, LoRaWANChannel_t* dlChannels, RadioLibTime_t* dlDelays, uint8_t numWindows, RadioLibTime_t tReference) { +int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChannels, const RadioLibTime_t* dlDelays, uint8_t numWindows, RadioLibTime_t tReference) { Module* mod = this->phyLayer->getMod(); int16_t state = RADIOLIB_ERR_UNKNOWN; @@ -1886,7 +1885,7 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin // try to apply the datarate configuration // if value is set to 'keep current values', retrieve current value if(macDrUp == 0x0F) { - macDrUp = this->channels[RADIOLIB_LORAWAN_UPLINK].dr; + macDrUp = currentDr; } if (this->band->dataRates[macDrUp] != RADIOLIB_LORAWAN_DATA_RATE_UNUSED) { @@ -1954,7 +1953,11 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin // restore original active channels this->setAvailableChannels(chMaskActive); - // save to the single ADR MAC location + // save to the ADR MAC location + // but first re-set the Dr/Tx/NbTrans field to make sure they're not set to 0xF + optIn[0] = (this->channels[RADIOLIB_LORAWAN_UPLINK].dr) << 4; + optIn[0] |= this->txPowerSteps; + optIn[13] = this->nbTrans; memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_LINK_ADR], optIn, lenIn); return(true); @@ -2707,7 +2710,7 @@ RadioLibTime_t LoRaWANNode::getLastToA() { return(this->lastToA); } -int16_t LoRaWANNode::setPhyProperties(LoRaWANChannel_t* chnl, uint8_t dir, int8_t pwr, size_t pre) { +int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir, int8_t pwr, size_t pre) { // set the physical layer configuration int16_t state = this->phyLayer->standby(); if(state != RADIOLIB_ERR_NONE) { @@ -3313,11 +3316,11 @@ int16_t LoRaWANNode::checkBufferCommon(uint8_t *buffer, uint16_t size) { uint16_t LoRaWANNode::checkSum16(uint8_t *key, uint16_t keyLen) { uint16_t checkSum = 0; for(uint16_t i = 0; i < keyLen; i += 2) { - checkSum ^= ((uint16_t)key[i] << 8) | key[i + 1]; - } - if(keyLen % 2 == 1) { - uint16_t val = ((uint16_t)key[keyLen - 1] << 8); - checkSum ^= val; + uint16_t word = (key[i] << 8); + if(i + 1 < keyLen) { + word |= key[i + 1]; + } + checkSum ^= word; } return(checkSum); } diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index 6d3c1e6e..cb50f1c5 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -297,8 +297,9 @@ enum LoRaWANSchemeSession_t { RADIOLIB_LORAWAN_SESSION_LAST_TIME = RADIOLIB_LORAWAN_SESSION_PERIODICITY + 1, // 4 bytes RADIOLIB_LORAWAN_SESSION_UL_CHANNELS = RADIOLIB_LORAWAN_SESSION_LAST_TIME + 4, // 16*5 bytes RADIOLIB_LORAWAN_SESSION_DL_CHANNELS = RADIOLIB_LORAWAN_SESSION_UL_CHANNELS + RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS*5, // 16*4 bytes - RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL = RADIOLIB_LORAWAN_SESSION_DL_CHANNELS + RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS*4, // 15 bytes - RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL + RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN, // 4 bytes + RADIOLIB_LORAWAN_SESSION_MAC_QUEUE = RADIOLIB_LORAWAN_SESSION_DL_CHANNELS + RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS*4, // 15 bytes + RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_LEN = RADIOLIB_LORAWAN_SESSION_MAC_QUEUE + 1, // 1 byte + RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_LEN + RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN, // 4 bytes RADIOLIB_LORAWAN_SESSION_ADR_FCNT = RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN + sizeof(uint32_t), // 4 bytes RADIOLIB_LORAWAN_SESSION_LINK_ADR = RADIOLIB_LORAWAN_SESSION_ADR_FCNT + sizeof(uint32_t), // 14 bytes RADIOLIB_LORAWAN_SESSION_AVAILABLE_CHANNELS = RADIOLIB_LORAWAN_SESSION_LINK_ADR + 14, // 2 bytes @@ -568,8 +569,9 @@ class LoRaWANNode { \param devEUI 8-byte device identifier. \param nwkKey Pointer to the network AES-128 key. \param appKey Pointer to the application AES-128 key. + \returns \ref status_codes */ - void beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey); + int16_t beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey); /*! \brief Set the device credentials and activation configuration @@ -579,8 +581,9 @@ class LoRaWANNode { \param nwkSEncKey Pointer to the MAC command network session key [NwkSEncKey] (LoRaWAN 1.1) or network session AES-128 key [NwkSKey] (LoRaWAN 1.0). \param appSKey Pointer to the application session AES-128 key. + \returns \ref status_codes */ - void beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey); + int16_t beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey); /*! \brief Join network by restoring OTAA session or performing over-the-air activation. By this procedure, @@ -617,6 +620,19 @@ class LoRaWANNode { virtual int16_t sendReceive(String& strUp, uint8_t fPort, String& strDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); #endif + /*! + \brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window. + \param strUp C-string that will be transmitted. + \param fPort 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 + (fPort, 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 + (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user. + \returns Window number > 0 if downlink was received, 0 is no downlink was received, otherwise \ref status_codes + */ + virtual int16_t sendReceive(const char* strUp, uint8_t fPort, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); + /*! \brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window. \param strUp C-string that will be transmitted. @@ -632,6 +648,20 @@ class LoRaWANNode { */ virtual int16_t sendReceive(const char* strUp, uint8_t fPort, 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 fPort 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 + (fPort, 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 + (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user. + \returns Window number > 0 if downlink was received, 0 is no downlink was received, otherwise \ref status_codes + */ + virtual int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort = 1, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); + /*! \brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window. \param dataUp Data to send. @@ -648,20 +678,6 @@ class LoRaWANNode { */ virtual int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, 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 fPort 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 - (fPort, 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 - (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user. - \returns Window number > 0 if downlink was received, 0 is no downlink was received, otherwise \ref status_codes - */ - virtual int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort = 1, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); - /*! \brief Add a MAC command to the uplink queue. Only LinkCheck and DeviceTime are available to the user. @@ -996,7 +1012,7 @@ class LoRaWANNode { int16_t transmitUplink(LoRaWANChannel_t* chnl, uint8_t* in, uint8_t len); // wait for, open and listen during receive windows; only performs listening - int16_t receiveCommon(uint8_t dir, LoRaWANChannel_t* dlChannels, RadioLibTime_t* dlDelays, uint8_t numWindows, RadioLibTime_t tReference); + int16_t receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChannels, const RadioLibTime_t* dlDelays, uint8_t numWindows, RadioLibTime_t tReference); // extract downlink payload and process MAC commands int16_t parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event = NULL); @@ -1033,7 +1049,7 @@ class LoRaWANNode { void clearMacCommands(uint8_t* inOut, uint8_t* lenInOut, uint8_t dir); // configure the common physical layer properties (frequency, sync word etc.) - int16_t setPhyProperties(LoRaWANChannel_t* chnl, uint8_t dir, int8_t pwr, size_t pre = 0); + int16_t setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir, int8_t pwr, size_t pre = 0); // Performs CSMA as per LoRa Alliance Technical Recommendation 13 (TR-013). bool csmaChannelClear(uint8_t difs, uint8_t numBackoff);