diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md
index 02b4dc209..4e0cdc436 100644
--- a/tasmota/CHANGELOG.md
+++ b/tasmota/CHANGELOG.md
@@ -9,6 +9,7 @@
- Add initial support for Telegram bot (#8619)
- Add support for HP303B Temperature and Pressure sensor by Robert Jaakke (#8638)
- Add rule trigger ``System#Init`` to allow early rule execution without wifi and mqtt initialized yet
+- Add serial to TCP bridge, ``TCPStart`` and ``TCPBaudRate`` (needs #define USE_TCP_BRIDGE)
### 8.3.1.2 20200522
diff --git a/tasmota/i18n.h b/tasmota/i18n.h
index 1a254bdfc..543a4c9b9 100644
--- a/tasmota/i18n.h
+++ b/tasmota/i18n.h
@@ -643,6 +643,7 @@
#define D_LOG_UPNP "UPP: " // UPnP
#define D_LOG_WIFI "WIF: " // Wifi
#define D_LOG_ZIGBEE "ZIG: " // Zigbee
+#define D_LOG_TCP "TCP: " // TCP bridge
/********************************************************************************************/
diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h
index 935704e74..62d48e0a4 100644
--- a/tasmota/language/bg_BG.h
+++ b/tasmota/language/bg_BG.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h
index a04a6b16b..cbbe58921 100644
--- a/tasmota/language/cs_CZ.h
+++ b/tasmota/language/cs_CZ.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h
index 02464daa6..9c605da62 100644
--- a/tasmota/language/de_DE.h
+++ b/tasmota/language/de_DE.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h
index 333458c72..ff5486540 100644
--- a/tasmota/language/el_GR.h
+++ b/tasmota/language/el_GR.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h
index 92637b350..4f4180dd4 100644
--- a/tasmota/language/en_GB.h
+++ b/tasmota/language/en_GB.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h
index 701f3e107..2447cdc05 100644
--- a/tasmota/language/es_ES.h
+++ b/tasmota/language/es_ES.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h
index f91bd7fbd..80cf87061 100644
--- a/tasmota/language/fr_FR.h
+++ b/tasmota/language/fr_FR.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h
index 3550a1abd..e6af68ddc 100644
--- a/tasmota/language/he_HE.h
+++ b/tasmota/language/he_HE.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h
index 1a58472e4..eb797bcab 100644
--- a/tasmota/language/hu_HU.h
+++ b/tasmota/language/hu_HU.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h
index 22181a7be..75a1d4361 100644
--- a/tasmota/language/it_IT.h
+++ b/tasmota/language/it_IT.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h
index a004ecec7..4b7e8538a 100644
--- a/tasmota/language/ko_KO.h
+++ b/tasmota/language/ko_KO.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h
index ab6a28485..c9979814b 100644
--- a/tasmota/language/nl_NL.h
+++ b/tasmota/language/nl_NL.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h
index aea969baf..4827d26be 100644
--- a/tasmota/language/pl_PL.h
+++ b/tasmota/language/pl_PL.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h
index 02c4b4ecc..450bea0d5 100644
--- a/tasmota/language/pt_BR.h
+++ b/tasmota/language/pt_BR.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h
index 4507cecba..189b5ec3c 100644
--- a/tasmota/language/pt_PT.h
+++ b/tasmota/language/pt_PT.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h
index 66e82ad55..aaea0a0b2 100644
--- a/tasmota/language/ro_RO.h
+++ b/tasmota/language/ro_RO.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h
index 7c7fc770b..be28c69a2 100644
--- a/tasmota/language/ru_RU.h
+++ b/tasmota/language/ru_RU.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "А"
diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h
index e242f9bc1..4b667150a 100644
--- a/tasmota/language/sk_SK.h
+++ b/tasmota/language/sk_SK.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h
index 1649b7f5f..edf7b3f1e 100644
--- a/tasmota/language/sv_SE.h
+++ b/tasmota/language/sv_SE.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h
index 8a1063d7a..5089b6e15 100644
--- a/tasmota/language/tr_TR.h
+++ b/tasmota/language/tr_TR.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h
index a16675ae4..5f6b23754 100644
--- a/tasmota/language/uk_UA.h
+++ b/tasmota/language/uk_UA.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "А"
diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h
index 0da3126fd..a86e2c7ee 100644
--- a/tasmota/language/zh_CN.h
+++ b/tasmota/language/zh_CN.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "安"
diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h
index 1fb664d08..b1b4424cd 100644
--- a/tasmota/language/zh_TW.h
+++ b/tasmota/language/zh_TW.h
@@ -691,6 +691,8 @@
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD "CAM_HSD"
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
+#define D_SENSOR_TCP_TXD "TCP Tx"
+#define D_SENSOR_TCP_RXD "TCP Rx"
// Units
#define D_UNIT_AMPERE "安"
diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h
index 3bec4d347..1e57de3bb 100644
--- a/tasmota/my_user_config.h
+++ b/tasmota/my_user_config.h
@@ -577,6 +577,7 @@
#define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached
//#define USE_HPMA // Add support for Honeywell HPMA115S0 particle concentration sensor (+1k4)
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
+//#define USE_TCP_BRIDGE // Add support for Serial to TCP bridge (+1.3k code)
//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
#define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max)
//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code)
diff --git a/tasmota/settings.h b/tasmota/settings.h
index afc2f5672..db19c1199 100644
--- a/tasmota/settings.h
+++ b/tasmota/settings.h
@@ -568,8 +568,9 @@ struct {
uint8_t windmeter_tele_pchange; // F3E
uint8_t ledpwm_on; // F3F
uint8_t ledpwm_off; // F40
+ uint8_t tcp_baudrate; // F41
- uint8_t free_f42[119]; // F41 - Decrement if adding new Setting variables just above and below
+ uint8_t free_f42[118]; // F42 - Decrement if adding new Setting variables just above and below
// Only 32 bit boundary variables below
uint16_t pulse_counter_debounce_low; // FB8
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index 8b44a547b..a87c39939 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -234,6 +234,8 @@ enum UserSelectablePins {
GPIO_BOILER_OT_TX, // OpenTherm Boiler TX pin
GPIO_WINDMETER_SPEED, // WindMeter speed counter pin
GPIO_BL0940_RX, // BL0940 serial interface
+ GPIO_TCP_TX, // TCP Serial bridge
+ GPIO_TCP_RX, // TCP Serial bridge
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality
@@ -324,7 +326,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_AS3935 "|" D_SENSOR_PMS5003_TX "|"
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
D_SENSOR_WINDMETER_SPEED "|"
- D_SENSOR_BL0940_RX
+ D_SENSOR_BL0940_RX "|"
+ D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD
;
const char kSensorNamesFixed[] PROGMEM =
@@ -682,6 +685,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
#ifdef USE_AS3935
GPIO_AS3935,
#endif
+#ifdef USE_TCP_BRIDGE
+ AGPIO(GPIO_TCP_TX), // TCP Serial bridge
+ AGPIO(GPIO_TCP_RX), // TCP Serial bridge
+#endif
};
/********************************************************************************************/
diff --git a/tasmota/tasmota_template_ESP32.h b/tasmota/tasmota_template_ESP32.h
index aea45ea6a..5457ed33a 100644
--- a/tasmota/tasmota_template_ESP32.h
+++ b/tasmota/tasmota_template_ESP32.h
@@ -129,6 +129,7 @@ enum UserSelectablePins {
GPIO_WINDMETER_SPEED, // WindMeter speed counter pin
GPIO_KEY1_TC, // Touch pin as button
GPIO_BL0940_RX, // BL0940 serial interface
+ GPIO_TCP_TX, GPIO_TCP_RX, // TCP to serial bridge
GPIO_SENSOR_END };
enum ProgramSelectablePins {
@@ -218,7 +219,8 @@ const char kSensorNames[] PROGMEM =
D_GPIO_WEBCAM_PSRCS "|"
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
D_SENSOR_WINDMETER_SPEED "|" D_SENSOR_BUTTON "_tc|"
- D_SENSOR_BL0940_RX
+ D_SENSOR_BL0940_RX "|"
+ D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD
;
const char kSensorNamesFixed[] PROGMEM =
@@ -547,6 +549,10 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_WEBCAM_PSCLK),
AGPIO(GPIO_WEBCAM_HSD) + MAX_WEBCAM_HSD,
AGPIO(GPIO_WEBCAM_PSRCS),
+#endif
+#ifdef USE_TCP_BRIDGE
+ AGPIO(GPIO_TCP_TX), // TCP Serial bridge
+ AGPIO(GPIO_TCP_RX), // TCP Serial bridge
#endif
AGPIO(GPIO_KEY1_TC) + MAX_KEYS
};
diff --git a/tasmota/xdrv_41_tcp_bridge.ino b/tasmota/xdrv_41_tcp_bridge.ino
new file mode 100644
index 000000000..a6513ec46
--- /dev/null
+++ b/tasmota/xdrv_41_tcp_bridge.ino
@@ -0,0 +1,205 @@
+/*
+ xdrv_41_tcp_bridge.ino - TCP to serial bridge
+
+ Copyright (C) 2020 Theo Arends and Stephan Hadinger
+
+ 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 .
+*/
+
+#ifdef USE_TCP_BRIDGE
+
+#define XDRV_41 41
+
+#ifndef TCP_BRIDGE_CONNECTIONS
+#define TCP_BRIDGE_CONNECTIONS 2 // number of maximum parallel connections
+#endif
+
+#ifndef TCP_BRIDGE_BUF_SIZE
+#define TCP_BRIDGE_BUF_SIZE 255 // size of the buffer, above 132 required for efficient XMODEM
+#endif
+
+//const uint16_t tcp_port = 8880;
+WiFiServer *server_tcp = nullptr;
+//WiFiClient client_tcp1, client_tcp2;
+WiFiClient client_tcp[TCP_BRIDGE_CONNECTIONS];
+uint8_t client_next = 0;
+uint8_t *tcp_buf = nullptr; // data transfer buffer
+
+#include
+TasmotaSerial *TCPSerial = nullptr;
+
+const char kTCPCommands[] PROGMEM = "TCP" "|" // prefix
+ "Start" "|" "Baudrate"
+ ;
+
+void (* const TCPCommand[])(void) PROGMEM = {
+ &CmndTCPStart, &CmndTCPBaudrate
+ };
+
+//
+// Called at event loop, checks for incoming data from the CC2530
+//
+void TCPLoop(void)
+{
+ uint8_t c;
+ bool busy; // did we transfer some data?
+ int32_t buf_len;
+
+ if (!TCPSerial) return;
+
+ // check for a new client connection
+ if ((server_tcp) && (server_tcp->hasClient())) {
+ // find an empty slot
+ uint32_t i;
+ for (i=0; iavailable();
+ break;
+ }
+ }
+ if (i >= ARRAY_SIZE(client_tcp)) {
+ i = client_next++ % ARRAY_SIZE(client_tcp);
+ WiFiClient &client = client_tcp[i];
+ client.stop();
+ client = server_tcp->available();
+ }
+ }
+
+ do {
+ busy = false; // exit loop if no data was transferred
+
+ // start reading the UART, this buffer can quickly overflow
+ buf_len = 0;
+ while ((buf_len < TCP_BRIDGE_BUF_SIZE) && (TCPSerial->available())) {
+ c = TCPSerial->read();
+ if (c >= 0) {
+ tcp_buf[buf_len++] = c;
+ busy = true;
+ }
+ }
+ if (buf_len > 0) {
+ char hex_char[TCP_BRIDGE_BUF_SIZE+1];
+ ToHex_P(tcp_buf, buf_len, hex_char, 256);
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "from MCU: %s"), hex_char);
+
+ for (uint32_t i=0; i= 0) {
+ tcp_buf[buf_len++] = c;
+ busy = true;
+ }
+ }
+ if (buf_len > 0) {
+ char hex_char[TCP_BRIDGE_BUF_SIZE+1];
+ ToHex_P(tcp_buf, buf_len, hex_char, 256);
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "to MCU/%d: %s"), i+1, hex_char);
+ TCPSerial->write(tcp_buf, buf_len);
+ }
+ }
+
+ yield(); // avoid WDT if heavy traffic
+ } while (busy);
+}
+
+/********************************************************************************************/
+void TCPInit(void) {
+ if (PinUsed(GPIO_TCP_RX) && PinUsed(GPIO_TCP_TX)) {
+ tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE);
+ if (!tcp_buf) { AddLog_P2(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), seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes
+ TCPSerial->begin(Settings.tcp_baudrate * 1200);
+ if (TCPSerial->hardwareSerial()) {
+ ClaimSerial();
+ }
+ }
+}
+
+/*********************************************************************************************\
+ * Commands
+\*********************************************************************************************/
+
+//
+// Command `ZbConfig`
+//
+void CmndTCPStart(void) {
+
+ if (!TCPSerial) { return; }
+ int32_t tcp_port = XdrvMailbox.payload;
+
+ if (server_tcp) {
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Stopping TCP server"));
+ server_tcp->stop();
+ delete server_tcp;
+ server_tcp = nullptr;
+
+ for (uint32_t i=0; i 0) {
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Starting TCP server on port %d"), tcp_port);
+ server_tcp = new WiFiServer(tcp_port);
+ server_tcp->begin(); // start TCP server
+ server_tcp->setNoDelay(true);
+ }
+
+ ResponseCmndDone();
+}
+
+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
+ }
+ ResponseCmndNumber(Settings.tcp_baudrate * 1200);
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xdrv41(uint8_t function)
+{
+ bool result = false;
+
+ switch (function) {
+ case FUNC_LOOP:
+ TCPLoop();
+ break;
+ case FUNC_PRE_INIT:
+ TCPInit();
+ break;
+ case FUNC_COMMAND:
+ result = DecodeCommand(kTCPCommands, TCPCommand);
+ break;
+ }
+ return result;
+}
+
+#endif // USE_TCP_BRIDGE