mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-25 11:46:31 +00:00
Add Support for LoRaWan Rx1 and Rx2 profiles (#23394)
This commit is contained in:
parent
08e8f0b64d
commit
7fb8654c6c
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
## [14.6.0.2]
|
## [14.6.0.2]
|
||||||
### Added
|
### Added
|
||||||
- Allow temporary change of DisplayDimmer (#23406)
|
- Allow temporary change of DisplayDimmer (#23406)
|
||||||
|
- Support for LoRaWan Rx1 and Rx2 profiles (#23394)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
|||||||
- Command `JsonPP 0..7` to enable (>0) JSON Pretty Print on user interfaces and set number of indents
|
- Command `JsonPP 0..7` to enable (>0) JSON Pretty Print on user interfaces and set number of indents
|
||||||
- Command `JsonPP <command>|backlog <command>;...` to enable JSON PP only once
|
- Command `JsonPP <command>|backlog <command>;...` to enable JSON PP only once
|
||||||
- Support for multi channel AU915-928 LoRaWanBridge by Rob Clark [#23372](https://github.com/arendst/Tasmota/issues/23372)
|
- Support for multi channel AU915-928 LoRaWanBridge by Rob Clark [#23372](https://github.com/arendst/Tasmota/issues/23372)
|
||||||
|
- Support for LoRaWan Rx1 and Rx2 profiles [#23394](https://github.com/arendst/Tasmota/issues/23394)
|
||||||
- Allow temporary change of DisplayDimmer [#23406](https://github.com/arendst/Tasmota/issues/23406)
|
- Allow temporary change of DisplayDimmer [#23406](https://github.com/arendst/Tasmota/issues/23406)
|
||||||
- WebUI status line for MQTT and TLS, added `FUNC_WEB_STATUS_LEFT` and `FUNC_WEB_STATUS_RIGHT` event [#23354](https://github.com/arendst/Tasmota/issues/23354)
|
- WebUI status line for MQTT and TLS, added `FUNC_WEB_STATUS_LEFT` and `FUNC_WEB_STATUS_RIGHT` event [#23354](https://github.com/arendst/Tasmota/issues/23354)
|
||||||
- WebUI heap status [#23356](https://github.com/arendst/Tasmota/issues/23356)
|
- WebUI heap status [#23356](https://github.com/arendst/Tasmota/issues/23356)
|
||||||
|
@ -266,7 +266,6 @@ struct TasmotaGlobal_t {
|
|||||||
uint32_t zc_offset; // Zero cross moment offset due to monitoring chip processing (microseconds)
|
uint32_t zc_offset; // Zero cross moment offset due to monitoring chip processing (microseconds)
|
||||||
uint32_t zc_code_offset; // Zero cross moment offset due to executing power code (microseconds)
|
uint32_t zc_code_offset; // Zero cross moment offset due to executing power code (microseconds)
|
||||||
uint32_t zc_interval; // Zero cross interval around 8333 (60Hz) or 10000 (50Hz) (microseconds)
|
uint32_t zc_interval; // Zero cross interval around 8333 (60Hz) or 10000 (50Hz) (microseconds)
|
||||||
uint32_t skip_sleep; // Skip sleep
|
|
||||||
GpioOptionABits gpio_optiona; // GPIO Option_A flags
|
GpioOptionABits gpio_optiona; // GPIO Option_A flags
|
||||||
void *log_buffer_mutex; // Control access to log buffer
|
void *log_buffer_mutex; // Control access to log buffer
|
||||||
|
|
||||||
@ -328,6 +327,7 @@ struct TasmotaGlobal_t {
|
|||||||
|
|
||||||
uint8_t user_globals[3]; // User set global temp/hum/press
|
uint8_t user_globals[3]; // User set global temp/hum/press
|
||||||
uint8_t busy_time; // Time in ms to allow executing of time critical functions
|
uint8_t busy_time; // Time in ms to allow executing of time critical functions
|
||||||
|
uint8_t skip_sleep; // Skip sleep loops
|
||||||
uint8_t init_state; // Tasmota init state
|
uint8_t init_state; // Tasmota init state
|
||||||
uint8_t heartbeat_inverted; // Heartbeat pulse inverted flag
|
uint8_t heartbeat_inverted; // Heartbeat pulse inverted flag
|
||||||
uint8_t spi_enabled; // SPI configured (bus1)
|
uint8_t spi_enabled; // SPI configured (bus1)
|
||||||
@ -747,20 +747,18 @@ void BacklogLoop(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SleepSkip(uint32_t no_sleep) {
|
void SleepSkip(void) {
|
||||||
if (0 == no_sleep) {
|
TasmotaGlobal.skip_sleep = 250; // Skip sleep for 250 loops;
|
||||||
return !TimeReached(TasmotaGlobal.skip_sleep);
|
|
||||||
}
|
|
||||||
SetNextTimeInterval(TasmotaGlobal.skip_sleep, no_sleep); // Skip sleep for some ms
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SleepDelay(uint32_t mseconds) {
|
void SleepDelay(uint32_t mseconds) {
|
||||||
if (SleepSkip(0)) { return; } // Temporarily skip sleep to handle imminent interrupts outside interrupt handler
|
|
||||||
if (!TasmotaGlobal.backlog_nodelay && mseconds) {
|
if (!TasmotaGlobal.backlog_nodelay && mseconds) {
|
||||||
uint32_t wait = millis() + mseconds;
|
uint32_t wait = millis() + mseconds;
|
||||||
while (!TimeReached(wait) && !Serial.available() && !SleepSkip(0)) { // We need to service serial buffer ASAP as otherwise we get uart buffer overrun
|
while (!TasmotaGlobal.skip_sleep && // We need to service imminent interrupts ASAP
|
||||||
|
!TimeReached(wait) &&
|
||||||
|
!Serial.available()) { // We need to service serial buffer ASAP as otherwise we get uart buffer overrun
|
||||||
XdrvXsnsCall(FUNC_SLEEP_LOOP); // Main purpose is reacting ASAP on serial data availability or interrupt handling (ADE7880)
|
XdrvXsnsCall(FUNC_SLEEP_LOOP); // Main purpose is reacting ASAP on serial data availability or interrupt handling (ADE7880)
|
||||||
|
if (TasmotaGlobal.skip_sleep) { break; }
|
||||||
delay(1);
|
delay(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -846,19 +844,22 @@ void loop(void) {
|
|||||||
|
|
||||||
uint32_t my_activity = millis() - my_sleep;
|
uint32_t my_activity = millis() - my_sleep;
|
||||||
|
|
||||||
if (Settings->flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
|
if (TasmotaGlobal.skip_sleep) {
|
||||||
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
|
TasmotaGlobal.skip_sleep--; // Temporarily skip sleep to handle imminent interrupts outside interrupt handler
|
||||||
SleepDelay(TasmotaGlobal.sleep); // https://github.com/esp8266/Arduino/issues/2021
|
|
||||||
} else {
|
} else {
|
||||||
if (my_activity < (uint32_t)TasmotaGlobal.sleep) {
|
if (Settings->flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
|
||||||
SleepDelay((uint32_t)TasmotaGlobal.sleep - my_activity); // Provide time for background tasks like wifi
|
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
|
||||||
|
SleepDelay(TasmotaGlobal.sleep); // https://github.com/esp8266/Arduino/issues/2021
|
||||||
} else {
|
} else {
|
||||||
if (TasmotaGlobal.global_state.network_down) {
|
if (my_activity < (uint32_t)TasmotaGlobal.sleep) {
|
||||||
SleepDelay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/2 of my_activity period
|
SleepDelay((uint32_t)TasmotaGlobal.sleep - my_activity); // Provide time for background tasks like wifi
|
||||||
|
} else {
|
||||||
|
if (TasmotaGlobal.global_state.network_down) {
|
||||||
|
SleepDelay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/2 of my_activity period
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!my_activity) { my_activity++; } // We cannot divide by 0
|
if (!my_activity) { my_activity++; } // We cannot divide by 0
|
||||||
uint32_t loop_delay = TasmotaGlobal.sleep;
|
uint32_t loop_delay = TasmotaGlobal.sleep;
|
||||||
if (!loop_delay) { loop_delay++; } // We cannot divide by 0
|
if (!loop_delay) { loop_delay++; } // We cannot divide by 0
|
||||||
|
@ -106,13 +106,30 @@
|
|||||||
|
|
||||||
// EU868 values
|
// EU868 values
|
||||||
#ifndef TAS_LORAWAN_FREQUENCY
|
#ifndef TAS_LORAWAN_FREQUENCY
|
||||||
#define TAS_LORAWAN_FREQUENCY 868.1 // Allowed values range from 150.0 to 960.0 MHz
|
#define TAS_LORAWAN_FREQUENCY 868.1 // Allowed values are 868.1, 868.3 and 868.5 MHz
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_BANDWIDTH
|
#ifndef TAS_LORAWAN_BANDWIDTH
|
||||||
#define TAS_LORAWAN_BANDWIDTH 125.0 // Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz
|
#define TAS_LORAWAN_BANDWIDTH 125.0 // Allowed values are 125.0 and 250.0 kHz
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_SPREADING_FACTOR
|
#ifndef TAS_LORAWAN_SPREADING_FACTOR
|
||||||
#define TAS_LORAWAN_SPREADING_FACTOR 9 // Allowed values range from 5 to 12
|
#define TAS_LORAWAN_SPREADING_FACTOR 9 // Allowed values range from 7 to 12
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAS_LORAWAN_BANDWIDTH_RX1
|
||||||
|
#define TAS_LORAWAN_BANDWIDTH_RX1 125.0 // DR3
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_SPREADING_FACTOR_RX1
|
||||||
|
#define TAS_LORAWAN_SPREADING_FACTOR_RX1 9 // DR3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAS_LORAWAN_FREQUENCY_DN
|
||||||
|
#define TAS_LORAWAN_FREQUENCY_DN 869.525 // Class B downlink channel
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_BANDWIDTH_RX2
|
||||||
|
#define TAS_LORAWAN_BANDWIDTH_RX2 125.0 // DR0
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_SPREADING_FACTOR_RX2
|
||||||
|
#define TAS_LORAWAN_SPREADING_FACTOR_RX2 12 // DR0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Common LoRaWan values
|
// Common LoRaWan values
|
||||||
@ -278,7 +295,7 @@ typedef struct LoraSettings_t {
|
|||||||
} LoraSettings_t;
|
} LoraSettings_t;
|
||||||
|
|
||||||
typedef struct Lora_t {
|
typedef struct Lora_t {
|
||||||
bool (* Config)(void);
|
bool (* Config)(bool);
|
||||||
bool (* Available)(void);
|
bool (* Available)(void);
|
||||||
int (* Receive)(char*);
|
int (* Receive)(char*);
|
||||||
bool (* Send)(uint8_t*, uint32_t, bool);
|
bool (* Send)(uint8_t*, uint32_t, bool);
|
||||||
@ -293,10 +310,13 @@ typedef struct Lora_t {
|
|||||||
bool raw;
|
bool raw;
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
uint32_t device_address;
|
uint32_t device_address;
|
||||||
|
LoraSettings_t backup_settings;
|
||||||
uint8_t* send_buffer;
|
uint8_t* send_buffer;
|
||||||
uint8_t send_buffer_step;
|
uint8_t send_buffer_step;
|
||||||
uint8_t send_buffer_len;
|
uint8_t send_buffer_len;
|
||||||
bool rx;
|
bool rx;
|
||||||
|
bool send_request;
|
||||||
|
bool profile_changed;
|
||||||
#endif // USE_LORAWAN_BRIDGE
|
#endif // USE_LORAWAN_BRIDGE
|
||||||
} Lora_t;
|
} Lora_t;
|
||||||
Lora_t* Lora = nullptr;
|
Lora_t* Lora = nullptr;
|
||||||
|
@ -46,7 +46,8 @@ bool LoraSx126xBusy(void) {
|
|||||||
void IRAM_ATTR LoraSx126xOnInterrupt(void);
|
void IRAM_ATTR LoraSx126xOnInterrupt(void);
|
||||||
void LoraSx126xOnInterrupt(void) {
|
void LoraSx126xOnInterrupt(void) {
|
||||||
// This is called after EVERY type of enabled interrupt so chk for valid receivedFlag in LoraAvailableSx126x()
|
// This is called after EVERY type of enabled interrupt so chk for valid receivedFlag in LoraAvailableSx126x()
|
||||||
if (!Lora->send_flag && !Lora->received_flag && !Lora->receive_time) {
|
// if (!Lora->send_flag && !Lora->received_flag && !Lora->receive_time) {
|
||||||
|
if (!Lora->send_flag && !Lora->received_flag) {
|
||||||
Lora->receive_time = millis();
|
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
|
||||||
@ -119,29 +120,31 @@ bool LoraSx126xSend(uint8_t* data, uint32_t len, bool invert) {
|
|||||||
return (RADIOLIB_ERR_NONE == state);
|
return (RADIOLIB_ERR_NONE == state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoraSx126xConfig(void) {
|
bool LoraSx126xConfig(bool full) {
|
||||||
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.setSpreadingFactor(Lora->settings.spreading_factor);
|
||||||
LoRaRadio.setBandwidth(Lora->settings.bandwidth);
|
LoRaRadio.setBandwidth(Lora->settings.bandwidth);
|
||||||
LoRaRadio.setFrequency(Lora->settings.frequency);
|
LoRaRadio.setFrequency(Lora->settings.frequency);
|
||||||
LoRaRadio.setOutputPower(Lora->settings.output_power);
|
if (full) {
|
||||||
if (Lora->settings.implicit_header) {
|
LoRaRadio.setCodingRate(Lora->settings.coding_rate);
|
||||||
LoRaRadio.implicitHeader(Lora->settings.implicit_header);
|
LoRaRadio.setSyncWord(Lora->settings.sync_word);
|
||||||
} else {
|
LoRaRadio.setPreambleLength(Lora->settings.preamble_length);
|
||||||
LoRaRadio.explicitHeader();
|
LoRaRadio.setCurrentLimit(Lora->settings.current_limit);
|
||||||
|
LoRaRadio.setCRC(Lora->settings.crc_bytes);
|
||||||
|
LoRaRadio.setOutputPower(Lora->settings.output_power);
|
||||||
|
if (Lora->settings.implicit_header) {
|
||||||
|
LoRaRadio.implicitHeader(Lora->settings.implicit_header);
|
||||||
|
} else {
|
||||||
|
LoRaRadio.explicitHeader();
|
||||||
|
}
|
||||||
|
LoRaRadio.invertIQ(false);
|
||||||
}
|
}
|
||||||
LoRaRadio.invertIQ(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoraSx126xInit(void) {
|
bool LoraSx126xInit(void) {
|
||||||
LoRaRadio = new Module(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_DI1), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_BUSY));
|
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(Lora->settings.frequency)) {
|
if (RADIOLIB_ERR_NONE == LoRaRadio.begin(Lora->settings.frequency)) {
|
||||||
LoraSx126xConfig();
|
LoraSx126xConfig(true);
|
||||||
LoRaRadio.setDio1Action(LoraSx126xOnInterrupt);
|
LoRaRadio.setDio1Action(LoraSx126xOnInterrupt);
|
||||||
if (RADIOLIB_ERR_NONE == LoRaRadio.startReceive()) {
|
if (RADIOLIB_ERR_NONE == LoRaRadio.startReceive()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -72,35 +72,37 @@ bool LoraSx127xSend(uint8_t* data, uint32_t len, bool invert) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoraSx127xConfig(void) {
|
bool LoraSx127xConfig(bool full) {
|
||||||
LoRa.setFrequency(Lora->settings.frequency * 1000 * 1000);
|
LoRa.setFrequency(Lora->settings.frequency * 1000 * 1000);
|
||||||
LoRa.setSignalBandwidth(Lora->settings.bandwidth * 1000);
|
LoRa.setSignalBandwidth(Lora->settings.bandwidth * 1000);
|
||||||
LoRa.setSpreadingFactor(Lora->settings.spreading_factor);
|
LoRa.setSpreadingFactor(Lora->settings.spreading_factor);
|
||||||
LoRa.setCodingRate4(Lora->settings.coding_rate);
|
if (full) {
|
||||||
LoRa.setSyncWord(Lora->settings.sync_word);
|
LoRa.setCodingRate4(Lora->settings.coding_rate);
|
||||||
LoRa.setTxPower(Lora->settings.output_power);
|
LoRa.setSyncWord(Lora->settings.sync_word);
|
||||||
LoRa.setPreambleLength(Lora->settings.preamble_length);
|
LoRa.setTxPower(Lora->settings.output_power);
|
||||||
LoRa.setOCP(Lora->settings.current_limit);
|
LoRa.setPreambleLength(Lora->settings.preamble_length);
|
||||||
if (Lora->settings.crc_bytes) {
|
LoRa.setOCP(Lora->settings.current_limit);
|
||||||
LoRa.enableCrc();
|
if (Lora->settings.crc_bytes) {
|
||||||
} else {
|
LoRa.enableCrc();
|
||||||
LoRa.disableCrc();
|
} else {
|
||||||
}
|
LoRa.disableCrc();
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
if (Lora->settings.implicit_header) {
|
if (Lora->settings.implicit_header) {
|
||||||
LoRa.implicitHeaderMode();
|
LoRa.implicitHeaderMode();
|
||||||
} else {
|
} else {
|
||||||
LoRa.explicitHeaderMode();
|
LoRa.explicitHeaderMode();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
LoRa.disableInvertIQ(); // normal mode
|
LoRa.disableInvertIQ(); // normal mode
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoraSx127xInit(void) {
|
bool LoraSx127xInit(void) {
|
||||||
LoRa.setPins(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_DI0));
|
LoRa.setPins(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_DI0));
|
||||||
if (LoRa.begin(Lora->settings.frequency * 1000 * 1000)) {
|
if (LoRa.begin(Lora->settings.frequency * 1000 * 1000)) {
|
||||||
LoraSx127xConfig();
|
LoraSx127xConfig(true);
|
||||||
LoRa.onReceive(LoraSx127xOnReceive);
|
LoRa.onReceive(LoraSx127xOnReceive);
|
||||||
LoRa.receive();
|
LoRa.receive();
|
||||||
return true;
|
return true;
|
||||||
|
@ -53,25 +53,27 @@ void LoraWanPublishFooter(uint32_t node) {
|
|||||||
InfluxDbProcess(1); // Use a copy of ResponseData
|
InfluxDbProcess(1); // Use a copy of ResponseData
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Settings->flag4.zigbee_distinct_topics) { // SetOption89 - (MQTT, Zigbee) Distinct MQTT topics per device for Zigbee (1) (#7835)
|
if (!Settings->flag6.mqtt_disable_publish) { // SetOption147 - If it is activated, Tasmota will not publish MQTT messages, but it will proccess event trigger rules
|
||||||
char subtopic[TOPSZ];
|
if (Settings->flag4.zigbee_distinct_topics) { // SetOption89 - (MQTT, Zigbee) Distinct MQTT topics per device for Zigbee (1) (#7835)
|
||||||
// Clean special characters
|
char subtopic[TOPSZ];
|
||||||
char stemp[TOPSZ];
|
// Clean special characters
|
||||||
strlcpy(stemp, Lora->settings.end_node[node].name.c_str(), sizeof(stemp));
|
char stemp[TOPSZ];
|
||||||
MakeValidMqtt(0, stemp);
|
strlcpy(stemp, Lora->settings.end_node[node].name.c_str(), sizeof(stemp));
|
||||||
if (Settings->flag5.zigbee_hide_bridge_topic) { // SetOption125 - (Zigbee) Hide bridge topic from zigbee topic (use with SetOption89) (1)
|
MakeValidMqtt(0, stemp);
|
||||||
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s"), 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);
|
||||||
|
} else {
|
||||||
|
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s/%s"), TasmotaGlobal.mqtt_topic, stemp);
|
||||||
|
}
|
||||||
|
char stopic[TOPSZ];
|
||||||
|
if (Settings->flag5.zb_received_as_subtopic) // SetOption118 - (Zigbee) Move LwReceived from JSON message and into the subtopic replacing "SENSOR" default
|
||||||
|
GetTopic_P(stopic, TELE, subtopic, PSTR("LwReceived"));
|
||||||
|
else
|
||||||
|
GetTopic_P(stopic, TELE, subtopic, PSTR(D_RSLT_SENSOR));
|
||||||
|
MqttPublish(stopic, Settings->flag.mqtt_sensor_retain);
|
||||||
} else {
|
} else {
|
||||||
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s/%s"), TasmotaGlobal.mqtt_topic, stemp);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain);
|
||||||
}
|
}
|
||||||
char stopic[TOPSZ];
|
|
||||||
if (Settings->flag5.zb_received_as_subtopic) // SetOption118 - (Zigbee) Move LwReceived from JSON message and into the subtopic replacing "SENSOR" default
|
|
||||||
GetTopic_P(stopic, TELE, subtopic, PSTR("LwReceived"));
|
|
||||||
else
|
|
||||||
GetTopic_P(stopic, TELE, subtopic, PSTR(D_RSLT_SENSOR));
|
|
||||||
MqttPublish(stopic, Settings->flag.mqtt_sensor_retain);
|
|
||||||
} else {
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain);
|
|
||||||
}
|
}
|
||||||
XdrvRulesProcess(0); // Apply rules
|
XdrvRulesProcess(0); // Apply rules
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ uint32_t LoraWanFrequencyToChannel(void) {
|
|||||||
}
|
}
|
||||||
if (250 == channel) {
|
if (250 == channel) {
|
||||||
Lora->settings.frequency = 868.1;
|
Lora->settings.frequency = 868.1;
|
||||||
Lora->Config();
|
Lora->Config(false);
|
||||||
channel = 0;
|
channel = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,33 +309,50 @@ void LoraWanRadioInfo(uint8_t mode, void* pInfo, uint32_t uChannel = 0) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: { // TAS_LORA_REGION_EU868
|
default: { // TAS_LORA_REGION_EU868
|
||||||
//Default TX/RX1/TX1 same
|
switch (mode) {
|
||||||
(*pResult).frequency = TAS_LORAWAN_FREQUENCY;
|
case TAS_LORAWAN_RADIO_UPLINK: {
|
||||||
(*pResult).bandwidth = TAS_LORAWAN_BANDWIDTH;
|
(*pResult).frequency = TAS_LORAWAN_FREQUENCY;
|
||||||
(*pResult).spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
|
(*pResult).bandwidth = TAS_LORAWAN_BANDWIDTH;
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TAS_LORAWAN_RADIO_RX1: {
|
||||||
|
// RX1 DR depends on the Uplink settings
|
||||||
|
// https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||||
|
// Page 19
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_FREQUENCY;
|
||||||
|
(*pResult).bandwidth = TAS_LORAWAN_BANDWIDTH_RX1;
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_SPREADING_FACTOR_RX1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TAS_LORAWAN_RADIO_RX2: {
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_FREQUENCY_DN;
|
||||||
|
(*pResult).bandwidth = TAS_LORAWAN_BANDWIDTH_RX2;
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_SPREADING_FACTOR_RX2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// default:
|
||||||
|
// not implemented
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoraWanDefaults(uint32_t region = TAS_LORA_REGION_EU868, LoRaWanRadioMode_t mode = TAS_LORAWAN_RADIO_UPLINK) {
|
bool LoraWanProfile(uint32_t mode) {
|
||||||
bool multi_profile = false;
|
LoRaWanRadioInfo_t RadioInfo;
|
||||||
|
LoraWanRadioInfo(mode, &RadioInfo, LoraWanFrequencyToChannel()); // Region specific
|
||||||
|
bool changed = ((Lora->settings.frequency != RadioInfo.frequency) ||
|
||||||
|
(Lora->settings.bandwidth != RadioInfo.bandwidth) ||
|
||||||
|
(Lora->settings.spreading_factor != RadioInfo.spreading_factor));
|
||||||
|
Lora->settings.frequency = RadioInfo.frequency;
|
||||||
|
Lora->settings.bandwidth = RadioInfo.bandwidth;
|
||||||
|
Lora->settings.spreading_factor = RadioInfo.spreading_factor;
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoraWanDefaults(uint32_t region) {
|
||||||
Lora->settings.region = region;
|
Lora->settings.region = region;
|
||||||
switch (region) {
|
LoraWanProfile(TAS_LORAWAN_RADIO_UPLINK);
|
||||||
case TAS_LORA_REGION_AU915:
|
|
||||||
// TO DO: Need 3 profiles: Uplink, RX1, RX2
|
|
||||||
// Works OK for now as RX2 always received by end device.
|
|
||||||
multi_profile = true;
|
|
||||||
LoRaWanRadioInfo_t RadioInfo;
|
|
||||||
LoraWanRadioInfo(mode, &RadioInfo, LoraWanFrequencyToChannel()); // Region specific
|
|
||||||
Lora->settings.frequency = RadioInfo.frequency;
|
|
||||||
Lora->settings.bandwidth = RadioInfo.bandwidth;
|
|
||||||
Lora->settings.spreading_factor = RadioInfo.spreading_factor;
|
|
||||||
break;
|
|
||||||
default: // TAS_LORA_REGION_EU868
|
|
||||||
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.coding_rate = TAS_LORAWAN_CODING_RATE;
|
||||||
Lora->settings.sync_word = TAS_LORAWAN_SYNC_WORD;
|
Lora->settings.sync_word = TAS_LORAWAN_SYNC_WORD;
|
||||||
Lora->settings.output_power = TAS_LORAWAN_OUTPUT_POWER;
|
Lora->settings.output_power = TAS_LORAWAN_OUTPUT_POWER;
|
||||||
@ -343,45 +360,51 @@ bool LoraWanDefaults(uint32_t region = TAS_LORA_REGION_EU868, LoRaWanRadioMode_t
|
|||||||
Lora->settings.current_limit = TAS_LORAWAN_CURRENT_LIMIT;
|
Lora->settings.current_limit = TAS_LORAWAN_CURRENT_LIMIT;
|
||||||
Lora->settings.implicit_header = TAS_LORAWAN_HEADER;
|
Lora->settings.implicit_header = TAS_LORAWAN_HEADER;
|
||||||
Lora->settings.crc_bytes = TAS_LORAWAN_CRC_BYTES;
|
Lora->settings.crc_bytes = TAS_LORAWAN_CRC_BYTES;
|
||||||
return multi_profile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
#include <Ticker.h>
|
#include <Ticker.h>
|
||||||
Ticker LoraWan_Send;
|
Ticker LoraWan_Send_RX1;
|
||||||
|
Ticker LoraWan_Send_RX2;
|
||||||
|
|
||||||
void LoraWanSend(uint8_t* data, uint32_t len, bool uplink_profile) {
|
void LoRaWanSend(void) {
|
||||||
LoraSettings_t RXsettings;
|
if (!Lora->send_request) { return; }
|
||||||
if (uplink_profile) {
|
Lora->send_request = false;
|
||||||
// Different TX/RX profiles allowed. (e.g. LoRaWAN)
|
LoraSend(Lora->send_buffer, Lora->send_buffer_len, true);
|
||||||
// For CmndLoraSend() ... do not allow changes.
|
if (Lora->profile_changed) {
|
||||||
RXsettings = Lora->settings; // Make a copy;
|
Lora->settings = Lora->backup_settings; // Restore copy for reception
|
||||||
LoraWanDefaults(Lora->settings.region, TAS_LORAWAN_RADIO_RX2); // Set Downlink profile TO DO: Support different RX1 & RX2 profiles
|
if (0 == Lora->send_buffer_step) {
|
||||||
Lora->Config();
|
Lora->Init(); // Necessary to re-init the SXxxxx chip in cases where TX/RX frequencies differ
|
||||||
}
|
} else {
|
||||||
LoraSend(data, len, true);
|
Lora->Config(false);
|
||||||
if (uplink_profile) {
|
}
|
||||||
Lora->settings = RXsettings; // Restore copy
|
|
||||||
Lora->Config();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoraWanTickerSend(void) {
|
void LoraWanTickerSend(void) {
|
||||||
|
// Need to stay here as short as possible to not initiate watchdog exception
|
||||||
|
// As SF12 can take over 1 sec do send in loop instead of here
|
||||||
Lora->send_buffer_step--;
|
Lora->send_buffer_step--;
|
||||||
if (1 == Lora->send_buffer_step) {
|
if (1 == Lora->send_buffer_step) {
|
||||||
Lora->rx = true; // Always send during RX1
|
Lora->rx = true; // Always send during RX1
|
||||||
Lora->receive_time = 0; // Reset receive timer
|
Lora->receive_time = 0; // Reset receive timer
|
||||||
LoraWan_Send.once_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uplink_profile = (Lora->settings.region == TAS_LORA_REGION_AU915);
|
|
||||||
if (Lora->rx) { // If received in RX1 do not resend in RX2
|
if (Lora->rx) { // If received in RX1 do not resend in RX2
|
||||||
LoraWanSend(Lora->send_buffer, Lora->send_buffer_len, uplink_profile);
|
if (1 == Lora->send_buffer_step) {
|
||||||
}
|
Lora->profile_changed = LoraWanProfile(TAS_LORAWAN_RADIO_RX1); // Set Downlink RX1 profile
|
||||||
|
} else {
|
||||||
if (uplink_profile && (0 == Lora->send_buffer_step)) {
|
Lora->profile_changed = LoraWanProfile(TAS_LORAWAN_RADIO_RX2); // Set Downlink RX2 profile
|
||||||
Lora->Init(); // Necessary to re-init the SXxxxx chip in cases where TX/RX frequencies differ
|
}
|
||||||
|
if (Lora->profile_changed) {
|
||||||
|
Lora->Config(false);
|
||||||
|
}
|
||||||
|
Lora->send_request = true; // Send in loop fixing watchdogs
|
||||||
|
#ifdef ESP8266
|
||||||
|
SleepSkip(); // Skip sleep
|
||||||
|
#else // ESP32
|
||||||
|
LoRaWanSend();
|
||||||
|
#endif // ESP8266/ESP32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,8 +414,19 @@ void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
|
|||||||
if (nullptr == Lora->send_buffer) { return; }
|
if (nullptr == Lora->send_buffer) { return; }
|
||||||
memcpy(Lora->send_buffer, buffer, len);
|
memcpy(Lora->send_buffer, buffer, len);
|
||||||
Lora->send_buffer_len = len;
|
Lora->send_buffer_len = len;
|
||||||
|
|
||||||
|
Lora->send_request = false;
|
||||||
|
Lora->backup_settings = Lora->settings; // Make a copy;
|
||||||
Lora->send_buffer_step = 2; // Send at RX1 and RX2
|
Lora->send_buffer_step = 2; // Send at RX1 and RX2
|
||||||
LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora->receive_time), LoraWanTickerSend);
|
|
||||||
|
uint32_t delay_rx1 = lorawan_delay - TimePassedSince(Lora->receive_time);
|
||||||
|
LoraWan_Send_RX1.once_ms(delay_rx1, LoraWanTickerSend);
|
||||||
|
uint32_t delay_rx2 = delay_rx1 + TAS_LORAWAN_RECEIVE_DELAY2;
|
||||||
|
LoraWan_Send_RX2.once_ms(delay_rx2, LoraWanTickerSend); // Retry after 1000 ms
|
||||||
|
#ifdef USE_LORA_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: About to send '%*_H' in %d and (optional) %d ms"),
|
||||||
|
Lora->send_buffer_len, Lora->send_buffer, delay_rx1, delay_rx2);
|
||||||
|
#endif // USE_LORA_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------*/
|
||||||
@ -400,12 +434,12 @@ void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
|
|||||||
size_t LoraWanCFList(uint8_t * CFList, size_t uLen) {
|
size_t LoraWanCFList(uint8_t * CFList, size_t uLen) {
|
||||||
// Populates CFList for use in JOIN-ACCEPT message to lock device to specific frequencies
|
// Populates CFList for use in JOIN-ACCEPT message to lock device to specific frequencies
|
||||||
// Returns: Number of bytes added
|
// Returns: Number of bytes added
|
||||||
|
if (uLen < 16) return 0;
|
||||||
|
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
|
|
||||||
switch (Lora->settings.region) {
|
switch (Lora->settings.region) {
|
||||||
case TAS_LORA_REGION_AU915: {
|
case TAS_LORA_REGION_AU915: {
|
||||||
if (uLen < 16) return 0;
|
|
||||||
|
|
||||||
uint8_t uChannel = LoraWanFrequencyToChannel(); // 0..71
|
uint8_t uChannel = LoraWanFrequencyToChannel(); // 0..71
|
||||||
uint8_t uMaskByte = uChannel /8; // 0..8
|
uint8_t uMaskByte = uChannel /8; // 0..8
|
||||||
|
|
||||||
@ -415,17 +449,28 @@ size_t LoraWanCFList(uint8_t * CFList, size_t uLen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add next 6 bytes
|
// Add next 6 bytes
|
||||||
CFList[idx++] = 0x00; //RFU
|
CFList[idx++] = 0x00; // RFU
|
||||||
CFList[idx++] = 0x00;
|
CFList[idx++] = 0x00;
|
||||||
|
|
||||||
CFList[idx++] = 0x00; //RFU
|
CFList[idx++] = 0x00; // RFU
|
||||||
CFList[idx++] = 0x00;
|
CFList[idx++] = 0x00;
|
||||||
CFList[idx++] = 0x00;
|
CFList[idx++] = 0x00;
|
||||||
|
|
||||||
CFList[idx++] = 0x01; //CFListType
|
CFList[idx++] = 0x01; // CFListType
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: { // TAS_LORA_REGION_EU868
|
default: { // TAS_LORA_REGION_EU868
|
||||||
|
/*
|
||||||
|
uint32_t frequency = (Lora->settings.frequency * 10000); // 868.1 -> 8681000
|
||||||
|
|
||||||
|
// Add first 15 bytes
|
||||||
|
for (uint32_t i = 0; i < 5; i++) {
|
||||||
|
CFList[idx++] = frequency;
|
||||||
|
CFList[idx++] = frequency >> 8;
|
||||||
|
CFList[idx++] = frequency >> 16;
|
||||||
|
}
|
||||||
|
CFList[idx++] = 0x00; // CFListType
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return idx;
|
return idx;
|
||||||
@ -551,8 +596,9 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
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) {
|
if (TAS_LORAWAN_MTYPE_JOIN_REQUEST == MType) {
|
||||||
// 0007010000004140A8D64A89710E4140A82893A8AD137F - Dragino
|
// 0007010000004140A8D64A89710E4140A82893A8AD137F - Dragino LDS02
|
||||||
// 000600000000161600B51F000000161600FDA5D8127912 - MerryIoT
|
// 0000010000004140A889AD5C17544140A849E1B2CAC27B - Dragino LHT52
|
||||||
|
// 000600000000161600B51F000000161600FDA5D8127912 - MerryIoT DW10
|
||||||
uint64_t JoinEUI = (uint64_t)data[ 1] | ((uint64_t)data[ 2] << 8) |
|
uint64_t JoinEUI = (uint64_t)data[ 1] | ((uint64_t)data[ 2] << 8) |
|
||||||
((uint64_t)data[ 3] << 16) | ((uint64_t)data[ 4] << 24) |
|
((uint64_t)data[ 3] << 16) | ((uint64_t)data[ 4] << 24) |
|
||||||
((uint64_t)data[ 5] << 32) | ((uint64_t)data[ 6] << 40) |
|
((uint64_t)data[ 5] << 32) | ((uint64_t)data[ 6] << 40) |
|
||||||
@ -569,8 +615,8 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
uint32_t CalcMIC = LoraWanGenerateMIC(data, 19, Lora->settings.end_node[node].AppKey);
|
uint32_t CalcMIC = LoraWanGenerateMIC(data, 19, Lora->settings.end_node[node].AppKey);
|
||||||
if (MIC == CalcMIC) { // Valid MIC based on LoraWanAppKey
|
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"),
|
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Node %d, JoinEUI %8_H, DevEUIh %08X, DevEUIl %08X, DevNonce %04X, MIC %08X"),
|
||||||
(uint8_t*)&JoinEUI, DevEUIh, DevEUIl, DevNonce, MIC);
|
node +1, (uint8_t*)&JoinEUI, DevEUIh, DevEUIl, DevNonce, MIC);
|
||||||
|
|
||||||
Lora->settings.end_node[node].DevEUIl = DevEUIl;
|
Lora->settings.end_node[node].DevEUIl = DevEUIl;
|
||||||
Lora->settings.end_node[node].DevEUIh = DevEUIh;
|
Lora->settings.end_node[node].DevEUIh = DevEUIh;
|
||||||
@ -583,6 +629,7 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
ext_snprintf_P(name, sizeof(name), PSTR("0x%04X"), Lora->settings.end_node[node].DevEUIl & 0x0000FFFF);
|
ext_snprintf_P(name, sizeof(name), PSTR("0x%04X"), Lora->settings.end_node[node].DevEUIl & 0x0000FFFF);
|
||||||
Lora->settings.end_node[node].name = name;
|
Lora->settings.end_node[node].name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t JoinNonce = TAS_LORAWAN_JOINNONCE +node;
|
uint32_t JoinNonce = TAS_LORAWAN_JOINNONCE +node;
|
||||||
uint32_t DevAddr = Lora->device_address +node;
|
uint32_t DevAddr = Lora->device_address +node;
|
||||||
uint32_t NetID = TAS_LORAWAN_NETID;
|
uint32_t NetID = TAS_LORAWAN_NETID;
|
||||||
@ -621,8 +668,9 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
EncData[0] = join_data[0];
|
EncData[0] = join_data[0];
|
||||||
LoraWanEncryptJoinAccept(Lora->settings.end_node[node].AppKey, &join_data[1], join_data_index-1, &EncData[1]);
|
LoraWanEncryptJoinAccept(Lora->settings.end_node[node].AppKey, &join_data[1], join_data_index-1, &EncData[1]);
|
||||||
|
|
||||||
// 203106E5000000412E010003017CB31DD4 - Dragino
|
// 203106E5000000412E010003017CB31DD4 - Dragino LDS02
|
||||||
// 203206E5000000422E010003016A210EEA - MerryIoT
|
// 2026B4E06C390AFA1B166D465987F31EC4 - Dragino LHT52
|
||||||
|
// 203206E5000000422E010003016A210EEA - MerryIoT DW10
|
||||||
LoraWanSendResponse(EncData, join_data_index, TAS_LORAWAN_JOIN_ACCEPT_DELAY1);
|
LoraWanSendResponse(EncData, join_data_index, TAS_LORAWAN_JOIN_ACCEPT_DELAY1);
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -46,7 +46,7 @@ void LoraSettings2Json(bool show = false) {
|
|||||||
ResponseAppend_P(PSTR("\"" D_JSON_REGION "\":%d"), Lora->settings.region); // enum 0 = EU868, 1 = AU915
|
ResponseAppend_P(PSTR("\"" D_JSON_REGION "\":%d"), Lora->settings.region); // enum 0 = EU868, 1 = AU915
|
||||||
}
|
}
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
if (show && (Lora->settings.region == TAS_LORA_REGION_AU915)) {
|
if (show && (bitRead(Lora->settings.flags, TAS_LORA_FLAG_BRIDGE_ENABLED))) {
|
||||||
LoRaWanRadioInfo_t Rx1Info;
|
LoRaWanRadioInfo_t Rx1Info;
|
||||||
LoraWanRadioInfo(TAS_LORAWAN_RADIO_RX1, &Rx1Info, LoraWanFrequencyToChannel()); // Get Rx1Info with values used for RX1 transmit window. (Region specific, calculated from Uplink radio settings)
|
LoraWanRadioInfo(TAS_LORAWAN_RADIO_RX1, &Rx1Info, LoraWanFrequencyToChannel()); // Get Rx1Info with values used for RX1 transmit window. (Region specific, calculated from Uplink radio settings)
|
||||||
LoRaWanRadioInfo_t Rx2Info;
|
LoRaWanRadioInfo_t Rx2Info;
|
||||||
@ -193,8 +193,8 @@ void LoraSettingsSave(void) {
|
|||||||
bool LoraSend(uint8_t* data, uint32_t len, bool invert) {
|
bool LoraSend(uint8_t* data, uint32_t len, bool invert) {
|
||||||
uint32_t lora_time = millis(); // Time is important for LoRaWan RX windows
|
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"),
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Send (%u) '%*_H', Invert %d, Freq %1_f, BW %1_f, SF %d, Time %d"),
|
||||||
lora_time, len, data, invert, TimePassedSince(lora_time));
|
lora_time, len, data, invert, &Lora->settings.frequency, &Lora->settings.bandwidth, Lora->settings.spreading_factor, TimePassedSince(lora_time));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,8 +204,8 @@ void LoraInput(void) {
|
|||||||
char data[TAS_LORA_MAX_PACKET_LENGTH] = { 0 };
|
char data[TAS_LORA_MAX_PACKET_LENGTH] = { 0 };
|
||||||
int packet_size = Lora->Receive(data);
|
int packet_size = Lora->Receive(data);
|
||||||
if (!packet_size) { return; }
|
if (!packet_size) { return; }
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Rcvd (%u) '%*_H', RSSI %1_f, SNR %1_f"),
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Rcvd (%u) '%*_H', Freq %1_f, BW %1_f, SF %d, RSSI %1_f, SNR %1_f"),
|
||||||
Lora->receive_time, packet_size, data, &Lora->rssi, &Lora->snr);
|
Lora->receive_time, packet_size, data, &Lora->settings.frequency, &Lora->settings.bandwidth, Lora->settings.spreading_factor, &Lora->rssi, &Lora->snr);
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
if (bitRead(Lora->settings.flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
|
if (bitRead(Lora->settings.flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
|
||||||
if (LoraWanInput((uint8_t*)data, packet_size)) {
|
if (LoraWanInput((uint8_t*)data, packet_size)) {
|
||||||
@ -457,9 +457,9 @@ void CmndLoraConfig(void) {
|
|||||||
LoraDefaults(region); // Default region LoRa values
|
LoraDefaults(region); // Default region LoRa values
|
||||||
break;
|
break;
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
case 2:
|
case 2: {
|
||||||
switch (region) {
|
switch (region) {
|
||||||
case TAS_LORA_REGION_AU915:
|
case TAS_LORA_REGION_AU915: {
|
||||||
uint32_t parm[2] = { 0, 0 };
|
uint32_t parm[2] = { 0, 0 };
|
||||||
ParseParameters(2, parm); // parm[1] will hold channel
|
ParseParameters(2, parm); // parm[1] will hold channel
|
||||||
Lora->settings.region = region; // Need valid region for LoraWanRadioInfo()
|
Lora->settings.region = region; // Need valid region for LoraWanRadioInfo()
|
||||||
@ -467,21 +467,23 @@ void CmndLoraConfig(void) {
|
|||||||
LoraWanRadioInfo(TAS_LORAWAN_RADIO_UPLINK, &UpInfo, parm[1]); // Set uplink frequency based on channel
|
LoraWanRadioInfo(TAS_LORAWAN_RADIO_UPLINK, &UpInfo, parm[1]); // Set uplink frequency based on channel
|
||||||
Lora->settings.frequency = UpInfo.frequency;
|
Lora->settings.frequency = UpInfo.frequency;
|
||||||
break;
|
break;
|
||||||
// default:
|
}
|
||||||
// not implemented
|
default: // TAS_LORA_REGION_EU868
|
||||||
|
Lora->settings.frequency = TAS_LORAWAN_FREQUENCY;
|
||||||
}
|
}
|
||||||
LoraWanDefaults(region); // Default region LoRaWan values
|
LoraWanDefaults(region); // Default region LoRaWan values
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#endif // USE_LORAWAN_BRIDGE
|
#endif // USE_LORAWAN_BRIDGE
|
||||||
}
|
}
|
||||||
Lora->Config();
|
Lora->Config(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JsonParser parser(XdrvMailbox.data);
|
JsonParser parser(XdrvMailbox.data);
|
||||||
JsonParserObject root = parser.getRootObject();
|
JsonParserObject root = parser.getRootObject();
|
||||||
if (root) {
|
if (root) {
|
||||||
LoraJson2Settings(root);
|
LoraJson2Settings(root);
|
||||||
Lora->Config();
|
Lora->Config(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint8_t data[1] = { 0 };
|
uint8_t data[1] = { 0 };
|
||||||
@ -507,6 +509,9 @@ bool Xdrv73(uint32_t function) {
|
|||||||
switch (function) {
|
switch (function) {
|
||||||
case FUNC_LOOP:
|
case FUNC_LOOP:
|
||||||
case FUNC_SLEEP_LOOP:
|
case FUNC_SLEEP_LOOP:
|
||||||
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
|
LoRaWanSend();
|
||||||
|
#endif // USE_LORAWAN_BRIDGE
|
||||||
LoraInput();
|
LoraInput();
|
||||||
break;
|
break;
|
||||||
case FUNC_RESET_SETTINGS:
|
case FUNC_RESET_SETTINGS:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user