mirror of https://github.com/arendst/Tasmota.git
v5.12.0h - Add Serial Bridges
5.12.0h * Add support for Software Serial bridge using commands SerialDelimiter, SBaudrate and SSerialSend. Supports 8N1 and text only (#2190) * Add support for Hardware Serial bridge using commands SerialDelimiter, Baudrate and SerialSend. Supports 8N1 and text only (#2182)
This commit is contained in:
parent
d3ef9caa34
commit
2ba4d6fb47
|
@ -1,7 +1,7 @@
|
|||
## Sonoff-Tasmota
|
||||
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
|
||||
|
||||
Current version is **5.12.0g** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.12.0h** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
### ATTENTION All versions
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# TasmotaSerial
|
||||
|
||||
Implementation of software serial library for the ESP8266 at 9600 baud
|
||||
Implementation of software serial library for the ESP8266
|
||||
|
||||
Allows for several instances to be active at the same time.
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"name": "TasmotaSerial",
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.0",
|
||||
"keywords": [
|
||||
"serial", "io", "TasmotaSerial"
|
||||
],
|
||||
"description": "Implementation of software serial for ESP8266 at 9600 baud.",
|
||||
"description": "Implementation of software serial for ESP8266.",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
|
@ -1,8 +1,8 @@
|
|||
name=TasmotaSerial
|
||||
version=1.0
|
||||
version=1.2.0
|
||||
author=Theo Arends
|
||||
maintainer=Theo Arends <theo@arends.com>
|
||||
sentence=Implementation of software serial for ESP8266 at 9600 baud.
|
||||
sentence=Implementation of software serial for ESP8266.
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=
|
|
@ -87,9 +87,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin)
|
|||
m_in_pos = m_out_pos = 0;
|
||||
if (m_rx_pin > -1) {
|
||||
m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE);
|
||||
if (m_buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
if (m_buffer == NULL) return;
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE;
|
||||
pinMode(m_rx_pin, INPUT);
|
||||
|
@ -111,7 +109,8 @@ bool TasmotaSerial::isValidGPIOpin(int pin)
|
|||
bool TasmotaSerial::begin(long speed) {
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed;
|
||||
return m_valid && (speed <= TM_SERIAL_BAUDRATE);
|
||||
m_high_speed = (speed > 9600);
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
bool TasmotaSerial::begin() {
|
||||
|
@ -123,17 +122,13 @@ void TasmotaSerial::flush() {
|
|||
}
|
||||
|
||||
int TasmotaSerial::peek() {
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) {
|
||||
return -1;
|
||||
}
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
|
||||
return m_buffer[m_out_pos];
|
||||
}
|
||||
|
||||
int TasmotaSerial::read()
|
||||
{
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) {
|
||||
return -1;
|
||||
}
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
|
||||
uint8_t ch = m_buffer[m_out_pos];
|
||||
m_out_pos = (m_out_pos +1) % TM_SERIAL_BUFFER_SIZE;
|
||||
return ch;
|
||||
|
@ -142,23 +137,20 @@ int TasmotaSerial::read()
|
|||
int TasmotaSerial::available()
|
||||
{
|
||||
int avail = m_in_pos - m_out_pos;
|
||||
if (avail < 0) {
|
||||
avail += TM_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
if (avail < 0) avail += TM_SERIAL_BUFFER_SIZE;
|
||||
return avail;
|
||||
}
|
||||
|
||||
#ifdef TM_SERIAL_USE_IRAM
|
||||
#define TM_SERIAL_WAIT { while (ESP.getCycleCount()-start < wait) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts
|
||||
#define TM_SERIAL_WAIT { while (ESP.getCycleCount()-start < wait) if (!m_high_speed) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts
|
||||
#else
|
||||
#define TM_SERIAL_WAIT { while (ESP.getCycleCount()-start < wait); wait += m_bit_time; }
|
||||
#endif
|
||||
|
||||
size_t TasmotaSerial::write(uint8_t b)
|
||||
{
|
||||
if (-1 == m_tx_pin) {
|
||||
return 0;
|
||||
}
|
||||
if (-1 == m_tx_pin) return 0;
|
||||
if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit
|
||||
unsigned long wait = m_bit_time;
|
||||
digitalWrite(m_tx_pin, HIGH);
|
||||
unsigned long start = ESP.getCycleCount();
|
||||
|
@ -173,6 +165,7 @@ size_t TasmotaSerial::write(uint8_t b)
|
|||
// Stop bit
|
||||
digitalWrite(m_tx_pin, HIGH);
|
||||
TM_SERIAL_WAIT;
|
||||
if (m_high_speed) sei();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -191,9 +184,7 @@ void TasmotaSerial::rxRead()
|
|||
for (int i = 0; i < 8; i++) {
|
||||
TM_SERIAL_WAIT;
|
||||
rec >>= 1;
|
||||
if (digitalRead(m_rx_pin)) {
|
||||
rec |= 0x80;
|
||||
}
|
||||
if (digitalRead(m_rx_pin)) rec |= 0x80;
|
||||
}
|
||||
// Stop bit
|
||||
TM_SERIAL_WAIT;
|
|
@ -20,12 +20,12 @@
|
|||
#ifndef TasmotaSerial_h
|
||||
#define TasmotaSerial_h
|
||||
/*********************************************************************************************\
|
||||
* TasmotaSerial supports up to 9600 baud with fixed buffer size of 64 bytes using optional no iram
|
||||
* TasmotaSerial supports up to 115200 baud with fixed buffer size of 64 bytes using optional no iram
|
||||
*
|
||||
* Based on EspSoftwareSerial v3.3.1 by Peter Lerup (https://github.com/plerup/espsoftwareserial)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define TM_SERIAL_BAUDRATE 9600 // Max supported baudrate
|
||||
#define TM_SERIAL_BAUDRATE 9600 // Default baudrate
|
||||
#define TM_SERIAL_BUFFER_SIZE 64 // Receive buffer size
|
||||
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
|
@ -57,6 +57,7 @@ class TasmotaSerial : public Stream {
|
|||
|
||||
// Member variables
|
||||
bool m_valid;
|
||||
bool m_high_speed;
|
||||
int m_rx_pin;
|
||||
int m_tx_pin;
|
||||
unsigned long m_bit_time;
|
|
@ -1,5 +1,6 @@
|
|||
/* 5.12.0g
|
||||
* Add support for MQTT to hardware serial bridge using commands Baudrate and SerialSend. Currently supports 8N1 and text only (#2182)
|
||||
/* 5.12.0h
|
||||
* Add support for Software Serial bridge using commands SerialDelimiter, SBaudrate and SSerialSend. Supports 8N1 and text only (#2190)
|
||||
* Add support for Hardware Serial bridge using commands SerialDelimiter, Baudrate and SerialSend. Supports 8N1 and text only (#2182)
|
||||
*
|
||||
* 5.12.0f
|
||||
* Add compile time support for WS2812 BRG and RBG led configurations to be defined in user_config.h (#1690)
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
#define D_CMND_CFGDUMP "CfgDump"
|
||||
#define D_CMND_I2CSCAN "I2CScan"
|
||||
#define D_CMND_SERIALSEND "SerialSend"
|
||||
#define D_CMND_SERIALDELIMITER "SerialDelimiter"
|
||||
#define D_CMND_BAUDRATE "Baudrate"
|
||||
#define D_CMND_EXCEPTION "Exception"
|
||||
|
||||
|
@ -340,6 +341,11 @@
|
|||
#define D_CMND_DISP_SIZE "Size"
|
||||
#define D_CMND_DISP_TEXT "Text"
|
||||
|
||||
// Commands xdrv_08_serial_bridge.ino
|
||||
#define D_CMND_SSERIALSEND "SSerialSend"
|
||||
#define D_CMND_SBAUDRATE "SBaudrate"
|
||||
#define D_JSON_SSERIALRECEIVED "SSerialReceived"
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
#ifndef MY_LANGUAGE
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "Háttérvil"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "Luz negra"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -192,9 +192,8 @@ struct SYSCFG {
|
|||
uint16_t ws_wakeup; // 3AA Not used since 5.8.0
|
||||
char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC
|
||||
char switch_topic[33]; // 430
|
||||
|
||||
byte free_451[2]; // 451
|
||||
|
||||
char serial_delimiter; // 451
|
||||
uint8_t sbaudrate; // 452
|
||||
uint8_t sleep; // 453
|
||||
uint16_t domoticz_switch_idx[MAX_DOMOTICZ_IDX]; // 454
|
||||
uint16_t domoticz_sensor_idx[MAX_DOMOTICZ_SNS_IDX]; // 45C
|
||||
|
|
|
@ -458,6 +458,8 @@ void SettingsDefaultSet2()
|
|||
Settings.timezone = APP_TIMEZONE;
|
||||
strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url));
|
||||
Settings.baudrate = APP_BAUDRATE / 1200;
|
||||
Settings.sbaudrate = SOFT_BAUDRATE / 1200;
|
||||
Settings.serial_delimiter = 0xff;
|
||||
|
||||
Settings.seriallog_level = SERIAL_LOG_LEVEL;
|
||||
// Settings.sta_active = 0;
|
||||
|
@ -903,6 +905,10 @@ void SettingsDelta()
|
|||
if (Settings.version < 0x050C0007) {
|
||||
Settings.baudrate = APP_BAUDRATE / 1200;
|
||||
}
|
||||
if (Settings.version < 0x050C0008) {
|
||||
Settings.sbaudrate = SOFT_BAUDRATE / 1200;
|
||||
Settings.serial_delimiter = 0xff;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
|
|
|
@ -98,6 +98,7 @@ typedef unsigned long power_t; // Power (Relay) type
|
|||
#define MAX_BACKLOG 16 // Max number of commands in backlog (chk backlog_index and backlog_pointer code)
|
||||
#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds
|
||||
|
||||
#define SOFT_BAUDRATE 9600 // Default software serial baudrate
|
||||
#define APP_BAUDRATE 115200 // Default serial baudrate
|
||||
#define SERIAL_POLLING 100 // Serial receive polling in ms
|
||||
#define MAX_STATUS 11 // Max number of status lines
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x050C0007 // 5.12.0g
|
||||
#define VERSION 0x050C0008 // 5.12.0h
|
||||
|
||||
// Location specific includes
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
|
@ -76,7 +76,7 @@ enum TasmotaCommands {
|
|||
CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME,
|
||||
CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_EMULATION,
|
||||
CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE,
|
||||
CMND_CFGDUMP, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_EXCEPTION };
|
||||
CMND_CFGDUMP, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_EXCEPTION };
|
||||
const char kTasmotaCommands[] PROGMEM =
|
||||
D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|"
|
||||
D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|"
|
||||
|
@ -86,7 +86,7 @@ const char kTasmotaCommands[] PROGMEM =
|
|||
D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|"
|
||||
D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_EMULATION "|"
|
||||
D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|"
|
||||
D_CMND_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE
|
||||
D_CMND_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER
|
||||
#ifdef DEBUG_THEO
|
||||
"|" D_CMND_EXCEPTION
|
||||
#endif
|
||||
|
@ -821,15 +821,35 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200);
|
||||
}
|
||||
else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 2)) {
|
||||
else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 3)) {
|
||||
SetSeriallog(LOG_LEVEL_NONE);
|
||||
Settings.flag.mqtt_serial = 1;
|
||||
if (data_len > 0) {
|
||||
if (1 == index) Serial.printf("%s\n", dataBuf);
|
||||
if (2 == index) Serial.printf("%s", dataBuf);
|
||||
if (1 == index) {
|
||||
Serial.printf("%s\n", dataBuf);
|
||||
}
|
||||
else if (2 == index) {
|
||||
Serial.printf("%s", dataBuf);
|
||||
}
|
||||
else if (3 == index) {
|
||||
uint16_t dat_len = data_len;
|
||||
Serial.printf("%s", Unescape(dataBuf, &dat_len));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
}
|
||||
}
|
||||
else if (CMND_SERIALDELIMITER == command_code) {
|
||||
if ((data_len > 0) && (payload < 256)) {
|
||||
if (payload > 0) {
|
||||
Settings.serial_delimiter = payload;
|
||||
} else {
|
||||
uint16_t dat_len = data_len;
|
||||
Unescape(dataBuf, &dat_len);
|
||||
Settings.serial_delimiter = dataBuf[0];
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.serial_delimiter);
|
||||
}
|
||||
else if (CMND_SERIALLOG == command_code) {
|
||||
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
|
@ -1921,17 +1941,26 @@ void SerialInput()
|
|||
|
||||
if (serial_in_byte > 127) { // binary data...
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
if (isprint(serial_in_byte)) {
|
||||
if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
serial_polling_window = millis();
|
||||
} else {
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
if (!Settings.flag.mqtt_serial) {
|
||||
if (isprint(serial_in_byte)) {
|
||||
if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
} else {
|
||||
serial_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (serial_in_byte) {
|
||||
if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
serial_polling_window = millis();
|
||||
} else {
|
||||
serial_polling_window = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1949,24 +1978,7 @@ void SerialInput()
|
|||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
else if (serial_in_byte == '\n') {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
if (!Settings.flag.mqtt_serial) {
|
||||
seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (byte)LOG_LEVEL_INFO : Settings.seriallog_level;
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), serial_in_buffer);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
ExecuteCommand(serial_in_buffer);
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
}
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
else if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (byte)LOG_LEVEL_INFO : Settings.seriallog_level;
|
||||
|
@ -1985,8 +1997,6 @@ void SerialInput()
|
|||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ void WifiWpsStatusCallback(wps_cb_status status);
|
|||
#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code)
|
||||
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
|
||||
#define USE_IR_HVAC // Support for HVAC system using IR (+2k code)
|
||||
#define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram)
|
||||
|
|
|
@ -89,6 +89,8 @@ enum UserSelectablePins {
|
|||
GPIO_BACKLIGHT, // Display backlight control
|
||||
GPIO_PMS5003, // Plantower PMS5003 Serial interface
|
||||
GPIO_SDS0X1, // Nova Fitness SDS011 Serial interface
|
||||
GPIO_SBR_TX, // Serial Bridge Serial interface
|
||||
GPIO_SBR_RX, // Serial Bridge Serial interface
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
|
@ -130,7 +132,8 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"
|
||||
D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|"
|
||||
D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|"
|
||||
D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1;
|
||||
D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1 "|"
|
||||
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
|
|
@ -197,6 +197,50 @@ char* dtostrfd(double number, unsigned char prec, char *s)
|
|||
return dtostrf(number, 1, prec, s);
|
||||
}
|
||||
|
||||
char* Unescape(char* buffer, uint16_t* size)
|
||||
{
|
||||
uint8_t* read = (uint8_t*)buffer;
|
||||
uint8_t* write = (uint8_t*)buffer;
|
||||
uint16_t start_size = *size;
|
||||
uint16_t end_size = *size;
|
||||
uint8_t che = 0;
|
||||
|
||||
while (start_size > 0) {
|
||||
uint8_t ch = *read++;
|
||||
start_size--;
|
||||
if (ch != '\\') {
|
||||
*write++ = ch;
|
||||
} else {
|
||||
if (start_size > 0) {
|
||||
uint8_t chi = *read++;
|
||||
start_size--;
|
||||
end_size--;
|
||||
switch (chi) {
|
||||
case '\\': che = '\\'; break; // 5C Backslash
|
||||
case 'a': che = '\a'; break; // 07 Bell (Alert)
|
||||
case 'b': che = '\b'; break; // 08 Backspace
|
||||
case 'e': che = '\e'; break; // 1B Escape
|
||||
case 'f': che = '\f'; break; // 0C Formfeed
|
||||
case 'n': che = '\n'; break; // 0A Linefeed (Newline)
|
||||
case 'r': che = '\r'; break; // 0D Carriage return
|
||||
// case 's': che = ' '; break; // 20 Space
|
||||
case 't': che = '\t'; break; // 09 Horizontal tab
|
||||
case 'v': che = '\v'; break; // 0B Vertical tab
|
||||
// case '?': che = '\?'; break; // 3F Question mark
|
||||
default : {
|
||||
che = chi;
|
||||
*write++ = ch;
|
||||
end_size++;
|
||||
}
|
||||
}
|
||||
*write++ = che;
|
||||
}
|
||||
}
|
||||
}
|
||||
*size = end_size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
boolean ParseIp(uint32_t* addr, const char* str)
|
||||
{
|
||||
uint8_t *part = (uint8_t*)addr;
|
||||
|
|
|
@ -220,6 +220,7 @@
|
|||
#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code)
|
||||
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||
|
||||
// -- Low level interface devices -----------------
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
xdrv_08_serial_bridge.ino - serial bridge support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends and Dániel Zoltán Tolnai
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SERIAL_BRIDGE
|
||||
/*********************************************************************************************\
|
||||
* Serial Bridge using Software Serial library (TasmotaSerial)
|
||||
\*********************************************************************************************/
|
||||
#define SERIAL_BRIDGE_BUFFER_SIZE 130
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
enum SerialBridgeCommands { CMND_SSERIALSEND, CMND_SBAUDRATE };
|
||||
const char kSerialBridgeCommands[] PROGMEM = D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE;
|
||||
|
||||
TasmotaSerial *SerialBridgeSerial;
|
||||
|
||||
uint8_t serial_bridge_active = 1;
|
||||
uint8_t serial_bridge_in_byte_counter = 0;
|
||||
unsigned long serial_bridge_polling_window = 0;
|
||||
char serial_bridge_buffer[SERIAL_BRIDGE_BUFFER_SIZE];
|
||||
|
||||
void SerialBridgeInput()
|
||||
{
|
||||
while (SerialBridgeSerial->available()) {
|
||||
yield();
|
||||
uint8_t serial_in_byte = SerialBridgeSerial->read();
|
||||
|
||||
if (serial_in_byte > 127) { // binary data...
|
||||
serial_bridge_in_byte_counter = 0;
|
||||
SerialBridgeSerial->flush();
|
||||
return;
|
||||
}
|
||||
if (serial_in_byte) {
|
||||
if ((serial_in_byte_counter < sizeof(serial_bridge_buffer) -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits
|
||||
serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte;
|
||||
serial_bridge_polling_window = millis(); // Wait for more data
|
||||
} else {
|
||||
serial_bridge_polling_window = 0; // Publish now
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) {
|
||||
serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // serial data completed
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED));
|
||||
serial_bridge_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void SerialBridgeInit(void)
|
||||
{
|
||||
serial_bridge_active = 0;
|
||||
if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) {
|
||||
SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]);
|
||||
if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte
|
||||
serial_bridge_active = 1;
|
||||
SerialBridgeSerial->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean SerialBridgeCommand()
|
||||
{
|
||||
char command [CMDSZ];
|
||||
boolean serviced = true;
|
||||
|
||||
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kSerialBridgeCommands);
|
||||
if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (1 == XdrvMailbox.index) {
|
||||
SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len);
|
||||
SerialBridgeSerial->write("\n");
|
||||
}
|
||||
else if (2 == XdrvMailbox.index) {
|
||||
SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len);
|
||||
}
|
||||
else if (3 == XdrvMailbox.index) {
|
||||
SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
}
|
||||
}
|
||||
else if (CMND_SBAUDRATE == command_code) {
|
||||
char *p;
|
||||
int baud = strtol(XdrvMailbox.data, &p, 10);
|
||||
if (baud > 0) {
|
||||
baud /= 1200; // Make it a valid baudrate
|
||||
Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud;
|
||||
SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, Settings.sbaudrate * 1200);
|
||||
}
|
||||
else {
|
||||
serviced = false; // Unknown command
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_08
|
||||
|
||||
boolean Xdrv08(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (serial_bridge_active) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
SerialBridgeInit();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
SerialBridgeInput();
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = SerialBridgeCommand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_SERIAL_BRIDGE
|
Loading…
Reference in New Issue