Skip to content

Commit

Permalink
[LoRaWAN] Added event struct to pass extra info (#821)
Browse files Browse the repository at this point in the history
  • Loading branch information
jgromes committed Nov 12, 2023
1 parent cb9ba88 commit 75a9420
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/*
RadioLib LoRaWAN End Device Example
RadioLib LoRaWAN End Device Persistent Example
This example assumes you have tried one of the OTAA or ABP
examples and are familiar with the required keys and procedures.
This example restores and saves a session such that you can use
deepsleep or survive power cycles. Before you start, you will
have to register your device at https://www.thethingsnetwork.org/
and join the network using either OTAA or ABP.
Please refer to one of the other examples for more
Please refer to one of the other LoRaWAN examples for more
information regarding joining a network.
NOTE: LoRaWAN requires storing some parameters persistently!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
RadioLib LoRaWAN End Device Example
RadioLib LoRaWAN End Device Reference Example
This example joins a LoRaWAN network and will send
uplink packets. Before you start, you will have to
Expand Down Expand Up @@ -131,13 +131,13 @@ void setup() {
// this tries to minimize packet loss by searching for a free channel
// before actually sending an uplink
node.setCSMA(6, 2, true);

}

void loop() {
int state = RADIOLIB_ERR_NONE;

// set battery fill level,
// set battery fill level - the LoRaWAN network server
// may periodically request this information
// 0 = external power source
// 1 = lowest (empty battery)
// 254 = highest (full battery)
Expand Down Expand Up @@ -170,7 +170,12 @@ void loop() {
// after uplink to receive the downlink!
Serial.print(F("[LoRaWAN] Waiting for downlink ... "));
String strDown;
state = node.downlink(strDown);

// you can also retrieve additional information about
// uplink or downlink by passing a reference to
// LoRaWANEvent_t structure
LoRaWANEvent_t event;
state = node.downlink(strDown, &event);
if(state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));

Expand All @@ -196,6 +201,31 @@ void loop() {
Serial.print(F("[LoRaWAN] Frequency error:\t"));
Serial.print(radio.getFrequencyError());
Serial.println(F(" Hz"));

// print extra information about the event
Serial.println(F("[LoRaWAN] Event information:"));
Serial.print(F("[LoRaWAN] Direction:\t"));
if(event.dir == RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK) {
Serial.println(F("uplink"));
} else {
Serial.println(F("downlink"));
}
Serial.print(F("[LoRaWAN] Confirmed:\t"));
Serial.println(event.confirmed);
Serial.print(F("[LoRaWAN] Confirming:\t"));
Serial.println(event.confirming);
Serial.print(F("[LoRaWAN] Frequency:\t"));
Serial.print(event.freq, 3);
Serial.println(F(" MHz"));
Serial.print(F("[LoRaWAN] Output power:\t"));
Serial.print(event.power);
Serial.println(F(" dBm"));
Serial.print(F("[LoRaWAN] Frame count:\t"));
Serial.println(event.fcnt);
Serial.print(F("[LoRaWAN] Port:\t\t"));
Serial.println(event.port);

Serial.print(radio.getFrequencyError());

} else if(state == RADIOLIB_ERR_RX_TIMEOUT) {
Serial.println(F("timeout!"));
Expand Down
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ ExternalRadio KEYWORD1
BellClient KEYWORD1
LoRaWANNode KEYWORD1
LoRaWANBand_t KEYWORD1
LoRaWANEvent_t KEYWORD1

# SSTV modes
Scottie1 KEYWORD1
Expand Down
75 changes: 38 additions & 37 deletions src/protocols/LoRaWAN/LoRaWAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,16 +657,16 @@ int16_t LoRaWANNode::saveChannels() {


#if defined(RADIOLIB_BUILD_ARDUINO)
int16_t LoRaWANNode::uplink(String& str, uint8_t port, bool isConfirmed) {
return(this->uplink(str.c_str(), port, isConfirmed));
int16_t LoRaWANNode::uplink(String& str, uint8_t port, bool isConfirmed, LoRaWANEvent_t* event) {
return(this->uplink(str.c_str(), port, isConfirmed, event));
}
#endif

int16_t LoRaWANNode::uplink(const char* str, uint8_t port, bool isConfirmed) {
return(this->uplink((uint8_t*)str, strlen(str), port, isConfirmed));
int16_t LoRaWANNode::uplink(const char* str, uint8_t port, bool isConfirmed, LoRaWANEvent_t* event) {
return(this->uplink((uint8_t*)str, strlen(str), port, isConfirmed, event));
}

int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConfirmed) {
int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConfirmed, LoRaWANEvent_t* event) {
Module* mod = this->phyLayer->getMod();

// check if the Rx windows were closed after sending the previous uplink
Expand Down Expand Up @@ -783,12 +783,11 @@ 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
bool isConfirmingDown;
bool isConfirmingDown = false;
if(this->confFcntDown != RADIOLIB_LORAWAN_FCNT_NONE) {
isConfirmingDown = true;
uplinkMsg[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= RADIOLIB_LORAWAN_FCTRL_ACK;
}
(void)isConfirmingDown;

LoRaWANNode::hton<uint16_t>(&uplinkMsg[RADIOLIB_LORAWAN_FHDR_FCNT_POS], (uint16_t)this->fcntUp);

Expand Down Expand Up @@ -895,13 +894,16 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
// the downlink confirmation was acknowledged, so clear the counter value
this->confFcntDown = RADIOLIB_LORAWAN_FCNT_NONE;

// LoRaWANEvent:
// dir = RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK
// confirmed = isConfirmed
// confirming = isConfirmingDown
// power = this->txPwrCur
// fcnt = this->fcntUp
// port = port
// pass the extra info if requested
if(event) {
event->dir = RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK;
event->confirmed = isConfirmed;
event->confirming = isConfirmingDown;
event->freq = currentChannels[event->dir].freq;
event->power = this->txPwrCur;
event->fcnt = this->fcntUp;
event->port = port;
}

return(RADIOLIB_ERR_NONE);
}
Expand Down Expand Up @@ -1012,7 +1014,7 @@ int16_t LoRaWANNode::downlinkCommon() {
}

#if defined(RADIOLIB_BUILD_ARDUINO)
int16_t LoRaWANNode::downlink(String& str) {
int16_t LoRaWANNode::downlink(String& str, LoRaWANEvent_t* event) {
int16_t state = RADIOLIB_ERR_NONE;

// build a temporary buffer
Expand All @@ -1021,7 +1023,7 @@ int16_t LoRaWANNode::downlink(String& str) {
uint8_t data[251];

// wait for downlink
state = this->downlink(data, &length);
state = this->downlink(data, &length, event);
if(state == RADIOLIB_ERR_NONE) {
// add null terminator
data[length] = '\0';
Expand All @@ -1034,8 +1036,7 @@ int16_t LoRaWANNode::downlink(String& str) {
}
#endif

int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) {

int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len, LoRaWANEvent_t* event) {
// handle Rx1 and Rx2 windows - returns RADIOLIB_ERR_NONE if a downlink is received
int16_t state = downlinkCommon();
RADIOLIB_ASSERT(state);
Expand Down Expand Up @@ -1086,13 +1087,11 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) {
LoRaWANNode::hton<uint16_t>(&downlinkMsg[RADIOLIB_LORAWAN_BLOCK_FCNT_POS], fcnt16);

// if this downlink is confirming an uplink, its MIC was generated with the least-significant 16 bits of that fcntUp
// TODO get this to the user somehow
bool isConfirmingUp = false;
if((downlinkMsg[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] & RADIOLIB_LORAWAN_FCTRL_ACK) && (this->rev == 1)) {
isConfirmingUp = true;
LoRaWANNode::hton<uint16_t>(&downlinkMsg[RADIOLIB_LORAWAN_BLOCK_CONF_FCNT_POS], (uint16_t)this->confFcntUp);
}
(void)isConfirmingUp;

RADIOLIB_DEBUG_PRINTLN("downlinkMsg:");
RADIOLIB_DEBUG_HEXDUMP(downlinkMsg, RADIOLIB_AES128_BLOCK_SIZE + downlinkMsgLen);
Expand Down Expand Up @@ -1157,7 +1156,6 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) {
this->confFcntDown = this->aFcntDown;
isConfirmedDown = true;
}
(void)isConfirmedDown;

// check the address
uint32_t addr = LoRaWANNode::ntoh<uint32_t>(&downlinkMsg[RADIOLIB_LORAWAN_FHDR_DEV_ADDR_POS]);
Expand Down Expand Up @@ -1242,13 +1240,16 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) {
// a downlink was received, so reset the ADR counter to this uplink's fcnt
this->adrFcnt = this->fcntUp;

// LoRaWANEvent:
// dir = RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK
// confirmed = isConfirmedDown
// confirming = isConfirmingUp
// power = this->txPwrCur
// fcnt = isAppDownlink ? this->aFcntDown : this->nFcntDown
// port = ...
// pass the extra info if requested
if(event) {
event->dir = RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK;
event->confirmed = isConfirmedDown;
event->confirming = isConfirmingUp;
event->freq = currentChannels[event->dir].freq;
event->power = this->txPwrCur;
event->fcnt = isAppDownlink ? this->aFcntDown : this->nFcntDown;
event->port = downlinkMsg[RADIOLIB_LORAWAN_FHDR_FPORT_POS(foptsLen)];
}

// process payload (if there is any)
if(payLen <= 0) {
Expand Down Expand Up @@ -1276,34 +1277,34 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) {
}

#if defined(RADIOLIB_BUILD_ARDUINO)
int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t port, String& strDown, bool isConfirmed) {
int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t port, String& strDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
// send the uplink
int16_t state = this->uplink(strUp, port, isConfirmed);
int16_t state = this->uplink(strUp, port, isConfirmed, eventUp);
RADIOLIB_ASSERT(state);

// wait for the downlink
state = this->downlink(strDown);
state = this->downlink(strDown, eventDown);
return(state);
}
#endif

int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed) {
int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
// send the uplink
int16_t state = this->uplink(strUp, port, isConfirmed);
int16_t state = this->uplink(strUp, port, isConfirmed, eventUp);
RADIOLIB_ASSERT(state);

// wait for the downlink
state = this->downlink(dataDown, lenDown);
state = this->downlink(dataDown, lenDown, eventDown);
return(state);
}

int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t port, uint8_t* dataDown, size_t* lenDown, bool isConfirmed) {
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) {
// send the uplink
int16_t state = this->uplink(dataUp, lenUp, port, isConfirmed);
int16_t state = this->uplink(dataUp, lenUp, port, isConfirmed, eventUp);
RADIOLIB_ASSERT(state);

// wait for the downlink
state = this->downlink(dataDown, lenDown);
state = this->downlink(dataDown, lenDown, eventDown);
return(state);
}

Expand Down
Loading

0 comments on commit 75a9420

Please sign in to comment.