diff --git a/CHANGELOG.md b/CHANGELOG.md index 855e17018..458019d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ All notable changes to this project will be documented in this file. - Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs (#10196) - Support for FTC532 8-button touch controller by Peter Franck (#10222) +### Changed +- Logging from fixed global memory buffer to stack buffer freeing 700 bytes RAM + ### Fixed - Redesign syslog and mqttlog using log buffer (#10164) - Shutter stop issue (#10170) @@ -20,6 +23,7 @@ All notable changes to this project will be documented in this file. - Wemo emulation for single devices (#10165, #10194) - ESP32 LoadStoreError when using ``#define USER_TEMPLATE`` (#9506) - Compile error when ``#ifdef USE_IR_RECEIVE`` is disabled regression from 9.1.0.2 +- Prometheus memory leak (#10221) ## [Released] diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1d606f988..e9cb5b4d5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -64,8 +64,11 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs [#10196](https://github.com/arendst/Tasmota/issues/10196) - Support for FTC532 8-button touch controller by Peter Franck [#10222](https://github.com/arendst/Tasmota/issues/10222) +### Changed +- Logging from fixed global memory buffer to stack buffer freeing 700 bytes RAM + ### Fixed -- Redesign syslog and mqttlog using log buffer [#10164](https://github.com/arendst/Tasmota/issues/10152) +- Redesign syslog and mqttlog using log buffer [#10164](https://github.com/arendst/Tasmota/issues/10164) - Shutter stop issue [#10170](https://github.com/arendst/Tasmota/issues/10170) - Scripter script_sub_command [#10181](https://github.com/arendst/Tasmota/issues/10181) - Scripter JSON variable above 32 chars [#10193](https://github.com/arendst/Tasmota/issues/10193) @@ -73,3 +76,4 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Wemo emulation for single devices [#10165](https://github.com/arendst/Tasmota/issues/10165) [#10194](https://github.com/arendst/Tasmota/issues/10194) - ESP32 LoadStoreError when using ``#define USER_TEMPLATE`` [#9506](https://github.com/arendst/Tasmota/issues/9506) - Compile error when ``#ifdef USE_IR_RECEIVE`` is disabled regression from 9.1.0.2 +- Prometheus memory leak [#10221](https://github.com/arendst/Tasmota/issues/10221) diff --git a/lib/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h b/lib/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h index cb3ef8a2a..4bfbccc8c 100644 --- a/lib/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h +++ b/lib/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h @@ -5,8 +5,8 @@ //#include -#ifndef _PGMSPACE_BEARSSL_H_ -#define _PGMSPACE_BEARSSL_H_ +#ifndef _PGMSPACE_H_ +#define _PGMSPACE_H_ #include diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index ee86985a8..3f76397af 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -91,7 +91,7 @@ build_flags = ${esp82xx_defaults.build_flags} ; *** Esp8266 core for Arduino version stage platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git ; *** Use Xtensa build chain 10.2. GNU13 from https://github.com/earlephilhower/esp-quick-toolchain - mcspr/toolchain-xtensa @ 5.100200.200918 + mcspr/toolchain-xtensa @ 5.100200.201223 platformio/tool-esptoolpy @ ~1.30000.0 platformio/tool-esptool @ 1.413.0 build_unflags = ${esp_defaults.build_unflags} diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 82273baae..0a0242ff2 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v9.0.0.3 + * Updated until v9.2.0.1 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -461,30 +461,30 @@ #define D_KNX_RX_SCENE "KNX SCENE RX" // xdrv_23_zigbee -#define D_ZIGBEE_PERMITJOIN_ACTIVE "Devices allowed to join" -#define D_ZIGBEE_MAPPING_TITLE "Tasmota Zigbee Mapping" -#define D_ZIGBEE_NOT_STARTED "Zigbee not started" -#define D_ZIGBEE_MAPPING_IN_PROGRESS_SEC "Mapping in progress (%d s. remaining)" -#define D_ZIGBEE_MAPPING_NOT_PRESENT "No mapping" -#define D_ZIGBEE_MAP_REFRESH "Zigbee Map Refresh" -#define D_ZIGBEE_MAP "Zigbee Map" -#define D_ZIGBEE_PERMITJOIN "Zigbee Permit Join" -#define D_ZIGBEE_GENERATE_KEY "generating random Zigbee network key" -#define D_ZIGBEE_UNKNOWN_DEVICE "Unknown device" -#define D_ZIGBEE_UNKNOWN_ATTRIBUTE "Unknown attribute" -#define D_ZIGBEE_INVALID_PARAM "Invalid parameter" -#define D_ZIGBEE_MISSING_PARAM "Missing parameters" -#define D_ZIGBEE_UNKNWON_ATTRIBUTE "Unknown attribute name (ignored): %s" -#define D_ZIGBEE_TOO_MANY_CLUSTERS "No more than one cluster id per command" -#define D_ZIGBEE_WRONG_DELIMITER "Wrong delimiter for payload" -#define D_ZIGBEE_UNRECOGNIZED_COMMAND "Unrecognized zigbee command: %s" -#define D_ZIGBEE_TOO_MANY_COMMANDS "Only 1 command allowed (%d)" -#define D_ZIGBEE_NO_ATTRIBUTE "No attribute in list" -#define D_ZIGBEE_UNSUPPORTED_ATTRIBUTE_TYPE "Unsupported attribute type" -#define D_ZIGBEE_JSON_REQUIRED "Config requires JSON objects" -#define D_ZIGBEE_RESET_1_OR_2 "1 or 2 to reset" -#define D_ZIGBEE_EEPROM_FOUND_AT_ADDRESS "ZBBridge EEPROM found at address" -#define D_ZIGBEE_RANDOMIZING_ZBCONFIG "Randomizing Zigbee parameters, please check with 'ZbConfig'" +#define D_ZIGBEE_PERMITJOIN_ACTIVE "Gerätekopplung erlaubt" +#define D_ZIGBEE_MAPPING_TITLE "Tasmota Zigbee Karte" +#define D_ZIGBEE_NOT_STARTED "Zigbee nicht gestartet" +#define D_ZIGBEE_MAPPING_IN_PROGRESS_SEC "Karte in Erstellung (%d s. verbleibend)" +#define D_ZIGBEE_MAPPING_NOT_PRESENT "Keine Karte" +#define D_ZIGBEE_MAP_REFRESH "Zigbee Karte erneuern" +#define D_ZIGBEE_MAP "Zigbee Karte" +#define D_ZIGBEE_PERMITJOIN "Zigbee Kopplung ein" +#define D_ZIGBEE_GENERATE_KEY "Erzeuge zufälligen Zigbee Netzwerkschlüssel" +#define D_ZIGBEE_UNKNOWN_DEVICE "Unbekanntes Gerät" +#define D_ZIGBEE_UNKNOWN_ATTRIBUTE "Unbekanntes Attribut" +#define D_ZIGBEE_INVALID_PARAM "Ungültiger Parameter" +#define D_ZIGBEE_MISSING_PARAM "Fehlende Parameter" +#define D_ZIGBEE_UNKNWON_ATTRIBUTE "Unbekannter Attribut Name (ignoriert): %s" +#define D_ZIGBEE_TOO_MANY_CLUSTERS "Nur eine Cluster id pro Kommando" +#define D_ZIGBEE_WRONG_DELIMITER "Falscher Delimeter für Payload" +#define D_ZIGBEE_UNRECOGNIZED_COMMAND "Unerkanntes zigbee Kommando: %s" +#define D_ZIGBEE_TOO_MANY_COMMANDS "Nur 1 Kommando zulässig (%d)" +#define D_ZIGBEE_NO_ATTRIBUTE "Kein Attribut in der Liste" +#define D_ZIGBEE_UNSUPPORTED_ATTRIBUTE_TYPE "Nicht unterstützter Attribut Typ" +#define D_ZIGBEE_JSON_REQUIRED "Konfiguration muss JSON basiert sein" +#define D_ZIGBEE_RESET_1_OR_2 "1 oder 2 für Reset" +#define D_ZIGBEE_EEPROM_FOUND_AT_ADDRESS "ZBBridge EEPROM gefunden auf Addresse" +#define D_ZIGBEE_RANDOMIZING_ZBCONFIG "Zufällige Zigbee Parameter erstellt, Überprüfung mit 'ZbConfig'" // xdrv_03_energy.ino #define D_ENERGY_TODAY "Energie heute" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index e1d55e923..349fd2d51 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -1,7 +1,7 @@ /* it-IT.h - localization for Italian - Italy for Tasmota - Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 21.12.2020 + Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 24.12.2020 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 @@ -461,30 +461,30 @@ #define D_KNX_RX_SCENE "Scena - RX" // xdrv_23_zigbee -#define D_ZIGBEE_PERMITJOIN_ACTIVE "Devices allowed to join" -#define D_ZIGBEE_MAPPING_TITLE "Tasmota Zigbee Mapping" -#define D_ZIGBEE_NOT_STARTED "Zigbee not started" -#define D_ZIGBEE_MAPPING_IN_PROGRESS_SEC "Mapping in progress (%d s. remaining)" -#define D_ZIGBEE_MAPPING_NOT_PRESENT "No mapping" -#define D_ZIGBEE_MAP_REFRESH "Zigbee Map Refresh" -#define D_ZIGBEE_MAP "Zigbee Map" -#define D_ZIGBEE_PERMITJOIN "Zigbee Permit Join" -#define D_ZIGBEE_GENERATE_KEY "generating random Zigbee network key" -#define D_ZIGBEE_UNKNOWN_DEVICE "Unknown device" -#define D_ZIGBEE_UNKNOWN_ATTRIBUTE "Unknown attribute" -#define D_ZIGBEE_INVALID_PARAM "Invalid parameter" -#define D_ZIGBEE_MISSING_PARAM "Missing parameters" -#define D_ZIGBEE_UNKNWON_ATTRIBUTE "Unknown attribute name (ignored): %s" -#define D_ZIGBEE_TOO_MANY_CLUSTERS "No more than one cluster id per command" -#define D_ZIGBEE_WRONG_DELIMITER "Wrong delimiter for payload" -#define D_ZIGBEE_UNRECOGNIZED_COMMAND "Unrecognized zigbee command: %s" -#define D_ZIGBEE_TOO_MANY_COMMANDS "Only 1 command allowed (%d)" -#define D_ZIGBEE_NO_ATTRIBUTE "No attribute in list" -#define D_ZIGBEE_UNSUPPORTED_ATTRIBUTE_TYPE "Unsupported attribute type" -#define D_ZIGBEE_JSON_REQUIRED "Config requires JSON objects" -#define D_ZIGBEE_RESET_1_OR_2 "1 or 2 to reset" -#define D_ZIGBEE_EEPROM_FOUND_AT_ADDRESS "ZBBridge EEPROM found at address" -#define D_ZIGBEE_RANDOMIZING_ZBCONFIG "Randomizing Zigbee parameters, please check with 'ZbConfig'" +#define D_ZIGBEE_PERMITJOIN_ACTIVE "Dispositivo abilitato al collegamento" +#define D_ZIGBEE_MAPPING_TITLE "Mappatura Zigbee Tasmota" +#define D_ZIGBEE_NOT_STARTED "Zigbee non avviato" +#define D_ZIGBEE_MAPPING_IN_PROGRESS_SEC "Mappatura in corso (rimanente %d s.)" +#define D_ZIGBEE_MAPPING_NOT_PRESENT "Nessuna mappatura" +#define D_ZIGBEE_MAP_REFRESH "Aggiornamento mappa Zigbee" +#define D_ZIGBEE_MAP "Mappa Zigbee" +#define D_ZIGBEE_PERMITJOIN "Consenti collegamento Zigbee" +#define D_ZIGBEE_GENERATE_KEY "Generazione chiave casuale rete Zigbee" +#define D_ZIGBEE_UNKNOWN_DEVICE "Dispositivo sconosciuto" +#define D_ZIGBEE_UNKNOWN_ATTRIBUTE "Attributo sconosciuto" +#define D_ZIGBEE_INVALID_PARAM "Parametro non valido" +#define D_ZIGBEE_MISSING_PARAM "Parametro mancante" +#define D_ZIGBEE_UNKNWON_ATTRIBUTE "Nome sconosciuto attributo (ignorato): %s" +#define D_ZIGBEE_TOO_MANY_CLUSTERS "Non più di un ID cluster per comando" +#define D_ZIGBEE_WRONG_DELIMITER "Delimitatore errato carico utile" +#define D_ZIGBEE_UNRECOGNIZED_COMMAND "Comando Zigbee non riconosciuto: %s" +#define D_ZIGBEE_TOO_MANY_COMMANDS "È consentito solo 1 comando (%d)" +#define D_ZIGBEE_NO_ATTRIBUTE "Nessun attributo in elenco" +#define D_ZIGBEE_UNSUPPORTED_ATTRIBUTE_TYPE "Tipo attributo non supportato" +#define D_ZIGBEE_JSON_REQUIRED "Configurazione richiede oggetti JSON" +#define D_ZIGBEE_RESET_1_OR_2 "1 o 2 per ripristino" +#define D_ZIGBEE_EEPROM_FOUND_AT_ADDRESS "Trovata EEPROM ZBBridge all'indirizzo" +#define D_ZIGBEE_RANDOMIZING_ZBCONFIG "Randomizzazione parametri Zigbee, controlla con "ZbConfig"" // xdrv_03_energy.ino #define D_ENERGY_TODAY "Energia - oggi" diff --git a/tasmota/support.ino b/tasmota/support.ino index 2697e257a..4f5b0ec18 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1916,21 +1916,21 @@ void SyslogAsync(bool refresh) { syslog_host_hash = current_hash; WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } - if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { - char log_data[len +72]; // Hostname + Id + log data - snprintf_P(log_data, sizeof(log_data), PSTR("%s ESP-"), NetworkHostname()); - uint32_t preamble_len = strlen(log_data); - len -= mxtime; - strlcpy(log_data +preamble_len, line +mxtime, len); - // wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 - PortUdp_write(log_data, preamble_len + len); - PortUdp.endPacket(); - delay(1); // Add time for UDP handling (#5512) - } else { + if (!PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { TasmotaGlobal.syslog_level = 0; TasmotaGlobal.syslog_timer = SYSLOG_TIMER; AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); + return; } + char log_data[len +72]; // Hostname + Id + log data + snprintf_P(log_data, sizeof(log_data), PSTR("%s ESP-"), NetworkHostname()); + uint32_t preamble_len = strlen(log_data); + len -= mxtime; + strlcpy(log_data +preamble_len, line +mxtime, len); + // wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + PortUdp_write(log_data, preamble_len + len); + PortUdp.endPacket(); + delay(1); // Add time for UDP handling (#5512) } } } @@ -1948,6 +1948,7 @@ bool NeedLogRefresh(uint32_t req_loglevel, uint32_t index) { bool GetLog(uint32_t req_loglevel, uint32_t* index_p, char** entry_pp, size_t* len_p) { uint32_t index = *index_p; + if (TasmotaGlobal.uptime < 3) { return false; } // Allow time to setup correct log level if (!req_loglevel || (index == TasmotaGlobal.log_buffer_pointer)) { return false; } if (!index) { // Dump all @@ -1988,8 +1989,6 @@ bool GetLog(uint32_t req_loglevel, uint32_t* index_p, char** entry_pp, size_t* l } void AddLogData(uint32_t loglevel, const char* log_data) { -// char mxtime[10]; // "13:45:21 " -// snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second); char mxtime[14]; // "13:45:21.999 " snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d.%03d "), RtcTime.hour, RtcTime.minute, RtcTime.second, RtcMillis()); @@ -2002,6 +2001,7 @@ void AddLogData(uint32_t loglevel, const char* log_data) { if (Settings.mqttlog_level > highest_loglevel) { highest_loglevel = Settings.mqttlog_level; } if (TasmotaGlobal.syslog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.syslog_level; } if (TasmotaGlobal.templog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.templog_level; } + if (TasmotaGlobal.uptime < 3) { highest_loglevel = LOG_LEVEL_DEBUG_MORE; } // Log all before setup correct log level if ((loglevel <= highest_loglevel) && // Log only when needed (TasmotaGlobal.masterlog_level <= highest_loglevel)) { diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h index 14cc1532d..8dbdb2073 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/tasmota_globals.h @@ -157,6 +157,13 @@ String EthernetMacAddress(void); #endif #ifdef USE_TASMOTA_SLAVE_SERIAL_SPEED #define USE_TASMOTA_CLIENT_SERIAL_SPEED USE_TASMOTA_SLAVE_SERIAL_SPEED +#endif + +#ifdef USE_SCRIPT +#define USE_UNISHOX_COMPRESSION // Add support for string compression +#endif +#ifdef USE_ZIGBEE +#define USE_UNISHOX_COMPRESSION // Add support for string compression #endif // See https://github.com/esp8266/Arduino/pull/4889 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index f0f65e77b..1deb269d0 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2351,7 +2351,7 @@ void OtherSaveSettings(void) SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp); snprintf_P(message, sizeof(message), PSTR("%s%s %s"), message, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); } - AddLog_P(LOG_LEVEL_INFO, message); + AddLogData(LOG_LEVEL_INFO, message); WebGetArg("t1", tmp, sizeof(tmp)); if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index 786bde4b9..543da7d25 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -897,7 +897,7 @@ void TimerSaveSettings(void) } snprintf_P(message, sizeof(message), PSTR("%s,0x%08X"), message, Settings.timer[i].data); } - AddLog_P(LOG_LEVEL_DEBUG, message); + AddLogData(LOG_LEVEL_DEBUG, message); } #endif // USE_TIMERS_WEB #endif // USE_WEBSERVER diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index d2a1c328f..06c59ece8 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -642,7 +642,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Ztuya4, CxEF00, 0x046F, Z_(TuyaWeekSelect), Cm1, 0 }, // Aqara Opple spacific - { Zbool, CxFCC0, 0x0009, Z_(OppleMode), Cm1, 0 }, + { Zuint8, CxFCC0, 0x0009, Z_(OppleMode), Cm1, 0 }, // Terncy specific - 0xFCCC { Zuint16, CxFCCC, 0x001A, Z_(TerncyDuration), Cm1, 0 }, diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index 804eb1859..cccfde736 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -877,7 +877,7 @@ void Dump2log(void) { char c=SML_SREAD&0x7f; if (c=='\n' || c=='\r') { log_data[sml_logindex]=0; - AddLog(LOG_LEVEL_INFO); + AddLogData(LOG_LEVEL_INFO, log_data); sml_logindex=2; log_data[0]=':'; log_data[1]=' '; diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index e4880a3fd..b6afd3f70 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -26,68 +26,47 @@ const char *UnitfromType(const char *type) // find unit for measurment type { - if (strcmp(type, "time") == 0) - { - return "_seconds"; + if (strcmp(type, "time") == 0) { + return "seconds"; } - if (strcmp(type, "temperature") == 0 || strcmp(type, "dewpoint") == 0) - { - return "_celsius"; + if (strcmp(type, "temperature") == 0 || strcmp(type, "dewpoint") == 0) { + return "celsius"; } - if (strcmp(type, "pressure") == 0) - { - return "_hpa"; + if (strcmp(type, "pressure") == 0) { + return "hpa"; } - if (strcmp(type, "voltage") == 0) - { - return "_volts"; + if (strcmp(type, "voltage") == 0) { + return "volts"; } - if (strcmp(type, "current") == 0) - { - return "_amperes"; + if (strcmp(type, "current") == 0) { + return "amperes"; } - if (strcmp(type, "mass") == 0) - { - return "_grams"; + if (strcmp(type, "mass") == 0) { + return "grams"; } - if (strcmp(type, "carbondioxide") == 0) - { - return "_ppm"; + if (strcmp(type, "carbondioxide") == 0) { + return "ppm"; } - if (strcmp(type, "humidity") == 0) - { - return "_percentage"; + if (strcmp(type, "humidity") == 0) { + return "percentage"; } return ""; } -const char *FormatMetricName(const char *metric) // cleanup spaces and uppercases for Prmetheus metrics conventions -{ - char *formated = (char *)malloc(strlen(metric)+1); - uint32_t cnt = 0; - for (cnt; cnt < strlen(metric)+1; cnt++) - { - if (metric[cnt] == ' ') - { - formated[cnt] = '_'; - } - else - { - formated[cnt] = tolower(metric[cnt]); - } - } - return formated; +String FormatMetricName(const char *metric) { // cleanup spaces and uppercases for Prmetheus metrics conventions + String formatted = metric; + formatted.toLowerCase(); + formatted.replace(" ", "_"); + return formatted; } -void HandleMetrics(void) -{ +void HandleMetrics(void) { if (!HttpCheckPriviledgedAccess()) { return; } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Prometheus")); WSContentBegin(200, CT_PLAIN); - char parameter[FLOATSZ]; // Pseudo-metric providing metadata about the running firmware version. @@ -142,52 +121,43 @@ void HandleMetrics(void) String jsonStr = json; JsonParser parser((char *)jsonStr.c_str()); JsonParserObject root = parser.getRootObject(); - if (root) - { // did JSON parsing went ok? - for (auto key1 : root) - { + if (root) { // did JSON parsing went ok? + for (auto key1 : root) { JsonParserToken value1 = key1.getValue(); - if (value1.isObject()) - { + if (value1.isObject()) { JsonParserObject Object2 = value1.getObject(); - for (auto key2 : Object2) - { + for (auto key2 : Object2) { JsonParserToken value2 = key2.getValue(); - if (value2.isObject()) - { + if (value2.isObject()) { JsonParserObject Object3 = value2.getObject(); - for (auto key3 : Object3) - { + for (auto key3 : Object3) { const char *value = key3.getValue().getStr(nullptr); - if (value != nullptr && isdigit(value[0])) - { - const char *sensor = FormatMetricName(key2.getStr()); //cleanup sensor name - const char *type = FormatMetricName(key3.getStr()); //cleanup sensor type - const char *unit = UnitfromType(type); //grab base unit corresponding to type - WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s%s gauge\ntasmota_sensors_%s%s{sensor=\"%s\"} %s\n"), type, unit, type, unit, sensor, value); //build metric as "# TYPE tasmota_sensors_%type%_%unit% gauge\ntasmotasensors_%type%_%unit%{sensor=%sensor%"} %value%"" + if (value != nullptr && isdigit(value[0])) { + String sensor = FormatMetricName(key2.getStr()); + String type = FormatMetricName(key3.getStr()); + const char *unit = UnitfromType(type.c_str()); //grab base unit corresponding to type + WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s_%s gauge\ntasmota_sensors_%s_%s{sensor=\"%s\"} %s\n"), + type.c_str(), unit, type.c_str(), unit, sensor.c_str(), value); //build metric as "# TYPE tasmota_sensors_%type%_%unit% gauge\ntasmotasensors_%type%_%unit%{sensor=%sensor%"} %value%"" + } + } + } else { + const char *value = value2.getStr(nullptr); + if (value != nullptr && isdigit(value[0])) { + String sensor = FormatMetricName(key1.getStr()); + String type = FormatMetricName(key2.getStr()); + const char *unit = UnitfromType(type.c_str()); + if (strcmp(type.c_str(), "totalstarttime") != 0) { // this metric causes prometheus of fail + WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s_%s gauge\ntasmota_sensors_%s_%s{sensor=\"%s\"} %s\n"), + type.c_str(), unit, type.c_str(), unit, sensor.c_str(), value); } } } - else - { - const char *value = value2.getStr(nullptr); - if (value != nullptr && isdigit(value[0])) - { - const char *sensor = FormatMetricName(key1.getStr()); - const char *type = FormatMetricName(key2.getStr()); - const char *unit = UnitfromType(type); - WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s%s gauge\ntasmota_sensors_%s%s{sensor=\"%s\"} %s\n"), type, unit, type, unit, sensor, value); - } - } } - } - else - { + } else { const char *value = value1.getStr(nullptr); - if (value != nullptr && isdigit(value[0] && strcmp(key1.getStr(), "Time") != 0)) //remove false 'time' metric - { - const char *sensor = FormatMetricName(key1.getStr()); - WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s gauge\ntasmota_sensors{sensor=\"%s\"} %s\n"), sensor, sensor, value); + String sensor = FormatMetricName(key1.getStr()); + if (value != nullptr && isdigit(value[0] && strcmp(sensor.c_str(), "time") != 0)) { //remove false 'time' metric + WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s gauge\ntasmota_sensors{sensor=\"%s\"} %s\n"), sensor.c_str(), sensor.c_str(), value); } } } @@ -200,8 +170,7 @@ void HandleMetrics(void) * Interface \*********************************************************************************************/ -bool Xsns75(uint8_t function) -{ +bool Xsns75(uint8_t function) { bool result = false; switch (function) {