From 517eae733be1c5314b47f18f2c42942b52891fff Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:07:36 +0200 Subject: [PATCH] Add displaymode 7 - Extend state JSON message with functional hostname and ipaddress which could be WiFi or Ethernet --- CHANGELOG.md | 3 +- RELEASENOTES.md | 2 + tasmota/tasmota_support/support_tasmota.ino | 17 ++++ .../tasmota_xdrv_driver/xdrv_13_display.ino | 90 +++++++++++++------ 4 files changed, 84 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 478c2dff7..58a43e39c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [15.0.1.3] ### Added - ESP32 ROM SHA Hardware Acceleration to BearSSL (#23819) +- Extend state JSON message with functional hostname and ipaddress which could be WiFi or Ethernet ### Breaking Changed @@ -18,7 +19,7 @@ All notable changes to this project will be documented in this file. ### Fixed - Syslog RFC5424 compliance (#23509) -- Berry fix calling `setmember` with a function +- Berry calling `setmember` with a function (#23825) ### Removed - `user-scalable=no` from HTTP HEADER (#23798) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e8ecd5d1e..aade9d4bb 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -119,6 +119,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Commands `LoRaWanDecoder "` and `LoRaWanName "` to clear name [#23394](https://github.com/arendst/Tasmota/issues/23394) - Command `I2sPause` [#23646](https://github.com/arendst/Tasmota/issues/23646) - Support for RV3028 RTC [#23672](https://github.com/arendst/Tasmota/issues/23672) +- Extend state JSON message with functional hostname and ipaddress which could be WiFi or Ethernet - Internal function 'WSContentSendRaw_P' [#23641](https://github.com/arendst/Tasmota/issues/23641) - Universal display driver for ZJY169S0800TG01 ST7789 280x240 [#23638](https://github.com/arendst/Tasmota/issues/23638) - NeoPool add Redox tank alarm [#19811](https://github.com/arendst/Tasmota/issues/19811) @@ -154,6 +155,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry security issues in `int64` and improve documentation [#23605](https://github.com/arendst/Tasmota/issues/23605) - Berry security issues in `berry_mapping` and improve documentation [#23606](https://github.com/arendst/Tasmota/issues/23606) - Berry Hue regression from #23429 [#23623](https://github.com/arendst/Tasmota/issues/23623) +- Berry calling `setmember` with a function [#23825](https://github.com/arendst/Tasmota/issues/23825) - LVGL restore `lv_chart.set_range` removed in LVGL 9.3.0 in favor of `lv_chart.set_axis_range` [#23567](https://github.com/arendst/Tasmota/issues/23567) ### Removed diff --git a/tasmota/tasmota_support/support_tasmota.ino b/tasmota/tasmota_support/support_tasmota.ino index 33f961e28..53cc5bbd2 100644 --- a/tasmota/tasmota_support/support_tasmota.ino +++ b/tasmota/tasmota_support/support_tasmota.ino @@ -906,6 +906,15 @@ void MqttShowState(void) ResponseAppend_P(PSTR(",")); MqttShowPWMState(); } + + char *hostname = TasmotaGlobal.hostname; + uint32_t ipaddress = 0; +#if defined(ESP32) && defined(USE_ETHERNET) + if (static_cast(EthernetLocalIP()) != 0) { + hostname = EthernetHostname(); // Set ethernet as IP connection + ipaddress = (uint32_t)EthernetLocalIP(); + } +#endif if (!TasmotaGlobal.global_state.wifi_down) { int32_t rssi = WiFi.RSSI(); @@ -913,7 +922,15 @@ void MqttShowState(void) Settings->sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetPhyMode().c_str(), WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); + + if (static_cast(WiFi.localIP()) != 0) { + hostname = TasmotaGlobal.hostname; // Overrule ethernet as primary IP connection + ipaddress = (uint32_t)WiFi.localIP(); + } } + // I only want to show one active connection for device access + ResponseAppend_P(PSTR(",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\""), + hostname, ipaddress); ResponseJsonEnd(); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino index 31fed12a6..54c11127a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino @@ -167,6 +167,7 @@ enum DisplayModes { DM_MQTT_SENSORS, DM_TIME_MQTT_SENSORS, DM_MQTT_TOPIC_UPTIME, + DM_MQTT_HOSTNAME_IPADDRESS, DM_MAX }; @@ -1801,38 +1802,72 @@ void DisplayAnalyzeJson(char *topic, const char *json) { } } -void DisplayState(char *topic, const char *json) { +void DisplayState(const char *topic, const char *json) { + // Impact DisplayCols1 and DisplayCols2: + // 12345678901234567890123456 = DisplayCols1 = 26 - Visible display columns + // leftitem rightitem DisplayCols2 = 3 - Display both left and rightaligned item + // leftitem right DisplayCols2 = 2 - Display both left and truncated rightaligned item + // leftitem DisplayCols2 = 1 - Display left item only static uint32_t minute = 61; - char buffer[Settings->display_cols[0] +1]; // Max sized buffer string - if (minute != RtcTime.minute) { - minute = RtcTime.minute; - char buffer2[Settings->display_cols[0] +1]; // Max sized buffer string - memset(buffer2, '-', sizeof(buffer2)); // Set to - - buffer2[sizeof(buffer2) -1] = '\0'; - snprintf_P(buffer, sizeof(buffer), PSTR("- %02d" D_HOUR_MINUTE_SEPARATOR "%02d %s"), RtcTime.hour, RtcTime.minute, buffer2); - DisplayLogBufferAdd(buffer); - } + String jsonStr = json; // {"Time":"2025-08-24T14:34:59","Uptime":"0T00:05:10","UptimeSec":310,"Heap":49,... + JsonParser parser((char*)jsonStr.c_str()); + JsonParserObject root = parser.getRootObject(); + if (!root) { return; } // Did JSON parsing went ok? - const char *uptime = EmptyStr; - if (Settings->display_cols[0] > 20) { // Need space for displaying topic and uptime - String jsonStr = json; // {"Time":"2025-08-24T14:34:59","Uptime":"0T00:05:10","UptimeSec":310,"Heap":49,... - JsonParser parser((char*)jsonStr.c_str()); - JsonParserObject root = parser.getRootObject(); - if (root) { // Did JSON parsing went ok? - uptime = root.getStr(PSTR(D_JSON_UPTIME), EmptyStr); - if (strlen(uptime) && (Settings->display_cols[0] < 24)) { - char *eol = (char*)uptime + strlen(uptime) -3; - *eol = '\0'; // Remove uptime seconds + const char *leftitem = EmptyStr; + const char *rightitem = EmptyStr; + + if (DM_MQTT_TOPIC_UPTIME == Settings->display_mode) { + leftitem = topic; + if (Settings->display_cols[1] > 1) { // Need space for displaying topic and uptime + rightitem = root.getStr(PSTR(D_JSON_UPTIME), EmptyStr); + if (strlen(rightitem) && (2 == Settings->display_cols[1])) { + char *eol = (char*)rightitem + strlen(rightitem) -3; + *eol = '\0'; // Remove uptime seconds + } + } + } + else if (DM_MQTT_HOSTNAME_IPADDRESS == Settings->display_mode) { + leftitem = root.getStr(PSTR(D_CMND_HOSTNAME), EmptyStr); + if (Settings->display_cols[1] > 1) { // Need space for displaying hostname and ipaddress + rightitem = root.getStr(PSTR(D_CMND_IPADDRESS), EmptyStr); + if (strlen(rightitem) && (2 == Settings->display_cols[1])) { + uint32_t netmask = Settings->ipv4_address[2]; // Assume WiFi netmask = Ethernet netmask +#if defined(ESP32) && defined(USE_ETHERNET) + if (0 == netmask) { // Assume Ethernet netmask = WiFi netmask + netmask = Settings->eth_ipv4_address[2]; + } +#endif + if (netmask != 0) { + for (uint32_t i = 0; i < 3; i++) { + if (netmask >= 0x000000FF) { + rightitem = strchr(rightitem +1, '.'); // Skip network IP address octets + } + netmask >>= 8; + } + } else { + rightitem = strrchr(rightitem, '.'); // last IP address octet assuming netmask 255.255.255.0 + } } } } -// int spaces = Settings->display_cols[0] - Settings->display_cols[1] - strlen(topic); // Left align on DisplayCols2 - int spaces = Settings->display_cols[0] - strlen(topic) - strlen(uptime); // Right align on DisplayCols1 - if (spaces < 1) { spaces = 1; } - snprintf_P(buffer, sizeof(buffer), PSTR("%s%*s%s"), topic, spaces, "", uptime); - DisplayLogBufferAdd(buffer); + if (strlen(leftitem)) { + char buffer[Settings->display_cols[0] +1]; // Max sized buffer string + if (minute != RtcTime.minute) { + minute = RtcTime.minute; + char buffer2[Settings->display_cols[0] +1]; // Max sized buffer string + memset(buffer2, '-', sizeof(buffer2)); // Set to - + buffer2[sizeof(buffer2) -1] = '\0'; + snprintf_P(buffer, sizeof(buffer), PSTR("- %02d" D_HOUR_MINUTE_SEPARATOR "%02d %s"), RtcTime.hour, RtcTime.minute, buffer2); + DisplayLogBufferAdd(buffer); + } + int spaces = Settings->display_cols[0] - strlen(leftitem) - strlen(rightitem); // Right align on DisplayCols1 + if (spaces < 1) { spaces = 1; } + snprintf_P(buffer, sizeof(buffer), PSTR("%s%*s%s"), leftitem, spaces, "", rightitem); + DisplayLogBufferAdd(buffer); + } } void DisplayMqttSubscribe(void) { @@ -1880,11 +1915,12 @@ bool DisplayMqttData(void) { char *sensor = strstr_P(tp, PSTR("SENSOR")); char *topic = strtok(tp, "/"); // tasmota if (topic) { - if (DM_MQTT_TOPIC_UPTIME == Settings->display_mode) { + if ((DM_MQTT_TOPIC_UPTIME == Settings->display_mode) || + (DM_MQTT_HOSTNAME_IPADDRESS == Settings->display_mode)) { if (state) { DisplayState(topic, XdrvMailbox.data); } - } else { // DM_MQTT_SENSORS and DM_TIME_MQTT_SENSORS + } else { // DM_MQTT_SENSORS and DM_TIME_MQTT_SENSORS if (state || sensor) { DisplayAnalyzeJson(topic, XdrvMailbox.data); }