mirror of https://github.com/arendst/Tasmota.git
v5.12.0g - Add hardware serial mqtt bridge
5.12.0g * Add support for MQTT to hardware serial bridge using commands Baudrate and SerialSend. Currently supports 8N1 and text only (#2182)
This commit is contained in:
parent
bdb652547e
commit
d3ef9caa34
|
@ -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.0f** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.12.0g** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
### ATTENTION All versions
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
/* 5.12.0f
|
||||
/* 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.0f
|
||||
* Add compile time support for WS2812 BRG and RBG led configurations to be defined in user_config.h (#1690)
|
||||
*
|
||||
* 5.12.0e
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#define D_JSON_SAVESTATE "SaveState"
|
||||
#define D_JSON_SDKVERSION "SDK"
|
||||
#define D_JSON_SELECTED "selected"
|
||||
#define D_JSON_SERIALRECEIVED "SerialReceived"
|
||||
#define D_JSON_SSID "SSId"
|
||||
#define D_JSON_STARTDST "StartDST" // Start Daylight Savings Time
|
||||
#define D_JSON_STARTED "Started"
|
||||
|
@ -240,6 +241,8 @@
|
|||
#define D_CMND_LEDSTATE "LedState"
|
||||
#define D_CMND_CFGDUMP "CfgDump"
|
||||
#define D_CMND_I2CSCAN "I2CScan"
|
||||
#define D_CMND_SERIALSEND "SerialSend"
|
||||
#define D_CMND_BAUDRATE "Baudrate"
|
||||
#define D_CMND_EXCEPTION "Exception"
|
||||
|
||||
// Commands xdrv_01_light.ino
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t hass_discovery : 1; // bit 19 (v5.11.1a)
|
||||
uint32_t not_power_linked : 1; // bit 20 (v5.11.1f)
|
||||
uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i)
|
||||
uint32_t spare22 : 1;
|
||||
uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f)
|
||||
uint32_t spare23 : 1;
|
||||
uint32_t spare24 : 1;
|
||||
uint32_t spare25 : 1;
|
||||
|
@ -99,9 +99,7 @@ struct SYSCFG {
|
|||
int8_t timezone; // 016
|
||||
char ota_url[101]; // 017
|
||||
char mqtt_prefix[3][11]; // 07C
|
||||
|
||||
byte free_09D[1]; // 09D
|
||||
|
||||
uint8_t baudrate; // 09D
|
||||
byte seriallog_level; // 09E
|
||||
uint8_t sta_config; // 09F
|
||||
byte sta_active; // 0A0
|
||||
|
@ -128,7 +126,6 @@ struct SYSCFG {
|
|||
char mqtt_topic[33]; // 26F
|
||||
char button_topic[33]; // 290
|
||||
char mqtt_grptopic[33]; // 2B1
|
||||
|
||||
uint8_t display_model; // 2D2
|
||||
uint8_t display_mode; // 2D3
|
||||
uint8_t display_refresh; // 2D4
|
||||
|
@ -137,12 +134,12 @@ struct SYSCFG {
|
|||
uint8_t display_address[8]; // 2D8
|
||||
uint8_t display_dimmer; // 2E0
|
||||
uint8_t display_size; // 2E1
|
||||
|
||||
uint8_t free_2E2[4]; // 2E2
|
||||
|
||||
uint16_t pwm_frequency; // 2E6
|
||||
power_t power; // 2E8
|
||||
uint16_t pwm_value[MAX_PWMS]; // 2EC
|
||||
|
||||
int16_t altitude; // 2F6 Add since 5.8.0i
|
||||
uint16_t tele_period; // 2F8
|
||||
uint8_t ex_power; // 2FA Not used since 5.8.0j
|
||||
|
@ -152,10 +149,8 @@ struct SYSCFG {
|
|||
uint8_t energy_power_delta; // 33F
|
||||
uint16_t domoticz_update_timer; // 340
|
||||
uint16_t pwm_range; // 342
|
||||
|
||||
unsigned long domoticz_relay_idx[MAX_DOMOTICZ_IDX]; // 344
|
||||
unsigned long domoticz_key_idx[MAX_DOMOTICZ_IDX]; // 354
|
||||
|
||||
unsigned long energy_power_calibration; // 364
|
||||
unsigned long energy_voltage_calibration; // 368
|
||||
unsigned long energy_current_calibration; // 36C
|
||||
|
@ -179,7 +174,6 @@ struct SYSCFG {
|
|||
uint16_t mqtt_retry; // 396
|
||||
uint8_t poweronstate; // 398
|
||||
uint8_t last_module; // 399
|
||||
|
||||
uint16_t blinktime; // 39A
|
||||
uint16_t blinkcount; // 39C
|
||||
uint16_t light_rotation; // 39E
|
||||
|
@ -205,10 +199,8 @@ struct SYSCFG {
|
|||
uint16_t domoticz_switch_idx[MAX_DOMOTICZ_IDX]; // 454
|
||||
uint16_t domoticz_sensor_idx[MAX_DOMOTICZ_SNS_IDX]; // 45C
|
||||
uint8_t module; // 474
|
||||
|
||||
uint8_t ws_color[4][3]; // 475
|
||||
uint8_t ws_width[3]; // 481
|
||||
|
||||
myio my_gp; // 484
|
||||
uint16_t light_pixels; // 496
|
||||
uint8_t light_color[5]; // 498
|
||||
|
@ -231,9 +223,7 @@ struct SYSCFG {
|
|||
char web_password[33]; // 4A9
|
||||
uint8_t switchmode[MAX_SWITCHES]; // 4CA
|
||||
char ntp_server[3][33]; // 4CE
|
||||
|
||||
byte ina219_mode; // 531
|
||||
|
||||
uint16_t pulse_timer[MAX_PULSETIMERS]; // 532
|
||||
|
||||
byte free_542[2]; // 542
|
||||
|
@ -241,9 +231,7 @@ struct SYSCFG {
|
|||
uint32_t ip_address[4]; // 544
|
||||
unsigned long energy_kWhtotal; // 554
|
||||
char mqtt_fulltopic[100]; // 558
|
||||
|
||||
SysBitfield2 flag2; // 5BC Add flag2 since 5.9.2
|
||||
|
||||
unsigned long pulse_counter[MAX_COUNTERS]; // 5C0
|
||||
uint16_t pulse_counter_type; // 5D0
|
||||
uint16_t pulse_counter_debounce; // 5D2
|
||||
|
|
|
@ -457,6 +457,7 @@ void SettingsDefaultSet2()
|
|||
Settings.save_data = SAVE_DATA;
|
||||
Settings.timezone = APP_TIMEZONE;
|
||||
strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url));
|
||||
Settings.baudrate = APP_BAUDRATE / 1200;
|
||||
|
||||
Settings.seriallog_level = SERIAL_LOG_LEVEL;
|
||||
// Settings.sta_active = 0;
|
||||
|
@ -899,6 +900,9 @@ void SettingsDelta()
|
|||
Settings.mqtt_fingerprint[1][i] = Settings.mqtt_fingerprint[0][i];
|
||||
}
|
||||
}
|
||||
if (Settings.version < 0x050C0007) {
|
||||
Settings.baudrate = APP_BAUDRATE / 1200;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
|
|
|
@ -99,6 +99,7 @@ typedef unsigned long power_t; // Power (Relay) type
|
|||
#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds
|
||||
|
||||
#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 0x050C0006 // 5.12.0f
|
||||
#define VERSION 0x050C0007 // 5.12.0g
|
||||
|
||||
// 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_EXCEPTION };
|
||||
CMND_CFGDUMP, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, 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_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE
|
||||
#ifdef DEBUG_THEO
|
||||
"|" D_CMND_EXCEPTION
|
||||
#endif
|
||||
|
@ -102,6 +102,7 @@ const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ;
|
|||
int baudrate = APP_BAUDRATE; // Serial interface baud rate
|
||||
SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit
|
||||
byte serial_in_byte; // Received byte
|
||||
unsigned long serial_polling_window = 0; // Serial polling window
|
||||
int serial_in_byte_counter = 0; // Index in receive buffer
|
||||
byte dual_hex_code = 0; // Sonoff dual input flag
|
||||
uint16_t dual_button_code = 0; // Sonoff dual received code
|
||||
|
@ -422,10 +423,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
if (!strcmp(dataBuf,"?")) data_len = 0;
|
||||
int16_t payload = -99; // No payload
|
||||
uint16_t payload16 = 0;
|
||||
long lnum = strtol(dataBuf, &p, 10);
|
||||
long payload32 = strtol(dataBuf, &p, 10);
|
||||
if (p != dataBuf) {
|
||||
payload = (int16_t) lnum; // -32766 - 32767
|
||||
payload16 = (uint16_t) lnum; // 0 - 65535
|
||||
payload = (int16_t) payload32; // -32766 - 32767
|
||||
payload16 = (uint16_t) payload32; // 0 - 65535
|
||||
} else {
|
||||
payload32 = 0;
|
||||
}
|
||||
backlog_delay = MIN_BACKLOG_DELAY; // Reset backlog delay
|
||||
|
||||
|
@ -810,11 +813,27 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
strlcpy(Settings.ota_url, (1 == payload) ? OTA_URL : dataBuf, sizeof(Settings.ota_url));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.ota_url);
|
||||
}
|
||||
else if (CMND_BAUDRATE == command_code) {
|
||||
if (payload32 > 0) {
|
||||
payload32 /= 1200; // Make it a valid baudrate
|
||||
baudrate = (1 == payload) ? APP_BAUDRATE : payload32 * 1200;
|
||||
SetSerialBaudrate(baudrate);
|
||||
}
|
||||
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)) {
|
||||
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);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
}
|
||||
}
|
||||
else if (CMND_SERIALLOG == command_code) {
|
||||
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
|
||||
Settings.seriallog_level = payload;
|
||||
seriallog_level = payload;
|
||||
seriallog_timer = 0;
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
SetSeriallog(payload);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.seriallog_level, seriallog_level);
|
||||
}
|
||||
|
@ -1016,7 +1035,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3)));
|
||||
}
|
||||
else if (CMND_LEDSTATE ==command_code) {
|
||||
else if (CMND_LEDSTATE == command_code) {
|
||||
if ((payload >= 0) && (payload < MAX_LED_OPTION)) {
|
||||
Settings.ledstate = payload;
|
||||
if (!Settings.ledstate) SetLedPower(0);
|
||||
|
@ -1902,41 +1921,73 @@ 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) { // add char to string if it still fits
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
* Sonoff SC 19200 baud serial interface
|
||||
\*-------------------------------------------------------------------------------------------*/
|
||||
if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
SonoffScSerialInput(serial_in_buffer);
|
||||
serial_in_byte_counter = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
if (SONOFF_SC == Settings.module) {
|
||||
if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
SonoffScSerialInput(serial_in_buffer);
|
||||
serial_in_byte_counter = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
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;
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), serial_in_buffer);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
ExecuteCommand(serial_in_buffer);
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -2033,18 +2084,22 @@ void GpioInit()
|
|||
}
|
||||
|
||||
if (SONOFF_BRIDGE == Settings.module) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
baudrate = 19200;
|
||||
}
|
||||
|
||||
if (SONOFF_DUAL == Settings.module) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
devices_present = 2;
|
||||
baudrate = 19200;
|
||||
}
|
||||
else if (CH4 == Settings.module) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
devices_present = 4;
|
||||
baudrate = 19200;
|
||||
}
|
||||
else if (SONOFF_SC == Settings.module) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
devices_present = 0;
|
||||
baudrate = 19200;
|
||||
}
|
||||
|
@ -2141,6 +2196,7 @@ void setup()
|
|||
|
||||
OsWatchInit();
|
||||
|
||||
baudrate = Settings.baudrate * 1200;
|
||||
seriallog_level = Settings.seriallog_level;
|
||||
seriallog_timer = SERIALLOG_TIMER;
|
||||
#ifndef USE_EMULATION
|
||||
|
@ -2246,7 +2302,7 @@ void loop()
|
|||
|
||||
if (millis() >= state_loop_timer) StateLoop();
|
||||
|
||||
if (Serial.available()) SerialInput();
|
||||
SerialInput();
|
||||
|
||||
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
|
||||
delay(sleep); // https://github.com/esp8266/Arduino/issues/2021
|
||||
|
|
|
@ -401,6 +401,7 @@ int GetCommandCode(char* destination, size_t destination_size, const char* needl
|
|||
|
||||
void SetSerialBaudrate(int baudrate)
|
||||
{
|
||||
Settings.baudrate = baudrate / 1200;
|
||||
if (Serial.baudRate() != baudrate) {
|
||||
if (seriallog_level) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate);
|
||||
|
@ -1378,6 +1379,13 @@ boolean Xsns02(byte function)
|
|||
*
|
||||
\*********************************************************************************************/
|
||||
|
||||
void SetSeriallog(byte loglevel)
|
||||
{
|
||||
Settings.seriallog_level = loglevel;
|
||||
seriallog_level = loglevel;
|
||||
seriallog_timer = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
void GetLog(byte idx, char** entry_pp, size_t* len_p)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue