diff --git a/tasmota/settings.h b/tasmota/settings.h index 4e41c5916..d16568768 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -733,8 +733,9 @@ typedef struct { uint8_t shd_leading_edge; // F5B uint16_t shd_warmup_brightness; // F5C uint8_t shd_warmup_time; // F5E + uint8_t tcp_config; // F5F - uint8_t free_f5f[61]; // F5F - Decrement if adding new Setting variables just above and below + uint8_t free_f60[60]; // F60 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below diff --git a/tasmota/support.ino b/tasmota/support.ino index 0840bf5cf..d60654161 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1818,7 +1818,7 @@ uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, fl * Serial \*********************************************************************************************/ -String GetSerialConfig(void) { +String GetSerialConfig(uint8_t serial_config) { // Settings->serial_config layout // b000000xx - 5, 6, 7 or 8 data bits // b00000x00 - 1 or 2 stop bits @@ -1827,13 +1827,49 @@ String GetSerialConfig(void) { const static char kParity[] PROGMEM = "NEOI"; char config[4]; - config[0] = '5' + (Settings->serial_config & 0x3); - config[1] = pgm_read_byte(&kParity[(Settings->serial_config >> 3) & 0x3]); - config[2] = '1' + ((Settings->serial_config >> 2) & 0x1); + config[0] = '5' + (serial_config & 0x3); + config[1] = pgm_read_byte(&kParity[(serial_config >> 3) & 0x3]); + config[2] = '1' + ((serial_config >> 2) & 0x1); config[3] = '\0'; return String(config); } +String GetSerialConfig(void) { + return GetSerialConfig(Settings->serial_config); +} + +int8_t ParseSerialConfig(const char *pstr) +{ + if (strlen(pstr) < 3) + return -1; + + int8_t serial_config = (uint8_t)atoi(pstr); + if (serial_config < 5 || serial_config > 8) + return -1; + serial_config -= 5; + + char parity = (pstr[1] & 0xdf); + if ('E' == parity) { + serial_config += 0x08; // Even parity + } + else if ('O' == parity) { + serial_config += 0x10; // Odd parity + } + else if ('N' != parity) { + return -1; + } + + if ('2' == pstr[2]) { + serial_config += 0x04; // Stop bits 2 + } + else if ('1' != pstr[2]) { + return -1; + } + + return serial_config; +} + + #if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 // temporary workaround, see https://github.com/espressif/arduino-esp32/issues/5287 #include diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 384823203..3daea88a7 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1525,28 +1525,8 @@ void CmndSerialConfig(void) } } else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { - uint8_t serial_config = XdrvMailbox.payload -5; // Data bits 5, 6, 7 or 8, No parity and 1 stop bit - - bool valid = true; - char parity = (XdrvMailbox.data[1] & 0xdf); - if ('E' == parity) { - serial_config += 0x08; // Even parity - } - else if ('O' == parity) { - serial_config += 0x10; // Odd parity - } - else if ('N' != parity) { - valid = false; - } - - if ('2' == XdrvMailbox.data[2]) { - serial_config += 0x04; // Stop bits 2 - } - else if ('1' != XdrvMailbox.data[2]) { - valid = false; - } - - if (valid) { + int8_t serial_config = ParseSerialConfig(XdrvMailbox.data); + if (serial_config >= 0) { SetSerialConfig(serial_config); } } diff --git a/tasmota/xdrv_41_tcp_bridge.ino b/tasmota/xdrv_41_tcp_bridge.ino index 3d4d3bec5..d9b6f280d 100644 --- a/tasmota/xdrv_41_tcp_bridge.ino +++ b/tasmota/xdrv_41_tcp_bridge.ino @@ -41,11 +41,11 @@ IPAddress ip_filter; TasmotaSerial *TCPSerial = nullptr; const char kTCPCommands[] PROGMEM = "TCP" "|" // prefix - "Start" "|" "Baudrate" + "Start" "|" "Baudrate" "|" "Config" ; void (* const TCPCommand[])(void) PROGMEM = { - &CmndTCPStart, &CmndTCPBaudrate + &CmndTCPStart, &CmndTCPBaudrate, &CmndTCPConfig }; // @@ -136,12 +136,14 @@ void TCPLoop(void) /********************************************************************************************/ void TCPInit(void) { if (PinUsed(GPIO_TCP_RX) && PinUsed(GPIO_TCP_TX)) { + if (0 == (0x80 & Settings->tcp_config)) // !0x80 means unitialized + Settings->tcp_config = 0x80 | ParseSerialConfig("8N1"); // default as 8N1 for backward compatibility tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE); if (!tcp_buf) { AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer")); return; } if (!Settings->tcp_baudrate) { Settings->tcp_baudrate = 115200 / 1200; } TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), TasmotaGlobal.seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes - TCPSerial->begin(Settings->tcp_baudrate * 1200); + TCPSerial->begin(Settings->tcp_baudrate * 1200, 0x7F & Settings->tcp_config); if (TCPSerial->hardwareSerial()) { ClaimSerial(); } @@ -197,11 +199,22 @@ void CmndTCPBaudrate(void) { if ((XdrvMailbox.payload >= 1200) && (XdrvMailbox.payload <= 115200)) { XdrvMailbox.payload /= 1200; // Make it a valid baudrate Settings->tcp_baudrate = XdrvMailbox.payload; - TCPSerial->begin(Settings->tcp_baudrate * 1200); // Reinitialize serial port with new baud rate + TCPSerial->begin(Settings->tcp_baudrate * 1200, 0x7F & Settings->tcp_config); // Reinitialize serial port with new baud rate } ResponseCmndNumber(Settings->tcp_baudrate * 1200); } +void CmndTCPConfig(void) { + if (XdrvMailbox.data_len > 0) { + uint8_t serial_config = ParseSerialConfig(XdrvMailbox.data); + if (serial_config >= 0) { + Settings->tcp_config = 0x80 | serial_config; // default 0x00 should be 8N1 + TCPSerial->begin(Settings->tcp_baudrate * 1200, 0x7F & Settings->tcp_config); // Reinitialize serial port with new config + } + } + ResponseCmndChar_P(GetSerialConfig(0x7F & Settings->tcp_config).c_str()); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/