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:
Theo Arends 2018-03-18 13:47:30 +01:00
parent bdb652547e
commit d3ef9caa34
8 changed files with 99 additions and 36 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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
/*

View File

@ -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,20 +1921,24 @@ 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 (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);
@ -1923,20 +1946,48 @@ void SerialInput()
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

View File

@ -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)
{