[LoRaWAN] Implement requested changes
This commit is contained in:
parent
2da09b5adc
commit
7c676f9393
6 changed files with 72 additions and 93 deletions
|
@ -157,7 +157,7 @@ void loop() {
|
|||
// wait before sending another packet
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ void loop() {
|
|||
// wait before sending another packet
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ void setup() {
|
|||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
Serial.print(F("Restored an "));
|
||||
if(state == RADIOLIB_LORAWAN_MODE_OTAA)
|
||||
if(state == RADIOLIB_LORAWAN_MODE_OTAA)
|
||||
Serial.println(F("OTAA session."));
|
||||
else {
|
||||
Serial.println(F("ABP session."));
|
||||
|
@ -142,7 +142,7 @@ void loop() {
|
|||
// make sure to send the radio to sleep as well using radio.sleep()
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
||||
|
|
|
@ -28,39 +28,6 @@ uint8_t getDownlinkDataRate(uint8_t uplink, uint8_t offset, uint8_t base, uint8_
|
|||
return(dr);
|
||||
}
|
||||
|
||||
uint16_t checkSum16(uint32_t key) {
|
||||
uint8_t bufLen = 2;
|
||||
uint16_t buf16[bufLen];
|
||||
memcpy(buf16, &key, bufLen);
|
||||
uint16_t checkSum = 0;
|
||||
for(int i = 0; i < bufLen; i++) {
|
||||
checkSum ^= buf16[i];
|
||||
}
|
||||
return(checkSum);
|
||||
}
|
||||
|
||||
uint16_t checkSum16(uint64_t key) {
|
||||
uint8_t bufLen = 4;
|
||||
uint16_t buf16[bufLen];
|
||||
memcpy(buf16, &key, bufLen);
|
||||
uint16_t checkSum = 0;
|
||||
for(int i = 0; i < bufLen; i++) {
|
||||
checkSum ^= buf16[i];
|
||||
}
|
||||
return(checkSum);
|
||||
}
|
||||
|
||||
uint16_t checkSum16(uint8_t *key, uint8_t keyLen) {
|
||||
uint8_t bufLen = keyLen / 2;
|
||||
uint16_t buf16[bufLen];
|
||||
memcpy(buf16, key, bufLen);
|
||||
uint16_t checkSum = 0;
|
||||
for(int i = 0; i < bufLen; i++) {
|
||||
checkSum ^= buf16[i];
|
||||
}
|
||||
return(checkSum);
|
||||
}
|
||||
|
||||
LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band) {
|
||||
this->phyLayer = phy;
|
||||
this->band = band;
|
||||
|
@ -395,8 +362,8 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
|
|||
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
uint16_t checkSum = 0;
|
||||
checkSum ^= checkSum16(joinEUI);
|
||||
checkSum ^= checkSum16(devEUI);
|
||||
checkSum ^= checkSum16((uint8_t*)joinEUI, 8);
|
||||
checkSum ^= checkSum16((uint8_t*)devEUI, 8);
|
||||
checkSum ^= checkSum16(nwkKey, 16);
|
||||
checkSum ^= checkSum16(appKey, 16);
|
||||
|
||||
|
@ -666,13 +633,11 @@ int16_t LoRaWANNode::beginABP(uint32_t addr, uint8_t* nwkSKey, uint8_t* appSKey,
|
|||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
// check if we actually need to restart from a clean session
|
||||
uint16_t checkSum = 0;
|
||||
checkSum ^= checkSum16(addr);
|
||||
checkSum ^= checkSum16((uint8_t*)addr, 4);
|
||||
checkSum ^= checkSum16(nwkSKey, 16);
|
||||
checkSum ^= checkSum16(appSKey, 16);
|
||||
if(fNwkSIntKey)
|
||||
checkSum ^= checkSum16(fNwkSIntKey, 16);
|
||||
if(sNwkSIntKey)
|
||||
checkSum ^= checkSum16(sNwkSIntKey, 16);
|
||||
if(fNwkSIntKey) { checkSum ^= checkSum16(fNwkSIntKey, 16); }
|
||||
if(sNwkSIntKey) { checkSum ^= checkSum16(sNwkSIntKey, 16); }
|
||||
|
||||
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_ABP;
|
||||
|
@ -904,10 +869,9 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
|
|||
|
||||
// check maximum payload len as defined in phy
|
||||
if(len > this->band->payloadLenMax[this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK]]) {
|
||||
len = this->band->payloadLenMax[this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK]];
|
||||
// return(RADIOLIB_ERR_PACKET_TOO_LONG);
|
||||
// len = this->band->payloadLenMax[this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK]];
|
||||
return(RADIOLIB_ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
if(RADIOLIB_LORAWAN_FRAME_LEN(len, foptsLen))
|
||||
|
||||
// increase frame counter by one
|
||||
this->fcntUp += 1;
|
||||
|
@ -2575,10 +2539,10 @@ bool LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom) {
|
|||
RADIOLIB_DEBUG_PRINTLN("TX timing: dlDwell = %d, ulDwell = %d, maxEirp = %d dBm", dlDwell, ulDwell, this->txPowerMax);
|
||||
|
||||
this->dwellTimeEnabledUp = ulDwell ? true : false;
|
||||
this->dwellTimeUp = ulDwell ? 400 : 0;
|
||||
this->dwellTimeUp = ulDwell ? RADIOLIB_LORAWAN_DWELL_TIME : 0;
|
||||
|
||||
this->dwellTimeEnabledDn = dlDwell ? true : false;
|
||||
this->dwellTimeDn = dlDwell ? 400 : 0;
|
||||
this->dwellTimeDn = dlDwell ? RADIOLIB_LORAWAN_DWELL_TIME : 0;
|
||||
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
if(saveToEeprom) {
|
||||
|
@ -2673,31 +2637,32 @@ uint8_t LoRaWANNode::getMacPayloadLength(uint8_t cid) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool LoRaWANNode::getMacLinkCheckAns(uint8_t* margin, uint8_t* gwCnt) {
|
||||
int16_t LoRaWANNode::getMacLinkCheckAns(uint8_t* margin, uint8_t* gwCnt) {
|
||||
uint8_t payload[5];
|
||||
int16_t state = deleteMacCommand(RADIOLIB_LORAWAN_LINK_CHECK_REQ, &this->commandsDown, payload);
|
||||
if(state != RADIOLIB_ERR_NONE)
|
||||
return false;
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
*margin = payload[0];
|
||||
*gwCnt = payload[1];
|
||||
RADIOLIB_DEBUG_PRINTLN("Link check: margin = %d dB, gwCnt = %d", margin, gwCnt);
|
||||
return(true);
|
||||
if(margin) { *margin = payload[0]; }
|
||||
if(gwCnt) { *gwCnt = payload[1]; }
|
||||
// RADIOLIB_DEBUG_PRINTLN("Link check: margin = %d dB, gwCnt = %d", margin, gwCnt);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
bool LoRaWANNode::getMacDeviceTimeAns(uint32_t* gpsEpoch, uint8_t* fraction, bool returnUnix) {
|
||||
int16_t LoRaWANNode::getMacDeviceTimeAns(uint32_t* gpsEpoch, uint8_t* fraction, bool returnUnix) {
|
||||
uint8_t payload[5];
|
||||
int16_t state = deleteMacCommand(RADIOLIB_LORAWAN_MAC_DEVICE_TIME, &this->commandsDown, payload);
|
||||
if(state != RADIOLIB_ERR_NONE)
|
||||
return false;
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
*gpsEpoch = LoRaWANNode::ntoh<uint32_t>(&payload[0]);
|
||||
*fraction = payload[4];
|
||||
RADIOLIB_DEBUG_PRINTLN("Network time: gpsEpoch = %d s, delayExp = %f", gpsEpoch, (float)(*fraction)/256.0f);
|
||||
|
||||
uint32_t unixOffset = 315964800;
|
||||
*gpsEpoch += unixOffset;
|
||||
return(true);
|
||||
if(gpsEpoch) {
|
||||
*gpsEpoch = LoRaWANNode::ntoh<uint32_t>(&payload[0]);
|
||||
if(returnUnix) {
|
||||
uint32_t unixOffset = 315964800;
|
||||
*gpsEpoch += unixOffset;
|
||||
}
|
||||
}
|
||||
if(fraction) { *fraction = payload[4]; }
|
||||
// RADIOLIB_DEBUG_PRINTLN("Network time: gpsEpoch = %d s, delayExp = %f", gpsEpoch, (float)(*fraction)/256.0f);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2786,6 +2751,17 @@ void LoRaWANNode::processAES(uint8_t* in, size_t len, uint8_t* key, uint8_t* out
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t LoRaWANNode::checkSum16(uint8_t *key, uint8_t keyLen) {
|
||||
uint16_t buf16[RADIOLIB_AES128_KEY_SIZE/2];
|
||||
uint8_t bufLen = keyLen / 2;
|
||||
memcpy(buf16, key, bufLen);
|
||||
uint16_t checkSum = 0;
|
||||
for(int i = 0; i < bufLen; i++) {
|
||||
checkSum ^= buf16[i];
|
||||
}
|
||||
return(checkSum);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LoRaWANNode::ntoh(uint8_t* buff, size_t size) {
|
||||
uint8_t* buffPtr = buff;
|
||||
|
|
|
@ -159,9 +159,6 @@
|
|||
#define RADIOLIB_LORAWAN_MIC_DATA_RATE_POS (3)
|
||||
#define RADIOLIB_LORAWAN_MIC_CH_INDEX_POS (4)
|
||||
|
||||
// magic word saved in persistent memory upon activation
|
||||
#define RADIOLIB_LORAWAN_MAGIC (0x39EA)
|
||||
|
||||
// MAC commands
|
||||
#define RADIOLIB_LORAWAN_NUM_MAC_COMMANDS (16)
|
||||
|
||||
|
@ -191,6 +188,9 @@
|
|||
// the maximum number of simultaneously available channels
|
||||
#define RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS (16)
|
||||
|
||||
// maximum allowed dwell time on bands that implement dwell time limitations
|
||||
#define RADIOLIB_LORAWAN_DWELL_TIME (400)
|
||||
|
||||
struct LoRaWANMacSpec_t {
|
||||
const uint8_t cid;
|
||||
const uint8_t lenDn;
|
||||
|
@ -199,23 +199,23 @@ struct LoRaWANMacSpec_t {
|
|||
};
|
||||
|
||||
const LoRaWANMacSpec_t MacTable[RADIOLIB_LORAWAN_NUM_MAC_COMMANDS + 1] = {
|
||||
{ 0x00, 0, 0, false }, // not an actual MAC command, exists for offsetting
|
||||
{ 0x01, 1, 1, false }, // RADIOLIB_LORAWAN_MAC_RESET
|
||||
{ 0x02, 2, 0, true }, // RADIOLIB_LORAWAN_MAC_LINK_CHECK
|
||||
{ 0x03, 4, 1, false }, // RADIOLIB_LORAWAN_MAC_LINK_ADR
|
||||
{ 0x04, 1, 0, false }, // RADIOLIB_LORAWAN_MAC_DUTY_CYCLE
|
||||
{ 0x05, 4, 1, false }, // RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP
|
||||
{ 0x06, 0, 2, false }, // RADIOLIB_LORAWAN_MAC_DEV_STATUS
|
||||
{ 0x07, 5, 1, false }, // RADIOLIB_LORAWAN_MAC_NEW_CHANNEL
|
||||
{ 0x08, 1, 0, false }, // RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP
|
||||
{ 0x09, 1, 0, false }, // RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP
|
||||
{ 0x0A, 4, 1, false }, // RADIOLIB_LORAWAN_MAC_DL_CHANNEL
|
||||
{ 0x0B, 1, 1, false }, // RADIOLIB_LORAWAN_MAC_REKEY
|
||||
{ 0x0C, 1, 0, false }, // RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP
|
||||
{ 0x0D, 5, 0, true }, // RADIOLIB_LORAWAN_MAC_DEVICE_TIME
|
||||
{ 0x0E, 2, 0, false }, // RADIOLIB_LORAWAN_MAC_FORCE_REJOIN
|
||||
{ 0x0F, 1, 1, false }, // RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP
|
||||
{ 0x80, 5, 0, true } // RADIOLIB_LORAWAN_MAC_PROPRIETARY
|
||||
{ 0x00, 0, 0, false }, // not an actual MAC command, exists for index offsetting
|
||||
{ RADIOLIB_LORAWAN_MAC_RESET, 1, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_LINK_CHECK, 2, 0, true },
|
||||
{ RADIOLIB_LORAWAN_MAC_LINK_ADR, 4, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_DUTY_CYCLE, 1, 0, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP, 4, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_DEV_STATUS, 0, 2, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_NEW_CHANNEL, 5, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP, 1, 0, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP, 1, 0, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_DL_CHANNEL, 4, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_REKEY, 1, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP, 1, 0, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_DEVICE_TIME, 5, 0, true },
|
||||
{ RADIOLIB_LORAWAN_MAC_FORCE_REJOIN, 2, 0, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP, 1, 1, false },
|
||||
{ RADIOLIB_LORAWAN_MAC_PROPRIETARY, 5, 0, true }
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -681,9 +681,9 @@ class LoRaWANNode {
|
|||
Returns 'false' if there was no network response / parsing failed.
|
||||
\param margin Link margin in dB of LinkCheckReq demodulation at gateway side.
|
||||
\param gwCnt Number of gateways that received the LinkCheckReq.
|
||||
\returns Whether the parameters where succesfully parsed.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
bool getMacLinkCheckAns(uint8_t* margin, uint8_t* gwCnt);
|
||||
int16_t getMacLinkCheckAns(uint8_t* margin, uint8_t* gwCnt);
|
||||
|
||||
/*!
|
||||
\brief Returns the network time after requesting a DeviceTime MAC command.
|
||||
|
@ -692,9 +692,9 @@ class LoRaWANNode {
|
|||
\param gpsEpoch Number of seconds since GPS epoch (Jan. 6th 1980)
|
||||
\param fraction Fractional-second, in 1/256-second steps
|
||||
\param returnUnix If true, returns Unix timestamp instead of GPS (default true)
|
||||
\returns Whether the parameters where succesfully parsed.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
bool getMacDeviceTimeAns(uint32_t* gpsEpoch, uint8_t* fraction, bool returnUnix = true);
|
||||
int16_t getMacDeviceTimeAns(uint32_t* gpsEpoch, uint8_t* fraction, bool returnUnix = true);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
@ -876,6 +876,9 @@ class LoRaWANNode {
|
|||
// 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);
|
||||
|
||||
// 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum
|
||||
static uint16_t checkSum16(uint8_t *key, uint8_t keyLen);
|
||||
|
||||
// network-to-host conversion method - takes data from network packet and converts it to the host endians
|
||||
template<typename T>
|
||||
static T ntoh(uint8_t* buff, size_t size = 0);
|
||||
|
|
|
@ -53,7 +53,7 @@ const LoRaWANBand_t US915 = {
|
|||
.powerMax = 30,
|
||||
.powerNumSteps = 10,
|
||||
.dutyCycle = 0,
|
||||
.dwellTimeUp = 400,
|
||||
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
|
||||
.dwellTimeDn = 0,
|
||||
.txFreqs = {
|
||||
RADIOLIB_LORAWAN_CHANNEL_NONE,
|
||||
|
@ -334,8 +334,8 @@ const LoRaWANBand_t AS923 = {
|
|||
.powerMax = 16,
|
||||
.powerNumSteps = 7,
|
||||
.dutyCycle = 36000,
|
||||
.dwellTimeUp = 400,
|
||||
.dwellTimeDn = 400,
|
||||
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
|
||||
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
|
||||
.txFreqs = {
|
||||
{ .enabled = true, .idx = 0, .freq = 923.200, .drMin = 0, .drMax = 5},
|
||||
{ .enabled = true, .idx = 1, .freq = 923.400, .drMin = 0, .drMax = 5},
|
||||
|
|
Loading…
Add table
Reference in a new issue