diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index bd12c06f6..e4c379c36 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -42,9 +42,18 @@ LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band, uint8_t } void LoRaWANNode::setCSMA(uint8_t backoffMax, uint8_t difsSlots, bool enableCSMA) { - this->backoffMax = backoffMax; - this->difsSlots = difsSlots; - this->enableCSMA = enableCSMA; + this->backoffMax = backoffMax; + this->difsSlots = difsSlots; + this->enableCSMA = enableCSMA; +} + +void LoRaWANNode::createNonces() { + // set the device credentials + LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_VERSION], RADIOLIB_LORAWAN_NONCES_VERSION_VAL); + LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_MODE], this->lwMode); + LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_CLASS], this->lwClass); + LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_PLAN], this->band->bandNum); + LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_CHECKSUM], this->keyCheckSum); } void LoRaWANNode::clearNonces() { @@ -54,6 +63,7 @@ void LoRaWANNode::clearNonces() { this->devNonce = 0; this->joinNonce = 0; this->isActive = false; + this->rev = 0; } void LoRaWANNode::clearSession() { @@ -299,7 +309,7 @@ int16_t LoRaWANNode::checkBufferCommon(uint8_t *buffer, uint16_t size) { uint16_t checkSum = LoRaWANNode::checkSum16(buffer, size - 2); uint16_t signature = LoRaWANNode::ntoh(&buffer[size - 2]); if(signature != checkSum) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Calculated checksum: %04X, expected: %04X", checkSum, signature); + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Calculated checksum: %04x, expected: %04x", checkSum, signature); return(RADIOLIB_ERR_CHECKSUM_MISMATCH); } return(RADIOLIB_ERR_NONE); @@ -445,20 +455,30 @@ void LoRaWANNode::activateCommon(uint8_t initialDr) { } void LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey) { + // clear all the device credentials in case there were any + this->clearNonces(); + this->joinEUI = joinEUI; this->devEUI = devEUI; - memcpy(this->nwkKey, nwkKey, RADIOLIB_AES128_KEY_SIZE); memcpy(this->appKey, appKey, RADIOLIB_AES128_KEY_SIZE); + if(nwkKey) { + this->rev = 1; + memcpy(this->nwkKey, nwkKey, RADIOLIB_AES128_KEY_SIZE); + } // generate activation key checksum this->keyCheckSum ^= LoRaWANNode::checkSum16(reinterpret_cast(&joinEUI), 8); this->keyCheckSum ^= LoRaWANNode::checkSum16(reinterpret_cast(&devEUI), 8); - this->keyCheckSum ^= LoRaWANNode::checkSum16(nwkKey, 16); this->keyCheckSum ^= LoRaWANNode::checkSum16(appKey, 16); + if(nwkKey) { + this->keyCheckSum ^= LoRaWANNode::checkSum16(nwkKey, 16); + } - this->clearNonces(); this->lwMode = RADIOLIB_LORAWAN_MODE_OTAA; this->lwClass = RADIOLIB_LORAWAN_CLASS_A; + + // set the device credentials + this->createNonces(); } int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) { @@ -530,7 +550,12 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) LoRaWANNode::hton(&joinRequestMsg[RADIOLIB_LORAWAN_JOIN_REQUEST_DEV_NONCE_POS], devNonceUsed); // add the authentication code - uint32_t mic = this->generateMIC(joinRequestMsg, RADIOLIB_LORAWAN_JOIN_REQUEST_LEN - sizeof(uint32_t), this->nwkKey); + uint32_t mic = 0; + if(this->rev == 1) { + mic =this->generateMIC(joinRequestMsg, RADIOLIB_LORAWAN_JOIN_REQUEST_LEN - sizeof(uint32_t), this->nwkKey); + } else { + mic =this->generateMIC(joinRequestMsg, RADIOLIB_LORAWAN_JOIN_REQUEST_LEN - sizeof(uint32_t), this->appKey); + } LoRaWANNode::hton(&joinRequestMsg[RADIOLIB_LORAWAN_JOIN_REQUEST_LEN - sizeof(uint32_t)], mic); // send it @@ -584,7 +609,11 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) // the first byte is the MAC header which is not encrypted uint8_t joinAcceptMsg[RADIOLIB_LORAWAN_JOIN_ACCEPT_MAX_LEN]; joinAcceptMsg[0] = joinAcceptMsgEnc[0]; - RadioLibAES128Instance.init(this->nwkKey); + if(this->rev == 1) { + RadioLibAES128Instance.init(this->nwkKey); + } else { + RadioLibAES128Instance.init(this->appKey); + } RadioLibAES128Instance.encryptECB(&joinAcceptMsgEnc[1], RADIOLIB_LORAWAN_JOIN_ACCEPT_MAX_LEN - 1, &joinAcceptMsg[1]); // get current joinNonce from downlink @@ -593,9 +622,16 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) RADIOLIB_DEBUG_PROTOCOL_PRINTLN("JoinAccept (JoinNonce = %lu, previously %lu):", (unsigned long)joinNonceNew, (unsigned long)this->joinNonce); RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(joinAcceptMsg, lenRx); - // joinNonce received must be greater than the last joinNonce heard, else error - if((this->joinNonce > 0) && (joinNonceNew <= this->joinNonce)) { - return(RADIOLIB_ERR_JOIN_NONCE_INVALID); + if(this->rev == 1) { + // for v1.1, the JoinNonce received must be greater than the last joinNonce heard, else error + if((this->joinNonce > 0) && (joinNonceNew <= this->joinNonce)) { + return(RADIOLIB_ERR_JOIN_NONCE_INVALID); + } + } else { + // for v1.0.4, the JoinNonce is simply a non-repeating value (we only check the last value) + if(joinNonceNew == this->joinNonce) { + return(RADIOLIB_ERR_JOIN_NONCE_INVALID); + } } this->joinNonce = joinNonceNew; @@ -629,7 +665,7 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) } else { // 1.0 version - if(!verifyMIC(joinAcceptMsg, lenRx, this->nwkKey)) { + if(!verifyMIC(joinAcceptMsg, lenRx, this->appKey)) { return(RADIOLIB_ERR_CRC_MISMATCH); } @@ -704,11 +740,11 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) LoRaWANNode::hton(&keyDerivationBuff[RADIOLIB_LORAWAN_JOIN_ACCEPT_HOME_NET_ID_POS], this->homeNetId, 3); LoRaWANNode::hton(&keyDerivationBuff[RADIOLIB_LORAWAN_JOIN_ACCEPT_DEV_ADDR_POS], devNonceUsed); keyDerivationBuff[0] = RADIOLIB_LORAWAN_JOIN_ACCEPT_APP_S_KEY; - RadioLibAES128Instance.init(this->nwkKey); + RadioLibAES128Instance.init(this->appKey); RadioLibAES128Instance.encryptECB(keyDerivationBuff, RADIOLIB_AES128_BLOCK_SIZE, this->appSKey); keyDerivationBuff[0] = RADIOLIB_LORAWAN_JOIN_ACCEPT_F_NWK_S_INT_KEY; - RadioLibAES128Instance.init(this->nwkKey); + RadioLibAES128Instance.init(this->appKey); RadioLibAES128Instance.encryptECB(keyDerivationBuff, RADIOLIB_AES128_BLOCK_SIZE, this->fNwkSIntKey); memcpy(this->sNwkSIntKey, this->fNwkSIntKey, RADIOLIB_AES128_KEY_SIZE); @@ -724,12 +760,7 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) this->confFCntDown = RADIOLIB_LORAWAN_FCNT_NONE; this->adrFCnt = 0; - // save the activation keys checksum, device address & keys as well as JoinAccept values; these are only ever set when joining - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_VERSION], RADIOLIB_LORAWAN_NONCES_VERSION_VAL); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_MODE], RADIOLIB_LORAWAN_MODE_OTAA); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_CLASS], RADIOLIB_LORAWAN_CLASS_A); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_PLAN], this->band->bandNum); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_CHECKSUM], this->keyCheckSum); + LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_JOIN_NONCE], this->joinNonce, 3); this->bufferNonces[RADIOLIB_LORAWAN_NONCES_ACTIVE] = (uint8_t)true; @@ -763,17 +794,19 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent) } void LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey) { + // clear all the device credentials in case there were any + this->clearNonces(); + this->devAddr = addr; memcpy(this->appSKey, appSKey, RADIOLIB_AES128_KEY_SIZE); memcpy(this->nwkSEncKey, nwkSEncKey, RADIOLIB_AES128_KEY_SIZE); - if(fNwkSIntKey) { + if(fNwkSIntKey && sNwkSIntKey) { this->rev = 1; memcpy(this->fNwkSIntKey, fNwkSIntKey, RADIOLIB_AES128_KEY_SIZE); + memcpy(this->sNwkSIntKey, sNwkSIntKey, RADIOLIB_AES128_KEY_SIZE); } else { memcpy(this->fNwkSIntKey, nwkSEncKey, RADIOLIB_AES128_KEY_SIZE); - } - if(sNwkSIntKey) { - memcpy(this->sNwkSIntKey, sNwkSIntKey, RADIOLIB_AES128_KEY_SIZE); + memcpy(this->sNwkSIntKey, nwkSEncKey, RADIOLIB_AES128_KEY_SIZE); } // generate activation key checksum @@ -783,10 +816,11 @@ void LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIn if(fNwkSIntKey) { this->keyCheckSum ^= LoRaWANNode::checkSum16(fNwkSIntKey, 16); } if(sNwkSIntKey) { this->keyCheckSum ^= LoRaWANNode::checkSum16(sNwkSIntKey, 16); } - // clear & set all the device credentials - this->clearNonces(); this->lwMode = RADIOLIB_LORAWAN_MODE_ABP; this->lwClass = RADIOLIB_LORAWAN_CLASS_A; + + // set the device credentials + this->createNonces(); } int16_t LoRaWANNode::activateABP(uint8_t initialDr) { @@ -822,13 +856,6 @@ int16_t LoRaWANNode::activateABP(uint8_t initialDr) { this->confFCntDown = RADIOLIB_LORAWAN_FCNT_NONE; this->adrFCnt = 0; - // save the activation keys checksum, mode, class, frequency plan - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_VERSION], RADIOLIB_LORAWAN_NONCES_VERSION_VAL); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_MODE], RADIOLIB_LORAWAN_MODE_ABP); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_CLASS], RADIOLIB_LORAWAN_CLASS_A); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_PLAN], this->band->bandNum); - LoRaWANNode::hton(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_CHECKSUM], this->keyCheckSum); - // new session all good, so set active-bit to true this->bufferNonces[RADIOLIB_LORAWAN_NONCES_ACTIVE] = (uint8_t)true; @@ -1060,8 +1087,13 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t fPort, bool isCon uplinkMsgLen = RADIOLIB_LORAWAN_FRAME_LEN(len, fOptsLen); uplinkMsg[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= fOptsLen; - // encrypt it - processAES(fOptsBuff, fOptsLen, this->nwkSEncKey, &uplinkMsg[RADIOLIB_LORAWAN_FHDR_FOPTS_POS], this->fCntUp, RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK, 0x01, true); + if(this->rev == 1) { + // in LoRaWAN v1.1, the FOpts are encrypted using the NwkSEncKey + processAES(fOptsBuff, fOptsLen, this->nwkSEncKey, &uplinkMsg[RADIOLIB_LORAWAN_FHDR_FOPTS_POS], this->fCntUp, RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK, 0x01, true); + } else { + // in LoRaWAN v1.0.x, the FOpts are unencrypted + memcpy(&uplinkMsg[RADIOLIB_LORAWAN_FHDR_FOPTS_POS], fOptsBuff, fOptsLen); + } } @@ -1484,8 +1516,14 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event) // if there are <= 15 bytes of FOpts, they are in the FHDR, otherwise they are in the payload // in case of the latter, process AES is if it were a normal payload but using the NwkSEncKey if(fOptsLen <= RADIOLIB_LORAWAN_FHDR_FOPTS_LEN_MASK) { - uint8_t ctrId = 0x01 + isAppDownlink; // see LoRaWAN v1.1 errata - processAES(&downlinkMsg[RADIOLIB_LORAWAN_FHDR_FOPTS_POS], (size_t)fOptsLen, this->nwkSEncKey, fOpts, fCnt32, RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK, ctrId, true); + if(this->rev == 1) { + // in LoRaWAN v1.1, the piggy-backed FOpts are encrypted using the NwkSEncKey + uint8_t ctrId = 0x01 + isAppDownlink; // see LoRaWAN v1.1 errata + processAES(&downlinkMsg[RADIOLIB_LORAWAN_FHDR_FOPTS_POS], (size_t)fOptsLen, this->nwkSEncKey, fOpts, fCnt32, RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK, ctrId, true); + } else { + // in LoRaWAN v1.0.x, the piggy-backed FOpts are unencrypted + memcpy(fOpts, &downlinkMsg[RADIOLIB_LORAWAN_FHDR_FOPTS_POS], (size_t)fOptsLen); + } } else { processAES(&downlinkMsg[RADIOLIB_LORAWAN_FRAME_PAYLOAD_POS(0)], (size_t)fOptsLen, this->nwkSEncKey, fOpts, fCnt32, RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK, 0x00, true); } @@ -1839,23 +1877,9 @@ int16_t LoRaWANNode::setupChannelsDyn(bool joinRequest) { this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][num] = RADIOLIB_LORAWAN_CHANNEL_NONE; } - for (int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { - if(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("UL: %3d %d %7.3f (%d - %d) | DL: %3d %d %7.3f (%d - %d)", - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].idx, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].freq, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMin, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMax, - - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].idx, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].enabled, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].freq, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMin, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMax - ); - } - } + #if RADIOLIB_DEBUG_PROTOCOL + this->printChannels(); + #endif return(RADIOLIB_ERR_NONE); } @@ -2262,7 +2286,7 @@ int16_t LoRaWANNode::deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* que } bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("[MAC] 0x%02X", cmd->cid); + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("[MAC] 0x%02x", cmd->cid); RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(cmd->payload, cmd->len); if(cmd->cid >= RADIOLIB_LORAWAN_MAC_PROPRIETARY) { @@ -2683,6 +2707,26 @@ bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd) { return(false); } +void LoRaWANNode::printChannels() { + for (int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { + if(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled) { + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("UL: %3d %d %7.3f (%d - %d) | DL: %3d %d %7.3f (%d - %d)", + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].idx, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].freq, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMin, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMax, + + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].idx, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].enabled, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].freq, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMin, + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMax + ); + } + } +} + bool LoRaWANNode::applyChannelMaskDyn(uint8_t chMaskCntl, uint16_t chMask) { for(size_t i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { if(chMaskCntl == 0) { @@ -2703,26 +2747,12 @@ bool LoRaWANNode::applyChannelMaskDyn(uint8_t chMaskCntl, uint16_t chMask) { this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled = true; } } - + } - for (int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { - if(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("UL: %3d %d %7.3f (%d - %d) | DL: %3d %d %7.3f (%d - %d)", - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].idx, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].freq, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMin, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMax, - - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].idx, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].enabled, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].freq, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMin, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMax - ); - } - } + #if RADIOLIB_DEBUG_PROTOCOL + this->printChannels(); + #endif return(true); } @@ -2738,9 +2768,9 @@ bool LoRaWANNode::applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask) { } } + LoRaWANChannel_t chnl; if((this->band->numTxSpans == 1 && chMaskCntl <= 5) || (this->band->numTxSpans == 2 && chMaskCntl <= 3)) { // select channels from first span - LoRaWANChannel_t chnl; for(uint8_t i = 0; i < 16; i++) { uint16_t mask = 1 << i; if(mask & chMask) { @@ -2763,7 +2793,6 @@ bool LoRaWANNode::applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask) { } if(this->band->numTxSpans == 2 && chMaskCntl == 4) { // select channels from second span - LoRaWANChannel_t chnl; for(uint8_t i = 0; i < 8; i++) { uint16_t mask = 1 << i; if(mask & chMask) { @@ -2780,7 +2809,6 @@ bool LoRaWANNode::applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask) { } if(this->band->numTxSpans == 2 && chMaskCntl == 5) { // a '1' enables a bank of 8 + 1 channels from 1st and 2nd span respectively - LoRaWANChannel_t chnl; for(uint8_t i = 0; i < 8; i++) { uint16_t mask = 1 << i; if(mask & chMask) { @@ -2811,7 +2839,6 @@ bool LoRaWANNode::applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask) { this->setupChannelsFix(this->subBand); // a '1' enables a single channel from second span - LoRaWANChannel_t chnl; for(uint8_t i = 0; i < 8; i++) { uint16_t mask = 1 << i; if(mask & chMask) { @@ -2829,7 +2856,7 @@ bool LoRaWANNode::applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask) { } if(this->band->numTxSpans == 2 && chMaskCntl == 7) { // all channels off (clear all channels) - LoRaWANChannel_t chnl = RADIOLIB_LORAWAN_CHANNEL_NONE; + chnl = RADIOLIB_LORAWAN_CHANNEL_NONE; for(int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i] = chnl; // downlink channels are not defined so don't need to reset @@ -2852,23 +2879,9 @@ bool LoRaWANNode::applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask) { } - for (int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { - if(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("UL: %3d %d %7.3f (%d - %d) | DL: %3d %d %7.3f (%d - %d)", - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].idx, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].freq, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMin, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].drMax, - - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].idx, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].enabled, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].freq, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMin, - this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].drMax - ); - } - } + #if RADIOLIB_DEBUG_PROTOCOL + this->printChannels(); + #endif return(true); } diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index 3af9477f4..a9524d990 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -1002,6 +1002,9 @@ class LoRaWANNode { // save the selected sub-band in case this must be restored in ADR control uint8_t subBand = 0; + // initalize the Nonces buffer after beginX() has been called + void createNonces(); + // this will reset the device credentials, so the device starts completely new void clearNonces(); @@ -1019,6 +1022,9 @@ class LoRaWANNode { // channels must be configured separately by setupChannelsDyn()! int16_t setPhyProperties(uint8_t dir); + // print the available channels through debug + void printChannels(); + // setup uplink/downlink channel data rates and frequencies // for dynamic channels, there is a small set of predefined channels // in case of JoinRequest, add some optional extra frequencies