[LoRaWAN] Consistent fCnt/fPort casing to match documents

This commit is contained in:
StevenCellist 2024-05-04 23:18:36 +02:00
parent 43adfee174
commit 163a4020d2
6 changed files with 160 additions and 160 deletions

View file

@ -42,7 +42,7 @@ void setup() {
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true); debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
Serial.println(F("Initialise LoRaWAN Network credentials")); Serial.println(F("Initialise LoRaWAN Network credentials"));
state = node.beginABP(devAddr, NwkSEncKey, AppSKey, NwkSKey, SNwkSIntKey, true); state = node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey, true);
debug(state < RADIOLIB_ERR_NONE, F("Session setup failed"), state, true); debug(state < RADIOLIB_ERR_NONE, F("Session setup failed"), state, true);
Serial.println(F("Ready!\n")); Serial.println(F("Ready!\n"));

View file

@ -118,10 +118,10 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
// copy over the keys in to the something that will not compile if incorrectly formatted // copy over the keys in to the something that will not compile if incorrectly formatted
uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR; uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR;
uint8_t NwkSKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY }; uint8_t fNwkSIntKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY };
uint8_t SNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY }; // Previously sNwkSIntKey uint8_t sNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY };
uint8_t NwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY }; // Previously fNwkSIntKey uint8_t nwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY };
uint8_t AppSKey[] = { RADIOLIB_LORAWAN_APPS_KEY }; uint8_t appSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
// create the LoRaWAN node // create the LoRaWAN node
LoRaWANNode node(&radio, &Region, subBand); LoRaWANNode node(&radio, &Region, subBand);

View file

@ -105,7 +105,7 @@ void loop() {
uint8_t Port = 10; uint8_t Port = 10;
// Retrieve the last uplink frame counter // Retrieve the last uplink frame counter
uint32_t fcntUp = node.getFcntUp(); uint32_t fcntUp = node.getFCntUp();
// Send a confirmed uplink every 64th frame // Send a confirmed uplink every 64th frame
// and also request the LinkCheck and DeviceTime MAC commands // and also request the LinkCheck and DeviceTime MAC commands
@ -159,9 +159,9 @@ void loop() {
Serial.print(downlinkDetails.power); Serial.print(downlinkDetails.power);
Serial.println(F(" dBm")); Serial.println(F(" dBm"));
Serial.print(F("[LoRaWAN] Frame count:\t")); Serial.print(F("[LoRaWAN] Frame count:\t"));
Serial.println(downlinkDetails.fcnt); Serial.println(downlinkDetails.fCnt);
Serial.print(F("[LoRaWAN] Port:\t\t")); Serial.print(F("[LoRaWAN] Port:\t\t"));
Serial.println(downlinkDetails.port); Serial.println(downlinkDetails.fPort);
uint8_t margin = 0; uint8_t margin = 0;
uint8_t gwCnt = 0; uint8_t gwCnt = 0;

View file

@ -317,10 +317,10 @@ uplink KEYWORD2
downlink KEYWORD2 downlink KEYWORD2
sendReceive KEYWORD2 sendReceive KEYWORD2
setDeviceStatus KEYWORD2 setDeviceStatus KEYWORD2
getFcntUp KEYWORD2 getFCntUp KEYWORD2
getNFcntDown KEYWORD2 getNFCntDown KEYWORD2
getAFcntDown KEYWORD2 getAFCntDown KEYWORD2
resetFcntDown KEYWORD2 resetFCntDown KEYWORD2
setDatarate KEYWORD2 setDatarate KEYWORD2
setADR KEYWORD2 setADR KEYWORD2
setDutyCycle KEYWORD2 setDutyCycle KEYWORD2

View file

@ -176,12 +176,12 @@ int16_t LoRaWANNode::restore(uint16_t checkSum, uint16_t lwMode, uint8_t lwClass
this->rev = LoRaWANNode::ntoh<uint8_t>(&this->bufferSession[RADIOLIB_LW_SESSION_VERSION]); this->rev = LoRaWANNode::ntoh<uint8_t>(&this->bufferSession[RADIOLIB_LW_SESSION_VERSION]);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("LoRaWAN session: v1.%d", this->rev); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("LoRaWAN session: v1.%d", this->rev);
this->homeNetId = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_HOMENET_ID]); this->homeNetId = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_HOMENET_ID]);
this->aFcntDown = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_A_FCNT_DOWN]); this->aFCntDown = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_A_FCNT_DOWN]);
this->nFcntDown = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_N_FCNT_DOWN]); this->nFCntDown = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_N_FCNT_DOWN]);
this->confFcntUp = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_UP]); this->confFCntUp = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_UP]);
this->confFcntDown = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_DOWN]); this->confFCntDown = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_DOWN]);
this->adrFcnt = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_ADR_FCNT]); this->adrFCnt = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_ADR_FCNT]);
this->fcntUp = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_FCNT_UP]); this->fCntUp = LoRaWANNode::ntoh<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_FCNT_UP]);
int16_t state = RADIOLIB_ERR_UNKNOWN; int16_t state = RADIOLIB_ERR_UNKNOWN;
@ -700,12 +700,12 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
} }
// reset all frame counters // reset all frame counters
this->fcntUp = 0; this->fCntUp = 0;
this->aFcntDown = 0; this->aFCntDown = 0;
this->nFcntDown = 0; this->nFCntDown = 0;
this->confFcntUp = RADIOLIB_LW_FCNT_NONE; this->confFCntUp = RADIOLIB_LW_FCNT_NONE;
this->confFcntDown = RADIOLIB_LW_FCNT_NONE; this->confFCntDown = RADIOLIB_LW_FCNT_NONE;
this->adrFcnt = 0; this->adrFCnt = 0;
// save the activation keys checksum, device address & keys as well as JoinAccept values; these are only ever set when joining // save the activation keys checksum, device address & keys as well as JoinAccept values; these are only ever set when joining
LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LW_NONCES_VERSION], RADIOLIB_LW_NONCES_VERSION_VAL); LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LW_NONCES_VERSION], RADIOLIB_LW_NONCES_VERSION_VAL);
@ -778,12 +778,12 @@ int16_t LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwk
this->beginCommon(initialDr); this->beginCommon(initialDr);
// reset all frame counters // reset all frame counters
this->fcntUp = 0; this->fCntUp = 0;
this->aFcntDown = 0; this->aFCntDown = 0;
this->nFcntDown = 0; this->nFCntDown = 0;
this->confFcntUp = RADIOLIB_LW_FCNT_NONE; this->confFCntUp = RADIOLIB_LW_FCNT_NONE;
this->confFcntDown = RADIOLIB_LW_FCNT_NONE; this->confFCntDown = RADIOLIB_LW_FCNT_NONE;
this->adrFcnt = 0; this->adrFCnt = 0;
// save the activation keys checksum, mode, class, frequency plan // save the activation keys checksum, mode, class, frequency plan
LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LW_NONCES_VERSION], RADIOLIB_LW_NONCES_VERSION_VAL); LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LW_NONCES_VERSION], RADIOLIB_LW_NONCES_VERSION_VAL);
@ -823,12 +823,12 @@ int16_t LoRaWANNode::saveSession() {
LoRaWANNode::hton<uint8_t>(&this->bufferSession[RADIOLIB_LW_SESSION_VERSION], this->rev); LoRaWANNode::hton<uint8_t>(&this->bufferSession[RADIOLIB_LW_SESSION_VERSION], this->rev);
// store all frame counters // store all frame counters
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_A_FCNT_DOWN], this->aFcntDown); LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_A_FCNT_DOWN], this->aFCntDown);
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_N_FCNT_DOWN], this->nFcntDown); LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_N_FCNT_DOWN], this->nFCntDown);
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_UP], this->confFcntUp); LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_UP], this->confFCntUp);
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_DOWN], this->confFcntDown); LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_CONF_FCNT_DOWN], this->confFCntDown);
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_ADR_FCNT], this->adrFcnt); LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_ADR_FCNT], this->adrFCnt);
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_FCNT_UP], this->fcntUp); LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LW_SESSION_FCNT_UP], this->fCntUp);
// save the current uplink MAC command queue // save the current uplink MAC command queue
memcpy(&this->bufferSession[RADIOLIB_LW_SESSION_MAC_QUEUE_UL], &this->commandsUp, sizeof(LoRaWANMacCommandQueue_t)); memcpy(&this->bufferSession[RADIOLIB_LW_SESSION_MAC_QUEUE_UL], &this->commandsUp, sizeof(LoRaWANMacCommandQueue_t));
@ -841,16 +841,16 @@ int16_t LoRaWANNode::saveSession() {
} }
#if defined(RADIOLIB_BUILD_ARDUINO) #if defined(RADIOLIB_BUILD_ARDUINO)
int16_t LoRaWANNode::uplink(String& str, uint8_t port, bool isConfirmed, LoRaWANEvent_t* event) { int16_t LoRaWANNode::uplink(String& str, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* event) {
return(this->uplink(str.c_str(), port, isConfirmed, event)); return(this->uplink(str.c_str(), fPort, isConfirmed, event));
} }
#endif #endif
int16_t LoRaWANNode::uplink(const char* str, uint8_t port, bool isConfirmed, LoRaWANEvent_t* event) { int16_t LoRaWANNode::uplink(const char* str, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* event) {
return(this->uplink((uint8_t*)str, strlen(str), port, isConfirmed, event)); return(this->uplink((uint8_t*)str, strlen(str), fPort, isConfirmed, event));
} }
int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConfirmed, LoRaWANEvent_t* event) { int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* event) {
// if not joined, don't do anything // if not joined, don't do anything
if(!this->isJoined()) { if(!this->isJoined()) {
return(RADIOLIB_ERR_NETWORK_NOT_JOINED); return(RADIOLIB_ERR_NETWORK_NOT_JOINED);
@ -870,12 +870,12 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
return(RADIOLIB_ERR_UPLINK_UNAVAILABLE); return(RADIOLIB_ERR_UPLINK_UNAVAILABLE);
} }
// check destination port // check destination fPort
if(port > 0xDF) { if(fPort > 0xDF) {
return(RADIOLIB_ERR_INVALID_PORT); return(RADIOLIB_ERR_INVALID_PORT);
} }
// port 0 is only allowed for MAC-only payloads // fPort 0 is only allowed for MAC-only payloads
if(port == RADIOLIB_LW_FPORT_MAC_COMMAND) { if(fPort == RADIOLIB_LW_FPORT_MAC_COMMAND) {
if (!this->isMACPayload) { if (!this->isMACPayload) {
return(RADIOLIB_ERR_INVALID_PORT); return(RADIOLIB_ERR_INVALID_PORT);
} }
@ -887,7 +887,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
// 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;
if(this->commandsUp.numCommands > 0 && port != RADIOLIB_LW_FPORT_MAC_COMMAND) { if(this->commandsUp.numCommands > 0 && fPort != RADIOLIB_LW_FPORT_MAC_COMMAND) {
// there are, assume the maximum possible FOpts len for buffer allocation // there are, assume the maximum possible FOpts len for buffer allocation
foptsLen = this->commandsUp.len; foptsLen = this->commandsUp.len;
} }
@ -904,12 +904,12 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
// check if we need to do ADR stuff // check if we need to do ADR stuff
uint32_t adrLimit = 0x01 << this->adrLimitExp; uint32_t adrLimit = 0x01 << this->adrLimitExp;
uint32_t adrDelay = 0x01 << this->adrDelayExp; uint32_t adrDelay = 0x01 << this->adrDelayExp;
if((this->fcntUp - this->adrFcnt) >= adrLimit) { if((this->fCntUp - this->adrFCnt) >= adrLimit) {
adrAckReq = true; adrAckReq = true;
} }
// if we hit the Limit + Delay, try one of three, in order: // if we hit the Limit + Delay, try one of three, in order:
// set TxPower to max, set DR to min, enable all default channels // set TxPower to max, set DR to min, enable all default channels
if ((this->fcntUp - this->adrFcnt) == (adrLimit + adrDelay)) { if ((this->fCntUp - this->adrFCnt) == (adrLimit + adrDelay)) {
uint8_t adrStage = 1; uint8_t adrStage = 1;
while(adrStage != 0) { while(adrStage != 0) {
switch(adrStage) { switch(adrStage) {
@ -955,7 +955,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
} }
// we tried something to improve the range, so increase the ADR frame counter by 'ADR delay' // we tried something to improve the range, so increase the ADR frame counter by 'ADR delay'
this->adrFcnt += adrDelay; this->adrFCnt += adrDelay;
} }
} }
@ -981,7 +981,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
// set the packet fields // set the packet fields
if(isConfirmed) { if(isConfirmed) {
uplinkMsg[RADIOLIB_LW_FHDR_LEN_START_OFFS] = RADIOLIB_LW_MHDR_MTYPE_CONF_DATA_UP; uplinkMsg[RADIOLIB_LW_FHDR_LEN_START_OFFS] = RADIOLIB_LW_MHDR_MTYPE_CONF_DATA_UP;
this->confFcntUp = this->fcntUp; this->confFCntUp = this->fCntUp;
} else { } else {
uplinkMsg[RADIOLIB_LW_FHDR_LEN_START_OFFS] = RADIOLIB_LW_MHDR_MTYPE_UNCONF_DATA_UP; uplinkMsg[RADIOLIB_LW_FHDR_LEN_START_OFFS] = RADIOLIB_LW_MHDR_MTYPE_UNCONF_DATA_UP;
} }
@ -997,14 +997,14 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
} }
} }
// if the saved confirm-fcnt is set, set the ACK bit // if the saved confirm-fCnt is set, set the ACK bit
bool isConfirmingDown = false; bool isConfirmingDown = false;
if(this->confFcntDown != RADIOLIB_LW_FCNT_NONE) { if(this->confFCntDown != RADIOLIB_LW_FCNT_NONE) {
isConfirmingDown = true; isConfirmingDown = true;
uplinkMsg[RADIOLIB_LW_FHDR_FCTRL_POS] |= RADIOLIB_LW_FCTRL_ACK; uplinkMsg[RADIOLIB_LW_FHDR_FCTRL_POS] |= RADIOLIB_LW_FCTRL_ACK;
} }
LoRaWANNode::hton<uint16_t>(&uplinkMsg[RADIOLIB_LW_FHDR_FCNT_POS], (uint16_t)this->fcntUp); LoRaWANNode::hton<uint16_t>(&uplinkMsg[RADIOLIB_LW_FHDR_FCNT_POS], (uint16_t)this->fCntUp);
// check if we have some MAC commands to append // check if we have some MAC commands to append
if(foptsLen > 0) { if(foptsLen > 0) {
@ -1035,39 +1035,39 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
uplinkMsg[RADIOLIB_LW_FHDR_FCTRL_POS] |= foptsLen; uplinkMsg[RADIOLIB_LW_FHDR_FCTRL_POS] |= foptsLen;
// encrypt it // encrypt it
processAES(foptsBuff, foptsLen, this->nwkSEncKey, &uplinkMsg[RADIOLIB_LW_FHDR_FOPTS_POS], this->fcntUp, RADIOLIB_LW_CHANNEL_DIR_UPLINK, 0x01, true); processAES(foptsBuff, foptsLen, this->nwkSEncKey, &uplinkMsg[RADIOLIB_LW_FHDR_FOPTS_POS], this->fCntUp, RADIOLIB_LW_CHANNEL_DIR_UPLINK, 0x01, true);
} }
// set the port // set the fPort
uplinkMsg[RADIOLIB_LW_FHDR_FPORT_POS(foptsLen)] = port; uplinkMsg[RADIOLIB_LW_FHDR_FPORT_POS(foptsLen)] = fPort;
// select encryption key based on the target port // select encryption key based on the target fPort
uint8_t* encKey = this->appSKey; uint8_t* encKey = this->appSKey;
if(port == RADIOLIB_LW_FPORT_MAC_COMMAND) { if(fPort == RADIOLIB_LW_FPORT_MAC_COMMAND) {
encKey = this->nwkSEncKey; encKey = this->nwkSEncKey;
} }
// encrypt the frame payload // encrypt the frame payload
processAES(data, len, encKey, &uplinkMsg[RADIOLIB_LW_FRAME_PAYLOAD_POS(foptsLen)], this->fcntUp, RADIOLIB_LW_CHANNEL_DIR_UPLINK, 0x00, true); processAES(data, len, encKey, &uplinkMsg[RADIOLIB_LW_FRAME_PAYLOAD_POS(foptsLen)], this->fCntUp, RADIOLIB_LW_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_LW_BLOCK_MAGIC_POS] = RADIOLIB_LW_MIC_BLOCK_MAGIC; block0[RADIOLIB_LW_BLOCK_MAGIC_POS] = RADIOLIB_LW_MIC_BLOCK_MAGIC;
block0[RADIOLIB_LW_BLOCK_DIR_POS] = RADIOLIB_LW_CHANNEL_DIR_UPLINK; block0[RADIOLIB_LW_BLOCK_DIR_POS] = RADIOLIB_LW_CHANNEL_DIR_UPLINK;
LoRaWANNode::hton<uint32_t>(&block0[RADIOLIB_LW_BLOCK_DEV_ADDR_POS], this->devAddr); LoRaWANNode::hton<uint32_t>(&block0[RADIOLIB_LW_BLOCK_DEV_ADDR_POS], this->devAddr);
LoRaWANNode::hton<uint32_t>(&block0[RADIOLIB_LW_BLOCK_FCNT_POS], this->fcntUp); LoRaWANNode::hton<uint32_t>(&block0[RADIOLIB_LW_BLOCK_FCNT_POS], this->fCntUp);
block0[RADIOLIB_LW_MIC_BLOCK_LEN_POS] = uplinkMsgLen - RADIOLIB_AES128_BLOCK_SIZE - sizeof(uint32_t); block0[RADIOLIB_LW_MIC_BLOCK_LEN_POS] = uplinkMsgLen - RADIOLIB_AES128_BLOCK_SIZE - sizeof(uint32_t);
uint8_t block1[RADIOLIB_AES128_BLOCK_SIZE] = { 0 }; uint8_t block1[RADIOLIB_AES128_BLOCK_SIZE] = { 0 };
memcpy(block1, block0, RADIOLIB_AES128_BLOCK_SIZE); memcpy(block1, block0, RADIOLIB_AES128_BLOCK_SIZE);
if(this->confFcntDown != RADIOLIB_LW_FCNT_NONE) { if(this->confFCntDown != RADIOLIB_LW_FCNT_NONE) {
LoRaWANNode::hton<uint16_t>(&block1[RADIOLIB_LW_BLOCK_CONF_FCNT_POS], (uint16_t)this->confFcntDown); LoRaWANNode::hton<uint16_t>(&block1[RADIOLIB_LW_BLOCK_CONF_FCNT_POS], (uint16_t)this->confFCntDown);
} }
block1[RADIOLIB_LW_MIC_DATA_RATE_POS] = this->dataRates[RADIOLIB_LW_CHANNEL_DIR_UPLINK]; block1[RADIOLIB_LW_MIC_DATA_RATE_POS] = this->dataRates[RADIOLIB_LW_CHANNEL_DIR_UPLINK];
block1[RADIOLIB_LW_MIC_CH_INDEX_POS] = this->currentChannels[RADIOLIB_LW_CHANNEL_DIR_UPLINK].idx; block1[RADIOLIB_LW_MIC_CH_INDEX_POS] = this->currentChannels[RADIOLIB_LW_CHANNEL_DIR_UPLINK].idx;
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Uplink (FcntUp = %d) decoded:", this->fcntUp); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Uplink (FcntUp = %d) decoded:", this->fCntUp);
RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(uplinkMsg, uplinkMsgLen); RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(uplinkMsg, uplinkMsgLen);
@ -1106,7 +1106,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// the downlink confirmation was acknowledged, so clear the counter value // the downlink confirmation was acknowledged, so clear the counter value
this->confFcntDown = RADIOLIB_LW_FCNT_NONE; this->confFCntDown = RADIOLIB_LW_FCNT_NONE;
// pass the extra info if requested // pass the extra info if requested
if(event) { if(event) {
@ -1116,12 +1116,12 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
event->datarate = this->dataRates[RADIOLIB_LW_CHANNEL_DIR_UPLINK]; event->datarate = this->dataRates[RADIOLIB_LW_CHANNEL_DIR_UPLINK];
event->freq = currentChannels[event->dir].freq; event->freq = currentChannels[event->dir].freq;
event->power = this->txPowerMax - this->txPowerCur * 2; event->power = this->txPowerMax - this->txPowerCur * 2;
event->fcnt = this->fcntUp; event->fCnt = this->fCntUp;
event->port = port; event->fPort = fPort;
} }
// increase frame counter by one for the next uplink // increase frame counter by one for the next uplink
this->fcntUp += 1; this->fCntUp += 1;
return(RADIOLIB_ERR_NONE); return(RADIOLIB_ERR_NONE);
} }
@ -1279,7 +1279,7 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
size_t downlinkMsgLen = this->phyLayer->getPacketLength(); size_t downlinkMsgLen = this->phyLayer->getPacketLength();
// check the minimum required frame length // check the minimum required frame length
// an extra byte is subtracted because downlink frames may not have a port // an extra byte is subtracted because downlink frames may not have a fPort
if(downlinkMsgLen < RADIOLIB_LW_FRAME_LEN(0, 0) - 1 - RADIOLIB_AES128_BLOCK_SIZE) { if(downlinkMsgLen < RADIOLIB_LW_FRAME_LEN(0, 0) - 1 - RADIOLIB_AES128_BLOCK_SIZE) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Downlink message too short (%lu bytes)", downlinkMsgLen); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Downlink message too short (%lu bytes)", downlinkMsgLen);
return(RADIOLIB_ERR_DOWNLINK_MALFORMED); return(RADIOLIB_ERR_DOWNLINK_MALFORMED);
@ -1316,14 +1316,14 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
} }
// get the frame counter and set it to the MIC calculation block // get the frame counter and set it to the MIC calculation block
uint16_t fcnt16 = LoRaWANNode::ntoh<uint16_t>(&downlinkMsg[RADIOLIB_LW_FHDR_FCNT_POS]); uint16_t fCnt16 = LoRaWANNode::ntoh<uint16_t>(&downlinkMsg[RADIOLIB_LW_FHDR_FCNT_POS]);
LoRaWANNode::hton<uint16_t>(&downlinkMsg[RADIOLIB_LW_BLOCK_FCNT_POS], fcnt16); LoRaWANNode::hton<uint16_t>(&downlinkMsg[RADIOLIB_LW_BLOCK_FCNT_POS], fCnt16);
// if this downlink is confirming an uplink, its MIC was generated with the least-significant 16 bits of that fcntUp // if this downlink is confirming an uplink, its MIC was generated with the least-significant 16 bits of that fCntUp
bool isConfirmingUp = false; bool isConfirmingUp = false;
if((downlinkMsg[RADIOLIB_LW_FHDR_FCTRL_POS] & RADIOLIB_LW_FCTRL_ACK) && (this->rev == 1)) { if((downlinkMsg[RADIOLIB_LW_FHDR_FCTRL_POS] & RADIOLIB_LW_FCTRL_ACK) && (this->rev == 1)) {
isConfirmingUp = true; isConfirmingUp = true;
LoRaWANNode::hton<uint16_t>(&downlinkMsg[RADIOLIB_LW_BLOCK_CONF_FCNT_POS], (uint16_t)this->confFcntUp); LoRaWANNode::hton<uint16_t>(&downlinkMsg[RADIOLIB_LW_BLOCK_CONF_FCNT_POS], (uint16_t)this->confFCntUp);
} }
// calculate length of FOpts and payload // calculate length of FOpts and payload
@ -1332,7 +1332,7 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
// in LoRaWAN v1.1, a frame can be a network frame if there is no Application payload // in LoRaWAN v1.1, a frame can be a network frame if there is no Application payload
// i.e., no payload at all (empty frame or FOpts only), or MAC only payload (FPort = 0) // i.e., no payload at all (empty frame or FOpts only), or MAC only payload (FPort = 0)
// TODO "NFCntDown is used for MAC communication on port 0 and when the FPort field is missing" // TODO "NFCntDown is used for MAC communication on fPort 0 and when the FPort field is missing"
// so what about empty frames for ACK? Per TS008, these should be Application downlinks // so what about empty frames for ACK? Per TS008, these should be Application downlinks
bool isAppDownlink = true; bool isAppDownlink = true;
if(payLen <= 0) { if(payLen <= 0) {
@ -1347,23 +1347,23 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
} }
} }
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Downlink (%sFcntDown = %d) encoded:", isAppDownlink ? "A" : "N", fcnt16); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Downlink (%sFcntDown = %d) encoded:", isAppDownlink ? "A" : "N", fCnt16);
RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(downlinkMsg, RADIOLIB_AES128_BLOCK_SIZE + downlinkMsgLen); RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(downlinkMsg, RADIOLIB_AES128_BLOCK_SIZE + downlinkMsgLen);
// check the FcntDown value (Network or Application) // check the FcntDown value (Network or Application)
uint32_t fcntDownPrev = 0; uint32_t fCntDownPrev = 0;
if (isAppDownlink) { if (isAppDownlink) {
fcntDownPrev = this->aFcntDown; fCntDownPrev = this->aFCntDown;
} else { } else {
fcntDownPrev = this->nFcntDown; fCntDownPrev = this->nFCntDown;
} }
// if this is not the first downlink... // if this is not the first downlink...
// assume a 16-bit to 32-bit rollover if difference between counters in LSB is smaller than MAX_FCNT_GAP // assume a 16-bit to 32-bit rollover if difference between counters in LSB is smaller than MAX_FCNT_GAP
// if that isn't the case and the received fcnt is smaller or equal to the last heard fcnt, then error // if that isn't the case and the received fCnt is smaller or equal to the last heard fCnt, then error
uint32_t fcnt32 = fcnt16; uint32_t fCnt32 = fCnt16;
if(fcntDownPrev > 0) { if(fCntDownPrev > 0) {
if((fcnt16 <= fcntDownPrev) && ((0xFFFF - (uint16_t)fcntDownPrev + fcnt16) > RADIOLIB_LW_MAX_FCNT_GAP)) { if((fCnt16 <= fCntDownPrev) && ((0xFFFF - (uint16_t)fCntDownPrev + fCnt16) > RADIOLIB_LW_MAX_FCNT_GAP)) {
#if !RADIOLIB_STATIC_ONLY #if !RADIOLIB_STATIC_ONLY
delete[] downlinkMsg; delete[] downlinkMsg;
#endif #endif
@ -1372,9 +1372,9 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
} else { } else {
return(RADIOLIB_ERR_N_FCNT_DOWN_INVALID); return(RADIOLIB_ERR_N_FCNT_DOWN_INVALID);
} }
} else if (fcnt16 <= fcntDownPrev) { } else if (fCnt16 <= fCntDownPrev) {
uint16_t msb = (fcntDownPrev >> 16) + 1; // assume a rollover uint16_t msb = (fCntDownPrev >> 16) + 1; // assume a rollover
fcnt32 |= ((uint32_t)msb << 16); // add back the MSB part fCnt32 |= ((uint32_t)msb << 16); // add back the MSB part
} }
} }
@ -1386,17 +1386,17 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
return(RADIOLIB_ERR_CRC_MISMATCH); return(RADIOLIB_ERR_CRC_MISMATCH);
} }
// save current fcnt to respective frame counter // save current fCnt to respective frame counter
if (isAppDownlink) { if (isAppDownlink) {
this->aFcntDown = fcnt32; this->aFCntDown = fCnt32;
} else { } else {
this->nFcntDown = fcnt32; this->nFCntDown = fCnt32;
} }
// if this is a confirmed frame, save the downlink number (only app frames can be confirmed) // if this is a confirmed frame, save the downlink number (only app frames can be confirmed)
bool isConfirmedDown = false; bool isConfirmedDown = false;
if((downlinkMsg[RADIOLIB_LW_FHDR_LEN_START_OFFS] & 0xFE) == RADIOLIB_LW_MHDR_MTYPE_CONF_DATA_DOWN) { if((downlinkMsg[RADIOLIB_LW_FHDR_LEN_START_OFFS] & 0xFE) == RADIOLIB_LW_MHDR_MTYPE_CONF_DATA_DOWN) {
this->confFcntDown = this->aFcntDown; this->confFCntDown = this->aFCntDown;
isConfirmedDown = true; isConfirmedDown = true;
} }
@ -1419,14 +1419,14 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
uint8_t fopts[RADIOLIB_STATIC_ARRAY_SIZE]; uint8_t fopts[RADIOLIB_STATIC_ARRAY_SIZE];
#endif #endif
// TODO it COULD be the case that the assumed FCnt rollover is incorrect, if possible figure out a way to catch this and retry with just fcnt16 // TODO it COULD be the case that the assumed FCnt rollover is incorrect, if possible figure out a way to catch this and retry with just fCnt16
// if there are <= 15 bytes of FOpts, they are in the FHDR, otherwise they are in the payload // 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 // in case of the latter, process AES is if it were a normal payload but using the NwkSEncKey
if(foptsLen <= RADIOLIB_LW_FHDR_FOPTS_LEN_MASK) { if(foptsLen <= RADIOLIB_LW_FHDR_FOPTS_LEN_MASK) {
uint8_t ctrId = 0x01 + isAppDownlink; // see LoRaWAN v1.1 errata uint8_t ctrId = 0x01 + isAppDownlink; // see LoRaWAN v1.1 errata
processAES(&downlinkMsg[RADIOLIB_LW_FHDR_FOPTS_POS], (size_t)foptsLen, this->nwkSEncKey, fopts, fcnt32, RADIOLIB_LW_CHANNEL_DIR_DOWNLINK, ctrId, true); processAES(&downlinkMsg[RADIOLIB_LW_FHDR_FOPTS_POS], (size_t)foptsLen, this->nwkSEncKey, fopts, fCnt32, RADIOLIB_LW_CHANNEL_DIR_DOWNLINK, ctrId, true);
} else { } else {
processAES(&downlinkMsg[RADIOLIB_LW_FRAME_PAYLOAD_POS(0)], (size_t)foptsLen, this->nwkSEncKey, fopts, fcnt32, RADIOLIB_LW_CHANNEL_DIR_DOWNLINK, 0x00, true); processAES(&downlinkMsg[RADIOLIB_LW_FRAME_PAYLOAD_POS(0)], (size_t)foptsLen, this->nwkSEncKey, fopts, fCnt32, RADIOLIB_LW_CHANNEL_DIR_DOWNLINK, 0x00, true);
} }
bool hasADR = false; bool hasADR = false;
@ -1536,8 +1536,8 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
} }
// a downlink was received, so reset the ADR counter to the last uplink's fcnt // a downlink was received, so reset the ADR counter to the last uplink's fCnt
this->adrFcnt = this->getFcntUp(); this->adrFCnt = this->getFCntUp();
// pass the extra info if requested // pass the extra info if requested
if(event) { if(event) {
@ -1547,8 +1547,8 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
event->datarate = this->dataRates[RADIOLIB_LW_CHANNEL_DIR_DOWNLINK]; event->datarate = this->dataRates[RADIOLIB_LW_CHANNEL_DIR_DOWNLINK];
event->freq = currentChannels[event->dir].freq; event->freq = currentChannels[event->dir].freq;
event->power = this->txPowerMax - this->txPowerCur * 2; event->power = this->txPowerMax - this->txPowerCur * 2;
event->fcnt = isAppDownlink ? this->aFcntDown : this->nFcntDown; event->fCnt = isAppDownlink ? this->aFCntDown : this->nFCntDown;
event->port = isAppDownlink ? downlinkMsg[RADIOLIB_LW_FHDR_FPORT_POS(foptsLen)] : RADIOLIB_LW_FPORT_MAC_COMMAND; event->fPort = isAppDownlink ? downlinkMsg[RADIOLIB_LW_FHDR_FPORT_POS(foptsLen)] : RADIOLIB_LW_FPORT_MAC_COMMAND;
} }
// process Application payload (if there is any) // process Application payload (if there is any)
@ -1564,8 +1564,8 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
*len = payLen - 1; *len = payLen - 1;
// TODO it COULD be the case that the assumed rollover is incorrect, then figure out a way to catch this and retry with just fcnt16 // TODO it COULD be the case that the assumed rollover is incorrect, then figure out a way to catch this and retry with just fCnt16
processAES(&downlinkMsg[RADIOLIB_LW_FRAME_PAYLOAD_POS(foptsLen)], payLen - 1, this->appSKey, data, fcnt32, RADIOLIB_LW_CHANNEL_DIR_DOWNLINK, 0x00, true); processAES(&downlinkMsg[RADIOLIB_LW_FRAME_PAYLOAD_POS(foptsLen)], payLen - 1, this->appSKey, data, fCnt32, RADIOLIB_LW_CHANNEL_DIR_DOWNLINK, 0x00, true);
#if !RADIOLIB_STATIC_ONLY #if !RADIOLIB_STATIC_ONLY
delete[] downlinkMsg; delete[] downlinkMsg;
@ -1575,9 +1575,9 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event)
} }
#if defined(RADIOLIB_BUILD_ARDUINO) #if defined(RADIOLIB_BUILD_ARDUINO)
int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t port, String& strDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t fPort, String& strDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
// send the uplink // send the uplink
int16_t state = this->uplink(strUp, port, isConfirmed, eventUp); int16_t state = this->uplink(strUp, fPort, isConfirmed, eventUp);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// wait for the downlink // wait for the downlink
@ -1586,9 +1586,9 @@ int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t port, String& strDown, b
} }
#endif #endif
int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) { int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
// send the uplink // send the uplink
int16_t state = this->uplink(dataUp, lenUp, port, isConfirmed, eventUp); int16_t state = this->uplink(dataUp, lenUp, fPort, isConfirmed, eventUp);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// wait for the downlink // wait for the downlink
@ -1596,9 +1596,9 @@ int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port, bo
return(state); return(state);
} }
int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* 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) {
// send the uplink // send the uplink
int16_t state = this->uplink(strUp, port, isConfirmed, eventUp); int16_t state = this->uplink(strUp, fPort, isConfirmed, eventUp);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// wait for the downlink // wait for the downlink
@ -1606,9 +1606,9 @@ int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t port, uint8_t* dataD
return(state); return(state);
} }
int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* 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) {
// send the uplink // send the uplink
int16_t state = this->uplink(dataUp, lenUp, port, isConfirmed, eventUp); int16_t state = this->uplink(dataUp, lenUp, fPort, isConfirmed, eventUp);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// wait for the downlink // wait for the downlink
@ -1621,24 +1621,24 @@ void LoRaWANNode::setDeviceStatus(uint8_t battLevel) {
} }
// return Fcnt of last uplink; also return 0 if no uplink occured yet // return Fcnt of last uplink; also return 0 if no uplink occured yet
uint32_t LoRaWANNode::getFcntUp() { uint32_t LoRaWANNode::getFCntUp() {
if(this->fcntUp == 0) { if(this->fCntUp == 0) {
return(0); return(0);
} }
return(this->fcntUp - 1); return(this->fCntUp - 1);
} }
uint32_t LoRaWANNode::getNFcntDown() { uint32_t LoRaWANNode::getNFCntDown() {
return(this->nFcntDown); return(this->nFCntDown);
} }
uint32_t LoRaWANNode::getAFcntDown() { uint32_t LoRaWANNode::getAFCntDown() {
return(this->aFcntDown); return(this->aFCntDown);
} }
void LoRaWANNode::resetFcntDown() { void LoRaWANNode::resetFCntDown() {
this->nFcntDown = 0; this->nFCntDown = 0;
this->aFcntDown = 0; this->aFCntDown = 0;
} }
uint32_t LoRaWANNode::generateMIC(uint8_t* msg, size_t len, uint8_t* key) { uint32_t LoRaWANNode::generateMIC(uint8_t* msg, size_t len, uint8_t* key) {
@ -2858,7 +2858,7 @@ bool LoRaWANNode::performCAD() {
return false; // Channel is free 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;
if(len % RADIOLIB_AES128_BLOCK_SIZE) { if(len % RADIOLIB_AES128_BLOCK_SIZE) {
@ -2872,7 +2872,7 @@ void LoRaWANNode::processAES(uint8_t* in, size_t len, uint8_t* key, uint8_t* out
encBlock[RADIOLIB_LW_ENC_BLOCK_COUNTER_ID_POS] = ctrId; encBlock[RADIOLIB_LW_ENC_BLOCK_COUNTER_ID_POS] = ctrId;
encBlock[RADIOLIB_LW_BLOCK_DIR_POS] = dir; encBlock[RADIOLIB_LW_BLOCK_DIR_POS] = dir;
LoRaWANNode::hton<uint32_t>(&encBlock[RADIOLIB_LW_BLOCK_DEV_ADDR_POS], this->devAddr); LoRaWANNode::hton<uint32_t>(&encBlock[RADIOLIB_LW_BLOCK_DEV_ADDR_POS], this->devAddr);
LoRaWANNode::hton<uint32_t>(&encBlock[RADIOLIB_LW_BLOCK_FCNT_POS], fcnt); LoRaWANNode::hton<uint32_t>(&encBlock[RADIOLIB_LW_BLOCK_FCNT_POS], fCnt);
// now encrypt the input // now encrypt the input
// on downlink frames, this has a decryption effect because server actually "decrypts" the plaintext // on downlink frames, this has a decryption effect because server actually "decrypts" the plaintext

View file

@ -39,9 +39,9 @@
#define RADIOLIB_LW_FCTRL_ACK (0x01 << 5) // 5 5 confirmed message acknowledge #define RADIOLIB_LW_FCTRL_ACK (0x01 << 5) // 5 5 confirmed message acknowledge
#define RADIOLIB_LW_FCTRL_FRAME_PENDING (0x01 << 4) // 4 4 downlink frame is pending #define RADIOLIB_LW_FCTRL_FRAME_PENDING (0x01 << 4) // 4 4 downlink frame is pending
// port field // fPort field
#define RADIOLIB_LW_FPORT_MAC_COMMAND (0x00 << 0) // 7 0 payload contains MAC commands only #define RADIOLIB_LW_FPORT_MAC_COMMAND (0x00 << 0) // 7 0 payload contains MAC commands only
#define RADIOLIB_LW_FPORT_RESERVED (0xE0 << 0) // 7 0 reserved port values #define RADIOLIB_LW_FPORT_RESERVED (0xE0 << 0) // 7 0 reserved fPort values
// MAC commands - only those sent from end-device to gateway // MAC commands - only those sent from end-device to gateway
#define RADIOLIB_LW_LINK_CHECK_REQ (0x02 << 0) // 7 0 MAC command: request to check connectivity to network #define RADIOLIB_LW_LINK_CHECK_REQ (0x02 << 0) // 7 0 MAC command: request to check connectivity to network
@ -485,10 +485,10 @@ struct LoRaWANEvent_t {
int16_t power; int16_t power;
/*! \brief The appropriate frame counter - for different events, different frame counters will be reported! */ /*! \brief The appropriate frame counter - for different events, different frame counters will be reported! */
uint32_t fcnt; uint32_t fCnt;
/*! \brief Port number */ /*! \brief Port number */
uint8_t port; uint8_t fPort;
}; };
/*! /*!
@ -600,44 +600,44 @@ class LoRaWANNode {
/*! /*!
\brief Send a message to the server. \brief Send a message to the server.
\param str Address of Arduino String that will be transmitted. \param str Address of Arduino String that will be transmitted.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param event Pointer to a structure to store extra information about the event \param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t uplink(String& str, uint8_t port, bool isConfirmed = false, LoRaWANEvent_t* event = NULL); int16_t uplink(String& str, uint8_t fPort, bool isConfirmed = false, LoRaWANEvent_t* event = NULL);
#endif #endif
/*! /*!
\brief Send a message to the server. \brief Send a message to the server.
\param str C-string that will be transmitted. \param str C-string that will be transmitted.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param event Pointer to a structure to store extra information about the event \param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t uplink(const char* str, uint8_t port, bool isConfirmed = false, LoRaWANEvent_t* event = NULL); int16_t uplink(const char* str, uint8_t fPort, bool isConfirmed = false, LoRaWANEvent_t* event = NULL);
/*! /*!
\brief Send a message to the server. \brief Send a message to the server.
\param data Data to send. \param data Data to send.
\param len Length of the data. \param len Length of the data.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param event Pointer to a structure to store extra information about the event \param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t uplink(uint8_t* data, size_t len, uint8_t port, bool isConfirmed = false, LoRaWANEvent_t* event = NULL); int16_t uplink(uint8_t* data, size_t len, uint8_t fPort, bool isConfirmed = false, LoRaWANEvent_t* event = NULL);
#if defined(RADIOLIB_BUILD_ARDUINO) #if defined(RADIOLIB_BUILD_ARDUINO)
/*! /*!
\brief Wait for downlink from the server in either RX1 or RX2 window. \brief Wait for downlink from the server in either RX1 or RX2 window.
\param str Address of Arduino String to save the received data. \param str Address of Arduino String to save the received data.
\param event Pointer to a structure to store extra information about the event \param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t downlink(String& str, LoRaWANEvent_t* event = NULL); int16_t downlink(String& str, LoRaWANEvent_t* event = NULL);
@ -648,7 +648,7 @@ class LoRaWANNode {
\param data Buffer to save received data into. \param data Buffer to save received data into.
\param len Pointer to variable that will be used to save the number of received bytes. \param len Pointer to variable that will be used to save the number of received bytes.
\param event Pointer to a structure to store extra information about the event \param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event = NULL); int16_t downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event = NULL);
@ -656,7 +656,7 @@ class LoRaWANNode {
/*! /*!
\brief Wait for downlink, simplified to allow for simpler sendReceive \brief Wait for downlink, simplified to allow for simpler sendReceive
\param event Pointer to a structure to store extra information about the event \param event Pointer to a structure to store extra information about the event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t downlink(LoRaWANEvent_t* event = NULL); int16_t downlink(LoRaWANEvent_t* event = NULL);
@ -665,62 +665,62 @@ class LoRaWANNode {
/*! /*!
\brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window. \brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window.
\param strUp Address of Arduino String that will be transmitted. \param strUp Address of Arduino String that will be transmitted.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param strDown Address of Arduino String to save the received data. \param strDown Address of Arduino String to save the received data.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param eventUp Pointer to a structure to store extra information about the uplink event \param eventUp Pointer to a structure to store extra information about the uplink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (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 \param eventDown Pointer to a structure to store extra information about the downlink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t sendReceive(String& strUp, uint8_t port, String& strDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); int16_t sendReceive(String& strUp, uint8_t fPort, String& strDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
#endif #endif
/*! /*!
\brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window. \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 strUp C-string that will be transmitted.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param dataDown Buffer to save received data into. \param dataDown Buffer to save received data into.
\param lenDown Pointer to variable that will be used to save the number of received bytes. \param lenDown Pointer to variable that will be used to save the number of received bytes.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param eventUp Pointer to a structure to store extra information about the uplink event \param eventUp Pointer to a structure to store extra information about the uplink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (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 \param eventDown Pointer to a structure to store extra information about the downlink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t sendReceive(const char* strUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); 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 during Rx1 and/or Rx2 window. \brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window.
\param dataUp Data to send. \param dataUp Data to send.
\param lenUp Length of the data. \param lenUp Length of the data.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param dataDown Buffer to save received data into. \param dataDown Buffer to save received data into.
\param lenDown Pointer to variable that will be used to save the number of received bytes. \param lenDown Pointer to variable that will be used to save the number of received bytes.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param eventUp Pointer to a structure to store extra information about the uplink event \param eventUp Pointer to a structure to store extra information about the uplink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (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 \param eventDown Pointer to a structure to store extra information about the downlink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); 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 \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 dataUp Data to send.
\param lenUp Length of the data. \param lenUp Length of the data.
\param port Port number to send the message to. \param fPort Port number to send the message to.
\param isConfirmed Whether to send a confirmed uplink or not. \param isConfirmed Whether to send a confirmed uplink or not.
\param eventUp Pointer to a structure to store extra information about the uplink event \param eventUp Pointer to a structure to store extra information about the uplink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (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 \param eventDown Pointer to a structure to store extra information about the downlink event
(port, frame counter, etc.). If set to NULL, no extra information will be passed to the user. (fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port = 1, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL); 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 Set device status. \brief Set device status.
@ -733,26 +733,26 @@ class LoRaWANNode {
\brief Returns the last uplink's frame counter; \brief Returns the last uplink's frame counter;
also 0 if no uplink occured yet. also 0 if no uplink occured yet.
*/ */
uint32_t getFcntUp(); uint32_t getFCntUp();
/*! /*!
\brief Returns the last network downlink's frame counter; \brief Returns the last network downlink's frame counter;
also 0 if no network downlink occured yet. also 0 if no network downlink occured yet.
*/ */
uint32_t getNFcntDown(); uint32_t getNFCntDown();
/*! /*!
\brief Returns the last application downlink's frame counter; \brief Returns the last application downlink's frame counter;
also 0 if no application downlink occured yet. also 0 if no application downlink occured yet.
*/ */
uint32_t getAFcntDown(); uint32_t getAFCntDown();
/*! /*!
\brief Reset the downlink frame counters (application and network) \brief Reset the downlink frame counters (application and network)
This is unsafe and can possibly allow replay attacks using downlinks. This is unsafe and can possibly allow replay attacks using downlinks.
It mainly exists as part of the TS009 Specification Verification protocol. It mainly exists as part of the TS009 Specification Verification protocol.
*/ */
void resetFcntDown(); void resetFCntDown();
/*! /*!
\brief Set uplink datarate. This should not be used when ADR is enabled. \brief Set uplink datarate. This should not be used when ADR is enabled.
@ -889,12 +889,12 @@ class LoRaWANNode {
uint8_t nbTrans = 1; // Number of allowed frame retransmissions uint8_t nbTrans = 1; // Number of allowed frame retransmissions
uint8_t txPowerCur = 0; uint8_t txPowerCur = 0;
uint8_t txPowerMax = 0; uint8_t txPowerMax = 0;
uint32_t fcntUp = 0; uint32_t fCntUp = 0;
uint32_t aFcntDown = 0; uint32_t aFCntDown = 0;
uint32_t nFcntDown = 0; uint32_t nFCntDown = 0;
uint32_t confFcntUp = RADIOLIB_LW_FCNT_NONE; uint32_t confFCntUp = RADIOLIB_LW_FCNT_NONE;
uint32_t confFcntDown = RADIOLIB_LW_FCNT_NONE; uint32_t confFCntDown = RADIOLIB_LW_FCNT_NONE;
uint32_t adrFcnt = 0; uint32_t adrFCnt = 0;
// whether the current configured channel is in FSK mode // whether the current configured channel is in FSK mode
bool FSK = false; bool FSK = false;
@ -1028,7 +1028,7 @@ class LoRaWANNode {
bool performCAD(); 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);
// 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum // 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum
static uint16_t checkSum16(uint8_t *key, uint16_t keyLen); static uint16_t checkSum16(uint8_t *key, uint16_t keyLen);