Consolidate Lora memory usage

This commit is contained in:
Theo Arends 2024-03-30 15:02:20 +01:00
parent 6ccb3ae290
commit caed27645e
7 changed files with 201 additions and 215 deletions

View File

@ -183,13 +183,13 @@ typedef struct LoraSettings_t {
LoraEndNode_t end_node[TAS_LORAWAN_ENDNODES]; // End node parameters
#endif // USE_LORAWAN_BRIDGE
} LoraSettings_t;
LoraSettings_t* LoraSettings = nullptr;
typedef struct Lora_t {
bool (* Config)(void);
bool (* Available)(void);
int (* Receive)(char*);
bool (* Send)(uint8_t*, uint32_t, bool);
LoraSettings_t settings; // Persistent settings
uint32_t receive_time;
float rssi;
float snr;
@ -197,19 +197,15 @@ typedef struct Lora_t {
volatile bool received_flag; // flag to indicate that a packet was received
bool send_flag;
bool raw;
#ifdef USE_LORAWAN_BRIDGE
uint32_t device_address;
uint8_t* send_buffer;
uint8_t send_buffer_step;
uint8_t send_buffer_len;
bool rx;
#endif // USE_LORAWAN_BRIDGE
} Lora_t;
Lora_t* Lora = nullptr;
#ifdef USE_LORAWAN_BRIDGE
typedef struct Lorawan_t {
uint32_t device_address;
uint32_t send_buffer_step;
size_t send_buffer_len;
uint8_t send_buffer[64];
bool rx;
} Lorawan_t;
Lorawan_t* Lorawan = nullptr;
#endif // USE_LORAWAN_BRIDGE
#endif // USE_SPI_LORA
#endif // USE_SPI

View File

@ -29,7 +29,7 @@
//#define USE_LORA_SX126X_DEBUG
#include <RadioLib.h>
SX1262 LoRaRadio = nullptr; // Select LoRa support
SX1262 LoRaRadio = nullptr; // Select LoRa support
bool LoraSx126xBusy(void) {
// This is not consistently implemented in the used library
@ -49,12 +49,12 @@ void LoraSx126xOnInterrupt(void) {
if (!Lora->send_flag && !Lora->received_flag && !Lora->receive_time) {
Lora->receive_time = millis();
}
Lora->received_flag = true; // we got a packet, set the flag
Lora->received_flag = true; // we got a packet, set the flag
}
bool LoraSx126xAvailable(void) {
if (Lora->send_flag) {
Lora->received_flag = false; // Reset receive flag as it was caused by send interrupt
Lora->received_flag = false; // Reset receive flag as it was caused by send interrupt
uint32_t time = millis();
int state = LoRaRadio.startReceive(); // Put module back to listen mode
@ -73,14 +73,14 @@ bool LoraSx126xAvailable(void) {
#endif // USE_LORA_SX126X_DEBUG
if (0 == (irq_stat & RADIOLIB_SX126X_IRQ_RX_DONE)) {
Lora->received_flag = false; // Reset receive flag
Lora->received_flag = false; // Reset receive flag
}
}
return (Lora->received_flag); // Check if the receive flag is set
return (Lora->received_flag); // Check if the receive flag is set
}
int LoraSx126xReceive(char* data) {
Lora->received_flag = false; // Reset flag
Lora->received_flag = false; // Reset flag
int packet_size = LoRaRadio.getPacketLength();
int state = LoRaRadio.readData((uint8_t*)data, TAS_LORA_MAX_PACKET_LENGTH -1);
// LoRaWan downlink frames are sent without CRC, which will raise error on SX126x. We can ignore that error
@ -92,7 +92,7 @@ int LoraSx126xReceive(char* data) {
Lora->rssi = LoRaRadio.getRSSI();
Lora->snr = LoRaRadio.getSNR();
} else {
packet_size = 0; // Some other error occurred
packet_size = 0; // Some other error occurred
AddLog(LOG_LEVEL_DEBUG, PSTR("S6X: Receive error %d"), state);
}
return packet_size;
@ -107,7 +107,7 @@ bool LoraSx126xSend(uint8_t* data, uint32_t len, bool invert) {
LoraSx126xBusy();
}
int state = LoRaRadio.transmit(data, len);
Lora->send_flag = true; // Use this flag as LoRaRadio.transmit enable send interrupt
Lora->send_flag = true; // Use this flag as LoRaRadio.transmit enable send interrupt
if (invert) {
LoraSx126xBusy();
state2 = LoRaRadio.invertIQ(false);
@ -120,17 +120,17 @@ bool LoraSx126xSend(uint8_t* data, uint32_t len, bool invert) {
}
bool LoraSx126xConfig(void) {
LoRaRadio.setCodingRate(LoraSettings->coding_rate);
LoRaRadio.setSyncWord(LoraSettings->sync_word);
LoRaRadio.setPreambleLength(LoraSettings->preamble_length);
LoRaRadio.setCurrentLimit(LoraSettings->current_limit);
LoRaRadio.setCRC(LoraSettings->crc_bytes);
LoRaRadio.setSpreadingFactor(LoraSettings->spreading_factor);
LoRaRadio.setBandwidth(LoraSettings->bandwidth);
LoRaRadio.setFrequency(LoraSettings->frequency);
LoRaRadio.setOutputPower(LoraSettings->output_power);
if (LoraSettings->implicit_header) {
LoRaRadio.implicitHeader(LoraSettings->implicit_header);
LoRaRadio.setCodingRate(Lora->settings.coding_rate);
LoRaRadio.setSyncWord(Lora->settings.sync_word);
LoRaRadio.setPreambleLength(Lora->settings.preamble_length);
LoRaRadio.setCurrentLimit(Lora->settings.current_limit);
LoRaRadio.setCRC(Lora->settings.crc_bytes);
LoRaRadio.setSpreadingFactor(Lora->settings.spreading_factor);
LoRaRadio.setBandwidth(Lora->settings.bandwidth);
LoRaRadio.setFrequency(Lora->settings.frequency);
LoRaRadio.setOutputPower(Lora->settings.output_power);
if (Lora->settings.implicit_header) {
LoRaRadio.implicitHeader(Lora->settings.implicit_header);
} else {
LoRaRadio.explicitHeader();
}
@ -140,7 +140,7 @@ bool LoraSx126xConfig(void) {
bool LoraSx126xInit(void) {
LoRaRadio = new Module(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_DI1), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_BUSY));
if (RADIOLIB_ERR_NONE == LoRaRadio.begin(LoraSettings->frequency)) {
if (RADIOLIB_ERR_NONE == LoRaRadio.begin(Lora->settings.frequency)) {
LoraSx126xConfig();
LoRaRadio.setDio1Action(LoraSx126xOnInterrupt);
if (RADIOLIB_ERR_NONE == LoRaRadio.startReceive()) {

View File

@ -38,11 +38,11 @@ void LoraSx127xOnReceive(int packet_size) {
if (!Lora->receive_time) {
Lora->receive_time = millis();
}
Lora->packet_size = packet_size; // we got a packet, set the flag
Lora->packet_size = packet_size; // we got a packet, set the flag
}
bool LoraSx127xAvailable(void) {
return (Lora->packet_size > 0); // check if the flag is set
return (Lora->packet_size > 0); // check if the flag is set
}
int LoraSx127xReceive(char* data) {
@ -55,7 +55,7 @@ int LoraSx127xReceive(char* data) {
}
Lora->rssi = LoRa.packetRssi();
Lora->snr = LoRa.packetSnr();
Lora->packet_size = 0; // reset flag
Lora->packet_size = 0; // reset flag
return packet_size;
}
@ -63,7 +63,7 @@ bool LoraSx127xSend(uint8_t* data, uint32_t len, bool invert) {
if (invert) {
LoRa.enableInvertIQ(); // active invert I and Q signals
}
LoRa.beginPacket(LoraSettings->implicit_header); // start packet
LoRa.beginPacket(Lora->settings.implicit_header); // start packet
LoRa.write(data, len); // send message
LoRa.endPacket(); // finish packet and send it
if (invert) {
@ -74,21 +74,21 @@ bool LoraSx127xSend(uint8_t* data, uint32_t len, bool invert) {
}
bool LoraSx127xConfig(void) {
LoRa.setFrequency(LoraSettings->frequency * 1000 * 1000);
LoRa.setSignalBandwidth(LoraSettings->bandwidth * 1000);
LoRa.setSpreadingFactor(LoraSettings->spreading_factor);
LoRa.setCodingRate4(LoraSettings->coding_rate);
LoRa.setSyncWord(LoraSettings->sync_word);
LoRa.setTxPower(LoraSettings->output_power);
LoRa.setPreambleLength(LoraSettings->preamble_length);
LoRa.setOCP(LoraSettings->current_limit);
if (LoraSettings->crc_bytes) {
LoRa.setFrequency(Lora->settings.frequency * 1000 * 1000);
LoRa.setSignalBandwidth(Lora->settings.bandwidth * 1000);
LoRa.setSpreadingFactor(Lora->settings.spreading_factor);
LoRa.setCodingRate4(Lora->settings.coding_rate);
LoRa.setSyncWord(Lora->settings.sync_word);
LoRa.setTxPower(Lora->settings.output_power);
LoRa.setPreambleLength(Lora->settings.preamble_length);
LoRa.setOCP(Lora->settings.current_limit);
if (Lora->settings.crc_bytes) {
LoRa.enableCrc();
} else {
LoRa.disableCrc();
}
/*
if (LoraSettings->implicit_header) {
if (Lora->settings.implicit_header) {
LoRa.implicitHeaderMode();
} else {
LoRa.explicitHeaderMode();
@ -100,7 +100,7 @@ bool LoraSx127xConfig(void) {
bool LoraSx127xInit(void) {
LoRa.setPins(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_DI0));
if (LoRa.begin(LoraSettings->frequency * 1000 * 1000)) {
if (LoRa.begin(Lora->settings.frequency * 1000 * 1000)) {
LoraSx127xConfig();
LoRa.onReceive(LoraSx127xOnReceive);
LoRa.receive();

View File

@ -69,7 +69,7 @@ void _LoraWanDeriveLegacyAppSKey(uint8_t* key, uint32_t jn, uint32_t nid, uint16
}
void LoraWanDeriveLegacyAppSKey(uint32_t node, uint8_t* AppSKey) {
_LoraWanDeriveLegacyAppSKey(LoraSettings->end_node[node].AppKey, TAS_LORAWAN_JOINNONCE +node, TAS_LORAWAN_NETID, LoraSettings->end_node[node].DevNonce, AppSKey);
_LoraWanDeriveLegacyAppSKey(Lora->settings.end_node[node].AppKey, TAS_LORAWAN_JOINNONCE +node, TAS_LORAWAN_NETID, Lora->settings.end_node[node].DevNonce, AppSKey);
}
// DeriveLegacyNwkSKey derives the LoRaWAN 1.0 Network Session Key. AppNonce is entered as JoinNonce.
@ -82,7 +82,7 @@ void _LoraWanDeriveLegacyNwkSKey(uint8_t* appKey, uint32_t jn, uint32_t nid, uin
}
void LoraWanDeriveLegacyNwkSKey(uint32_t node, uint8_t* NwkSKey) {
_LoraWanDeriveLegacyNwkSKey(LoraSettings->end_node[node].AppKey, TAS_LORAWAN_JOINNONCE +node, TAS_LORAWAN_NETID, LoraSettings->end_node[node].DevNonce, NwkSKey);
_LoraWanDeriveLegacyNwkSKey(Lora->settings.end_node[node].AppKey, TAS_LORAWAN_JOINNONCE +node, TAS_LORAWAN_NETID, Lora->settings.end_node[node].DevNonce, NwkSKey);
}
#ifdef USE_LORAWAN_TEST

View File

@ -29,11 +29,11 @@ void LoraWanPublishHeader(uint32_t node) {
}
if (!Settings->flag5.zb_omit_json_addr) { // SetOption119 - (Zigbee) Remove the device addr from json payload, can be used with zb_topic_fname where the addr is already known from the topic
ResponseAppend_P(PSTR("{\"%s\":"), EscapeJSONString(LoraSettings->end_node[node].name.c_str()).c_str());
ResponseAppend_P(PSTR("{\"%s\":"), EscapeJSONString(Lora->settings.end_node[node].name.c_str()).c_str());
}
ResponseAppend_P(PSTR("{\"Node\":%d,\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), node +1, LoraSettings->end_node[node].DevEUIl & 0x0000FFFF);
if (!LoraSettings->end_node[node].name.startsWith(F("0x"))) {
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), EscapeJSONString(LoraSettings->end_node[node].name.c_str()).c_str());
ResponseAppend_P(PSTR("{\"Node\":%d,\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), node +1, Lora->settings.end_node[node].DevEUIl & 0x0000FFFF);
if (!Lora->settings.end_node[node].name.startsWith(F("0x"))) {
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), EscapeJSONString(Lora->settings.end_node[node].name.c_str()).c_str());
}
ResponseAppend_P(PSTR(",\"RSSI\":%1_f,\"SNR\":%1_f"), &Lora->rssi, &Lora->snr);
}
@ -57,7 +57,7 @@ void LoraWanPublishFooter(uint32_t node) {
char subtopic[TOPSZ];
// Clean special characters
char stemp[TOPSZ];
strlcpy(stemp, LoraSettings->end_node[node].name.c_str(), sizeof(stemp));
strlcpy(stemp, Lora->settings.end_node[node].name.c_str(), sizeof(stemp));
MakeValidMqtt(0, stemp);
if (Settings->flag5.zigbee_hide_bridge_topic) { // SetOption125 - (Zigbee) Hide bridge topic from zigbee topic (use with SetOption89) (1)
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s"), stemp);
@ -87,8 +87,8 @@ void LoraWanDecode(struct LoraNodeData_t* node_data) {
uint8_t node;
uint8_t FPort;
*/
if (bitRead(LoraSettings->flags, TAS_LORA_FLAG_DECODE_ENABLED)) { // LoraOption3 1
if (0x00161600 == LoraSettings->end_node[node_data->node].DevEUIh) { // MerryIoT
if (bitRead(Lora->settings.flags, TAS_LORA_FLAG_DECODE_ENABLED)) { // LoraOption3 1
if (0x00161600 == Lora->settings.end_node[node_data->node].DevEUIh) { // MerryIoT
if (120 == node_data->FPort) { // MerryIoT door/window Sensor (DW10)
if (9 == node_data->payload_len) { // MerryIoT Sensor state
// 1 2 3 4 5 6 7 8 9
@ -102,7 +102,7 @@ void LoraWanDecode(struct LoraNodeData_t* node_data) {
uint32_t events = node_data->payload[6] | (node_data->payload[7] << 8) | (node_data->payload[8] << 16);
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Node %d, DevEUI %08X%08X, Events %d, LastEvent %d min, DoorOpen %d, Button %d, Tamper %d, Tilt %d, Battery %1_fV, Temp %d, Hum %d"),
node_data->node +1, LoraSettings->end_node[node_data->node].DevEUIh, LoraSettings->end_node[node_data->node].DevEUIl,
node_data->node +1, Lora->settings.end_node[node_data->node].DevEUIh, Lora->settings.end_node[node_data->node].DevEUIl,
events, elapsed_time,
bitRead(status, 0), bitRead(status, 1), bitRead(status, 2), bitRead(status, 3),
&battery_volt,
@ -122,7 +122,7 @@ void LoraWanDecode(struct LoraNodeData_t* node_data) {
}
}
else if (0xA840410E == LoraSettings->end_node[node_data->node].DevEUIh) { // Dragino
else if (0xA840410E == Lora->settings.end_node[node_data->node].DevEUIh) { // Dragino
if (10 == node_data->FPort) { // Dragino LDS02
// 8CD2 01 000010 000000 00 - Door Open, 3.282V
// 0CD2 01 000011 000000 00 - Door Closed
@ -134,7 +134,7 @@ void LoraWanDecode(struct LoraNodeData_t* node_data) {
uint8_t alarm = node_data->payload[9];
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Node %d, DevEUI %08X%08X, Events %d, LastEvent %d min, DoorOpen %d, Battery %3_fV, Alarm %d"),
node_data->node +1, LoraSettings->end_node[node_data->node].DevEUIh, LoraSettings->end_node[node_data->node].DevEUIl,
node_data->node +1, Lora->settings.end_node[node_data->node].DevEUIh, Lora->settings.end_node[node_data->node].DevEUIl,
events, open_duration,
bitRead(status, 7),
&battery_volt,
@ -152,7 +152,7 @@ void LoraWanDecode(struct LoraNodeData_t* node_data) {
// Joined device without decoding
LoraWanPublishHeader(node_data->node);
ResponseAppend_P(PSTR(",\"DevEUIh\":\"%08X\",\"DevEUIl\":\"%08X\",\"FPort\":%d,\"Payload\":["),
LoraSettings->end_node[node_data->node].DevEUIh, LoraSettings->end_node[node_data->node].DevEUIl, node_data->FPort);
Lora->settings.end_node[node_data->node].DevEUIh, Lora->settings.end_node[node_data->node].DevEUIl, node_data->FPort);
for (uint32_t i = 0; i < node_data->payload_len; i++) {
ResponseAppend_P(PSTR("%s%d"), (0==i)?"":",", node_data->payload[i]);
}

View File

@ -93,18 +93,18 @@ bool LoraWanLoadData(void) {
app_key = root.getStr(PSTR(D_JSON_APPKEY), nullptr);
if (strlen(app_key)) {
size_t out_len = TAS_LORAWAN_AES128_KEY_SIZE;
HexToBytes(app_key, LoraSettings->end_node[n].AppKey, &out_len);
HexToBytes(app_key, Lora->settings.end_node[n].AppKey, &out_len);
}
LoraSettings->end_node[n].DevEUIh = root.getUInt(PSTR(D_JSON_DEVEUI "h"), LoraSettings->end_node[n].DevEUIh);
LoraSettings->end_node[n].DevEUIl = root.getUInt(PSTR(D_JSON_DEVEUI "l"), LoraSettings->end_node[n].DevEUIl);
LoraSettings->end_node[n].DevNonce = root.getUInt(PSTR(D_JSON_DEVNONCE), LoraSettings->end_node[n].DevNonce);
LoraSettings->end_node[n].FCntUp = root.getUInt(PSTR(D_JSON_FCNTUP), LoraSettings->end_node[n].FCntUp);
LoraSettings->end_node[n].FCntDown = root.getUInt(PSTR(D_JSON_FCNTDOWN), LoraSettings->end_node[n].FCntDown);
LoraSettings->end_node[n].flags = root.getUInt(PSTR(D_JSON_FLAGS), LoraSettings->end_node[n].flags);
Lora->settings.end_node[n].DevEUIh = root.getUInt(PSTR(D_JSON_DEVEUI "h"), Lora->settings.end_node[n].DevEUIh);
Lora->settings.end_node[n].DevEUIl = root.getUInt(PSTR(D_JSON_DEVEUI "l"), Lora->settings.end_node[n].DevEUIl);
Lora->settings.end_node[n].DevNonce = root.getUInt(PSTR(D_JSON_DEVNONCE), Lora->settings.end_node[n].DevNonce);
Lora->settings.end_node[n].FCntUp = root.getUInt(PSTR(D_JSON_FCNTUP), Lora->settings.end_node[n].FCntUp);
Lora->settings.end_node[n].FCntDown = root.getUInt(PSTR(D_JSON_FCNTDOWN), Lora->settings.end_node[n].FCntDown);
Lora->settings.end_node[n].flags = root.getUInt(PSTR(D_JSON_FLAGS), Lora->settings.end_node[n].flags);
const char* name = nullptr;
name = root.getStr(PSTR(D_JSON_NAME), nullptr);
if (strlen(app_key)) {
LoraSettings->end_node[n].name = name;
Lora->settings.end_node[n].name = name;
}
}
return true;
@ -113,7 +113,7 @@ bool LoraWanLoadData(void) {
bool LoraWanSaveData(void) {
bool result = false;
for (uint32_t n = 0; n < TAS_LORAWAN_ENDNODES; n++) {
if (LoraSettings->end_node[n].AppKey[0] > 0) { // Only save used slots
if (Lora->settings.end_node[n].AppKey[0] > 0) { // Only save used slots
Response_P(PSTR("{\"" XDRV_73_KEY "_%d\":{\"" D_JSON_APPKEY "\":\"%16_H\""
",\"" D_JSON_DEVEUI "h\":%lu,\"" D_JSON_DEVEUI "l\":%lu"
",\"" D_JSON_DEVNONCE "\":%u"
@ -121,12 +121,12 @@ bool LoraWanSaveData(void) {
",\"" D_JSON_FLAGS "\":%u"
",\"" D_JSON_NAME "\":\"%s\"}}"),
n +1,
LoraSettings->end_node[n].AppKey,
LoraSettings->end_node[n].DevEUIh,LoraSettings->end_node[n].DevEUIl,
LoraSettings->end_node[n].DevNonce,
LoraSettings->end_node[n].FCntUp, LoraSettings->end_node[n].FCntDown,
LoraSettings->end_node[n].flags,
LoraSettings->end_node[n].name.c_str());
Lora->settings.end_node[n].AppKey,
Lora->settings.end_node[n].DevEUIh, Lora->settings.end_node[n].DevEUIl,
Lora->settings.end_node[n].DevNonce,
Lora->settings.end_node[n].FCntUp, Lora->settings.end_node[n].FCntDown,
Lora->settings.end_node[n].flags,
Lora->settings.end_node[n].name.c_str());
result = UfsJsonSettingsWrite(ResponseData());
}
}
@ -148,21 +148,24 @@ void LoraWanDeleteData(void) {
Ticker LoraWan_Send;
void LoraWanTickerSend(void) {
Lorawan->send_buffer_step--;
if (1 == Lorawan->send_buffer_step) {
Lorawan->rx = true; // Always send during RX1
Lora->receive_time = 0; // Reset receive timer
Lora->send_buffer_step--;
if (1 == Lora->send_buffer_step) {
Lora->rx = true; // Always send during RX1
Lora->receive_time = 0; // Reset receive timer
LoraWan_Send.once_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms
}
if (Lorawan->rx) { // If received in RX1 do not resend in RX2
LoraSend(Lorawan->send_buffer, Lorawan->send_buffer_len, true);
if (Lora->rx) { // If received in RX1 do not resend in RX2
LoraSend(Lora->send_buffer, Lora->send_buffer_len, true);
}
}
void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
memcpy(Lorawan->send_buffer, buffer, sizeof(Lorawan->send_buffer));
Lorawan->send_buffer_len = len;
Lorawan->send_buffer_step = 2;
free(Lora->send_buffer); // Free previous buffer (if any)
Lora->send_buffer = (uint8_t*)malloc(len +1);
if (nullptr == Lora->send_buffer) { return; }
memcpy(Lora->send_buffer, buffer, len);
Lora->send_buffer_len = len;
Lora->send_buffer_step = 2; // Send at RX1 and RX2
LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora->receive_time), LoraWanTickerSend);
}
@ -170,19 +173,19 @@ void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
uint32_t LoraWanSpreadingFactorToDataRate(void) {
// Allow only JoinReq message datarates (125kHz bandwidth)
if (LoraSettings->spreading_factor > 12) {
LoraSettings->spreading_factor = 12;
if (Lora->settings.spreading_factor > 12) {
Lora->settings.spreading_factor = 12;
}
if (LoraSettings->spreading_factor < 7) {
LoraSettings->spreading_factor = 7;
if (Lora->settings.spreading_factor < 7) {
Lora->settings.spreading_factor = 7;
}
LoraSettings->bandwidth = 125;
return 12 - LoraSettings->spreading_factor;
Lora->settings.bandwidth = 125;
return 12 - Lora->settings.spreading_factor;
}
uint32_t LoraWanFrequencyToChannel(void) {
// EU863-870 (EU868) JoinReq message frequencies are 868.1, 868.3 and 868.5
uint32_t frequency = (LoraSettings->frequency * 10);
uint32_t frequency = (Lora->settings.frequency * 10);
uint32_t channel = 250;
if (8681 == frequency) {
channel = 0;
@ -194,7 +197,7 @@ uint32_t LoraWanFrequencyToChannel(void) {
channel = 2;
}
if (250 == channel) {
LoraSettings->frequency = 868.1;
Lora->settings.frequency = 868.1;
Lora->Config();
channel = 0;
}
@ -204,8 +207,8 @@ uint32_t LoraWanFrequencyToChannel(void) {
/*********************************************************************************************/
void LoraWanSendLinkADRReq(uint32_t node) {
uint32_t DevAddr = Lorawan->device_address +node;
uint16_t FCnt = LoraSettings->end_node[node].FCntDown++;
uint32_t DevAddr = Lora->device_address +node;
uint16_t FCnt = Lora->settings.end_node[node].FCntDown++;
uint8_t NwkSKey[TAS_LORAWAN_AES128_KEY_SIZE];
LoraWanDeriveLegacyNwkSKey(node, NwkSKey);
@ -236,7 +239,7 @@ void LoraWanSendLinkADRReq(uint32_t node) {
bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
bool result = false;
uint32_t MType = data[0] >> 5; // Upper three bits (used to be called FType)
uint32_t MType = data[0] >> 5; // Upper three bits (used to be called FType)
if (TAS_LORAWAN_MTYPE_JOIN_REQUEST == MType) {
// 0007010000004140A8D64A89710E4140A82893A8AD137F - Dragino
@ -254,26 +257,26 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
((uint32_t)data[21] << 16) | ((uint32_t)data[22] << 24);
for (uint32_t node = 0; node < TAS_LORAWAN_ENDNODES; node++) {
uint32_t CalcMIC = LoraWanGenerateMIC(data, 19, LoraSettings->end_node[node].AppKey);
if (MIC == CalcMIC) { // Valid MIC based on LoraWanAppKey
uint32_t CalcMIC = LoraWanGenerateMIC(data, 19, Lora->settings.end_node[node].AppKey);
if (MIC == CalcMIC) { // Valid MIC based on LoraWanAppKey
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: JoinEUI %8_H, DevEUIh %08X, DevEUIl %08X, DevNonce %04X, MIC %08X"),
(uint8_t*)&JoinEUI, DevEUIh, DevEUIl, DevNonce, MIC);
LoraSettings->end_node[node].DevEUIl = DevEUIl;
LoraSettings->end_node[node].DevEUIh = DevEUIh;
LoraSettings->end_node[node].DevNonce = DevNonce;
LoraSettings->end_node[node].FCntUp = 0;
LoraSettings->end_node[node].FCntDown = 0;
bitClear(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
if (LoraSettings->end_node[node].name.equals(F("0x0000"))) {
Lora->settings.end_node[node].DevEUIl = DevEUIl;
Lora->settings.end_node[node].DevEUIh = DevEUIh;
Lora->settings.end_node[node].DevNonce = DevNonce;
Lora->settings.end_node[node].FCntUp = 0;
Lora->settings.end_node[node].FCntDown = 0;
bitClear(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
if (Lora->settings.end_node[node].name.equals(F("0x0000"))) {
char name[10];
ext_snprintf_P(name, sizeof(name), PSTR("0x%04X"), LoraSettings->end_node[node].DevEUIl & 0x0000FFFF);
LoraSettings->end_node[node].name = name;
ext_snprintf_P(name, sizeof(name), PSTR("0x%04X"), Lora->settings.end_node[node].DevEUIl & 0x0000FFFF);
Lora->settings.end_node[node].name = name;
}
uint32_t JoinNonce = TAS_LORAWAN_JOINNONCE +node;
uint32_t DevAddr = Lorawan->device_address +node;
uint32_t DevAddr = Lora->device_address +node;
uint32_t NetID = TAS_LORAWAN_NETID;
uint8_t join_data[33] = { 0 };
join_data[0] = TAS_LORAWAN_MTYPE_JOIN_ACCEPT << 5;
@ -288,16 +291,16 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
join_data[9] = DevAddr >> 16;
join_data[10] = DevAddr >> 24;
join_data[11] = LoraWanSpreadingFactorToDataRate(); // DLSettings
join_data[12] = 1; // RXDelay;
join_data[12] = 1; // RXDelay;
uint32_t NewMIC = LoraWanGenerateMIC(join_data, 13, LoraSettings->end_node[node].AppKey);
uint32_t NewMIC = LoraWanGenerateMIC(join_data, 13, Lora->settings.end_node[node].AppKey);
join_data[13] = NewMIC;
join_data[14] = NewMIC >> 8;
join_data[15] = NewMIC >> 16;
join_data[16] = NewMIC >> 24;
uint8_t EncData[33];
EncData[0] = join_data[0];
LoraWanEncryptJoinAccept(LoraSettings->end_node[node].AppKey, &join_data[1], 16, &EncData[1]);
LoraWanEncryptJoinAccept(Lora->settings.end_node[node].AppKey, &join_data[1], 16, &EncData[1]);
// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Join %17_H"), join_data);
@ -335,12 +338,12 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
uint32_t DevAddr = (uint32_t)data[1] | ((uint32_t)data[2] << 8) | ((uint32_t)data[3] << 16) | ((uint32_t)data[4] << 24);
for (uint32_t node = 0; node < TAS_LORAWAN_ENDNODES; node++) {
if (0 == LoraSettings->end_node[node].DevEUIh) { continue; } // No DevEUI so never joined
if ((Lorawan->device_address +node) != DevAddr) { continue; } // Not my device
if (0 == Lora->settings.end_node[node].DevEUIh) { continue; } // No DevEUI so never joined
if ((Lora->device_address +node) != DevAddr) { continue; } // Not my device
uint32_t FCtrl = data[5];
uint32_t FOptsLen = FCtrl & 0x0F;
uint32_t FCnt = (LoraSettings->end_node[node].FCntUp & 0xFFFF0000) | data[6] | (data[7] << 8);
uint32_t FCnt = (Lora->settings.end_node[node].FCntUp & 0xFFFF0000) | data[6] | (data[7] << 8);
uint8_t* FOpts = &data[8];
uint32_t FPort = data[8 +FOptsLen];
uint8_t* FRMPayload = &data[9 +FOptsLen];
@ -372,11 +375,11 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
LoraWanDecryptUplink(Key, DevAddr, FCnt, FRMPayload, payload_len, 0, payload_decrypted);
}
uint32_t org_payload_len = payload_len; // Save for logging
if ((0 == FOptsLen) && (0 == FOpts[0])) { // MAC response in payload only
FOptsLen = payload_len; // Payload length is MAC length
FOpts = payload_decrypted; // Payload is encrypted MAC
payload_len = 0; // Payload is MAC only
uint32_t org_payload_len = payload_len; // Save for logging
if ((0 == FOptsLen) && (0 == FOpts[0])) { // MAC response in payload only
FOptsLen = payload_len; // Payload length is MAC length
FOpts = payload_decrypted; // Payload is encrypted MAC
payload_len = 0; // Payload is MAC only
}
#ifdef USE_LORA_DEBUG
@ -384,17 +387,17 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
DevAddr, FCtrl, FOptsLen, FCnt, FOptsLen, FOpts, FPort, org_payload_len, FRMPayload, org_payload_len, payload_decrypted, MIC);
#endif // USE_LORA_DEBUG
if (LoraSettings->end_node[node].FCntUp <= FCnt) { // Skip re-transmissions
Lorawan->rx = false; // Skip RX2 as this is a response from RX1
LoraSettings->end_node[node].FCntUp++;
if (LoraSettings->end_node[node].FCntUp < FCnt) { // Report missed frames
uint32_t FCnt_missed = FCnt - LoraSettings->end_node[node].FCntUp;
if (Lora->settings.end_node[node].FCntUp <= FCnt) { // Skip re-transmissions
Lora->rx = false; // Skip RX2 as this is a response from RX1
Lora->settings.end_node[node].FCntUp++;
if (Lora->settings.end_node[node].FCntUp < FCnt) { // Report missed frames
uint32_t FCnt_missed = FCnt - Lora->settings.end_node[node].FCntUp;
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Missed frames %d"), FCnt_missed);
if (FCnt_missed > 1) { // Missed two or more frames
bitClear(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ); // Resend LinkADRReq
if (FCnt_missed > 1) { // Missed two or more frames
bitClear(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ); // Resend LinkADRReq
}
}
LoraSettings->end_node[node].FCntUp = FCnt;
Lora->settings.end_node[node].FCntUp = FCnt;
if (FOptsLen) {
uint32_t i = 0;
@ -408,7 +411,7 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
uint8_t status = FOpts[i];
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: MAC LinkADRAns PowerACK %d, DataRateACK %d, ChannelMaskACK %d"),
bitRead(status, 2), bitRead(status, 1), bitRead(status, 0));
bitSet(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
bitSet(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
}
else if (TAS_LORAWAN_CID_DUTY_CYCLE_ANS == FOpts[i]) {
i++;
@ -450,20 +453,20 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
node_data.FPort = FPort;
LoraWanDecode(&node_data);
if (0xA840410E == LoraSettings->end_node[node].DevEUIh) { // Dragino
if (0xA840410E == Lora->settings.end_node[node].DevEUIh) { // Dragino
// Dragino v1.7 fails to set DR with ADR so set it using serial interface:
// Password 123456
// AT+CHS=868100000
// Start join using reset button
// AT+CADR=0
// AT+CDATARATE=3
bitSet(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
bitSet(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
}
if (TAS_LORAWAN_MTYPE_CONFIRMED_DATA_UPLINK == MType) {
data[0] = TAS_LORAWAN_MTYPE_UNCONFIRMED_DATA_DOWNLINK << 5;
data[5] |= 0x20; // FCtrl Set ACK bit
uint16_t FCnt = LoraSettings->end_node[node].FCntDown++;
data[5] |= 0x20; // FCtrl Set ACK bit
uint16_t FCnt = Lora->settings.end_node[node].FCntDown++;
data[6] = FCnt;
data[7] = FCnt >> 8;
uint32_t MIC = LoraWanComputeLegacyDownlinkMIC(NwkSKey, DevAddr, FCnt, data, packet_size -4);
@ -475,10 +478,10 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
}
}
if (TAS_LORAWAN_MTYPE_UNCONFIRMED_DATA_UPLINK == MType) {
if (!bitRead(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ) &&
if (!bitRead(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ) &&
FCtrl_ADR && !FCtrl_ACK) {
// Try to fix single channel and datarate
LoraWanSendLinkADRReq(node); // Resend LinkADRReq
LoraWanSendLinkADRReq(node); // Resend LinkADRReq
}
}
}
@ -509,14 +512,14 @@ void CmndLoraWanBridge(void) {
// LoraWanBridge 1 - Set LoraOption1 1 = Enable LoraWanBridge
uint32_t pindex = 0;
if (XdrvMailbox.payload >= 0) {
bitWrite(LoraSettings->flags, pindex, XdrvMailbox.payload);
bitWrite(Lora->settings.flags, pindex, XdrvMailbox.payload);
}
#ifdef USE_LORAWAN_TEST
LoraWanTestKeyDerivation();
LorWanTestUplinkDownlinkEncryption();
LorWanTestUplinkDownlinkMIC();
#endif // USE_LORAWAN_TEST
ResponseCmndChar(GetStateText(bitRead(LoraSettings->flags, pindex)));
ResponseCmndChar(GetStateText(bitRead(Lora->settings.flags, pindex)));
}
void CmndLoraWanAppKey(void) {
@ -526,16 +529,16 @@ void CmndLoraWanAppKey(void) {
uint32_t node = XdrvMailbox.index -1;
if (32 == XdrvMailbox.data_len) {
size_t out_len = 16;
HexToBytes(XdrvMailbox.data, LoraSettings->end_node[node].AppKey, &out_len);
if (0 == LoraSettings->end_node[node].name.length()) {
LoraSettings->end_node[node].name = F("0x0000");
HexToBytes(XdrvMailbox.data, Lora->settings.end_node[node].AppKey, &out_len);
if (0 == Lora->settings.end_node[node].name.length()) {
Lora->settings.end_node[node].name = F("0x0000");
}
}
else if (0 == XdrvMailbox.payload) {
memset(&LoraSettings->end_node[node], 0, sizeof(LoraEndNode_t));
memset(&Lora->settings.end_node[node], 0, sizeof(LoraEndNode_t));
}
char appkey[33];
ext_snprintf_P(appkey, sizeof(appkey), PSTR("%16_H"), LoraSettings->end_node[node].AppKey);
ext_snprintf_P(appkey, sizeof(appkey), PSTR("%16_H"), Lora->settings.end_node[node].AppKey);
ResponseCmndIdxChar(appkey);
}
}
@ -549,13 +552,13 @@ void CmndLoraWanName(void) {
if (XdrvMailbox.data_len) {
if (1 == XdrvMailbox.payload) {
char name[10];
ext_snprintf_P(name, sizeof(name), PSTR("0x%04X"), LoraSettings->end_node[node].DevEUIl & 0x0000FFFF);
LoraSettings->end_node[node].name = name;
ext_snprintf_P(name, sizeof(name), PSTR("0x%04X"), Lora->settings.end_node[node].DevEUIl & 0x0000FFFF);
Lora->settings.end_node[node].name = name;
} else {
LoraSettings->end_node[node].name = XdrvMailbox.data;
Lora->settings.end_node[node].name = XdrvMailbox.data;
}
}
ResponseCmndIdxChar(LoraSettings->end_node[node].name.c_str());
ResponseCmndIdxChar(Lora->settings.end_node[node].name.c_str());
}
}
@ -563,16 +566,12 @@ void CmndLoraWanName(void) {
* Interface
\*********************************************************************************************/
bool LoraWanInit(void) {
Lorawan = (Lorawan_t*)calloc(sizeof(Lorawan_t), 1); // Need calloc to reset registers to 0/false
if (nullptr == Lorawan) { return false; }
void LoraWanInit(void) {
// The Things Network has been assigned a 7-bits "device address prefix" a.k.a. NwkID
// %0010011. Using that, TTN currently sends NetID 0x000013, and a TTN DevAddr always
// starts with 0x26 or 0x27
// Private networks are supposed to used NetID 0x000000.
Lorawan->device_address = (TAS_LORAWAN_NETID << 25) | (ESP_getChipId() & 0x01FFFFFF);
return true;
Lora->device_address = (TAS_LORAWAN_NETID << 25) | (ESP_getChipId() & 0x01FFFFFF);
}
#endif // USE_LORAWAN_BRIDGE

View File

@ -17,55 +17,55 @@
/*********************************************************************************************/
void LoraDefaults(void) {
LoraSettings->frequency = TAS_LORA_FREQUENCY;
LoraSettings->bandwidth = TAS_LORA_BANDWIDTH;
LoraSettings->spreading_factor = TAS_LORA_SPREADING_FACTOR;
LoraSettings->coding_rate = TAS_LORA_CODING_RATE;
LoraSettings->sync_word = TAS_LORA_SYNC_WORD;
LoraSettings->output_power = TAS_LORA_OUTPUT_POWER;
LoraSettings->preamble_length = TAS_LORA_PREAMBLE_LENGTH;
LoraSettings->current_limit = TAS_LORA_CURRENT_LIMIT;
LoraSettings->implicit_header = TAS_LORA_HEADER;
LoraSettings->crc_bytes = TAS_LORA_CRC_BYTES;
Lora->settings.frequency = TAS_LORA_FREQUENCY;
Lora->settings.bandwidth = TAS_LORA_BANDWIDTH;
Lora->settings.spreading_factor = TAS_LORA_SPREADING_FACTOR;
Lora->settings.coding_rate = TAS_LORA_CODING_RATE;
Lora->settings.sync_word = TAS_LORA_SYNC_WORD;
Lora->settings.output_power = TAS_LORA_OUTPUT_POWER;
Lora->settings.preamble_length = TAS_LORA_PREAMBLE_LENGTH;
Lora->settings.current_limit = TAS_LORA_CURRENT_LIMIT;
Lora->settings.implicit_header = TAS_LORA_HEADER;
Lora->settings.crc_bytes = TAS_LORA_CRC_BYTES;
}
void LoraWanDefaults(void) {
LoraSettings->frequency = TAS_LORAWAN_FREQUENCY;
LoraSettings->bandwidth = TAS_LORAWAN_BANDWIDTH;
LoraSettings->spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
LoraSettings->coding_rate = TAS_LORAWAN_CODING_RATE;
LoraSettings->sync_word = TAS_LORAWAN_SYNC_WORD;
LoraSettings->output_power = TAS_LORAWAN_OUTPUT_POWER;
LoraSettings->preamble_length = TAS_LORAWAN_PREAMBLE_LENGTH;
LoraSettings->current_limit = TAS_LORAWAN_CURRENT_LIMIT;
LoraSettings->implicit_header = TAS_LORAWAN_HEADER;
LoraSettings->crc_bytes = TAS_LORAWAN_CRC_BYTES;
Lora->settings.frequency = TAS_LORAWAN_FREQUENCY;
Lora->settings.bandwidth = TAS_LORAWAN_BANDWIDTH;
Lora->settings.spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
Lora->settings.coding_rate = TAS_LORAWAN_CODING_RATE;
Lora->settings.sync_word = TAS_LORAWAN_SYNC_WORD;
Lora->settings.output_power = TAS_LORAWAN_OUTPUT_POWER;
Lora->settings.preamble_length = TAS_LORAWAN_PREAMBLE_LENGTH;
Lora->settings.current_limit = TAS_LORAWAN_CURRENT_LIMIT;
Lora->settings.implicit_header = TAS_LORAWAN_HEADER;
Lora->settings.crc_bytes = TAS_LORAWAN_CRC_BYTES;
}
void LoraSettings2Json(void) {
ResponseAppend_P(PSTR("\"" D_JSON_FREQUENCY "\":%1_f"), &LoraSettings->frequency); // xxx.x MHz
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &LoraSettings->bandwidth); // xxx.x kHz
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":%d"), LoraSettings->spreading_factor);
ResponseAppend_P(PSTR(",\"" D_JSON_CODINGRATE4 "\":%d"), LoraSettings->coding_rate);
ResponseAppend_P(PSTR(",\"" D_JSON_SYNCWORD "\":%d"), LoraSettings->sync_word);
ResponseAppend_P(PSTR(",\"" D_JSON_OUTPUT_POWER "\":%d"), LoraSettings->output_power); // dBm
ResponseAppend_P(PSTR(",\"" D_JSON_PREAMBLE_LENGTH "\":%d"), LoraSettings->preamble_length); // symbols
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT_LIMIT "\":%1_f"), &LoraSettings->current_limit); // xx.x mA (Overcurrent Protection - OCP)
ResponseAppend_P(PSTR(",\"" D_JSON_IMPLICIT_HEADER "\":%d"), LoraSettings->implicit_header); // 0 = explicit
ResponseAppend_P(PSTR(",\"" D_JSON_CRC_BYTES "\":%d"), LoraSettings->crc_bytes); // bytes
ResponseAppend_P(PSTR("\"" D_JSON_FREQUENCY "\":%1_f"), &Lora->settings.frequency); // xxx.x MHz
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &Lora->settings.bandwidth); // xxx.x kHz
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":%d"), Lora->settings.spreading_factor);
ResponseAppend_P(PSTR(",\"" D_JSON_CODINGRATE4 "\":%d"), Lora->settings.coding_rate);
ResponseAppend_P(PSTR(",\"" D_JSON_SYNCWORD "\":%d"), Lora->settings.sync_word);
ResponseAppend_P(PSTR(",\"" D_JSON_OUTPUT_POWER "\":%d"), Lora->settings.output_power); // dBm
ResponseAppend_P(PSTR(",\"" D_JSON_PREAMBLE_LENGTH "\":%d"), Lora->settings.preamble_length); // symbols
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT_LIMIT "\":%1_f"), &Lora->settings.current_limit); // xx.x mA (Overcurrent Protection - OCP)
ResponseAppend_P(PSTR(",\"" D_JSON_IMPLICIT_HEADER "\":%d"), Lora->settings.implicit_header); // 0 = explicit
ResponseAppend_P(PSTR(",\"" D_JSON_CRC_BYTES "\":%d"), Lora->settings.crc_bytes); // bytes
}
void LoraJson2Settings(JsonParserObject root) {
LoraSettings->frequency = root.getFloat(PSTR(D_JSON_FREQUENCY), LoraSettings->frequency);
LoraSettings->bandwidth = root.getFloat(PSTR(D_JSON_BANDWIDTH), LoraSettings->bandwidth);
LoraSettings->spreading_factor = root.getUInt(PSTR(D_JSON_SPREADING_FACTOR), LoraSettings->spreading_factor);
LoraSettings->coding_rate = root.getUInt(PSTR(D_JSON_CODINGRATE4), LoraSettings->coding_rate);
LoraSettings->sync_word = root.getUInt(PSTR(D_JSON_SYNCWORD), LoraSettings->sync_word);
LoraSettings->output_power = root.getUInt(PSTR(D_JSON_OUTPUT_POWER), LoraSettings->output_power);
LoraSettings->preamble_length = root.getUInt(PSTR(D_JSON_PREAMBLE_LENGTH), LoraSettings->preamble_length);
LoraSettings->current_limit = root.getFloat(PSTR(D_JSON_CURRENT_LIMIT), LoraSettings->current_limit);
LoraSettings->implicit_header = root.getUInt(PSTR(D_JSON_IMPLICIT_HEADER), LoraSettings->implicit_header);
LoraSettings->crc_bytes = root.getUInt(PSTR(D_JSON_CRC_BYTES), LoraSettings->crc_bytes);
Lora->settings.frequency = root.getFloat(PSTR(D_JSON_FREQUENCY), Lora->settings.frequency);
Lora->settings.bandwidth = root.getFloat(PSTR(D_JSON_BANDWIDTH), Lora->settings.bandwidth);
Lora->settings.spreading_factor = root.getUInt(PSTR(D_JSON_SPREADING_FACTOR), Lora->settings.spreading_factor);
Lora->settings.coding_rate = root.getUInt(PSTR(D_JSON_CODINGRATE4), Lora->settings.coding_rate);
Lora->settings.sync_word = root.getUInt(PSTR(D_JSON_SYNCWORD), Lora->settings.sync_word);
Lora->settings.output_power = root.getUInt(PSTR(D_JSON_OUTPUT_POWER), Lora->settings.output_power);
Lora->settings.preamble_length = root.getUInt(PSTR(D_JSON_PREAMBLE_LENGTH), Lora->settings.preamble_length);
Lora->settings.current_limit = root.getFloat(PSTR(D_JSON_CURRENT_LIMIT), Lora->settings.current_limit);
Lora->settings.implicit_header = root.getUInt(PSTR(D_JSON_IMPLICIT_HEADER), Lora->settings.implicit_header);
Lora->settings.crc_bytes = root.getUInt(PSTR(D_JSON_CRC_BYTES), Lora->settings.crc_bytes);
}
/*********************************************************************************************\
@ -85,8 +85,8 @@ bool LoraLoadData(void) {
JsonParserObject root = parser.getRootObject();
if (!root) { return false; }
LoraSettings->crc32 = root.getUInt(PSTR("Crc"), LoraSettings->crc32);
LoraSettings->flags = root.getUInt(PSTR("Flags"), LoraSettings->flags);
Lora->settings.crc32 = root.getUInt(PSTR("Crc"), Lora->settings.crc32);
Lora->settings.flags = root.getUInt(PSTR("Flags"), Lora->settings.flags);
LoraJson2Settings(root);
#ifdef USE_LORAWAN_BRIDGE
@ -102,8 +102,8 @@ bool LoraSaveData(void) {
Response_P(PSTR("{\"" XDRV_73_KEY "\":{"
"\"Crc\":%u,"
"\"Flags\":%u,"),
LoraSettings->crc32,
LoraSettings->flags);
Lora->settings.crc32,
Lora->settings.flags);
LoraSettings2Json();
ResponseAppend_P(PSTR("}}"));
@ -134,7 +134,7 @@ void LoraSettingsLoad(bool erase) {
// Called from FUNC_RESET_SETTINGS (erase = 1) after command reset 4, 5, or 6
// *** Start init default values in case key is not found ***
memset(LoraSettings, 0x00, sizeof(LoraSettings_t));
memset(&Lora->settings, 0x00, sizeof(LoraSettings_t));
// Init any other parameter in struct LoraSettings
LoraDefaults();
// *** End Init default values ***
@ -159,11 +159,9 @@ void LoraSettingsLoad(bool erase) {
void LoraSettingsSave(void) {
// Called from FUNC_SAVE_SETTINGS every SaveData second and at restart
#ifdef USE_UFILESYS
uint32_t crc32 = GetCfgCrc32((uint8_t*)LoraSettings +4, sizeof(LoraSettings_t) -4); // Skip crc32
if (crc32 != LoraSettings->crc32) {
// Try to save file /.drvset122
LoraSettings->crc32 = crc32;
uint32_t crc32 = GetCfgCrc32((uint8_t*)&Lora->settings +4, sizeof(LoraSettings_t) -4); // Skip crc32
if (crc32 != Lora->settings.crc32) {
Lora->settings.crc32 = crc32;
if (LoraSaveData()) {
AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Lora saved to file"));
} else {
@ -194,7 +192,7 @@ void LoraInput(void) {
Lora->receive_time, packet_size, data, &Lora->rssi, &Lora->snr);
#ifdef USE_LORAWAN_BRIDGE
if (bitRead(LoraSettings->flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
if (bitRead(Lora->settings.flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
if (LoraWanInput((uint8_t*)data, packet_size)) {
return;
}
@ -255,16 +253,15 @@ void LoraInit(void) {
Lora = (Lora_t*)calloc(sizeof(Lora_t), 1); // Need calloc to reset registers to 0/false
if (nullptr == Lora) { return; }
LoraSettings = (LoraSettings_t*)calloc(sizeof(LoraSettings_t), 1); // Need calloc to reset registers to 0/false
if (nullptr == LoraSettings) {
free(Lora);
return;
}
LoraSettingsLoad(0);
#ifdef USE_LORAWAN_BRIDGE
LoraWanInit();
#endif // USE_LORAWAN_BRIDGE
bool present = false;
char hardware[20];
if (false) {
// Need this as following `else if`s may not be present
}
#ifdef USE_LORA_SX127X
else if (PinUsed(GPIO_LORA_DI0)) {
@ -293,15 +290,9 @@ void LoraInit(void) {
}
#endif // USE_LORA_SX126X
#ifdef USE_LORAWAN_BRIDGE
if (present && !LoraWanInit()) {
present = false;
}
#endif // USE_LORAWAN_BRIDGE
if (present) {
AddLog(LOG_LEVEL_INFO, PSTR("LOR: %s initialized"), hardware);
} else {
free(LoraSettings);
free(Lora);
Lora = nullptr;
}
@ -330,9 +321,9 @@ void CmndLoraOption(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) {
uint32_t pindex = XdrvMailbox.index -1;
if (XdrvMailbox.payload >= 0) {
bitWrite(LoraSettings->flags, pindex, XdrvMailbox.payload);
bitWrite(Lora->settings.flags, pindex, XdrvMailbox.payload);
}
ResponseCmndIdxChar(GetStateText(bitRead(LoraSettings->flags, pindex)));
ResponseCmndIdxChar(GetStateText(bitRead(Lora->settings.flags, pindex)));
}
}
@ -369,7 +360,7 @@ void CmndLoraSend(void) {
invert = true;
}
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) {
Lora->raw = (XdrvMailbox.index > 3); // Global flag set even without data
Lora->raw = (XdrvMailbox.index > 3); // Global flag set even without data
if (XdrvMailbox.data_len > 0) {
char data[TAS_LORA_MAX_PACKET_LENGTH] = { 0 };
uint32_t len = (XdrvMailbox.data_len < TAS_LORA_MAX_PACKET_LENGTH -1) ? XdrvMailbox.data_len : TAS_LORA_MAX_PACKET_LENGTH -2;