mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Consolidate Lora memory usage
This commit is contained in:
parent
6ccb3ae290
commit
caed27645e
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user