Merge pull request #942 from StevenCellist/master
[LoRaWAN] Fix channel logic: for fixed bands, persistence of dynamic bands, rejoining during active session
This commit is contained in:
commit
a981f9828a
1 changed files with 90 additions and 43 deletions
|
@ -111,8 +111,12 @@ int16_t LoRaWANNode::restore() {
|
||||||
.len = MacTable[RADIOLIB_LORAWAN_MAC_LINK_ADR].lenDn,
|
.len = MacTable[RADIOLIB_LORAWAN_MAC_LINK_ADR].lenDn,
|
||||||
.repeat = 0,
|
.repeat = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// only apply the single ADR command on dynamic bands; fixed bands is done through channel restore
|
||||||
|
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
|
||||||
mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID), cmd.payload, cmd.len);
|
mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID), cmd.payload, cmd.len);
|
||||||
execMacCommand(&cmd, false);
|
execMacCommand(&cmd, false);
|
||||||
|
}
|
||||||
|
|
||||||
cmd.cid = RADIOLIB_LORAWAN_MAC_DUTY_CYCLE;
|
cmd.cid = RADIOLIB_LORAWAN_MAC_DUTY_CYCLE;
|
||||||
cmd.len = MacTable[RADIOLIB_LORAWAN_MAC_DUTY_CYCLE].lenDn;
|
cmd.len = MacTable[RADIOLIB_LORAWAN_MAC_DUTY_CYCLE].lenDn;
|
||||||
|
@ -207,7 +211,7 @@ int16_t LoRaWANNode::restoreFcntUp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t LoRaWANNode::restoreChannels() {
|
int16_t LoRaWANNode::restoreChannels() {
|
||||||
// first do the default channels
|
// first do the default channels, in case these are not covered by restored channels
|
||||||
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
|
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
|
||||||
this->setupChannelsDyn(false);
|
this->setupChannelsDyn(false);
|
||||||
} else { // RADIOLIB_LORAWAN_BAND_FIXED
|
} else { // RADIOLIB_LORAWAN_BAND_FIXED
|
||||||
|
@ -226,6 +230,7 @@ int16_t LoRaWANNode::restoreChannels() {
|
||||||
cmd.len = MacTable[RADIOLIB_LORAWAN_MAC_NEW_CHANNEL].lenDn;
|
cmd.len = MacTable[RADIOLIB_LORAWAN_MAC_NEW_CHANNEL].lenDn;
|
||||||
memcpy(cmd.payload, &(bufferUp[i * cmd.len]), cmd.len);
|
memcpy(cmd.payload, &(bufferUp[i * cmd.len]), cmd.len);
|
||||||
if(memcmp(cmd.payload, bufferZeroes, cmd.len) != 0) { // only execute if it is not all zeroes
|
if(memcmp(cmd.payload, bufferZeroes, cmd.len) != 0) { // only execute if it is not all zeroes
|
||||||
|
cmd.repeat = 1;
|
||||||
(void)execMacCommand(&cmd, false);
|
(void)execMacCommand(&cmd, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +267,7 @@ int16_t LoRaWANNode::restoreChannels() {
|
||||||
memcpy(cmd.payload, &buffer[i * cmd.len], cmd.len);
|
memcpy(cmd.payload, &buffer[i * cmd.len], cmd.len);
|
||||||
// there COULD, according to spec, be an all zeroes ADR command - meh
|
// there COULD, according to spec, be an all zeroes ADR command - meh
|
||||||
if(memcmp(cmd.payload, bufferZeroes, cmd.len) != 0) {
|
if(memcmp(cmd.payload, bufferZeroes, cmd.len) != 0) {
|
||||||
|
cmd.repeat = (i+1);
|
||||||
execMacCommand(&cmd, false);
|
execMacCommand(&cmd, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,6 +277,11 @@ int16_t LoRaWANNode::restoreChannels() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void LoRaWANNode::beginCommon(uint8_t joinDr) {
|
void LoRaWANNode::beginCommon(uint8_t joinDr) {
|
||||||
|
// in case a new session is started while there is an ongoing session
|
||||||
|
// clear the MAC queues completely
|
||||||
|
memset(&(this->commandsUp), 0, sizeof(LoRaWANMacCommandQueue_t));
|
||||||
|
memset(&(this->commandsDown), 0, sizeof(LoRaWANMacCommandQueue_t));
|
||||||
|
|
||||||
LoRaWANMacCommand_t cmd = {
|
LoRaWANMacCommand_t cmd = {
|
||||||
.cid = RADIOLIB_LORAWAN_MAC_LINK_ADR,
|
.cid = RADIOLIB_LORAWAN_MAC_LINK_ADR,
|
||||||
.payload = { 0 },
|
.payload = { 0 },
|
||||||
|
@ -389,12 +400,21 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
|
||||||
bool validCheckSum = mod->hal->getPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID) == checkSum;
|
bool validCheckSum = mod->hal->getPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID) == checkSum;
|
||||||
bool validMode = mod->hal->getPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_MODE_ID) == RADIOLIB_LORAWAN_MODE_OTAA;
|
bool validMode = mod->hal->getPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_MODE_ID) == RADIOLIB_LORAWAN_MODE_OTAA;
|
||||||
|
|
||||||
if(!force && validCheckSum && validMode) {
|
if(validCheckSum && validMode) {
|
||||||
|
if(!force) {
|
||||||
// the device has joined already, we can just pull the data from persistent storage
|
// the device has joined already, we can just pull the data from persistent storage
|
||||||
RADIOLIB_DEBUG_PRINTLN("Found existing session; restoring...");
|
RADIOLIB_DEBUG_PRINTLN("Found existing session; restoring...");
|
||||||
|
|
||||||
return(this->restore());
|
return(this->restore());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// the credentials are still the same, so restore only DevNonce and JoinNonce
|
||||||
|
this->devNonce = mod->hal->getPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID);
|
||||||
|
this->joinNonce = mod->hal->getPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if forced by user, keys are new or changed mode, wipe the previous session
|
||||||
|
if(force || !validCheckSum || !validMode) {
|
||||||
#if RADIOLIB_DEBUG
|
#if RADIOLIB_DEBUG
|
||||||
RADIOLIB_DEBUG_PRINTLN("Didn't restore session (checksum: %d, mode: %d)", validCheckSum, validMode);
|
RADIOLIB_DEBUG_PRINTLN("Didn't restore session (checksum: %d, mode: %d)", validCheckSum, validMode);
|
||||||
RADIOLIB_DEBUG_PRINTLN("First 16 bytes of NVM:");
|
RADIOLIB_DEBUG_PRINTLN("First 16 bytes of NVM:");
|
||||||
|
@ -646,6 +666,7 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
|
||||||
|
|
||||||
// save join-request parameters
|
// save join-request parameters
|
||||||
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_HOME_NET_ID, this->homeNetId);
|
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_HOME_NET_ID, this->homeNetId);
|
||||||
|
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID, this->devNonce);
|
||||||
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID, this->joinNonce);
|
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID, this->joinNonce);
|
||||||
|
|
||||||
this->saveSession();
|
this->saveSession();
|
||||||
|
@ -756,13 +777,9 @@ bool LoRaWANNode::isJoined() {
|
||||||
int16_t LoRaWANNode::saveSession() {
|
int16_t LoRaWANNode::saveSession() {
|
||||||
Module* mod = this->phyLayer->getMod();
|
Module* mod = this->phyLayer->getMod();
|
||||||
|
|
||||||
// store session configuration (MAC commands)
|
|
||||||
if(mod->hal->getPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_VERSION_ID) != this->rev)
|
if(mod->hal->getPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_VERSION_ID) != this->rev)
|
||||||
mod->hal->setPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_VERSION_ID, this->rev);
|
mod->hal->setPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_VERSION_ID, this->rev);
|
||||||
|
|
||||||
if(mod->hal->getPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID) != this->devNonce)
|
|
||||||
mod->hal->setPersistentParameter<uint16_t>(RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID, this->devNonce);
|
|
||||||
|
|
||||||
// store all frame counters
|
// store all frame counters
|
||||||
if(mod->hal->getPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID) != this->aFcntDown)
|
if(mod->hal->getPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID) != this->aFcntDown)
|
||||||
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID, this->aFcntDown);
|
mod->hal->setPersistentParameter<uint32_t>(RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID, this->aFcntDown);
|
||||||
|
@ -1436,19 +1453,36 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
|
||||||
RADIOLIB_DEBUG_PRINTLN("fopts:");
|
RADIOLIB_DEBUG_PRINTLN("fopts:");
|
||||||
RADIOLIB_DEBUG_HEXDUMP(fopts, foptsLen);
|
RADIOLIB_DEBUG_HEXDUMP(fopts, foptsLen);
|
||||||
|
|
||||||
|
bool hasADR = false;
|
||||||
|
uint8_t numADR = 0;
|
||||||
|
uint8_t lastCID = 0;
|
||||||
|
|
||||||
// process the MAC command(s)
|
// process the MAC command(s)
|
||||||
int8_t remLen = foptsLen;
|
int8_t remLen = foptsLen;
|
||||||
uint8_t* foptsPtr = fopts;
|
uint8_t* foptsPtr = fopts;
|
||||||
while(remLen > 0) {
|
while(remLen > 0) {
|
||||||
uint8_t cid = *foptsPtr;
|
uint8_t cid = *foptsPtr;
|
||||||
uint8_t macLen = getMacPayloadLength(cid);
|
uint8_t macLen = getMacPayloadLength(cid);
|
||||||
|
if(cid == RADIOLIB_LORAWAN_MAC_LINK_ADR) {
|
||||||
|
// if there was an earlier ADR command but it was not the last, ignore it
|
||||||
|
if(hasADR && lastCID != RADIOLIB_LORAWAN_MAC_LINK_ADR) {
|
||||||
|
RADIOLIB_DEBUG_PRINTLN("Encountered non-consecutive block of ADR commands - skipping");
|
||||||
|
remLen -= (macLen + 1);
|
||||||
|
foptsPtr += (macLen + 1);
|
||||||
|
lastCID = cid;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// otherwise, set ADR flag to true and increase counter
|
||||||
|
hasADR = true;
|
||||||
|
numADR++;
|
||||||
|
}
|
||||||
if(macLen + 1 > remLen)
|
if(macLen + 1 > remLen)
|
||||||
break;
|
break;
|
||||||
LoRaWANMacCommand_t cmd = {
|
LoRaWANMacCommand_t cmd = {
|
||||||
.cid = cid,
|
.cid = cid,
|
||||||
.payload = { 0 },
|
.payload = { 0 },
|
||||||
.len = macLen,
|
.len = macLen,
|
||||||
.repeat = 0,
|
.repeat = (cid == RADIOLIB_LORAWAN_MAC_LINK_ADR ? numADR : (uint8_t)0),
|
||||||
};
|
};
|
||||||
memcpy(cmd.payload, foptsPtr + 1, macLen);
|
memcpy(cmd.payload, foptsPtr + 1, macLen);
|
||||||
RADIOLIB_DEBUG_PRINTLN("[%02X]: %02X %02X %02X %02X %02X (%d)",
|
RADIOLIB_DEBUG_PRINTLN("[%02X]: %02X %02X %02X %02X %02X (%d)",
|
||||||
|
@ -1463,6 +1497,7 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
|
||||||
// processing succeeded, move in the buffer to the next command
|
// processing succeeded, move in the buffer to the next command
|
||||||
remLen -= (macLen + 1);
|
remLen -= (macLen + 1);
|
||||||
foptsPtr += (macLen + 1);
|
foptsPtr += (macLen + 1);
|
||||||
|
lastCID = cid;
|
||||||
RADIOLIB_DEBUG_PRINTLN("Processed: %d, remaining: %d", (macLen + 1), remLen);
|
RADIOLIB_DEBUG_PRINTLN("Processed: %d, remaining: %d", (macLen + 1), remLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1710,6 +1745,11 @@ int16_t LoRaWANNode::setupChannelsDyn(bool joinRequest) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear all remaining channels
|
||||||
|
for(; num < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; num++) {
|
||||||
|
this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][num] = RADIOLIB_LORAWAN_CHANNEL_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
return(RADIOLIB_ERR_NONE);
|
return(RADIOLIB_ERR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1736,6 +1776,8 @@ int16_t LoRaWANNode::setupChannelsFix(uint8_t subBand) {
|
||||||
// chMask is set for 16 channels at once, so widen the Cntl value
|
// chMask is set for 16 channels at once, so widen the Cntl value
|
||||||
uint8_t chMaskCntl = (subBand - 1) / 2; // compensate the 1 offset
|
uint8_t chMaskCntl = (subBand - 1) / 2; // compensate the 1 offset
|
||||||
|
|
||||||
|
uint8_t numADR = 1;
|
||||||
|
|
||||||
LoRaWANMacCommand_t cmd = {
|
LoRaWANMacCommand_t cmd = {
|
||||||
.cid = RADIOLIB_LORAWAN_MAC_LINK_ADR,
|
.cid = RADIOLIB_LORAWAN_MAC_LINK_ADR,
|
||||||
.payload = { 0 },
|
.payload = { 0 },
|
||||||
|
@ -1752,6 +1794,7 @@ int16_t LoRaWANNode::setupChannelsFix(uint8_t subBand) {
|
||||||
cmd.payload[2] = 0;
|
cmd.payload[2] = 0;
|
||||||
cmd.payload[3] = (7 << 4); // set the chMaskCntl value to all channels off
|
cmd.payload[3] = (7 << 4); // set the chMaskCntl value to all channels off
|
||||||
cmd.payload[3] |= 0; // keep NbTrans the same
|
cmd.payload[3] |= 0; // keep NbTrans the same
|
||||||
|
cmd.repeat = numADR++;
|
||||||
(void)execMacCommand(&cmd, false);
|
(void)execMacCommand(&cmd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1770,6 +1813,7 @@ int16_t LoRaWANNode::setupChannelsFix(uint8_t subBand) {
|
||||||
}
|
}
|
||||||
cmd.payload[3] = (chMaskCntl << 4); // set the chMaskCntl value
|
cmd.payload[3] = (chMaskCntl << 4); // set the chMaskCntl value
|
||||||
cmd.payload[3] |= 0; // keep NbTrans the same
|
cmd.payload[3] |= 0; // keep NbTrans the same
|
||||||
|
cmd.repeat = numADR++;
|
||||||
(void)execMacCommand(&cmd, false);
|
(void)execMacCommand(&cmd, false);
|
||||||
|
|
||||||
return(RADIOLIB_ERR_NONE);
|
return(RADIOLIB_ERR_NONE);
|
||||||
|
@ -1821,13 +1865,11 @@ int16_t LoRaWANNode::processCFList(uint8_t* cfList) {
|
||||||
for(size_t chMaskCntl = 0; chMaskCntl < numChMasks; chMaskCntl++) {
|
for(size_t chMaskCntl = 0; chMaskCntl < numChMasks; chMaskCntl++) {
|
||||||
cmd.len = MacTable[RADIOLIB_LORAWAN_MAC_LINK_ADR].lenDn;
|
cmd.len = MacTable[RADIOLIB_LORAWAN_MAC_LINK_ADR].lenDn;
|
||||||
cmd.payload[3] = chMaskCntl << 4; // NbTrans = 0 -> keep the same
|
cmd.payload[3] = chMaskCntl << 4; // NbTrans = 0 -> keep the same
|
||||||
|
cmd.repeat = (chMaskCntl + 1);
|
||||||
memcpy(&cmd.payload[1], &cfList[chMaskCntl*2], 2);
|
memcpy(&cmd.payload[1], &cfList[chMaskCntl*2], 2);
|
||||||
(void)execMacCommand(&cmd);
|
(void)execMacCommand(&cmd);
|
||||||
// save the response as a MAC answer, as this signals execMacCommand() to store the masks contiguously
|
|
||||||
pushMacCommand(&cmd, &this->commandsUp);
|
|
||||||
}
|
}
|
||||||
// delete the ADR response
|
// delete the ADR response
|
||||||
(void)deleteMacCommand(RADIOLIB_LORAWAN_MAC_LINK_ADR, &this->commandsUp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(RADIOLIB_ERR_NONE);
|
return(RADIOLIB_ERR_NONE);
|
||||||
|
@ -1882,7 +1924,7 @@ int16_t LoRaWANNode::setDatarate(uint8_t drUp, bool saveToEeprom) {
|
||||||
for(size_t i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) {
|
for(size_t i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) {
|
||||||
LoRaWANChannel_t *chnl = &(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i]);
|
LoRaWANChannel_t *chnl = &(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i]);
|
||||||
if(chnl->enabled) {
|
if(chnl->enabled) {
|
||||||
if(drUp > chnl->drMin && drUp < chnl->drMax) {
|
if(drUp >= chnl->drMin && drUp <= chnl->drMax) {
|
||||||
isValidDR = true;
|
isValidDR = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1984,7 +2026,7 @@ int16_t LoRaWANNode::setTxPower(int8_t txPower, bool saveToEeprom) {
|
||||||
// Tx Power is set in steps of two
|
// Tx Power is set in steps of two
|
||||||
// the selected value is rounded down to nearest multiple of two away from txPowerMax
|
// the selected value is rounded down to nearest multiple of two away from txPowerMax
|
||||||
// e.g. on EU868, max is 16; if 13 is selected then we set to 12
|
// e.g. on EU868, max is 16; if 13 is selected then we set to 12
|
||||||
uint8_t txPowerNew = (this->txPowerMax - txPower) / 2 + 1;
|
uint8_t numSteps = (this->txPowerMax - txPower + 1) / (-RADIOLIB_LORAWAN_POWER_STEP_SIZE_DBM);
|
||||||
|
|
||||||
LoRaWANMacCommand_t cmd = {
|
LoRaWANMacCommand_t cmd = {
|
||||||
.cid = RADIOLIB_LORAWAN_MAC_LINK_ADR,
|
.cid = RADIOLIB_LORAWAN_MAC_LINK_ADR,
|
||||||
|
@ -1993,7 +2035,7 @@ int16_t LoRaWANNode::setTxPower(int8_t txPower, bool saveToEeprom) {
|
||||||
.repeat = 0,
|
.repeat = 0,
|
||||||
};
|
};
|
||||||
cmd.payload[0] = 0xF0; // keep datarate the same
|
cmd.payload[0] = 0xF0; // keep datarate the same
|
||||||
cmd.payload[0] |= txPowerNew; // set the Tx Power
|
cmd.payload[0] |= numSteps; // set the Tx Power
|
||||||
cmd.payload[3] = (1 << 7); // set the RFU bit, which means that the channel mask gets ignored
|
cmd.payload[3] = (1 << 7); // set the RFU bit, which means that the channel mask gets ignored
|
||||||
cmd.payload[3] |= 0; // keep NbTrans the same
|
cmd.payload[3] |= 0; // keep NbTrans the same
|
||||||
(void)execMacCommand(&cmd, saveToEeprom);
|
(void)execMacCommand(&cmd, saveToEeprom);
|
||||||
|
@ -2204,7 +2246,7 @@ bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSuccessive = false;
|
|
||||||
uint8_t chMaskAck = 1;
|
uint8_t chMaskAck = 1;
|
||||||
// only apply channel mask when the RFU bit is not set
|
// only apply channel mask when the RFU bit is not set
|
||||||
// (which is set on the internal MAC command when creating new session)
|
// (which is set on the internal MAC command when creating new session)
|
||||||
|
@ -2213,13 +2255,17 @@ bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom) {
|
||||||
chMaskAck = (uint8_t)this->applyChannelMaskDyn(chMaskCntl, chMask);
|
chMaskAck = (uint8_t)this->applyChannelMaskDyn(chMaskCntl, chMask);
|
||||||
|
|
||||||
} else { // RADIOLIB_LORAWAN_BAND_FIXED
|
} else { // RADIOLIB_LORAWAN_BAND_FIXED
|
||||||
// if there was already an ADR response in the uplink MAC queue,
|
bool clearChannels = false;
|
||||||
// this is a consecutive ADR command, so we delete the prior response
|
if(cmd->repeat == 1) {
|
||||||
int16_t state = deleteMacCommand(RADIOLIB_LORAWAN_MAC_LINK_ADR, &this->commandsUp);
|
// if this is the first ADR command in the queue, clear all saved channels
|
||||||
if(state == RADIOLIB_ERR_NONE) {
|
// so we can apply the new channel mask
|
||||||
isSuccessive = true;
|
clearChannels = true;
|
||||||
|
RADIOLIB_DEBUG_PRINTLN("ADR mask: clearing channels");
|
||||||
|
} else {
|
||||||
|
// if this is not the first ADR command, clear the ADR response that was in the queue
|
||||||
|
(void)deleteMacCommand(RADIOLIB_LORAWAN_MAC_LINK_ADR, &this->commandsUp);
|
||||||
}
|
}
|
||||||
chMaskAck = (uint8_t)this->applyChannelMaskFix(chMaskCntl, chMask, !isSuccessive);
|
chMaskAck = (uint8_t)this->applyChannelMaskFix(chMaskCntl, chMask, clearChannels);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2238,36 +2284,36 @@ bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom) {
|
||||||
if((cmd->payload[3] >> 7) == 1) {
|
if((cmd->payload[3] >> 7) == 1) {
|
||||||
mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID) + 1, &(cmd->payload[1]), 3);
|
mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID) + 1, &(cmd->payload[1]), 3);
|
||||||
}
|
}
|
||||||
|
// if there was no channel mask (all zeroes), we should never apply that channel mask, so set RFU bit again
|
||||||
|
if(cmd->payload[1] == 0 && cmd->payload[2] == 0) {
|
||||||
|
cmd->payload[3] |= (1 << 7);
|
||||||
|
}
|
||||||
|
|
||||||
// save to the single ADR MAC location
|
// save to the single ADR MAC location
|
||||||
mod->hal->writePersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID), &(cmd->payload[0]), payLen);
|
mod->hal->writePersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID), &(cmd->payload[0]), payLen);
|
||||||
|
|
||||||
} else {
|
} else { // RADIOLIB_LORAWAN_BAND_FIXED
|
||||||
// read how many ADR masks are already stored
|
RADIOLIB_DEBUG_PRINTLN("[1] Repeat: %d, RFU: %d, payload: %02X %02X %02X %02X",
|
||||||
uint8_t numMacADR = mod->hal->getPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID);
|
cmd->repeat, (cmd->payload[3] >> 7),
|
||||||
RADIOLIB_DEBUG_PRINTLN("[1] Successive: %d, numMacADR: %d, RFU: %d, payload: %02X %02X %02X %02X",
|
|
||||||
isSuccessive, numMacADR, (cmd->payload[3] >> 7),
|
|
||||||
cmd->payload[0], cmd->payload[1], cmd->payload[2], cmd->payload[3]);
|
cmd->payload[0], cmd->payload[1], cmd->payload[2], cmd->payload[3]);
|
||||||
// if RFU bit is set, this is just a change in Datarate or TxPower
|
// if RFU bit is set, this is just a change in Datarate or TxPower
|
||||||
// so read bytes 1..3 from last stored ADR command into the current MAC payload and re-store it
|
// so read bytes 1..3 from last stored ADR command into the current MAC payload and re-store it
|
||||||
if((cmd->payload[3] >> 7) == 1) {
|
if((cmd->payload[3] >> 7) == 1) {
|
||||||
|
// read how many ADR masks are already stored
|
||||||
|
uint8_t numMacADR = mod->hal->getPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID);
|
||||||
if(numMacADR > 0) {
|
if(numMacADR > 0) {
|
||||||
mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID) + (numMacADR - 1) * payLen + 1, &(cmd->payload[1]), 3);
|
mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID) + (numMacADR - 1) * payLen + 1, &(cmd->payload[1]), 3);
|
||||||
mod->hal->writePersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID) + (numMacADR - 1) * payLen, &(cmd->payload[0]), payLen);
|
mod->hal->writePersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID) + (numMacADR - 1) * payLen, &(cmd->payload[0]), payLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if no previous mask was processed, reset counter to 0
|
// save to the uplink channel location, to the cmd->repeat-th slot of 4 bytes
|
||||||
if(!isSuccessive) {
|
mod->hal->writePersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID) + (cmd->repeat - 1) * payLen, &(cmd->payload[0]), payLen);
|
||||||
numMacADR = 0;
|
// saved an ADR mask, so re-store counter
|
||||||
|
mod->hal->setPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID, cmd->repeat);
|
||||||
}
|
}
|
||||||
// save to the uplink channel location, to the numMacADR-th slot of 4 bytes
|
RADIOLIB_DEBUG_PRINTLN("[2] Repeat: %d, RFU: %d, payload: %02X %02X %02X %02X",
|
||||||
mod->hal->writePersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID) + numMacADR * payLen, &(cmd->payload[0]), payLen);
|
cmd->repeat, (cmd->payload[3] >> 7),
|
||||||
// saved an ADR mask, so increase counter
|
|
||||||
mod->hal->setPersistentParameter<uint8_t>(RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID, numMacADR + 1);
|
|
||||||
}
|
|
||||||
RADIOLIB_DEBUG_PRINTLN("[2] Successive: %d, numMacADR: %d, RFU: %d, payload: %02X %02X %02X %02X",
|
|
||||||
isSuccessive, numMacADR, (cmd->payload[3] >> 7),
|
|
||||||
cmd->payload[0], cmd->payload[1], cmd->payload[2], cmd->payload[3]);
|
cmd->payload[0], cmd->payload[1], cmd->payload[2], cmd->payload[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2276,6 +2322,7 @@ bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom) {
|
||||||
// send the reply
|
// send the reply
|
||||||
cmd->len = 1;
|
cmd->len = 1;
|
||||||
cmd->payload[0] = (pwrAck << 2) | (drAck << 1) | (chMaskAck << 0);
|
cmd->payload[0] = (pwrAck << 2) | (drAck << 1) | (chMaskAck << 0);
|
||||||
|
cmd->repeat = 0; // discard any repeat value that may have been set
|
||||||
RADIOLIB_DEBUG_PRINTLN("ADR ANS: status = 0x%02x", cmd->payload[0]);
|
RADIOLIB_DEBUG_PRINTLN("ADR ANS: status = 0x%02x", cmd->payload[0]);
|
||||||
return(true);
|
return(true);
|
||||||
} break;
|
} break;
|
||||||
|
|
Loading…
Add table
Reference in a new issue