diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index af9be6756..0d8dac0af 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog
-### Version 8.3.1.3
+### Version 8.3.1.4
- Change IRremoteESP8266 library updated to v2.7.7
- Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519)
@@ -81,3 +81,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add rule trigger ``System#Init`` to allow early rule execution without wifi and mqtt initialized yet
- Created Energy sensor (Denky) for French Smart Metering meter provided by global Energy Providers, need a adaptater. See dedicated full [blog](http://hallard.me/category/tinfo/) about French teleinformation stuff
- Added Library to be used for decoding Teleinfo (French Metering Smart Meter)
+- Add basic support for ESP32 ethernet adding commands ``Wifi 0/1`` and ``Ethernet 0/1`` both default ON
diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md
index 73582dfb7..4e0cdc436 100644
--- a/tasmota/CHANGELOG.md
+++ b/tasmota/CHANGELOG.md
@@ -1,10 +1,15 @@
## Unreleased (development)
+### 8.3.1.4 20200615
+
+- Add basic support for ESP32 ethernet adding commands ``Wifi 0/1`` and ``Ethernet 0/1`` both default ON
+
### 8.3.1.3 20200611
- 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 01122fabd..543a4c9b9 100644
--- a/tasmota/i18n.h
+++ b/tasmota/i18n.h
@@ -271,6 +271,8 @@
#define D_CMND_SSID "SSId"
#define D_CMND_PASSWORD "Password"
#define D_CMND_HOSTNAME "Hostname"
+#define D_CMND_WIFI "Wifi"
+#define D_CMND_ETHERNET "Ethernet"
#define D_CMND_WIFICONFIG "WifiConfig"
#define D_WCFG_0_RESTART "Restart"
#define D_WCFG_2_WIFIMANAGER "WifiManager"
@@ -641,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 769b9f66a..d0f1acc87 100644
--- a/tasmota/language/bg_BG.h
+++ b/tasmota/language/bg_BG.h
@@ -693,6 +693,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 64d8e32b0..f787c3c5b 100644
--- a/tasmota/language/cs_CZ.h
+++ b/tasmota/language/cs_CZ.h
@@ -693,6 +693,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 7cc9d6579..6eec835c2 100644
--- a/tasmota/language/de_DE.h
+++ b/tasmota/language/de_DE.h
@@ -693,6 +693,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 92769256f..e0ad92d4f 100644
--- a/tasmota/language/el_GR.h
+++ b/tasmota/language/el_GR.h
@@ -693,6 +693,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 e5fc07fa5..3525083fe 100644
--- a/tasmota/language/en_GB.h
+++ b/tasmota/language/en_GB.h
@@ -693,6 +693,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 ff2eda915..6f1ef896c 100644
--- a/tasmota/language/es_ES.h
+++ b/tasmota/language/es_ES.h
@@ -693,6 +693,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 38c160831..fcc007188 100644
--- a/tasmota/language/fr_FR.h
+++ b/tasmota/language/fr_FR.h
@@ -693,6 +693,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 59f2db4cb..c4752b7a6 100644
--- a/tasmota/language/he_HE.h
+++ b/tasmota/language/he_HE.h
@@ -693,6 +693,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 d976eecb4..0e85e9933 100644
--- a/tasmota/language/hu_HU.h
+++ b/tasmota/language/hu_HU.h
@@ -693,6 +693,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 b87d46535..10af70597 100644
--- a/tasmota/language/it_IT.h
+++ b/tasmota/language/it_IT.h
@@ -693,6 +693,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 a3a032086..23084ea59 100644
--- a/tasmota/language/ko_KO.h
+++ b/tasmota/language/ko_KO.h
@@ -693,6 +693,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 8ce2fc338..f0700450f 100644
--- a/tasmota/language/nl_NL.h
+++ b/tasmota/language/nl_NL.h
@@ -693,6 +693,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 676297b48..026d4e682 100644
--- a/tasmota/language/pl_PL.h
+++ b/tasmota/language/pl_PL.h
@@ -693,6 +693,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 3babc17ec..f19d63577 100644
--- a/tasmota/language/pt_BR.h
+++ b/tasmota/language/pt_BR.h
@@ -693,6 +693,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 2a0ad139f..32a3b509c 100644
--- a/tasmota/language/pt_PT.h
+++ b/tasmota/language/pt_PT.h
@@ -693,6 +693,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 e80dc8bc4..c173cde0d 100644
--- a/tasmota/language/ro_RO.h
+++ b/tasmota/language/ro_RO.h
@@ -693,6 +693,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 a037ff08f..6415e61d2 100644
--- a/tasmota/language/ru_RU.h
+++ b/tasmota/language/ru_RU.h
@@ -693,6 +693,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 c016a0c8e..8171d967f 100644
--- a/tasmota/language/sk_SK.h
+++ b/tasmota/language/sk_SK.h
@@ -693,6 +693,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 ff119f953..af6b6eeed 100644
--- a/tasmota/language/sv_SE.h
+++ b/tasmota/language/sv_SE.h
@@ -693,6 +693,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 e744e97e8..c65b7a71c 100644
--- a/tasmota/language/tr_TR.h
+++ b/tasmota/language/tr_TR.h
@@ -693,6 +693,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 4d4e25f44..00e0cf013 100644
--- a/tasmota/language/uk_UA.h
+++ b/tasmota/language/uk_UA.h
@@ -693,6 +693,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 b5f54991a..e1e784f53 100644
--- a/tasmota/language/zh_CN.h
+++ b/tasmota/language/zh_CN.h
@@ -693,6 +693,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 1d5ed6801..3c093a7c3 100644
--- a/tasmota/language/zh_TW.h
+++ b/tasmota/language/zh_TW.h
@@ -693,6 +693,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 dfb38beec..f2cf90b18 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)
@@ -589,7 +590,6 @@
//#define USE_GPS // Add support for GPS and NTP Server for becoming Stratus 1 Time Source (+3k1 code, +132 bytes RAM)
// #define USE_FLOG // Add support for GPS logging in OTA's Flash (Experimental) (+2k9 code, +8 bytes RAM)
//#define USE_HM10 // (ESP8266 only) Add support for HM-10 as a BLE-bridge (+9k3 code)
-//#define USE_MI_ESP32 // (ESP32 only) Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
//#define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k6 code, 64 mem)
#define USE_TASMOTA_SLAVE_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
@@ -663,6 +663,8 @@
#define USE_ZIGBEE_PRECFGKEY_H 0x0D0C0A0806040200L // note: changing requires to re-pair all devices
#define USE_ZIGBEE_COALESCE_ATTR_TIMER 350 // timer to coalesce attribute values (in ms)
+ #define USE_ZIGBEE_MODELID "Tasmota Z2T" // reported "ModelId" (cluster 0000 / attribute 0005)
+ #define USE_ZIGBEE_MANUFACTURER "Tasmota" // reported "Manufacturer" (cluster 0000 / attribute 0004)
// -- Other sensors/drivers -----------------------
@@ -722,6 +724,19 @@
// -- End of general directives -------------------
+/*********************************************************************************************\
+ * ESP32 only features
+\*********************************************************************************************/
+
+#ifdef ESP32
+
+//#define USE_ETHERNET // Add support for ethernet (Currently fixed for Olimex ESP32-PoE)
+//#define USE_SPI // Add support for hardware SPI
+//#define USE_MI_ESP32 // Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
+//#define USE_WEBCAM // Add support for webcam
+
+#endif
+
/*********************************************************************************************\
* Debug features
\*********************************************************************************************/
diff --git a/tasmota/settings.h b/tasmota/settings.h
index 08175d7db..db19c1199 100644
--- a/tasmota/settings.h
+++ b/tasmota/settings.h
@@ -114,8 +114,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t pwm_ct_mode : 1; // bit 10 (v8.2.0.4) - SetOption92 - Set PWM Mode from regular PWM to ColorTemp control (Xiaomi Philips ...)
uint32_t compress_rules_cpu : 1; // bit 11 (v8.2.0.6) - SetOption93 - Keep uncompressed rules in memory to avoid CPU load of uncompressing at each tick
uint32_t max6675 : 1; // bit 12 (v8.3.1.2) - SetOption94 - Implement simpler MAX6675 protocol instead of MAX31855
- uint32_t spare13 : 1;
- uint32_t spare14 : 1;
+ uint32_t network_wifi : 1; // bit 13 (v8.3.1.3) - CMND_WIFI
+ uint32_t network_ethernet : 1; // bit 14 (v8.3.1.3) = CMND_ETHERNET
uint32_t spare15 : 1;
uint32_t spare16 : 1;
uint32_t spare17 : 1;
@@ -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
@@ -676,10 +677,10 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
typedef union {
uint8_t data;
struct {
- uint8_t wifi_down : 1;
+ uint8_t network_down : 1;
uint8_t mqtt_down : 1;
- uint8_t spare02 : 1;
- uint8_t spare03 : 1;
+ uint8_t wifi_down : 1;
+ uint8_t eth_down : 1;
uint8_t spare04 : 1;
uint8_t spare05 : 1;
uint8_t spare06 : 1;
diff --git a/tasmota/settings.ino b/tasmota/settings.ino
index f8aa19ab9..1b2dca82d 100644
--- a/tasmota/settings.ino
+++ b/tasmota/settings.ino
@@ -798,7 +798,11 @@ void SettingsDefaultSet2(void)
Settings.serial_delimiter = 0xff;
Settings.seriallog_level = SERIAL_LOG_LEVEL;
+ // Ethernet
+ flag4.network_ethernet |= 1;
+
// Wifi
+ flag4.network_wifi |= 1;
flag3.use_wifi_scan |= WIFI_SCAN_AT_RESTART;
flag3.use_wifi_rescan |= WIFI_SCAN_REGULARLY;
Settings.wifi_output_power = 170;
@@ -1439,6 +1443,10 @@ void SettingsDelta(void)
Settings.ledpwm_on = 255;
Settings.ledpwm_mask = 0;
}
+ if (Settings.version < 0x08030104) {
+ Settings.flag4.network_wifi = 1;
+ Settings.flag4.network_ethernet = 1;
+ }
Settings.version = VERSION;
SettingsSave(1);
diff --git a/tasmota/support.ino b/tasmota/support.ino
index 0a5d26f10..8b2c144f7 100644
--- a/tasmota/support.ino
+++ b/tasmota/support.ino
@@ -156,7 +156,7 @@ float CharToFloat(const char *str)
signed char sign = 1;
if (*pt == '-') { sign = -1; }
- if (*pt == '-' || *pt=='+') { pt++; } // Skip any sign
+ if (*pt == '-' || *pt == '+') { pt++; } // Skip any sign
float left = 0;
if (*pt != '.') {
@@ -167,8 +167,9 @@ float CharToFloat(const char *str)
float right = 0;
if (*pt == '.') {
pt++;
- // limit decimals to float max
- pt[7]=0;
+ uint32_t max_decimals = 0;
+ while ((max_decimals < 8) && isdigit(pt[max_decimals])) { max_decimals++; }
+ pt[max_decimals] = '\0'; // Limit decimals to float max of 8
right = atoi(pt); // Decimal part
while (isdigit(*pt)) {
pt++;
@@ -1740,7 +1741,7 @@ void Syslog(void)
}
if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) {
char syslog_preamble[64]; // Hostname + Id
- snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), my_hostname);
+ snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), NetworkHostname());
memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble));
log_data[sizeof(log_data) -1] = '\0';
memcpy(log_data, syslog_preamble, strlen(syslog_preamble));
@@ -1787,7 +1788,7 @@ void AddLog(uint32_t loglevel)
!global_state.mqtt_down &&
(loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); }
- if (!global_state.wifi_down &&
+ if (!global_state.network_down &&
(loglevel <= syslog_level)) { Syslog(); }
prepped_loglevel = 0;
@@ -1910,4 +1911,4 @@ String Decompress(const char * compressed, size_t uncompressed_size) {
return content;
}
-#endif // USE_UNISHOX_COMPRESSION
+#endif // USE_UNISHOX_COMPRESSION
\ No newline at end of file
diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino
index fe855ee92..5d0180005 100644
--- a/tasmota/support_command.ino
+++ b/tasmota/support_command.ino
@@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|"
D_CMND_DEVICENAME "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|"
D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|"
- D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|"
+ D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_WIFI "|"
#ifdef USE_I2C
D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|"
#endif
@@ -54,7 +54,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig,
&CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd,
&CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode,
- &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum,
+ &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndWifi,
#ifdef USE_I2C
&CmndI2cScan, CmndI2cDriver,
#endif
@@ -499,8 +499,8 @@ void CmndStatus(void)
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\""
D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\""
D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"),
- my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(),
- IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), WiFi.macAddress().c_str(),
+ NetworkHostname(), NetworkAddress().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(),
+ IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), NetworkMacAddress().c_str(),
Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str());
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5"));
}
@@ -1497,6 +1497,15 @@ void CmndWifiConfig(void)
Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig));
}
+void CmndWifi(void)
+{
+ if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
+ Settings.flag4.network_wifi = XdrvMailbox.payload;
+ restart_flag = 2;
+ }
+ ResponseCmndStateText(Settings.flag4.network_wifi);
+}
+
void CmndDevicename(void)
{
if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino
index 8516ba1b0..8564aed3e 100644
--- a/tasmota/support_features.ino
+++ b/tasmota/support_features.ino
@@ -601,7 +601,9 @@ void GetFeatures(void)
// feature6 |= 0x10000000;
// feature6 |= 0x20000000;
-// feature6 |= 0x40000000;
+#ifdef USE_ETHERNET
+ feature6 |= 0x40000000;
+#endif
#ifdef USE_WEBCAM
feature6 |= 0x80000000;
#endif
diff --git a/tasmota/support_network.ino b/tasmota/support_network.ino
new file mode 100644
index 000000000..4f6da4d88
--- /dev/null
+++ b/tasmota/support_network.ino
@@ -0,0 +1,128 @@
+/*
+ support_network.ino - Network support for Tasmota
+
+ Copyright (C) 2020 Theo Arends
+
+ 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 .
+*/
+
+/*********************************************************************************************\
+ * MDNS
+\*********************************************************************************************/
+
+struct {
+ uint8_t begun = 0; // mDNS active
+} Mdns;
+
+#ifdef USE_DISCOVERY
+void StartMdns(void) {
+ if (Settings.flag3.mdns_enabled) { // SetOption55 - Control mDNS service
+ if (!Mdns.begun) {
+// if (mdns_delayed_start) {
+// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION));
+// mdns_delayed_start--;
+// } else {
+// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START];
+ Mdns.begun = (uint8_t)MDNS.begin(my_hostname);
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? D_INITIALIZED : D_FAILED);
+// }
+ }
+ }
+}
+
+#ifdef MQTT_HOST_DISCOVERY
+void MqttDiscoverServer(void)
+{
+ if (!Mdns.begun) { return; }
+
+ int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service
+
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n);
+
+ if (n > 0) {
+ uint32_t i = 0; // If the hostname isn't set, use the first record found.
+#ifdef MDNS_HOSTNAME
+ for (i = n; i > 0; i--) { // Search from last to first and use first if not found
+ if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) {
+ break; // Stop at matching record
+ }
+ }
+#endif // MDNS_HOSTNAME
+ SettingsUpdateText(SET_MQTT_HOST, MDNS.IP(i).toString().c_str());
+ Settings.mqtt_port = MDNS.port(i);
+
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), SettingsText(SET_MQTT_HOST), Settings.mqtt_port);
+ }
+}
+#endif // MQTT_HOST_DISCOVERY
+
+#ifdef WEBSERVER_ADVERTISE
+void MdnsAddServiceHttp(void) {
+ if (1 == Mdns.begun) {
+ Mdns.begun = 2;
+ MDNS.addService("http", "tcp", WEB_PORT);
+ }
+}
+
+void MdnsUpdate(void) {
+ if (2 == Mdns.begun) {
+ MDNS.update();
+ AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update");
+ }
+}
+#endif // WEBSERVER_ADVERTISE
+#endif // USE_DISCOVERY
+
+/*********************************************************************************************\
+ * Global network parameters
+\*********************************************************************************************/
+
+char* NetworkHostname(void) {
+ if (global_state.eth_down) {
+ return my_hostname;
+ }
+#ifdef ESP32
+#ifdef USE_ETHERNET
+ else {
+ return EthernetHostname();
+ }
+#endif
+#endif
+}
+
+IPAddress NetworkAddress(void) {
+ if (global_state.eth_down) {
+ return WiFi.localIP();
+ }
+#ifdef ESP32
+#ifdef USE_ETHERNET
+ else {
+ return EthernetLocalIP();
+ }
+#endif
+#endif
+}
+
+String NetworkMacAddress(void) {
+ if (global_state.eth_down) {
+ return WiFi.macAddress();
+ }
+#ifdef ESP32
+#ifdef USE_ETHERNET
+ else {
+ return EthernetMacAddress();
+ }
+#endif
+#endif
+}
diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino
index 3cbfb497c..a7430dfbb 100644
--- a/tasmota/support_tasmota.ino
+++ b/tasmota/support_tasmota.ino
@@ -684,10 +684,14 @@ void MqttShowState(void)
MqttShowPWMState();
}
- int32_t rssi = WiFi.RSSI();
- ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"),
- Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(),
- WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str());
+ if (!global_state.wifi_down) {
+ int32_t rssi = WiFi.RSSI();
+ ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}"),
+ Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(),
+ WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str());
+ }
+
+ ResponseJsonEnd();
}
void MqttPublishTeleState(void)
@@ -824,7 +828,7 @@ void PerformEverySecond(void)
if (Settings.tele_period) {
if (tele_period >= 9999) {
- if (!global_state.wifi_down) {
+ if (!global_state.network_down) {
tele_period = 0; // Allow teleperiod once wifi is connected
}
} else {
@@ -916,10 +920,12 @@ void Every250mSeconds(void)
state_250mS++;
state_250mS &= 0x3;
+ global_state.network_down = (global_state.wifi_down && global_state.eth_down);
+
if (!Settings.flag.global_state) { // Problem blinkyblinky enabled - SetOption31 - Control link led blinking
- if (global_state.data) { // Any problem
+ if (global_state.data &0x03) { // Any problem
if (global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest)
- if (global_state.wifi_down) { blinkinterval = 3; } // Wifi problem so blink every second (slow)
+ if (global_state.network_down) { blinkinterval = 3; } // Network problem so blink every second (slow)
blinks = 201; // Allow only a single blink in case the problem is solved
}
}
@@ -1151,11 +1157,75 @@ void Every250mSeconds(void)
}
break;
case 2: // Every x.5 second
- WifiCheck(wifi_state_flag);
- wifi_state_flag = WIFI_RESTART;
+ if (Settings.flag4.network_wifi) {
+ WifiCheck(wifi_state_flag);
+ wifi_state_flag = WIFI_RESTART;
+ }
break;
case 3: // Every x.75 second
- if (!global_state.wifi_down) { MqttCheck(); }
+ if (!global_state.network_down) {
+#ifdef FIRMWARE_MINIMAL
+ if (1 == RtcSettings.ota_loader) {
+ RtcSettings.ota_loader = 0;
+ ota_state_flag = 3;
+ }
+#endif // FIRMWARE_MINIMAL
+
+#ifdef USE_DISCOVERY
+ StartMdns();
+#endif // USE_DISCOVERY
+
+#ifdef USE_WEBSERVER
+ if (Settings.webserver) {
+
+#ifdef ESP8266
+ StartWebserver(Settings.webserver, WiFi.localIP());
+#else // ESP32
+#ifdef USE_ETHERNET
+ StartWebserver(Settings.webserver, (EthernetLocalIP()) ? EthernetLocalIP() : WiFi.localIP());
+#else
+ StartWebserver(Settings.webserver, WiFi.localIP());
+#endif
+#endif
+
+#ifdef USE_DISCOVERY
+#ifdef WEBSERVER_ADVERTISE
+ MdnsAddServiceHttp();
+#endif // WEBSERVER_ADVERTISE
+#endif // USE_DISCOVERY
+ } else {
+ StopWebserver();
+ }
+#ifdef USE_EMULATION
+ if (Settings.flag2.emulation) { UdpConnect(); }
+#endif // USE_EMULATION
+#endif // USE_WEBSERVER
+
+#ifdef USE_DEVICE_GROUPS
+ DeviceGroupsStart();
+#endif // USE_DEVICE_GROUPS
+
+#ifdef USE_KNX
+ if (!knx_started && Settings.flag.knx_enabled) { // CMND_KNX_ENABLED
+ KNXStart();
+ knx_started = true;
+ }
+#endif // USE_KNX
+
+ MqttCheck();
+ } else {
+#ifdef USE_EMULATION
+ UdpDisconnect();
+#endif // USE_EMULATION
+
+#ifdef USE_DEVICE_GROUPS
+ DeviceGroupsStop();
+#endif // USE_DEVICE_GROUPS
+
+#ifdef USE_KNX
+ knx_started = false;
+#endif // USE_KNX
+ }
break;
}
}
@@ -1174,7 +1244,7 @@ uint16_t arduino_ota_progress_dot_count = 0;
void ArduinoOTAInit(void)
{
ArduinoOTA.setPort(8266);
- ArduinoOTA.setHostname(my_hostname);
+ ArduinoOTA.setHostname(NetworkHostname());
if (strlen(SettingsText(SET_WEBPWD))) {
ArduinoOTA.setPassword(SettingsText(SET_WEBPWD));
}
diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino
index c42e1d49a..75de2523f 100644
--- a/tasmota/support_wifi.ino
+++ b/tasmota/support_wifi.ino
@@ -52,7 +52,6 @@ struct WIFI {
uint8_t status;
uint8_t config_type = 0;
uint8_t config_counter = 0;
- uint8_t mdns_begun = 0; // mDNS active
uint8_t scan_state;
uint8_t bssid[6];
int8_t best_network_db;
@@ -352,6 +351,9 @@ void WifiSetState(uint8_t state)
}
}
global_state.wifi_down = state ^1;
+ if (!global_state.wifi_down) {
+ global_state.network_down = 0;
+ }
}
#if LWIP_IPV6
@@ -410,10 +412,7 @@ void WifiCheckIp(void)
Wifi.status = WL_CONNECTED;
#ifdef USE_DISCOVERY
#ifdef WEBSERVER_ADVERTISE
- if (2 == Wifi.mdns_begun) {
- MDNS.update();
- AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update");
- }
+ MdnsUpdate();
#endif // USE_DISCOVERY
#endif // WEBSERVER_ADVERTISE
} else {
@@ -529,75 +528,14 @@ void WifiCheck(uint8_t param)
if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) {
#endif // LWIP_IPV6=1
WifiSetState(1);
-
if (Settings.flag3.use_wifi_rescan) { // SetOption57 - Scan wifi network every 44 minutes for configured AP's
if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) {
Wifi.scan_state = 2;
}
}
-
-#ifdef FIRMWARE_MINIMAL
- if (1 == RtcSettings.ota_loader) {
- RtcSettings.ota_loader = 0;
- ota_state_flag = 3;
- }
-#endif // FIRMWARE_MINIMAL
-
-#ifdef USE_DISCOVERY
- if (Settings.flag3.mdns_enabled) { // SetOption55 - Control mDNS service
- if (!Wifi.mdns_begun) {
-// if (mdns_delayed_start) {
-// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION));
-// mdns_delayed_start--;
-// } else {
-// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START];
- Wifi.mdns_begun = (uint8_t)MDNS.begin(my_hostname);
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Wifi.mdns_begun) ? D_INITIALIZED : D_FAILED);
-// }
- }
- }
-#endif // USE_DISCOVERY
-
-#ifdef USE_WEBSERVER
- if (Settings.webserver) {
- StartWebserver(Settings.webserver, WiFi.localIP());
-#ifdef USE_DISCOVERY
-#ifdef WEBSERVER_ADVERTISE
- if (1 == Wifi.mdns_begun) {
- Wifi.mdns_begun = 2;
- MDNS.addService("http", "tcp", WEB_PORT);
- }
-#endif // WEBSERVER_ADVERTISE
-#endif // USE_DISCOVERY
- } else {
- StopWebserver();
- }
-#ifdef USE_EMULATION
- if (Settings.flag2.emulation) { UdpConnect(); }
-#endif // USE_EMULATION
-#endif // USE_WEBSERVER
-#ifdef USE_DEVICE_GROUPS
- DeviceGroupsStart();
-#endif // USE_DEVICE_GROUPS
-#ifdef USE_KNX
- if (!knx_started && Settings.flag.knx_enabled) { // CMND_KNX_ENABLED
- KNXStart();
- knx_started = true;
- }
-#endif // USE_KNX
-
} else {
WifiSetState(0);
-#ifdef USE_EMULATION
- UdpDisconnect();
-#endif // USE_EMULATION
-#ifdef USE_DEVICE_GROUPS
- DeviceGroupsStop();
-#endif // USE_DEVICE_GROUPS
- Wifi.mdns_begun = 0;
-#ifdef USE_KNX
- knx_started = false;
-#endif // USE_KNX
+ Mdns.begun = 0;
}
}
}
@@ -652,6 +590,8 @@ RF_PRE_INIT()
void WifiConnect(void)
{
+ if (!Settings.flag4.network_wifi) { return; }
+
WifiSetState(0);
WifiSetOutputPower();
WiFi.persistent(false); // Solve possible wifi init errors
@@ -760,4 +700,4 @@ void wifiKeepAlive(void) {
SetNextTimeInterval(wifiTimer, wifiTimerSec * 1000);
}
}
-#endif // ARDUINO_ESP8266_RELEASE_2_3_0
\ No newline at end of file
+#endif // ARDUINO_ESP8266_RELEASE_2_3_0
diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino
index 06bd8d9e7..4a35d4327 100644
--- a/tasmota/tasmota.ino
+++ b/tasmota/tasmota.ino
@@ -205,7 +205,7 @@ void setup(void) {
#endif
#endif
- global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues
+ global_state.data = 0xF; // Init global state (wifi_down, mqtt_down) to solve possible network issues
RtcRebootLoad();
if (!RtcRebootValid()) {
@@ -413,7 +413,7 @@ void loop(void) {
if (my_activity < (uint32_t)ssleep) {
SleepDelay((uint32_t)ssleep - my_activity); // Provide time for background tasks like wifi
} else {
- if (global_state.wifi_down) {
+ if (global_state.network_down) {
SleepDelay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period
}
}
diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h
index f33024c45..c2acc6911 100644
--- a/tasmota/tasmota_globals.h
+++ b/tasmota/tasmota_globals.h
@@ -43,6 +43,16 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end);
extern "C" void resetPins();
+#ifdef ESP32
+
+#ifdef USE_ETHERNET
+IPAddress EthernetLocalIP(void);
+char* EthernetHostname(void);
+String EthernetMacAddress(void);
+#endif
+
+#endif // ESP32
+
/*********************************************************************************************\
* Preconfigured configurations
\*********************************************************************************************/
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index dab425f01..a99e34143 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -236,6 +236,8 @@ enum UserSelectablePins {
GPIO_BL0940_RX, // BL0940 serial interface
GPIO_TELEINFO_RX, // BL0940 serial interface
GPIO_TELEINFO_ENABLE, // BL0940 serial interface
+ GPIO_TCP_TX, // TCP Serial bridge
+ GPIO_TCP_RX, // TCP Serial bridge
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality
@@ -327,7 +329,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
D_SENSOR_WINDMETER_SPEED "|"
D_SENSOR_BL0940_RX "|"
- D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE
+ D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|"
+ D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD
;
const char kSensorNamesFixed[] PROGMEM =
@@ -689,7 +692,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_TELEINFO_RX,
GPIO_TELEINFO_ENABLE,
#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 f6424bfbf..769980939 100644
--- a/tasmota/tasmota_template_ESP32.h
+++ b/tasmota/tasmota_template_ESP32.h
@@ -131,6 +131,7 @@ enum UserSelectablePins {
GPIO_BL0940_RX, // BL0940 serial interface
GPIO_TELEINFO_RX, // Teleinfo telemetry data receive pin
GPIO_TELEINFO_ENABLE, // Teleinfo Enable Receive Pin
+ GPIO_TCP_TX, GPIO_TCP_RX, // TCP to serial bridge
GPIO_SENSOR_END };
enum ProgramSelectablePins {
@@ -221,7 +222,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
D_SENSOR_WINDMETER_SPEED "|" D_SENSOR_BUTTON "_tc|"
D_SENSOR_BL0940_RX "|"
- D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE
+ D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|"
+ D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD
;
const char kSensorNamesFixed[] PROGMEM =
@@ -554,6 +556,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/tasmota_version.h b/tasmota/tasmota_version.h
index f22a0288b..e01e1bcce 100644
--- a/tasmota/tasmota_version.h
+++ b/tasmota/tasmota_version.h
@@ -20,7 +20,7 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
-const uint32_t VERSION = 0x08030103;
+const uint32_t VERSION = 0x08030104;
// Lowest compatible version
const uint32_t VERSION_COMPATIBLE = 0x07010006;
diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino
index 7fcd82a9f..e21d3566b 100644
--- a/tasmota/xdrv_01_webserver.ino
+++ b/tasmota/xdrv_01_webserver.ino
@@ -868,10 +868,16 @@ void StartWebserver(int type, IPAddress ipweb)
if (Web.state != type) {
#if LWIP_IPV6
String ipv6_addr = WifiGetIPv6();
- if(ipv6_addr!="") AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s and IPv6 global address %s "), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str(),ipv6_addr.c_str());
- else AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str());
+ if (ipv6_addr!="") {
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s and IPv6 global address %s "),
+ NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str(), ipv6_addr.c_str());
+ } else {
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"),
+ NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str());
+ }
#else
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str());
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"),
+ NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str());
#endif // LWIP_IPV6 = 1
rules_flag.http_init = 1;
}
@@ -1151,8 +1157,8 @@ void WSContentSendStyle_P(const char* formatP, ...)
bool lip = (static_cast(WiFi.localIP()) != 0);
bool sip = (static_cast(WiFi.softAPIP()) != 0);
WSContentSend_P(PSTR("%s%s (%s%s%s)
"), // tasmota.local (192.168.2.12, 192.168.4.1)
- my_hostname,
- (Wifi.mdns_begun) ? ".local" : "",
+ NetworkHostname(),
+ (Mdns.begun) ? ".local" : "",
(lip) ? WiFi.localIP().toString().c_str() : "",
(lip && sip) ? ", " : "",
(sip) ? WiFi.softAPIP().toString().c_str() : "");
@@ -2471,26 +2477,39 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i));
}
WSContentSend_P(PSTR("}1}2 ")); // Empty line
- int32_t rssi = WiFi.RSSI();
- WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(rssi), rssi);
- WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "");
+#ifdef ESP32
+#ifdef USE_ETHERNET
+ if (static_cast(EthernetLocalIP()) != 0) {
+ WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? ".local" : "");
+ WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), EthernetMacAddress().c_str());
+ WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), EthernetLocalIP().toString().c_str());
+ }
+#endif
+#endif
+ if (Settings.flag4.network_wifi) {
+ int32_t rssi = WiFi.RSSI();
+ WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(rssi), rssi);
+ WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Mdns.begun) ? ".local" : "");
#if LWIP_IPV6
String ipv6_addr = WifiGetIPv6();
- if(ipv6_addr != ""){
+ if (ipv6_addr != "") {
WSContentSend_P(PSTR("}1 IPv6 Address }2%s"), ipv6_addr.c_str());
}
#endif
- if (static_cast(WiFi.localIP()) != 0) {
- WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str());
+ if (static_cast(WiFi.localIP()) != 0) {
+ WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str());
+ WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str());
+ }
+ }
+ if (!global_state.network_down) {
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str());
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str());
WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str());
- WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str());
}
if (static_cast(WiFi.softAPIP()) != 0) {
+ WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str());
WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.softAPIP().toString().c_str());
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str());
- WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str());
}
WSContentSend_P(PSTR("}1}2 ")); // Empty line
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
@@ -3288,7 +3307,7 @@ void CmndWebServer(void)
}
if (Settings.webserver) {
Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"),
- (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str());
+ (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str());
} else {
ResponseCmndStateText(0);
}
diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino
index 9e06f4e90..7a7eae075 100644
--- a/tasmota/xdrv_02_mqtt.ino
+++ b/tasmota/xdrv_02_mqtt.ino
@@ -123,34 +123,6 @@ void MakeValidMqtt(uint32_t option, char* str)
}
}
-#ifdef USE_DISCOVERY
-#ifdef MQTT_HOST_DISCOVERY
-void MqttDiscoverServer(void)
-{
- if (!Wifi.mdns_begun) { return; }
-
- int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service
-
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n);
-
- if (n > 0) {
- uint32_t i = 0; // If the hostname isn't set, use the first record found.
-#ifdef MDNS_HOSTNAME
- for (i = n; i > 0; i--) { // Search from last to first and use first if not found
- if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) {
- break; // Stop at matching record
- }
- }
-#endif // MDNS_HOSTNAME
- SettingsUpdateText(SET_MQTT_HOST, MDNS.IP(i).toString().c_str());
- Settings.mqtt_port = MDNS.port(i);
-
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), SettingsText(SET_MQTT_HOST), Settings.mqtt_port);
- }
-}
-#endif // MQTT_HOST_DISCOVERY
-#endif // USE_DISCOVERY
-
/*********************************************************************************************\
* MQTT driver specific code need to provide the following functions:
*
@@ -539,10 +511,10 @@ void MqttConnected(void)
if (Settings.webserver) {
#if LWIP_IPV6
Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"),
- (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str(),WifiGetIPv6().c_str());
+ (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str());
#else
Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"),
- (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str());
+ (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str());
#endif // LWIP_IPV6 = 1
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2"));
}
diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino
index 35427e67a..7fc893ffc 100755
--- a/tasmota/xdrv_10_scripter.ino
+++ b/tasmota/xdrv_10_scripter.ino
@@ -67,6 +67,8 @@ keywords if then else endif, or, and are better readable for beginners (others m
uint32_t EncodeLightId(uint8_t relay_id);
uint32_t DecodeLightId(uint32_t hue_id);
+
+
// solve conficting defines
// highest priority
#ifdef USE_SCRIPT_FATFS
@@ -118,6 +120,33 @@ uint32_t DecodeLightId(uint32_t hue_id);
#endif
#endif // USE_UNISHOX_COMPRESSION
+#define USE_SCRIPT_TIMER
+
+#ifdef USE_SCRIPT_TIMER
+#include
+Ticker Script_ticker1;
+Ticker Script_ticker2;
+Ticker Script_ticker3;
+Ticker Script_ticker4;
+
+void Script_ticker1_end(void) {
+ Script_ticker1.detach();
+ Run_Scripter(">ti1", 4,0);
+}
+void Script_ticker2_end(void) {
+ Script_ticker2.detach();
+ Run_Scripter(">ti2", 4,0);
+}
+void Script_ticker3_end(void) {
+ Script_ticker3.detach();
+ Run_Scripter(">ti3", 4,0);
+}
+void Script_ticker4_end(void) {
+ Script_ticker4.detach();
+ Run_Scripter(">ti4", 4,0);
+}
+#endif
+
#if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1)
#ifdef ESP32
@@ -770,7 +799,7 @@ char *script;
IPAddress script_udp_remote_ip;
void Script_Init_UDP() {
- if (global_state.wifi_down) return;
+ if (global_state.network_down) return;
if (glob_script_mem.udp_flags.udp_connected) return;
if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) {
@@ -1876,6 +1905,20 @@ chknext:
if (sp) strlcpy(sp,SettingsText(SET_MQTT_GRP_TOPIC),glob_script_mem.max_ssize);
goto strexit;
}
+
+#ifdef SCRIPT_GET_HTTPS_JP
+ if (!strncmp(vname,"gjp(",4)) {
+ char host[SCRIPT_MAXSSIZE];
+ lp=GetStringResult(lp+4,OPER_EQU,host,0);
+ SCRIPT_SKIP_SPACES
+ char path[SCRIPT_MAXSSIZE];
+ lp=GetStringResult(lp,OPER_EQU,path,0);
+ fvar=call2https(host,path);
+ lp++;
+ len=0;
+ goto exit;
+ }
+#endif
break;
case 'h':
if (!strncmp(vname,"hours",5)) {
@@ -2410,6 +2453,41 @@ chknext:
if (sp) strlcpy(sp,SettingsText(SET_MQTT_TOPIC),glob_script_mem.max_ssize);
goto strexit;
}
+#ifdef USE_SCRIPT_TIMER
+ if (!strncmp(vname,"ts1(",4)) {
+ lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0);
+ if (fvar<10) fvar=10;
+ Script_ticker1.attach_ms(fvar, Script_ticker1_end);
+ lp++;
+ len=0;
+ goto exit;
+ }
+ if (!strncmp(vname,"ts2(",4)) {
+ lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0);
+ if (fvar<10) fvar=10;
+ Script_ticker2.attach_ms(fvar, Script_ticker2_end);
+ lp++;
+ len=0;
+ goto exit;
+ }
+ if (!strncmp(vname,"ts3(",4)) {
+ lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0);
+ if (fvar<10) fvar=10;
+ Script_ticker3.attach_ms(fvar, Script_ticker3_end);
+ lp++;
+ len=0;
+ goto exit;
+ }
+ if (!strncmp(vname,"ts4(",4)) {
+ lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0);
+ if (fvar<10) fvar=10;
+ Script_ticker4.attach_ms(fvar, Script_ticker4_end);
+ lp++;
+ len=0;
+ goto exit;
+ }
+#endif // USE_SCRIPT_TIMER
+
#ifdef USE_DISPLAY
#ifdef USE_TOUCH_BUTTONS
if (!strncmp(vname,"tbut[",5)) {
@@ -4817,9 +4895,11 @@ void Script_Check_Hue(String *response) {
}
else {
if (hue_devs>0) *response+=",\"";
+ else *response+="\"";
}
*response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":";
Script_HueStatus(response,hue_devs);
+ //AddLog_P2(LOG_LEVEL_INFO, PSTR("Hue: %s - %d "),response->c_str(), hue_devs);
}
hue_devs++;
@@ -6118,6 +6198,62 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core) {
#endif // USE_SCRIPT_TASK
#endif // ESP32
+
+#ifdef SCRIPT_GET_HTTPS_JP
+#ifdef ESP8266
+#include "WiFiClientSecureLightBearSSL.h"
+#else
+#include
+#endif
+
+// get tesla powerwall info page json string
+uint32_t call2https(const char *host, const char *path) {
+ if (global_state.wifi_down) return 1;
+ uint32_t status=0;
+#ifdef ESP32
+ WiFiClientSecure *httpsClient;
+ httpsClient = new WiFiClientSecure;
+#else
+ BearSSL::WiFiClientSecure_light *httpsClient;
+ httpsClient = new BearSSL::WiFiClientSecure_light(1024, 1024);
+#endif
+
+ httpsClient->setTimeout(1500);
+
+ int retry = 0;
+ String result;
+ while ((!httpsClient->connect(host, 443)) && (retry < 5)) {
+ delay(100);
+ retry++;
+ }
+ if (retry == 5) {
+ return 2;
+ }
+ String request = String("GET ") + path +
+ " HTTP/1.1\r\n" +
+ "Host: " + host +
+ "\r\n" + "Connection: close\r\n\r\n";
+ httpsClient->print(request);
+
+ while (httpsClient->connected()) {
+ String line = httpsClient->readStringUntil('\n');
+ if (line == "\r") {
+ break;
+ }
+ }
+ while (httpsClient->available()) {
+ String line = httpsClient->readStringUntil('\n');
+ if (line!="") {
+ result += line;
+ }
+ }
+ httpsClient->stop();
+ Run_Scripter(">jp",3,(char*)result.c_str());
+ return 0;
+}
+
+#endif // SCRIPT_GET_HTTPS_JP
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino
index 47b62547d..f23e896fd 100644
--- a/tasmota/xdrv_11_knx.ino
+++ b/tasmota/xdrv_11_knx.ino
@@ -1208,7 +1208,7 @@ bool Xdrv11(uint8_t function)
bool result = false;
switch (function) {
case FUNC_LOOP:
- if (!global_state.wifi_down) { knx.loop(); } // Process knx events
+ if (!global_state.network_down) { knx.loop(); } // Process knx events
break;
case FUNC_EVERY_50_MSECOND:
if (toggle_inhibit) {
diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino
index 7ede88b44..70ab6d620 100644
--- a/tasmota/xdrv_12_home_assistant.ino
+++ b/tasmota/xdrv_12_home_assistant.ino
@@ -201,7 +201,7 @@ void HAssAnnounceRelayLight(void)
uint8_t max_lights = 1;
#ifdef ESP8266
- if (PWM_DIMMER == my_module_type) { PwmMod = true; }
+ if (PWM_DIMMER == my_module_type) { PwmMod = true; }
#endif //ESP8266
// If there is a special Light to be enabled and managed with SetOption68 or SetOption37 >= 128, Discovery calculates the maximum number of entities to be generated in advance
@@ -719,7 +719,7 @@ void HAssPublishStatus(void)
"\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"" D_JSON_SIGNAL " (dBm)""\":\"%d\","
"\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"LoadAvg\":%lu}"),
my_version, my_image, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(),
- GetUptime().c_str(), my_hostname, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()),
+ GetUptime().c_str(), NetworkHostname(), WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()),
WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), loop_load_avg);
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE));
}
diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino
index 43245c794..20e95eeb1 100644
--- a/tasmota/xdrv_13_display.ino
+++ b/tasmota/xdrv_13_display.ino
@@ -1013,14 +1013,14 @@ void DisplayLogBufferInit(void)
snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode);
DisplayLogBufferAdd(buffer);
- snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname);
+ snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), NetworkHostname());
DisplayLogBufferAdd(buffer);
- snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active));
+ snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), NetworkMacAddress().c_str());
DisplayLogBufferAdd(buffer);
- snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str());
+ snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), NetworkAddress().toString().c_str());
DisplayLogBufferAdd(buffer);
if (!global_state.wifi_down) {
- snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str());
+ snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active));
DisplayLogBufferAdd(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI()));
DisplayLogBufferAdd(buffer);
diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino
index aad2732ca..53590a4c4 100644
--- a/tasmota/xdrv_23_zigbee_8_parsers.ino
+++ b/tasmota/xdrv_23_zigbee_8_parsers.ino
@@ -835,8 +835,8 @@ void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const
// responder
switch (cluster) {
case 0x0000:
- if (HasKeyCaseInsensitive(json, PSTR("ModelId"))) { json_out[F("ModelId")] = F("Tasmota Z2T"); }
- if (HasKeyCaseInsensitive(json, PSTR("Manufacturer"))) { json_out[F("Manufacturer")] = F("Tasmota"); }
+ if (HasKeyCaseInsensitive(json, PSTR("ModelId"))) { json_out[F("ModelId")] = F(USE_ZIGBEE_MODELID); }
+ if (HasKeyCaseInsensitive(json, PSTR("Manufacturer"))) { json_out[F("Manufacturer")] = F(USE_ZIGBEE_MANUFACTURER); }
break;
#ifdef USE_LIGHT
case 0x0006:
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
diff --git a/tasmota/xdrv_82_ethernet.ino b/tasmota/xdrv_82_ethernet.ino
new file mode 100644
index 000000000..6d9725332
--- /dev/null
+++ b/tasmota/xdrv_82_ethernet.ino
@@ -0,0 +1,131 @@
+/*
+ xdrv_82_ethernet.ino - ESP32 (PoE) ethernet support for Tasmota
+
+ Copyright (C) 2020 Theo Arends
+
+ 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 ESP32
+#ifdef USE_ETHERNET
+/*********************************************************************************************\
+ * Ethernet support for ESP32
+\*********************************************************************************************/
+
+#define XDRV_82 82
+
+// Olimex ESP32-PoE
+#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
+#define ETH_PHY_POWER 12
+
+#include
+
+struct {
+ char hostname[33];
+} Eth;
+
+void EthernetEvent(WiFiEvent_t event) {
+ switch (event) {
+ case SYSTEM_EVENT_ETH_START:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION));
+ ETH.setHostname(Eth.hostname);
+ break;
+ case SYSTEM_EVENT_ETH_CONNECTED:
+ AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED));
+ break;
+ case SYSTEM_EVENT_ETH_GOT_IP:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %s, Hostname %s"),
+ ETH.macAddress().c_str(), ETH.localIP().toString().c_str(), Eth.hostname);
+/*
+ if (ETH.fullDuplex()) {
+ Serial.print(", FULL_DUPLEX");
+ }
+ Serial.print(", ");
+ Serial.print(ETH.linkSpeed());
+ Serial.println("Mbps");
+*/
+ global_state.eth_down = 0;
+ break;
+ case SYSTEM_EVENT_ETH_DISCONNECTED:
+ AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: Disconnected"));
+ global_state.eth_down = 1;
+ break;
+ case SYSTEM_EVENT_ETH_STOP:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Stopped"));
+ global_state.eth_down = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+void EthernetInit(void) {
+ if (!Settings.flag4.network_ethernet) { return; }
+
+ snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), my_hostname);
+ WiFi.onEvent(EthernetEvent);
+ ETH.begin();
+}
+
+IPAddress EthernetLocalIP(void) {
+ return ETH.localIP();
+}
+
+char* EthernetHostname(void) {
+ return Eth.hostname;
+}
+
+String EthernetMacAddress(void) {
+ return ETH.macAddress();
+}
+
+/*********************************************************************************************\
+ * Commands
+\*********************************************************************************************/
+
+const char kEthernetCommands[] PROGMEM = "|" // No prefix
+ D_CMND_ETHERNET;
+
+void (* const EthernetCommand[])(void) PROGMEM = {
+ &CmndEthernet };
+
+void CmndEthernet(void)
+{
+ if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
+ Settings.flag4.network_ethernet = XdrvMailbox.payload;
+ restart_flag = 2;
+ }
+ ResponseCmndStateText(Settings.flag4.network_ethernet);
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xdrv82(uint8_t function) {
+ bool result = false;
+
+ switch (function) {
+ case FUNC_COMMAND:
+ result = DecodeCommand(kEthernetCommands, EthernetCommand);
+ break;
+ case FUNC_INIT:
+ EthernetInit();
+ break;
+ }
+ return result;
+}
+
+#endif // USE_ETHERNET
+#endif // ESP32
diff --git a/tasmota/xdsp_04_ili9341.ino b/tasmota/xdsp_04_ili9341.ino
index f755314c8..f5c485e6f 100644
--- a/tasmota/xdsp_04_ili9341.ino
+++ b/tasmota/xdsp_04_ili9341.ino
@@ -90,7 +90,11 @@ void Ili9341InitDriver(void)
if (Settings.display_height != ILI9341_TFTHEIGHT) {
Settings.display_height = ILI9341_TFTHEIGHT;
}
+#ifdef ESP8266
tft = new Adafruit_ILI9341(Pin(GPIO_SPI_CS), Pin(GPIO_SPI_DC));
+#else // ESP32
+ tft = new Adafruit_ILI9341(Pin (GPIO_TFT_CS), Pin (GPIO_TFT_DC), Pin (GPIO_TFT_MOSI), Pin (GPIO_TFT_CLK), Pin (GPIO_TFT_RST), Pin(GPIO_TFT_MISO));
+#endif
tft->begin();
#ifdef USE_DISPLAY_MODES1TO5
diff --git a/tools/decode-status.py b/tools/decode-status.py
index 2ec5b472e..095e23e71 100755
--- a/tools/decode-status.py
+++ b/tools/decode-status.py
@@ -209,7 +209,7 @@ a_features = [[
"USE_HP303B","","","",
"","","","",
"","","","",
- "","","","USE_WEBCAM"
+ "","","USE_ETHERNET","USE_WEBCAM"
]]
usage = "usage: decode-status {-d | -f} arg"