[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 "LoRaWAN.h"
|
||||||
#include "LoRaWANBands.cpp"
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if !defined(RADIOLIB_EXCLUDE_LORAWAN)
|
#if !defined(RADIOLIB_EXCLUDE_LORAWAN)
|
||||||
|
@ -19,6 +18,16 @@ static void LoRaWANNodeOnDownlinkAction(void) {
|
||||||
downlinkAction = true;
|
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) {
|
LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band) {
|
||||||
this->phyLayer = phy;
|
this->phyLayer = phy;
|
||||||
this->band = band;
|
this->band = band;
|
||||||
|
@ -29,18 +38,18 @@ LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band) {
|
||||||
this->enableCSMA = false;
|
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) {
|
void LoRaWANNode::setCSMA(uint8_t backoffMax, uint8_t difsSlots, bool enableCSMA) {
|
||||||
this->backoffMax = backoffMax;
|
this->backoffMax = backoffMax;
|
||||||
this->difsSlots = difsSlots;
|
this->difsSlots = difsSlots;
|
||||||
this->enableCSMA = enableCSMA;
|
this->enableCSMA = enableCSMA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||||
|
void LoRaWANNode::wipe() {
|
||||||
|
Module* mod = this->phyLayer->getMod();
|
||||||
|
mod->hal->wipePersistentStorage();
|
||||||
|
}
|
||||||
|
|
||||||
int16_t LoRaWANNode::restore() {
|
int16_t LoRaWANNode::restore() {
|
||||||
// check the magic value
|
// check the magic value
|
||||||
Module* mod = this->phyLayer->getMod();
|
Module* mod = this->phyLayer->getMod();
|
||||||
|
@ -375,7 +384,6 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
|
||||||
// 1.0 version, just derive the keys
|
// 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<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);
|
LoRaWANNode::hton<uint16_t>(&keyDerivationBuff[RADIOLIB_LORAWAN_JOIN_ACCEPT_DEV_ADDR_POS], this->devNonce);
|
||||||
|
|
||||||
keyDerivationBuff[0] = RADIOLIB_LORAWAN_JOIN_ACCEPT_APP_S_KEY;
|
keyDerivationBuff[0] = RADIOLIB_LORAWAN_JOIN_ACCEPT_APP_S_KEY;
|
||||||
RadioLibAES128Instance.init(nwkKey);
|
RadioLibAES128Instance.init(nwkKey);
|
||||||
RadioLibAES128Instance.encryptECB(keyDerivationBuff, RADIOLIB_AES128_BLOCK_SIZE, this->appSKey);
|
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;
|
this->isMACPayload = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// check if there are some MAC commands to piggyback (only when piggybacking onto a application-frame)
|
// check if there are some MAC commands to piggyback (only when piggybacking onto a application-frame)
|
||||||
uint8_t foptsLen = 0;
|
uint8_t foptsLen = 0;
|
||||||
size_t foptsBufSize = 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
|
// encrypt the frame payload
|
||||||
processAES(data, len, encKey, &uplinkMsg[RADIOLIB_LORAWAN_FRAME_PAYLOAD_POS(foptsLen)], this->fcntUp, RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK, 0x00, true);
|
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
|
// create blocks for MIC calculation
|
||||||
uint8_t block0[RADIOLIB_AES128_BLOCK_SIZE] = { 0 };
|
uint8_t block0[RADIOLIB_AES128_BLOCK_SIZE] = { 0 };
|
||||||
block0[RADIOLIB_LORAWAN_BLOCK_MAGIC_POS] = RADIOLIB_LORAWAN_MIC_BLOCK_MAGIC;
|
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);
|
LoRaWANNode::hton<uint32_t>(&uplinkMsg[uplinkMsgLen - sizeof(uint32_t)], micF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RADIOLIB_DEBUG_PRINTLN("uplinkMsg:");
|
||||||
|
RADIOLIB_DEBUG_HEXDUMP(uplinkMsg, uplinkMsgLen);
|
||||||
|
|
||||||
// perform CSMA if enabled.
|
// perform CSMA if enabled.
|
||||||
if (enableCSMA) {
|
if (enableCSMA) {
|
||||||
performCSMA();
|
performCSMA();
|
||||||
}
|
}
|
||||||
|
|
||||||
RADIOLIB_DEBUG_PRINTLN("uplinkMsg:");
|
|
||||||
RADIOLIB_DEBUG_HEXDUMP(uplinkMsg, uplinkMsgLen);
|
|
||||||
|
|
||||||
// send it (without the MIC calculation blocks)
|
// 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);
|
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);
|
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) {
|
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
|
// figure out how many encryption blocks are there
|
||||||
size_t numBlocks = len/RADIOLIB_AES128_BLOCK_SIZE;
|
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,9 +338,11 @@ class LoRaWANNode {
|
||||||
// RX2 channel properties - may be changed by MAC command
|
// RX2 channel properties - may be changed by MAC command
|
||||||
LoRaWANChannel_t rx2;
|
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
|
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;
|
uint8_t backoffMax;
|
||||||
|
|
||||||
/*! \brief Num of CADs to estimate a clear CH. */
|
/*! \brief Num of CADs to estimate a clear CH. */
|
||||||
|
@ -370,14 +372,6 @@ class LoRaWANNode {
|
||||||
int16_t restore();
|
int16_t restore();
|
||||||
#endif
|
#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,
|
\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.
|
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);
|
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)
|
#if !defined(RADIOLIB_GODMODE)
|
||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
|
@ -628,6 +630,12 @@ class LoRaWANNode {
|
||||||
// execute mac command, return the number of processed bytes for sequential processing
|
// execute mac command, return the number of processed bytes for sequential processing
|
||||||
size_t execMacCommand(LoRaWANMacCommand_t* cmd);
|
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
|
// 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);
|
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
|
// host-to-network conversion method - takes data from host variable and and converts it to network packet endians
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void hton(uint8_t* buff, T val, size_t size = 0);
|
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
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue