Allow lora on ESP8266

This commit is contained in:
Theo Arends 2024-02-25 14:29:56 +01:00
parent 87567b25b2
commit b218f6bff1
3 changed files with 163 additions and 104 deletions

View File

@ -0,0 +1,15 @@
/*
xdrv_73_0_lora_struct.ino - LoRa support for Tasmota
SPDX-FileCopyrightText: 2024 Theo Arends
SPDX-License-Identifier: GPL-3.0-only
*/
#ifdef USE_SPI
#ifdef USE_SPI_LORA
#define LORA_MAX_PACKET_LENGTH 252 // Max packet length allowed (defined by RadioLib driver)
#endif // USE_SPI_LORA
#endif // USE_SPI

View File

@ -0,0 +1,106 @@
/*
xdrv_73_3_lora_sx1262.ino - LoRa support for Tasmota
SPDX-FileCopyrightText: 2024 Theo Arends
SPDX-License-Identifier: GPL-3.0-only
*/
#ifdef USE_SPI
#ifdef USE_SPI_LORA
#ifdef USE_LORA_SX1262
/*********************************************************************************************\
* Demo of LoRa using LilyGo T3S3 using SX1262 on 868MHz
*
* Tasmota currently does not support user config of GPIO33 and GPIO34 on ESP32S3
\*********************************************************************************************/
#include <RadioLib.h>
SX1262 LoRa = nullptr;
struct {
// flag to indicate that a packet was received
volatile bool receivedFlag;
// disable interrupt when it's not needed
volatile bool enableInterrupt;
bool sendFlag;
} Sx1262;
/*********************************************************************************************/
// this function is called when a complete packet is received by the module
// IMPORTANT: this function MUST be 'void' type and MUST NOT have any arguments!
void LoraSetFlagSx1262(void) {
// check if the interrupt is enabled
if (!Sx1262.enableInterrupt) { return; }
// we got a packet, set the flag
Sx1262.receivedFlag = true;
}
bool LoraAvailableSx1262(void) {
// check if the flag is set
return (Sx1262.receivedFlag);
}
int LoraInputSx1262(char* data) {
int packet_size = 0;
// disable the interrupt service routine while processing the data
Sx1262.enableInterrupt = false;
// reset flag
Sx1262.receivedFlag = false;
// String str;
// int state = LoRa.readData(str);
int state = LoRa.readData((uint8_t*)data, LORA_MAX_PACKET_LENGTH -1);
if (state == RADIOLIB_ERR_NONE) {
if (!Sx1262.sendFlag) {
// Find end of raw data being non-zero (No way to know raw data length)
packet_size = LORA_MAX_PACKET_LENGTH;
while (packet_size-- && (0 == data[packet_size]));
if (0 != data[packet_size]) { packet_size++; }
}
}
else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
// packet was received, but is malformed
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: CRC error"));
}
else {
// some other error occurred
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Receive error %d"), state);
}
// put module back to listen mode
LoRa.startReceive();
Sx1262.sendFlag = false;
// we're ready to receive more packets, enable interrupt service routine
Sx1262.enableInterrupt = true;
return packet_size;
}
bool LoraInitSx1262(void) {
// LoRa = new Module(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_DI1), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_BUSY));
LoRa = new Module(Pin(GPIO_LORA_CS), 33, Pin(GPIO_LORA_RST), 34);
if (RADIOLIB_ERR_NONE == LoRa.begin(868.0)) {
Sx1262.enableInterrupt = true;
LoRa.setDio1Action(LoraSetFlagSx1262);
if (RADIOLIB_ERR_NONE == LoRa.startReceive()) {
return true;
}
}
return false;
}
void LoraSendSx1262(char* data, uint32_t len) {
Sx1262.sendFlag = true;
LoRa.startTransmit(data, len);
}
#endif // USE_LORA_SX1262
#endif // USE_SPI_LORA
#endif // USE_SPI

View File

@ -1,133 +1,74 @@
/*
xdrv_80_esp32_lora.ino - LoRa support for Tasmota
xdrv_73_9_lora.ino - LoRa support for Tasmota
SPDX-FileCopyrightText: 2024 Theo Arends
SPDX-License-Identifier: GPL-3.0-only
*/
#ifdef ESP32
#ifdef USE_SPI
#ifdef USE_SPI_LORA
#ifdef USE_LORA_SX1262
/*********************************************************************************************\
* Demo of LoRa using LilyGo T3S3 using SX1262 on 868MHz
*
* Tasmota currently does not support user config of GPIO33 and GPIO34 on ESP32S3
* LoRa
\*********************************************************************************************/
#define XDRV_80 80
#define LORA_MAX_PACKET_LENGTH 252 // Max packet length allowed (defined by RadioLib driver)
#include <RadioLib.h>
SX1262 LoRa = nullptr;
#define XDRV_73 73
struct {
// flag to indicate that a packet was received
volatile bool receivedFlag;
// disable interrupt when it's not needed
volatile bool enableInterrupt;
bool sendFlag;
bool raw;
bool present;
} Lora;
/*********************************************************************************************/
// this function is called when a complete packet is received by the module
// IMPORTANT: this function MUST be 'void' type and MUST NOT have any arguments!
void LoraSetFlag(void) {
// check if the interrupt is enabled
if (!Lora.enableInterrupt) { return; }
// we got a packet, set the flag
Lora.receivedFlag = true;
}
/*********************************************************************************************/
void LoraInput(void) {
// check if the flag is set
if (!Lora.receivedFlag) { return; }
if (!LoraAvailableSx1262()) { return; }
// disable the interrupt service routine while processing the data
Lora.enableInterrupt = false;
// reset flag
Lora.receivedFlag = false;
// String str;
// int state = LoRa.readData(str);
char data[LORA_MAX_PACKET_LENGTH] = { 0 };
int state = LoRa.readData((uint8_t*)data, LORA_MAX_PACKET_LENGTH -1);
if (state == RADIOLIB_ERR_NONE) {
if (!Lora.sendFlag) {
// Find end of raw data being non-zero (No way to know raw data length)
uint32_t len = LORA_MAX_PACKET_LENGTH;
while (len-- && (0 == data[len]));
if (len) {
len++;
bool raw = Lora.raw;
// Set raw mode if zeroes within data
for (uint32_t i = 0; i < len; i++) {
if (0 == data[i]) {
raw = true;
break;
}
}
bool assume_json = (!raw && (data[0] == '{'));
Response_P(PSTR("{\"LoRaReceived\":"));
if (assume_json) {
ResponseAppend_P(data);
} else {
ResponseAppend_P(PSTR("\""));
if (raw) {
ResponseAppend_P(PSTR("%*_H"), len, data);
} else {
ResponseAppend_P(EscapeJSONString(data).c_str());
}
ResponseAppend_P(PSTR("\""));
}
float rssi = LoRa.getRSSI();
float snr = LoRa.getSNR();
ResponseAppend_P(PSTR(",\"RSSI\":%1_f,\"SNR\":%1_f}"), &rssi, &snr);
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR("LoRaReceived"));
}
int packet_size = LoraInputSx1262(data);
if (!packet_size) { return; }
bool raw = Lora.raw;
// Set raw mode if zeroes within data
for (uint32_t i = 0; i < packet_size; i++) {
if (0 == data[i]) {
raw = true;
break;
}
}
else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
// packet was received, but is malformed
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: CRC error"));
}
else {
// some other error occurred
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Receive error %d"), state);
bool assume_json = (!raw && (data[0] == '{'));
Response_P(PSTR("{\"LoRaReceived\":"));
if (assume_json) {
ResponseAppend_P(data);
} else {
ResponseAppend_P(PSTR("\""));
if (raw) {
ResponseAppend_P(PSTR("%*_H"), packet_size, data);
} else {
ResponseAppend_P(EscapeJSONString(data).c_str());
}
ResponseAppend_P(PSTR("\""));
}
// float rssi = LoRa.getRSSI();
// float snr = LoRa.getSNR();
// ResponseAppend_P(PSTR(",\"RSSI\":%1_f,\"SNR\":%1_f}"), &rssi, &snr);
ResponseJsonEnd();
// put module back to listen mode
LoRa.startReceive();
Lora.sendFlag = false;
// we're ready to receive more packets,
// enable interrupt service routine
Lora.enableInterrupt = true;
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR("LoRaReceived"));
}
void LoraInit(void) {
if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) &&
(PinUsed(GPIO_LORA_CS)) && (PinUsed(GPIO_LORA_RST))) {
#ifdef ESP8266
SPI.begin();
#endif // ESP8266
#ifdef ESP32
SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
// LoRa = new Module(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_DI1), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_BUSY));
LoRa = new Module(Pin(GPIO_LORA_CS), 33, Pin(GPIO_LORA_RST), 34);
if (RADIOLIB_ERR_NONE == LoRa.begin(868.0)) {
Lora.enableInterrupt = true;
LoRa.setDio1Action(LoraSetFlag);
if (RADIOLIB_ERR_NONE == LoRa.startReceive()) {
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Initialized"));
Lora.present = true;
}
#endif // ESP32
if (LoraInitSx1262()) {
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Initialized"));
Lora.present = true;
}
}
}
@ -156,11 +97,11 @@ void CmndLoraSend(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) {
Lora.raw = (XdrvMailbox.index > 3); // Global flag set even without data
if (XdrvMailbox.data_len > 0) {
uint8_t data[LORA_MAX_PACKET_LENGTH];
char data[LORA_MAX_PACKET_LENGTH];
uint32_t len = (XdrvMailbox.data_len < LORA_MAX_PACKET_LENGTH -1) ? XdrvMailbox.data_len : LORA_MAX_PACKET_LENGTH -2;
if (1 == XdrvMailbox.index) { // "Hello Tiger\n"
memcpy(data, XdrvMailbox.data, len);
data[len++] = (uint8_t)'\n';
data[len++] = '\n';
}
else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { // "Hello Tiger" or "A0"
memcpy(data, XdrvMailbox.data, len);
@ -199,8 +140,7 @@ void CmndLoraSend(void) {
len = 0;
}
if (len) {
Lora.sendFlag = true;
LoRa.startTransmit(data, len);
LoraSendSx1262(data, len);
}
ResponseCmndDone();
}
@ -211,7 +151,7 @@ void CmndLoraSend(void) {
* Interface
\*********************************************************************************************/
bool Xdrv80(uint32_t function) {
bool Xdrv73(uint32_t function) {
bool result = false;
if (FUNC_INIT == function) {
@ -234,8 +174,6 @@ bool Xdrv80(uint32_t function) {
return result;
}
#endif // USE_LORA_SX1262
#endif // USE_SPI_LORA
#endif // USE_SPI
#endif // ESP32