mirror of https://github.com/arendst/Tasmota.git
Move Lora variables from fixed to heap
This commit is contained in:
parent
7774ce5ad8
commit
6ccb3ae290
|
@ -91,7 +91,7 @@
|
|||
#define TAS_LORAWAN_RECEIVE_DELAY2 1000 // LoRaWan Receive delay 2
|
||||
#define TAS_LORAWAN_JOIN_ACCEPT_DELAY1 5000 // LoRaWan Join accept delay 1
|
||||
#define TAS_LORAWAN_JOIN_ACCEPT_DELAY2 1000 // LoRaWan Join accept delay 2
|
||||
#define TAS_LORAWAN_ENDNODES 4 // Max number od supported endnodes
|
||||
#define TAS_LORAWAN_ENDNODES 4 // Max number of supported endnodes
|
||||
#define TAS_LORAWAN_AES128_KEY_SIZE 16 // Size in bytes
|
||||
|
||||
enum TasLoraFlags {
|
||||
|
@ -166,7 +166,7 @@ typedef struct LoraEndNode_t {
|
|||
} LoraEndNode_t;
|
||||
|
||||
// Global structure containing driver saved variables
|
||||
struct {
|
||||
typedef struct LoraSettings_t {
|
||||
uint32_t crc32; // To detect file changes
|
||||
float frequency; // 868.0 MHz
|
||||
float bandwidth; // 125.0 kHz
|
||||
|
@ -182,9 +182,10 @@ struct {
|
|||
#ifdef USE_LORAWAN_BRIDGE
|
||||
LoraEndNode_t end_node[TAS_LORAWAN_ENDNODES]; // End node parameters
|
||||
#endif // USE_LORAWAN_BRIDGE
|
||||
} LoraSettings;
|
||||
} LoraSettings_t;
|
||||
LoraSettings_t* LoraSettings = nullptr;
|
||||
|
||||
struct {
|
||||
typedef struct Lora_t {
|
||||
bool (* Config)(void);
|
||||
bool (* Available)(void);
|
||||
int (* Receive)(char*);
|
||||
|
@ -193,20 +194,21 @@ struct {
|
|||
float rssi;
|
||||
float snr;
|
||||
uint8_t packet_size; // Max is 255 (LORA_MAX_PACKET_LENGTH)
|
||||
volatile bool receivedFlag; // flag to indicate that a packet was received
|
||||
bool sendFlag;
|
||||
volatile bool received_flag; // flag to indicate that a packet was received
|
||||
bool send_flag;
|
||||
bool raw;
|
||||
bool present;
|
||||
} Lora;
|
||||
} Lora_t;
|
||||
Lora_t* Lora = nullptr;
|
||||
|
||||
#ifdef USE_LORAWAN_BRIDGE
|
||||
struct {
|
||||
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;
|
||||
} Lorawan_t;
|
||||
Lorawan_t* Lorawan = nullptr;
|
||||
#endif // USE_LORAWAN_BRIDGE
|
||||
|
||||
#endif // USE_SPI_LORA
|
||||
|
|
|
@ -46,24 +46,24 @@ bool LoraSx126xBusy(void) {
|
|||
void IRAM_ATTR LoraSx126xOnInterrupt(void);
|
||||
void LoraSx126xOnInterrupt(void) {
|
||||
// This is called after EVERY type of enabled interrupt so chk for valid receivedFlag in LoraAvailableSx126x()
|
||||
if (!Lora.sendFlag && !Lora.receivedFlag && !Lora.receive_time) {
|
||||
Lora.receive_time = millis();
|
||||
if (!Lora->send_flag && !Lora->received_flag && !Lora->receive_time) {
|
||||
Lora->receive_time = millis();
|
||||
}
|
||||
Lora.receivedFlag = true; // we got a packet, set the flag
|
||||
Lora->received_flag = true; // we got a packet, set the flag
|
||||
}
|
||||
|
||||
bool LoraSx126xAvailable(void) {
|
||||
if (Lora.sendFlag) {
|
||||
Lora.receivedFlag = false; // Reset receive flag as it was caused by send interrupt
|
||||
if (Lora->send_flag) {
|
||||
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
|
||||
Lora.sendFlag = false;
|
||||
Lora->send_flag = false;
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("S6X: Rcvd (%d) restarted (%d)"), time, state);
|
||||
}
|
||||
}
|
||||
else if (Lora.receivedFlag) {
|
||||
else if (Lora->received_flag) {
|
||||
uint32_t irq_stat = LoRaRadio.getIrqStatus();
|
||||
|
||||
#ifdef USE_LORA_SX126X_DEBUG
|
||||
|
@ -73,14 +73,14 @@ bool LoraSx126xAvailable(void) {
|
|||
#endif // USE_LORA_SX126X_DEBUG
|
||||
|
||||
if (0 == (irq_stat & RADIOLIB_SX126X_IRQ_RX_DONE)) {
|
||||
Lora.receivedFlag = false; // Reset receive flag
|
||||
Lora->received_flag = false; // Reset receive flag
|
||||
}
|
||||
}
|
||||
return (Lora.receivedFlag); // Check if the receive flag is set
|
||||
return (Lora->received_flag); // Check if the receive flag is set
|
||||
}
|
||||
|
||||
int LoraSx126xReceive(char* data) {
|
||||
Lora.receivedFlag = 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
|
||||
|
@ -89,8 +89,8 @@ int LoraSx126xReceive(char* data) {
|
|||
AddLog(LOG_LEVEL_DEBUG, PSTR("S6X: Ignoring CRC error"));
|
||||
}
|
||||
if (RADIOLIB_ERR_NONE == state) {
|
||||
Lora.rssi = LoRaRadio.getRSSI();
|
||||
Lora.snr = LoRaRadio.getSNR();
|
||||
Lora->rssi = LoRaRadio.getRSSI();
|
||||
Lora->snr = LoRaRadio.getSNR();
|
||||
} else {
|
||||
packet_size = 0; // Some other error occurred
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("S6X: Receive error %d"), state);
|
||||
|
@ -107,7 +107,7 @@ bool LoraSx126xSend(uint8_t* data, uint32_t len, bool invert) {
|
|||
LoraSx126xBusy();
|
||||
}
|
||||
int state = LoRaRadio.transmit(data, len);
|
||||
Lora.sendFlag = 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(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);
|
||||
} 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(LoraSettings->frequency)) {
|
||||
LoraSx126xConfig();
|
||||
LoRaRadio.setDio1Action(LoraSx126xOnInterrupt);
|
||||
if (RADIOLIB_ERR_NONE == LoRaRadio.startReceive()) {
|
||||
|
|
|
@ -35,27 +35,27 @@ void LoraSx127xOnReceive(int packet_size) {
|
|||
// AddLog(LOG_LEVEL_DEBUG, PSTR("S7X: Packet size %d"), packet_size);
|
||||
#endif
|
||||
if (0 == packet_size) { return; } // if there's no packet, return
|
||||
if (!Lora.receive_time) {
|
||||
Lora.receive_time = millis();
|
||||
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) {
|
||||
int packet_size = 0;
|
||||
while (LoRa.available()) { // read packet up to LORA_MAX_PACKET_LENGTH
|
||||
while (Lora->Available()) { // read packet up to LORA_MAX_PACKET_LENGTH
|
||||
char sdata = LoRa.read();
|
||||
if (packet_size < TAS_LORA_MAX_PACKET_LENGTH -1) {
|
||||
data[packet_size++] = sdata;
|
||||
}
|
||||
}
|
||||
Lora.rssi = LoRa.packetRssi();
|
||||
Lora.snr = LoRa.packetSnr();
|
||||
Lora.packet_size = 0; // reset flag
|
||||
Lora->rssi = LoRa.packetRssi();
|
||||
Lora->snr = LoRa.packetSnr();
|
||||
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(LoraSettings->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(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.enableCrc();
|
||||
} else {
|
||||
LoRa.disableCrc();
|
||||
}
|
||||
/*
|
||||
if (LoraSettings.implicit_header) {
|
||||
if (LoraSettings->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(LoraSettings->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(LoraSettings->end_node[node].AppKey, TAS_LORAWAN_JOINNONCE +node, TAS_LORAWAN_NETID, LoraSettings->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(LoraSettings->end_node[node].AppKey, TAS_LORAWAN_JOINNONCE +node, TAS_LORAWAN_NETID, LoraSettings->end_node[node].DevNonce, NwkSKey);
|
||||
}
|
||||
|
||||
#ifdef USE_LORAWAN_TEST
|
||||
|
|
|
@ -29,13 +29,13 @@ 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(LoraSettings->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, 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(",\"RSSI\":%1_f,\"SNR\":%1_f"), &Lora.rssi, &Lora.snr);
|
||||
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, LoraSettings->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(LoraSettings->flags, TAS_LORA_FLAG_DECODE_ENABLED)) { // LoraOption3 1
|
||||
if (0x00161600 == LoraSettings->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, LoraSettings->end_node[node_data->node].DevEUIh, LoraSettings->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 == LoraSettings->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, LoraSettings->end_node[node_data->node].DevEUIh, LoraSettings->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);
|
||||
LoraSettings->end_node[node_data->node].DevEUIh, LoraSettings->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, LoraSettings->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);
|
||||
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);
|
||||
const char* name = nullptr;
|
||||
name = root.getStr(PSTR(D_JSON_NAME), nullptr);
|
||||
if (strlen(app_key)) {
|
||||
LoraSettings.end_node[n].name = name;
|
||||
LoraSettings->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 (LoraSettings->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());
|
||||
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());
|
||||
result = UfsJsonSettingsWrite(ResponseData());
|
||||
}
|
||||
}
|
||||
|
@ -148,41 +148,41 @@ 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
|
||||
Lorawan->send_buffer_step--;
|
||||
if (1 == Lorawan->send_buffer_step) {
|
||||
Lorawan->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 (Lorawan->rx) { // If received in RX1 do not resend in RX2
|
||||
LoraSend(Lorawan->send_buffer, Lorawan->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;
|
||||
LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora.receive_time), LoraWanTickerSend);
|
||||
memcpy(Lorawan->send_buffer, buffer, sizeof(Lorawan->send_buffer));
|
||||
Lorawan->send_buffer_len = len;
|
||||
Lorawan->send_buffer_step = 2;
|
||||
LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora->receive_time), LoraWanTickerSend);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
uint32_t LoraWanSpreadingFactorToDataRate(void) {
|
||||
// Allow only JoinReq message datarates (125kHz bandwidth)
|
||||
if (LoraSettings.spreading_factor > 12) {
|
||||
LoraSettings.spreading_factor = 12;
|
||||
if (LoraSettings->spreading_factor > 12) {
|
||||
LoraSettings->spreading_factor = 12;
|
||||
}
|
||||
if (LoraSettings.spreading_factor < 7) {
|
||||
LoraSettings.spreading_factor = 7;
|
||||
if (LoraSettings->spreading_factor < 7) {
|
||||
LoraSettings->spreading_factor = 7;
|
||||
}
|
||||
LoraSettings.bandwidth = 125;
|
||||
return 12 - LoraSettings.spreading_factor;
|
||||
LoraSettings->bandwidth = 125;
|
||||
return 12 - LoraSettings->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 = (LoraSettings->frequency * 10);
|
||||
uint32_t channel = 250;
|
||||
if (8681 == frequency) {
|
||||
channel = 0;
|
||||
|
@ -194,8 +194,8 @@ uint32_t LoraWanFrequencyToChannel(void) {
|
|||
channel = 2;
|
||||
}
|
||||
if (250 == channel) {
|
||||
LoraSettings.frequency = 868.1;
|
||||
Lora.Config();
|
||||
LoraSettings->frequency = 868.1;
|
||||
Lora->Config();
|
||||
channel = 0;
|
||||
}
|
||||
return channel;
|
||||
|
@ -204,8 +204,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 = Lorawan->device_address +node;
|
||||
uint16_t FCnt = LoraSettings->end_node[node].FCntDown++;
|
||||
uint8_t NwkSKey[TAS_LORAWAN_AES128_KEY_SIZE];
|
||||
LoraWanDeriveLegacyNwkSKey(node, NwkSKey);
|
||||
|
||||
|
@ -254,26 +254,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);
|
||||
uint32_t CalcMIC = LoraWanGenerateMIC(data, 19, LoraSettings->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"))) {
|
||||
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"))) {
|
||||
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"), LoraSettings->end_node[node].DevEUIl & 0x0000FFFF);
|
||||
LoraSettings->end_node[node].name = name;
|
||||
}
|
||||
|
||||
uint32_t JoinNonce = TAS_LORAWAN_JOINNONCE +node;
|
||||
uint32_t DevAddr = Lorawan.device_address +node;
|
||||
uint32_t DevAddr = Lorawan->device_address +node;
|
||||
uint32_t NetID = TAS_LORAWAN_NETID;
|
||||
uint8_t join_data[33] = { 0 };
|
||||
join_data[0] = TAS_LORAWAN_MTYPE_JOIN_ACCEPT << 5;
|
||||
|
@ -290,14 +290,14 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||
join_data[11] = LoraWanSpreadingFactorToDataRate(); // DLSettings
|
||||
join_data[12] = 1; // RXDelay;
|
||||
|
||||
uint32_t NewMIC = LoraWanGenerateMIC(join_data, 13, LoraSettings.end_node[node].AppKey);
|
||||
uint32_t NewMIC = LoraWanGenerateMIC(join_data, 13, LoraSettings->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(LoraSettings->end_node[node].AppKey, &join_data[1], 16, &EncData[1]);
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Join %17_H"), join_data);
|
||||
|
||||
|
@ -335,12 +335,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 == LoraSettings->end_node[node].DevEUIh) { continue; } // No DevEUI so never joined
|
||||
if ((Lorawan->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 = (LoraSettings->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];
|
||||
|
@ -384,17 +384,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 (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;
|
||||
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
|
||||
bitClear(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ); // Resend LinkADRReq
|
||||
}
|
||||
}
|
||||
LoraSettings.end_node[node].FCntUp = FCnt;
|
||||
LoraSettings->end_node[node].FCntUp = FCnt;
|
||||
|
||||
if (FOptsLen) {
|
||||
uint32_t i = 0;
|
||||
|
@ -408,7 +408,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(LoraSettings->end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ);
|
||||
}
|
||||
else if (TAS_LORAWAN_CID_DUTY_CYCLE_ANS == FOpts[i]) {
|
||||
i++;
|
||||
|
@ -442,28 +442,28 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||
|
||||
if (payload_len) {
|
||||
LoraNodeData_t node_data;
|
||||
node_data.rssi = Lora.rssi;
|
||||
node_data.snr = Lora.snr;
|
||||
node_data.rssi = Lora->rssi;
|
||||
node_data.snr = Lora->snr;
|
||||
node_data.payload = payload_decrypted;
|
||||
node_data.payload_len = payload_len;
|
||||
node_data.node = node;
|
||||
node_data.FPort = FPort;
|
||||
LoraWanDecode(&node_data);
|
||||
|
||||
if (0xA840410E == LoraSettings.end_node[node].DevEUIh) { // Dragino
|
||||
if (0xA840410E == LoraSettings->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(LoraSettings->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++;
|
||||
uint16_t FCnt = LoraSettings->end_node[node].FCntDown++;
|
||||
data[6] = FCnt;
|
||||
data[7] = FCnt >> 8;
|
||||
uint32_t MIC = LoraWanComputeLegacyDownlinkMIC(NwkSKey, DevAddr, FCnt, data, packet_size -4);
|
||||
|
@ -475,7 +475,7 @@ 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(LoraSettings->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
|
||||
|
@ -486,7 +486,7 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
Lora.receive_time = 0;
|
||||
Lora->receive_time = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -509,14 +509,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(LoraSettings->flags, pindex, XdrvMailbox.payload);
|
||||
}
|
||||
#ifdef USE_LORAWAN_TEST
|
||||
LoraWanTestKeyDerivation();
|
||||
LorWanTestUplinkDownlinkEncryption();
|
||||
LorWanTestUplinkDownlinkMIC();
|
||||
#endif // USE_LORAWAN_TEST
|
||||
ResponseCmndChar(GetStateText(bitRead(LoraSettings.flags, pindex)));
|
||||
ResponseCmndChar(GetStateText(bitRead(LoraSettings->flags, pindex)));
|
||||
}
|
||||
|
||||
void CmndLoraWanAppKey(void) {
|
||||
|
@ -526,16 +526,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, LoraSettings->end_node[node].AppKey, &out_len);
|
||||
if (0 == LoraSettings->end_node[node].name.length()) {
|
||||
LoraSettings->end_node[node].name = F("0x0000");
|
||||
}
|
||||
}
|
||||
else if (0 == XdrvMailbox.payload) {
|
||||
memset(&LoraSettings.end_node[node], 0, sizeof(LoraEndNode_t));
|
||||
memset(&LoraSettings->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"), LoraSettings->end_node[node].AppKey);
|
||||
ResponseCmndIdxChar(appkey);
|
||||
}
|
||||
}
|
||||
|
@ -549,13 +549,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"), LoraSettings->end_node[node].DevEUIl & 0x0000FFFF);
|
||||
LoraSettings->end_node[node].name = name;
|
||||
} else {
|
||||
LoraSettings.end_node[node].name = XdrvMailbox.data;
|
||||
LoraSettings->end_node[node].name = XdrvMailbox.data;
|
||||
}
|
||||
}
|
||||
ResponseCmndIdxChar(LoraSettings.end_node[node].name.c_str());
|
||||
ResponseCmndIdxChar(LoraSettings->end_node[node].name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,12 +563,16 @@ void CmndLoraWanName(void) {
|
|||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
void LoraWanInit(void) {
|
||||
bool LoraWanInit(void) {
|
||||
Lorawan = (Lorawan_t*)calloc(sizeof(Lorawan_t), 1); // Need calloc to reset registers to 0/false
|
||||
if (nullptr == Lorawan) { return false; }
|
||||
|
||||
// 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);
|
||||
Lorawan->device_address = (TAS_LORAWAN_NETID << 25) | (ESP_getChipId() & 0x01FFFFFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
#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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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"), &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
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -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);
|
||||
LoraSettings->crc32 = root.getUInt(PSTR("Crc"), LoraSettings->crc32);
|
||||
LoraSettings->flags = root.getUInt(PSTR("Flags"), LoraSettings->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);
|
||||
LoraSettings->crc32,
|
||||
LoraSettings->flags);
|
||||
LoraSettings2Json();
|
||||
ResponseAppend_P(PSTR("}}"));
|
||||
|
||||
|
@ -134,20 +134,20 @@ 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));
|
||||
memset(LoraSettings, 0x00, sizeof(LoraSettings_t));
|
||||
// Init any other parameter in struct LoraSettings
|
||||
LoraDefaults();
|
||||
// *** End Init default values ***
|
||||
|
||||
#ifndef USE_UFILESYS
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("CFG: Lora use defaults as file system not enabled"));
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Lora use defaults as file system not enabled"));
|
||||
#else
|
||||
// Try to load key
|
||||
if (erase) {
|
||||
LoraDeleteData();
|
||||
}
|
||||
else if (LoraLoadData()) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("CFG: Lora loaded from file"));
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Lora loaded from file"));
|
||||
}
|
||||
else {
|
||||
// File system not ready: No flash space reserved for file system
|
||||
|
@ -159,10 +159,10 @@ 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) -4); // Skip crc32
|
||||
if (crc32 != LoraSettings.crc32) {
|
||||
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;
|
||||
LoraSettings->crc32 = crc32;
|
||||
|
||||
if (LoraSaveData()) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Lora saved to file"));
|
||||
|
@ -178,29 +178,29 @@ void LoraSettingsSave(void) {
|
|||
|
||||
bool LoraSend(uint8_t* data, uint32_t len, bool invert) {
|
||||
uint32_t lora_time = millis(); // Time is important for LoRaWan RX windows
|
||||
bool result = Lora.Send(data, len, invert);
|
||||
bool result = Lora->Send(data, len, invert);
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Send (%u) '%*_H', Invert %d, Time %d"),
|
||||
lora_time, len, data, invert, TimePassedSince(lora_time));
|
||||
return result;
|
||||
}
|
||||
|
||||
void LoraInput(void) {
|
||||
if (!Lora.Available()) { return; }
|
||||
if (!Lora->Available()) { return; }
|
||||
|
||||
char data[TAS_LORA_MAX_PACKET_LENGTH] = { 0 };
|
||||
int packet_size = Lora.Receive(data);
|
||||
int packet_size = Lora->Receive(data);
|
||||
if (!packet_size) { return; }
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Rcvd (%u) '%*_H', RSSI %1_f, SNR %1_f"),
|
||||
Lora.receive_time, packet_size, data, &Lora.rssi, &Lora.snr);
|
||||
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(LoraSettings->flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
|
||||
if (LoraWanInput((uint8_t*)data, packet_size)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // USE_LORAWAN_BRIDGE
|
||||
Lora.receive_time = 0;
|
||||
Lora->receive_time = 0;
|
||||
|
||||
if (TAS_LORA_REMOTE_COMMAND == data[0]) {
|
||||
char *payload = data +1; // Skip TAS_LORA_REMOTE_COMMAND
|
||||
|
@ -216,7 +216,7 @@ void LoraInput(void) {
|
|||
}
|
||||
}
|
||||
|
||||
bool raw = Lora.raw;
|
||||
bool raw = Lora->raw;
|
||||
// Set raw mode if zeroes within data
|
||||
for (uint32_t i = 0; i < packet_size; i++) {
|
||||
if (0 == data[i]) {
|
||||
|
@ -237,7 +237,7 @@ void LoraInput(void) {
|
|||
}
|
||||
ResponseAppend_P(PSTR("\""));
|
||||
}
|
||||
ResponseAppend_P(PSTR(",\"RSSI\":%1_f,\"SNR\":%1_f}"), &Lora.rssi, &Lora.snr);
|
||||
ResponseAppend_P(PSTR(",\"RSSI\":%1_f,\"SNR\":%1_f}"), &Lora->rssi, &Lora->snr);
|
||||
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR("LoRaReceived"));
|
||||
}
|
||||
|
@ -253,25 +253,29 @@ void LoraInit(void) {
|
|||
// SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
||||
#endif // ESP32
|
||||
|
||||
#ifdef USE_LORAWAN_BRIDGE
|
||||
LoraWanInit();
|
||||
#endif // USE_LORAWAN_BRIDGE
|
||||
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);
|
||||
|
||||
bool present = false;
|
||||
char hardware[20];
|
||||
strcpy_P(hardware, PSTR("Not"));
|
||||
if (false) {
|
||||
}
|
||||
#ifdef USE_LORA_SX127X
|
||||
else if (PinUsed(GPIO_LORA_DI0)) {
|
||||
// SX1276, RFM95W
|
||||
if (LoraSx127xInit()) {
|
||||
Lora.Config = &LoraSx127xConfig;
|
||||
Lora.Available = &LoraSx127xAvailable;
|
||||
Lora.Receive = &LoraSx127xReceive;
|
||||
Lora.Send = &LoraSx127xSend;
|
||||
Lora->Config = &LoraSx127xConfig;
|
||||
Lora->Available = &LoraSx127xAvailable;
|
||||
Lora->Receive = &LoraSx127xReceive;
|
||||
Lora->Send = &LoraSx127xSend;
|
||||
strcpy_P(hardware, PSTR("SX127x"));
|
||||
Lora.present = true;
|
||||
present = true;
|
||||
}
|
||||
}
|
||||
#endif // USE_LORA_SX127X
|
||||
|
@ -279,16 +283,28 @@ void LoraInit(void) {
|
|||
else if (PinUsed(GPIO_LORA_DI1) && PinUsed(GPIO_LORA_BUSY)) {
|
||||
// SX1262, LilyGoT3S3
|
||||
if (LoraSx126xInit()) {
|
||||
Lora.Config = &LoraSx126xConfig;
|
||||
Lora.Available = &LoraSx126xAvailable;
|
||||
Lora.Receive = &LoraSx126xReceive;
|
||||
Lora.Send = &LoraSx126xSend;
|
||||
Lora->Config = &LoraSx126xConfig;
|
||||
Lora->Available = &LoraSx126xAvailable;
|
||||
Lora->Receive = &LoraSx126xReceive;
|
||||
Lora->Send = &LoraSx126xSend;
|
||||
strcpy_P(hardware, PSTR("SX126x"));
|
||||
Lora.present = true;
|
||||
present = true;
|
||||
}
|
||||
}
|
||||
#endif // USE_LORA_SX126X
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: %s initialized"), hardware);
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,9 +330,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(LoraSettings->flags, pindex, XdrvMailbox.payload);
|
||||
}
|
||||
ResponseCmndIdxChar(GetStateText(bitRead(LoraSettings.flags, pindex)));
|
||||
ResponseCmndIdxChar(GetStateText(bitRead(LoraSettings->flags, pindex)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,7 +369,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;
|
||||
|
@ -417,18 +433,18 @@ void CmndLoraConfig(void) {
|
|||
if (XdrvMailbox.data_len > 0) {
|
||||
if (XdrvMailbox.payload == 1) {
|
||||
LoraDefaults();
|
||||
Lora.Config();
|
||||
Lora->Config();
|
||||
}
|
||||
else if (XdrvMailbox.payload == 2) {
|
||||
LoraWanDefaults();
|
||||
Lora.Config();
|
||||
Lora->Config();
|
||||
}
|
||||
else {
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (root) {
|
||||
LoraJson2Settings(root);
|
||||
Lora.Config();
|
||||
Lora->Config();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +464,7 @@ bool Xdrv73(uint32_t function) {
|
|||
if (FUNC_INIT == function) {
|
||||
LoraInit();
|
||||
}
|
||||
else if (Lora.present) {
|
||||
else if (Lora) {
|
||||
switch (function) {
|
||||
case FUNC_LOOP:
|
||||
case FUNC_SLEEP_LOOP:
|
||||
|
|
Loading…
Reference in New Issue