[LoRaWAN] fix include logic
This commit is contained in:
parent
60f50e0a04
commit
ccb28f3b7b
2 changed files with 85 additions and 81 deletions
|
@ -1,5 +1,4 @@
|
|||
#include "LoRaWAN.h"
|
||||
#include "LoRaWANBands.cpp"
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(RADIOLIB_EXCLUDE_LORAWAN)
|
||||
|
@ -19,6 +18,16 @@ static void LoRaWANNodeOnDownlinkAction(void) {
|
|||
downlinkAction = true;
|
||||
}
|
||||
|
||||
uint8_t getDownlinkDataRate(uint8_t uplink, uint8_t offset, uint8_t base, uint8_t min, uint8_t max) {
|
||||
int8_t dr = uplink - offset + base;
|
||||
if(dr < min) {
|
||||
dr = min;
|
||||
} else if (dr > max) {
|
||||
dr = max;
|
||||
}
|
||||
return(dr);
|
||||
}
|
||||
|
||||
LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band) {
|
||||
this->phyLayer = phy;
|
||||
this->band = band;
|
||||
|
@ -29,18 +38,18 @@ LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band) {
|
|||
this->enableCSMA = false;
|
||||
}
|
||||
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
void LoRaWANNode::wipe() {
|
||||
Module* mod = this->phyLayer->getMod();
|
||||
mod->hal->wipePersistentStorage();
|
||||
}
|
||||
|
||||
void LoRaWANNode::setCSMA(uint8_t backoffMax, uint8_t difsSlots, bool enableCSMA) {
|
||||
this->backoffMax = backoffMax;
|
||||
this->difsSlots = difsSlots;
|
||||
this->enableCSMA = enableCSMA;
|
||||
}
|
||||
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
void LoRaWANNode::wipe() {
|
||||
Module* mod = this->phyLayer->getMod();
|
||||
mod->hal->wipePersistentStorage();
|
||||
}
|
||||
|
||||
int16_t LoRaWANNode::restore() {
|
||||
// check the magic value
|
||||
Module* mod = this->phyLayer->getMod();
|
||||
|
@ -314,7 +323,7 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// parse other contents
|
||||
this->homeNetId = LoRaWANNode::ntoh<uint32_t>(&joinAcceptMsg[RADIOLIB_LORAWAN_JOIN_ACCEPT_HOME_NET_ID_POS], 3);
|
||||
this->devAddr = LoRaWANNode::ntoh<uint32_t>(&joinAcceptMsg[RADIOLIB_LORAWAN_JOIN_ACCEPT_DEV_ADDR_POS]);
|
||||
|
@ -375,7 +384,6 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
|
|||
// 1.0 version, just derive the keys
|
||||
LoRaWANNode::hton<uint32_t>(&keyDerivationBuff[RADIOLIB_LORAWAN_JOIN_ACCEPT_HOME_NET_ID_POS], this->homeNetId, 3);
|
||||
LoRaWANNode::hton<uint16_t>(&keyDerivationBuff[RADIOLIB_LORAWAN_JOIN_ACCEPT_DEV_ADDR_POS], this->devNonce);
|
||||
|
||||
keyDerivationBuff[0] = RADIOLIB_LORAWAN_JOIN_ACCEPT_APP_S_KEY;
|
||||
RadioLibAES128Instance.init(nwkKey);
|
||||
RadioLibAES128Instance.encryptECB(keyDerivationBuff, RADIOLIB_AES128_BLOCK_SIZE, this->appSKey);
|
||||
|
@ -656,7 +664,6 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
|
|||
this->isMACPayload = false;
|
||||
}
|
||||
|
||||
|
||||
// check if there are some MAC commands to piggyback (only when piggybacking onto a application-frame)
|
||||
uint8_t foptsLen = 0;
|
||||
size_t foptsBufSize = 0;
|
||||
|
@ -804,7 +811,6 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
|
|||
// encrypt the frame payload
|
||||
processAES(data, len, encKey, &uplinkMsg[RADIOLIB_LORAWAN_FRAME_PAYLOAD_POS(foptsLen)], this->fcntUp, RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK, 0x00, true);
|
||||
|
||||
|
||||
// create blocks for MIC calculation
|
||||
uint8_t block0[RADIOLIB_AES128_BLOCK_SIZE] = { 0 };
|
||||
block0[RADIOLIB_LORAWAN_BLOCK_MAGIC_POS] = RADIOLIB_LORAWAN_MIC_BLOCK_MAGIC;
|
||||
|
@ -838,14 +844,14 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
|
|||
LoRaWANNode::hton<uint32_t>(&uplinkMsg[uplinkMsgLen - sizeof(uint32_t)], micF);
|
||||
}
|
||||
|
||||
RADIOLIB_DEBUG_PRINTLN("uplinkMsg:");
|
||||
RADIOLIB_DEBUG_HEXDUMP(uplinkMsg, uplinkMsgLen);
|
||||
|
||||
// perform CSMA if enabled.
|
||||
if (enableCSMA) {
|
||||
performCSMA();
|
||||
}
|
||||
|
||||
RADIOLIB_DEBUG_PRINTLN("uplinkMsg:");
|
||||
RADIOLIB_DEBUG_HEXDUMP(uplinkMsg, uplinkMsgLen);
|
||||
|
||||
// send it (without the MIC calculation blocks)
|
||||
state = this->phyLayer->transmit(&uplinkMsg[RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS], uplinkMsgLen - RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS);
|
||||
|
||||
|
@ -2009,6 +2015,50 @@ size_t LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd) {
|
|||
return(0);
|
||||
}
|
||||
|
||||
// The following function enables LMAC, a CSMA scheme for LoRa as specified
|
||||
// in the LoRa Alliance Technical Recommendation #13.
|
||||
// A user may enable CSMA to provide frames an additional layer of protection from interference.
|
||||
// https://resources.lora-alliance.org/technical-recommendations/tr013-1-0-0-csma
|
||||
void LoRaWANNode::performCSMA() {
|
||||
|
||||
// Compute initial random back-off.
|
||||
// When BO is reduced to zero, the function returns and the frame is transmitted.
|
||||
uint32_t BO = this->phyLayer->random(1, this->backoffMax + 1);
|
||||
while (BO > 0) {
|
||||
// DIFS: Check channel for DIFS_slots
|
||||
bool channelFreeDuringDIFS = true;
|
||||
for (uint8_t i = 0; i < this->difsSlots; i++) {
|
||||
if (performCAD()) {
|
||||
RADIOLIB_DEBUG_PRINTLN("OCCUPIED CHANNEL DURING DIFS");
|
||||
channelFreeDuringDIFS = false;
|
||||
// Channel is occupied during DIFS, hop to another.
|
||||
this->selectChannels();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Start reducing BO counter if DIFS slot was free.
|
||||
if (channelFreeDuringDIFS) {
|
||||
// Continue decrementing BO with per each CAD reporting free channel.
|
||||
while (BO > 0) {
|
||||
if (performCAD()) {
|
||||
RADIOLIB_DEBUG_PRINTLN("OCCUPIED CHANNEL DURING BO");
|
||||
// Channel is busy during CAD, hop to another and return to DIFS state again.
|
||||
this->selectChannels();
|
||||
break; // Exit loop. Go back to DIFS state.
|
||||
}
|
||||
BO--; // Decrement BO by one if channel is free
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool LoRaWANNode::performCAD() {
|
||||
int16_t state = this->phyLayer->scanChannel();
|
||||
if ((state == RADIOLIB_PREAMBLE_DETECTED) || (state == RADIOLIB_LORA_DETECTED)) {
|
||||
return true; // Channel is busy
|
||||
}
|
||||
return false; // Channel is free
|
||||
}
|
||||
|
||||
void LoRaWANNode::processAES(uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fcnt, uint8_t dir, uint8_t ctrId, bool counter) {
|
||||
// figure out how many encryption blocks are there
|
||||
size_t numBlocks = len/RADIOLIB_AES128_BLOCK_SIZE;
|
||||
|
@ -2076,52 +2126,4 @@ void LoRaWANNode::hton(uint8_t* buff, T val, size_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
// The following function enables LMAC, a CSMA scheme for LoRa as specified
|
||||
// in the LoRa Alliance Technical Recommendation #13.
|
||||
// A user may enable CSMA to provide frames an additional layer of protection from interference.
|
||||
// https://resources.lora-alliance.org/technical-recommendations/tr013-1-0-0-csma
|
||||
void LoRaWANNode::performCSMA() {
|
||||
|
||||
// Compute initial random back-off.
|
||||
// When BO is reduced to zero, the function returns and the frame is transmitted.
|
||||
uint32_t BO = this->phyLayer->random(1, this->backoffMax + 1);
|
||||
|
||||
while (BO > 0) {
|
||||
// DIFS: Check channel for DIFS_slots
|
||||
bool channelFreeDuringDIFS = true;
|
||||
for (uint8_t i = 0; i < this->difsSlots; i++) {
|
||||
if (performCAD()) {
|
||||
RADIOLIB_DEBUG_PRINTLN("OCCUPIED CHANNEL DURING DIFS");
|
||||
channelFreeDuringDIFS = false;
|
||||
// Channel is occupied during DIFS, hop to another.
|
||||
this->selectChannels();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Start reducing BO counter if DIFS slot was free.
|
||||
if (channelFreeDuringDIFS) {
|
||||
// Continue decrementing BO with per each CAD reporting free channel.
|
||||
while (BO > 0) {
|
||||
if (performCAD()) {
|
||||
RADIOLIB_DEBUG_PRINTLN("OCCUPIED CHANNEL DURING BO");
|
||||
// Channel is busy during CAD, hop to another and return to DIFS state again.
|
||||
this->selectChannels();
|
||||
break; // Exit loop. Go back to DIFS state.
|
||||
}
|
||||
BO--; // Decrement BO by one if channel is free
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LoRaWANNode::performCAD() {
|
||||
int16_t state = this->phyLayer->scanChannel();
|
||||
|
||||
if ((state == RADIOLIB_PREAMBLE_DETECTED) || (state == RADIOLIB_LORA_DETECTED)) {
|
||||
return true; // Channel is busy
|
||||
}
|
||||
return false; // Channel is free
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -338,14 +338,16 @@ class LoRaWANNode {
|
|||
// RX2 channel properties - may be changed by MAC command
|
||||
LoRaWANChannel_t rx2;
|
||||
|
||||
/*! \brief Num of Back Off(BO) slots to be decremented after DIFS phase. 0 to disable BO.
|
||||
/*!
|
||||
\brief Num of Back Off(BO) slots to be decremented after DIFS phase. 0 to disable BO.
|
||||
A random BO avoids collisions in the case where two or more nodes start the CSMA
|
||||
process at the same time. */
|
||||
process at the same time.
|
||||
*/
|
||||
uint8_t backoffMax;
|
||||
|
||||
|
||||
/*! \brief Num of CADs to estimate a clear CH. */
|
||||
uint8_t difsSlots;
|
||||
|
||||
|
||||
/*! \brief enable/disable CSMA for LoRaWAN. */
|
||||
bool enableCSMA;
|
||||
|
||||
|
@ -370,14 +372,6 @@ class LoRaWANNode {
|
|||
int16_t restore();
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Configures CSMA for LoRaWAN as per TR-13, LoRa Alliance.
|
||||
\param backoffMax Num of BO slots to be decremented after DIFS phase. 0 to disable BO.
|
||||
\param difsSlots Num of CADs to estimate a clear CH.
|
||||
\param enableCSMA enable/disable CSMA for LoRaWAN.
|
||||
*/
|
||||
void setCSMA(uint8_t backoffMax, uint8_t difsSlots, bool enableCSMA = false);
|
||||
|
||||
/*!
|
||||
\brief Join network by performing over-the-air activation. By this procedure,
|
||||
the device will perform an exchange with the network server and set all necessary configuration.
|
||||
|
@ -500,6 +494,14 @@ class LoRaWANNode {
|
|||
*/
|
||||
int16_t selectSubband(uint8_t startChannel, uint8_t endChannel);
|
||||
|
||||
/*!
|
||||
\brief Configures CSMA for LoRaWAN as per TR-13, LoRa Alliance.
|
||||
\param backoffMax Num of BO slots to be decremented after DIFS phase. 0 to disable BO.
|
||||
\param difsSlots Num of CADs to estimate a clear CH.
|
||||
\param enableCSMA enable/disable CSMA for LoRaWAN.
|
||||
*/
|
||||
void setCSMA(uint8_t backoffMax, uint8_t difsSlots, bool enableCSMA = false);
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
@ -627,6 +629,12 @@ class LoRaWANNode {
|
|||
|
||||
// execute mac command, return the number of processed bytes for sequential processing
|
||||
size_t execMacCommand(LoRaWANMacCommand_t* cmd);
|
||||
|
||||
// Performs CSMA as per LoRa Alliance Technical Reccomendation 13 (TR-013).
|
||||
void performCSMA();
|
||||
|
||||
// perform a single CAD operation for the under SF/CH combination. Returns either busy or otherwise.
|
||||
bool performCAD();
|
||||
|
||||
// function to encrypt and decrypt payloads
|
||||
void processAES(uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fcnt, uint8_t dir, uint8_t ctrId, bool counter);
|
||||
|
@ -638,12 +646,6 @@ class LoRaWANNode {
|
|||
// host-to-network conversion method - takes data from host variable and and converts it to network packet endians
|
||||
template<typename T>
|
||||
static void hton(uint8_t* buff, T val, size_t size = 0);
|
||||
|
||||
// perform a single CAD operation for the under SF/CH combination. Returns either busy or otherwise.
|
||||
bool performCAD();
|
||||
|
||||
// Performs CSMA as per LoRa Alliance Technical Reccomendation 13 (TR-013).
|
||||
void performCSMA();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue