diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6be73cfb3..615136a82 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,19 @@ All notable changes to this project will be documented in this file.
## [Unreleased] - Development
-## [12.4.0.2]
+## [12.4.0.3]
+### Added
+
+### Breaking Changed
+
+### Changed
+
+### Fixed
+- Refactor energy monitoring reducing stack usage and solve inherent exceptions and watchdogs (#18164)
+
+### Removed
+
+## [12.4.0.2] 20230317
### Added
- Support for multiple MCP23008 as switch/button/relay
- Support for multiple PCF8574 as switch/button/relay
@@ -32,8 +44,6 @@ All notable changes to this project will be documented in this file.
- Rule topic comparison (#18144)
- ESP32 energy period shows kWh value instead of Wh regression from v12.3.1.5 (#15856)
-### Removed
-
## [12.4.0.1] 20230301
### Added
- Matter read/write and commands (#18000)
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 657adff89..05d0815d8 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -110,7 +110,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
[Complete list](BUILDS.md) of available feature and sensors.
-## Changelog v12.4.0.2
+## Changelog v12.4.0.3
### Added
- Support for multiple MCP23008/MCP23017/MCP23S17 as switch/button/relay
- Support for multiple PCF8574 as switch/button/relay
@@ -143,4 +143,5 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
- TuyaMcu v1 timer integer overflow [#18048](https://github.com/arendst/Tasmota/issues/18048)
- PZEM energy monitor stabilize period on larger configs [#18103](https://github.com/arendst/Tasmota/issues/18103)
- Rule topic comparison [#18144](https://github.com/arendst/Tasmota/issues/18144)
+- Refactor energy monitoring reducing stack usage and solve inherent exceptions and watchdogs [#18164](https://github.com/arendst/Tasmota/issues/18164)
- ESP32 energy period shows kWh value instead of Wh regression from v12.3.1.5 [#15856](https://github.com/arendst/Tasmota/issues/15856)
diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h
index 78b17d960..7f0130695 100644
--- a/tasmota/include/tasmota.h
+++ b/tasmota/include/tasmota.h
@@ -200,11 +200,6 @@ const uint16_t MAX_INPUT_BUFFER_SIZE = 2048; // Max number of characters in Ardu
const uint16_t FLOATSZ = 16; // Max number of characters in float result from dtostrfd (max 32)
const uint16_t CMDSZ = 24; // Max number of characters in command
const uint16_t TOPSZ = 151; // Max number of characters in topic string
-#ifdef ESP8266
-const uint16_t GUISZ = 300; // Max number of characters in WebEnergyFormat string
-#else
-const uint16_t GUISZ = 600; // Max number of characters in WebEnergyFormat string
-#endif
#ifdef ESP8266
#ifdef PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
diff --git a/tasmota/include/tasmota_version.h b/tasmota/include/tasmota_version.h
index 6b644b6fa..678b2a337 100644
--- a/tasmota/include/tasmota_version.h
+++ b/tasmota/include/tasmota_version.h
@@ -20,6 +20,6 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
-const uint32_t VERSION = 0x0C040002; // 12.4.0.2
+const uint32_t VERSION = 0x0C040003; // 12.4.0.3
#endif // _TASMOTA_VERSION_H_
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino
index cd0afaca8..252de3f48 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino
@@ -101,6 +101,8 @@ typedef struct {
int32_t kWhtoday[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy->daily
int32_t period[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy->daily
+ char* value;
+
uint8_t fifth_second;
uint8_t command_code;
uint8_t data_valid[ENERGY_MAX_PHASES];
@@ -143,14 +145,32 @@ Ticker ticker_energy;
/********************************************************************************************/
-char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single = 0);
-char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single) {
+const uint16_t GUISZ = 300; // Max number of characters in WebEnergyFmt string
+
+bool EnergyFmtMalloc(void) {
+ if (Energy->value == nullptr) {
+ Energy->value = (char*)malloc(GUISZ);
+ if (!Energy->value) { return false; }
+ }
+ return true;
+}
+
+void EnergyFmtFree(void) {
+ free(Energy->value);
+ Energy->value = nullptr;
+}
+
+char* EnergyFmt(float* input, uint32_t resolution, uint32_t single = 0);
+char* EnergyFmt(float* input, uint32_t resolution, uint32_t single) {
// single = 0 - Energy->phase_count - xx or [xx,xx] or [xx,xx,xx]
// single = 1 - Energy->voltage_common or Energy->frequency_common - xx
// single = 2 - Sum of Energy->phase_count if SO129 0 - xx or if SO129 1 - [xx,xx,xx]
// single = 5 - single &0x03 = 1 - xx
// single = 6 - single &0x03 = 2 - [xx,xx] - used by tarriff
// single = 7 - single &0x03 = 3 - [xx,xx,xx]
+
+ if (!EnergyFmtMalloc()) { return EmptyStr; }
+
uint32_t index = (single > 3) ? single &0x03 : (0 == single) ? Energy->phase_count : 1; // 1,2,3
if (single > 2) { single = 0; } // 0,1,2
float input_sum = 0.0f;
@@ -166,19 +186,22 @@ char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t sin
index = Energy->phase_count;
}
}
- result[0] = '\0';
+ Energy->value[0] = '\0';
for (uint32_t i = 0; i < index; i++) {
- ext_snprintf_P(result, TOPSZ, PSTR("%s%s%*_f%s"), result, (0==i)?(1==index)?"":"[":",", resolution, &input[i], (index-1==i)?(1==index)?"":"]":"");
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%s%*_f%s"), Energy->value, (0==i)?(1==index)?"":"[":",", resolution, &input[i], (index-1==i)?(1==index)?"":"]":"");
}
- return result;
+ return Energy->value;
}
#ifdef USE_WEBSERVER
-char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single = 0);
-char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single) {
+char* WebEnergyFmt(float* input, uint32_t resolution, uint32_t single = 0);
+char* WebEnergyFmt(float* input, uint32_t resolution, uint32_t single) {
// single = 0 - Energy->phase_count - xx / xx / xx or multi column
// single = 1 - Energy->voltage_common or Energy->frequency_common - xx or single column using colspan (if needed)
// single = 2 - Sum of Energy->phase_count if SO129 0 - xx or single column using colspan (if needed) or if SO129 1 - xx / xx / xx or multi column
+
+ if (!EnergyFmtMalloc()) { return EmptyStr; }
+
float input_sum = 0.0f;
if (single > 1) { // Sum and/or Single column
if (!Settings->flag5.energy_phase) { // SetOption129 - (Energy) Show phase information
@@ -193,32 +216,32 @@ char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t
}
}
#ifdef USE_ENERGY_COLUMN_GUI
- ext_snprintf_P(result, GUISZ, PSTR("")); // Skip first column
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("")); // Skip first column
if ((Energy->phase_count > 1) && single) { // Need to set colspan so need new columns
//
1.23 | |
// | 1.23 | |
// | 1.23 | |
- ext_snprintf_P(result, GUISZ, PSTR("%s | %*_f | | "),
- result, (Energy->phase_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[0]);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%*_f | | "),
+ Energy->value, (Energy->phase_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[0]);
} else {
// 1.23 | |
// | 1.23 | | 1.23 | |
// | 1.23 | | 1.23 | | 1.23 | |
// | 1.23 | | 1.23 | | 1.23 | | 1.23 | |
for (uint32_t i = 0; i < Energy->phase_count; i++) {
- ext_snprintf_P(result, GUISZ, PSTR("%s | %*_f | | "),
- result, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[i]);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%*_f | | "),
+ Energy->value, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[i]);
}
}
- ext_snprintf_P(result, GUISZ, PSTR("%s"), result);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s | "), Energy->value);
#else // not USE_ENERGY_COLUMN_GUI
uint32_t index = (single) ? 1 : Energy->phase_count; // 1,2,3
- result[0] = '\0';
+ Energy->value[vidx][0] = '\0';
for (uint32_t i = 0; i < index; i++) {
- ext_snprintf_P(result, GUISZ, PSTR("%s%s%*_f"), result, (i)?" / ":"", resolution, &input[i]);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%s%*_f"), Energy->value, (i)?" / ":"", resolution, &input[i]);
}
#endif // USE_ENERGY_COLUMN_GUI
- return result;
+ return Energy->value;
}
#endif // USE_WEBSERVER
@@ -495,8 +518,7 @@ void EnergyMarginCheck(void) {
for (uint32_t phase = 0; phase < Energy->phase_count; phase++) {
power_diff_f[phase] = power_diff[phase];
}
- char value_chr[TOPSZ];
- ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFormat(value_chr, power_diff_f, 0));
+ ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFmt(power_diff_f, 0));
}
uint16_t energy_power_u = (uint16_t)(Energy->active_power[0]);
@@ -603,6 +625,7 @@ void EnergyMarginCheck(void) {
}
}
#endif // USE_ENERGY_POWER_LIMIT
+ EnergyFmtFree();
}
void EnergyMqttShow(void) {
@@ -668,10 +691,6 @@ void EnergyEverySecond(void) {
\*********************************************************************************************/
void ResponseCmndEnergyTotalYesterdayToday(void) {
- char value_chr[TOPSZ]; // Used by EnergyFormatIndex
- char value2_chr[TOPSZ];
- char value3_chr[TOPSZ];
-
float energy_yesterday_ph[3];
for (uint32_t i = 0; i < Energy->phase_count; i++) {
energy_yesterday_ph[i] = (float)Settings->energy_kWhyesterday_ph[i] / 100000;
@@ -681,16 +700,19 @@ void ResponseCmndEnergyTotalYesterdayToday(void) {
}
}
- Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"),
+ Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s"),
XdrvMailbox.command,
- EnergyFormat(value_chr, Energy->total, Settings->flag2.energy_resolution),
- EnergyFormat(value2_chr, energy_yesterday_ph, Settings->flag2.energy_resolution),
- EnergyFormat(value3_chr, Energy->daily, Settings->flag2.energy_resolution));
+ EnergyFmt(Energy->total, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s"),
+ EnergyFmt(energy_yesterday_ph, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY "\":%s"),
+ EnergyFmt(Energy->daily, Settings->flag2.energy_resolution));
if (Energy->local_energy_active_export) {
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"),
- EnergyFormat(value_chr, Energy->export_active, Settings->flag2.energy_resolution));
+ EnergyFmt(Energy->export_active, Settings->flag2.energy_resolution));
}
ResponseJsonEndEnd();
+ EnergyFmtFree();
}
void CmndEnergyTotal(void) {
@@ -1110,6 +1132,7 @@ void EnergyDrvInit(void) {
Energy = (tEnergy*)calloc(sizeof(tEnergy), 1); // Need calloc to reset registers to 0/false
if (!Energy) { return; }
+ EnergyFmtFree();
// Energy->voltage_common = false;
// Energy->frequency_common = false;
// Energy->use_overtemp = false;
@@ -1165,17 +1188,19 @@ void EnergySnsInit(void)
}
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_SNS1[] PROGMEM =
- "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}"
- "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}"
+const char HTTP_ENERGY_POWERUSAGE_APPARENT[] PROGMEM =
+ "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}";
+const char HTTP_ENERGY_POWERUSAGE_REACTIVE[] PROGMEM =
+ "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}";
+const char HTTP_ENERGY_POWER_FACTOR[] PROGMEM =
"{s}" D_POWER_FACTOR "{m}%s{e}";
-
-const char HTTP_ENERGY_SNS2[] PROGMEM =
- "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
- "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
+const char HTTP_ENERGY_TODAY[] PROGMEM =
+ "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
+const char HTTP_ENERGY_YESTERDAY[] PROGMEM =
+ "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
+const char HTTP_ENERGY_TOTAL[] PROGMEM =
"{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = | , {m} = | , {e} = |
-
-const char HTTP_ENERGY_SNS3[] PROGMEM =
+const char HTTP_ENERGY_EXPORT_ACTIVE[] PROGMEM =
"{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
#endif // USE_WEBSERVER
@@ -1256,34 +1281,31 @@ void EnergyShow(bool json) {
energy_tariff = true;
}
- char value_chr[GUISZ]; // Used by EnergyFormatIndex
- char value2_chr[GUISZ];
- char value3_chr[GUISZ];
-
if (json) {
bool show_energy_period = (0 == TasmotaGlobal.tele_period);
ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s"),
GetDateAndTime(DT_ENERGY).c_str(),
- EnergyFormat(value_chr, Energy->total, Settings->flag2.energy_resolution, 2));
+ EnergyFmt(Energy->total, Settings->flag2.energy_resolution, 2));
if (energy_tariff) {
ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL D_CMND_TARIFF "\":%s"),
- EnergyFormat(value_chr, energy_usage, Settings->flag2.energy_resolution, 6));
+ EnergyFmt(energy_usage, Settings->flag2.energy_resolution, 6));
}
- ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"),
- EnergyFormat(value_chr, energy_yesterday_ph, Settings->flag2.energy_resolution, 2),
- EnergyFormat(value2_chr, Energy->daily, Settings->flag2.energy_resolution, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s"),
+ EnergyFmt(energy_yesterday_ph, Settings->flag2.energy_resolution, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY "\":%s"),
+ EnergyFmt(Energy->daily, Settings->flag2.energy_resolution, 2));
/*
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
if (!isnan(Energy->import_active[0])) {
ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s"),
- EnergyFormat(value_chr, Energy->import_active, Settings->flag2.energy_resolution));
+ EnergyFmt(Energy->import_active, Settings->flag2.energy_resolution));
if (energy_tariff) {
ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT D_CMND_TARIFF "\":%s"),
- EnergyFormat(value_chr, energy_return, Settings->flag2.energy_resolution, 6));
+ EnergyFmt(energy_return, Settings->flag2.energy_resolution, 6));
}
}
#endif // SDM630_IMPORT || SDM72_IMPEXP
@@ -1291,13 +1313,16 @@ void EnergyShow(bool json) {
if (!isnan(Energy->export_active[0])) {
uint32_t single = (!isnan(Energy->export_active[1]) && !isnan(Energy->export_active[2])) ? 0 : 1;
- ResponseAppend_P(PSTR(",\"" D_JSON_TODAY_SUM_IMPORT "\":%s,\"" D_JSON_TODAY_SUM_EXPORT "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s"),
- EnergyFormat(value_chr, &Energy->daily_sum_import_balanced, Settings->flag2.energy_resolution, 1),
- EnergyFormat(value2_chr, &Energy->daily_sum_export_balanced, Settings->flag2.energy_resolution, 1),
- EnergyFormat(value3_chr, Energy->export_active, Settings->flag2.energy_resolution, single));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY_SUM_IMPORT "\":%s"),
+ EnergyFmt(&Energy->daily_sum_import_balanced, Settings->flag2.energy_resolution, 1));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY_SUM_EXPORT "\":%s"),
+ EnergyFmt(&Energy->daily_sum_export_balanced, Settings->flag2.energy_resolution, 1));
+ ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"),
+ EnergyFmt(Energy->export_active, Settings->flag2.energy_resolution, single));
+
if (energy_tariff) {
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT D_CMND_TARIFF "\":%s"),
- EnergyFormat(value_chr, energy_return, Settings->flag2.energy_resolution, 6));
+ EnergyFmt(energy_return, Settings->flag2.energy_resolution, 6));
}
}
@@ -1308,30 +1333,32 @@ void EnergyShow(bool json) {
Energy->period[i] = RtcSettings.energy_kWhtoday_ph[i];
}
ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"),
- EnergyFormat(value_chr, energy_period, Settings->flag2.wattage_resolution));
+ EnergyFmt(energy_period, Settings->flag2.wattage_resolution));
}
ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"),
- EnergyFormat(value_chr, Energy->active_power, Settings->flag2.wattage_resolution));
+ EnergyFmt(Energy->active_power, Settings->flag2.wattage_resolution));
if (!Energy->type_dc) {
if (Energy->current_available && Energy->voltage_available) {
- ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"),
- EnergyFormat(value_chr, apparent_power, Settings->flag2.wattage_resolution),
- EnergyFormat(value2_chr, reactive_power, Settings->flag2.wattage_resolution),
- EnergyFormat(value3_chr, power_factor, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s"),
+ EnergyFmt(apparent_power, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_REACTIVE_POWERUSAGE "\":%s"),
+ EnergyFmt(reactive_power, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_POWERFACTOR "\":%s"),
+ EnergyFmt(power_factor, 2));
}
if (!isnan(Energy->frequency[0])) {
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"),
- EnergyFormat(value_chr, Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
+ EnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
}
}
if (Energy->voltage_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"),
- EnergyFormat(value_chr, Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
+ EnergyFmt(Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
}
if (Energy->current_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"),
- EnergyFormat(value_chr, Energy->current, Settings->flag2.current_resolution));
+ EnergyFmt(Energy->current, Settings->flag2.current_resolution));
}
XnrgCall(FUNC_JSON_APPEND);
ResponseJsonEnd();
@@ -1388,37 +1415,38 @@ void EnergyShow(bool json) {
WSContentSend_P(PSTR("
{t}{s} | ")); // First column is empty ({t} = , {s} = )
bool label_o = voltage_common;
bool no_label = (1 == Energy->phase_count);
+ char number[4];
for (uint32_t i = 0; i < Energy->phase_count; i++) {
- WSContentSend_P(PSTR(" | %s%s | | "), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
+ WSContentSend_P(PSTR("%s%s | | "), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, number, 10));
}
WSContentSend_P(PSTR("{e}")); // Last column is units ({e} = |
)
#endif // USE_ENERGY_COLUMN_GUI
if (Energy->voltage_available) {
- WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFormat(value_chr, Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
+ WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFmt(Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
}
if (!Energy->type_dc) {
if (!isnan(Energy->frequency[0])) {
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"),
- WebEnergyFormat(value_chr, Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
+ WebEnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
}
}
if (Energy->current_available) {
- WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFormat(value_chr, Energy->current, Settings->flag2.current_resolution));
+ WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFmt(Energy->current, Settings->flag2.current_resolution));
}
- WSContentSend_PD(HTTP_SNS_POWER, WebEnergyFormat(value_chr, Energy->active_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_SNS_POWER, WebEnergyFmt(Energy->active_power, Settings->flag2.wattage_resolution));
if (!Energy->type_dc) {
if (Energy->current_available && Energy->voltage_available) {
- WSContentSend_PD(HTTP_ENERGY_SNS1, WebEnergyFormat(value_chr, apparent_power, Settings->flag2.wattage_resolution),
- WebEnergyFormat(value2_chr, reactive_power, Settings->flag2.wattage_resolution),
- WebEnergyFormat(value3_chr, power_factor, 2));
+ WSContentSend_PD(HTTP_ENERGY_POWERUSAGE_APPARENT, WebEnergyFmt(apparent_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_ENERGY_POWERUSAGE_REACTIVE, WebEnergyFmt(reactive_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_ENERGY_POWER_FACTOR, WebEnergyFmt(power_factor, 2));
}
}
- WSContentSend_PD(HTTP_ENERGY_SNS2, WebEnergyFormat(value_chr, Energy->daily, Settings->flag2.energy_resolution, 2),
- WebEnergyFormat(value2_chr, energy_yesterday_ph, Settings->flag2.energy_resolution, 2),
- WebEnergyFormat(value3_chr, Energy->total, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_TODAY, WebEnergyFmt(Energy->daily, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_YESTERDAY, WebEnergyFmt(energy_yesterday_ph, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_TOTAL, WebEnergyFmt(Energy->total, Settings->flag2.energy_resolution, 2));
if (!isnan(Energy->export_active[0])) {
uint32_t single = (!isnan(Energy->export_active[1]) && !isnan(Energy->export_active[2])) ? 2 : 1;
- WSContentSend_PD(HTTP_ENERGY_SNS3, WebEnergyFormat(value_chr, Energy->export_active, Settings->flag2.energy_resolution, single));
+ WSContentSend_PD(HTTP_ENERGY_EXPORT_ACTIVE, WebEnergyFmt(Energy->export_active, Settings->flag2.energy_resolution, single));
}
#ifdef USE_ENERGY_COLUMN_GUI
XnrgCall(FUNC_WEB_COL_SENSOR);
@@ -1427,6 +1455,7 @@ void EnergyShow(bool json) {
XnrgCall(FUNC_WEB_SENSOR);
#endif // USE_WEBSERVER
}
+ EnergyFmtFree();
}
/*********************************************************************************************\
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino
index 122c1a62b..2edf08b33 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino
@@ -159,6 +159,8 @@ typedef struct {
int32_t kWhtoday[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy->daily
// Local only
+ char* value;
+
float daily_kWh[ENERGY_MAX_PHASES]; // 123.123 kWh
float energy_today_offset_kWh[ENERGY_MAX_PHASES]; // 123.12312 kWh = Energy->daily
float period_kWh[ENERGY_MAX_PHASES]; // 123.12312 kWh = Energy->daily
@@ -370,14 +372,32 @@ void EnergySettingsSave(void) {
/********************************************************************************************/
-char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single = 0);
-char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single) {
+const uint16_t GUISZ = 600; // Max number of characters in WebEnergyFmt string
+
+bool EnergyFmtMalloc(void) {
+ if (Energy->value == nullptr) {
+ Energy->value = (char*)malloc(GUISZ);
+ if (!Energy->value) { return false; }
+ }
+ return true;
+}
+
+void EnergyFmtFree(void) {
+ free(Energy->value);
+ Energy->value = nullptr;
+}
+
+char* EnergyFmt(float* input, uint32_t resolution, uint32_t single = 0);
+char* EnergyFmt(float* input, uint32_t resolution, uint32_t single) {
// single = 0 - Energy->phase_count - xx or [xx,xx] or [xx,xx,xx]
// single = 1 - Energy->voltage_common or Energy->frequency_common - xx
// single = 2 - Sum of Energy->phase_count if SO129 0 - xx or if SO129 1 - [xx,xx,xx]
// single = 5 - single &0x03 = 1 - xx
// single = 6 - single &0x03 = 2 - [xx,xx] - used by tarriff
// single = 7 - single &0x03 = 3 - [xx,xx,xx]
+
+ if (!EnergyFmtMalloc()) { return EmptyStr; }
+
uint32_t index = (single > 3) ? single &0x03 : (0 == single) ? Energy->phase_count : 1; // 1,2,3
if (single > 2) { single = 0; } // 0,1,2
float input_sum = 0.0f;
@@ -393,19 +413,22 @@ char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t sin
index = Energy->phase_count;
}
}
- result[0] = '\0';
+ Energy->value[0] = '\0';
for (uint32_t i = 0; i < index; i++) {
- ext_snprintf_P(result, GUISZ, PSTR("%s%s%*_f%s"), result, (0==i)?(1==index)?"":"[":",", resolution, &input[i], (index-1==i)?(1==index)?"":"]":"");
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%s%*_f%s"), Energy->value, (0==i)?(1==index)?"":"[":",", resolution, &input[i], (index-1==i)?(1==index)?"":"]":"");
}
- return result;
+ return Energy->value;
}
#ifdef USE_WEBSERVER
-char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single = 0);
-char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t single) {
+char* WebEnergyFmt(float* input, uint32_t resolution, uint32_t single = 0);
+char* WebEnergyFmt(float* input, uint32_t resolution, uint32_t single) {
// single = 0 - Energy->phase_count - xx / xx / xx or multi column
// single = 1 - Energy->voltage_common or Energy->frequency_common - xx or single column using colspan (if needed)
// single = 2 - Sum of Energy->phase_count if SO129 0 - xx or single column using colspan (if needed) or if SO129 1 - xx / xx / xx or multi column
+
+ if (!EnergyFmtMalloc()) { return EmptyStr; }
+
float input_sum = 0.0f;
if (single > 1) { // Sum and/or Single column
if (!Settings->flag5.energy_phase) { // SetOption129 - (Energy) Show phase information
@@ -420,32 +443,32 @@ char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t
}
}
#ifdef USE_ENERGY_COLUMN_GUI
- ext_snprintf_P(result, GUISZ, PSTR("")); // Skip first column
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("")); // Skip first column
if ((Energy->gui_count > 1) && single) { // Need to set colspan so need new columns
// 1.23 | |
// | 1.23 | |
// | 1.23 | |
- ext_snprintf_P(result, GUISZ, PSTR("%s | %*_f | | "),
- result, (Energy->gui_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[Energy->gui_indirect[0]]);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%*_f | | "),
+ Energy->value, (Energy->gui_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[Energy->gui_indirect[0]]);
} else {
// 1.23 | |
// | 1.23 | | 1.23 | |
// | 1.23 | | 1.23 | | 1.23 | |
// | 1.23 | | 1.23 | | 1.23 | | 1.23 | |
for (uint32_t i = 0; i < Energy->gui_count; i++) {
- ext_snprintf_P(result, GUISZ, PSTR("%s | %*_f | | "),
- result, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[Energy->gui_indirect[Energy->gui_offset +i]]);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%*_f | | "),
+ Energy->value, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[Energy->gui_indirect[Energy->gui_offset +i]]);
}
}
- ext_snprintf_P(result, GUISZ, PSTR("%s"), result);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s | "), Energy->value);
#else // not USE_ENERGY_COLUMN_GUI
uint32_t index = (single) ? 1 : Energy->phase_count; // 1,2,3
- result[0] = '\0';
+ Energy->value[0] = '\0';
for (uint32_t i = 0; i < index; i++) {
- ext_snprintf_P(result, GUISZ, PSTR("%s%s%*_f"), result, (i)?" / ":"", resolution, &input[i]);
+ ext_snprintf_P(Energy->value, GUISZ, PSTR("%s%s%*_f"), Energy->value, (i)?" / ":"", resolution, &input[i]);
}
#endif // USE_ENERGY_COLUMN_GUI
- return result;
+ return Energy->value;
}
#endif // USE_WEBSERVER
@@ -717,8 +740,7 @@ void EnergyMarginCheck(void) {
for (uint32_t phase = 0; phase < Energy->phase_count; phase++) {
power_diff_f[phase] = power_diff[phase];
}
- char value_chr[GUISZ];
- ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFormat(value_chr, power_diff_f, 0));
+ ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFmt(power_diff_f, 0));
}
uint16_t energy_power_u = (uint16_t)(Energy->active_power[0]);
@@ -823,6 +845,7 @@ void EnergyMarginCheck(void) {
SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY);
}
}
+ EnergyFmtFree();
}
void EnergyMqttShow(void) {
@@ -885,10 +908,6 @@ void EnergyEverySecond(void) {
\*********************************************************************************************/
void ResponseCmndEnergyTotalYesterdayToday(void) {
- char value_chr[GUISZ]; // Used by EnergyFormatIndex
- char value2_chr[GUISZ];
- char value3_chr[GUISZ];
-
float energy_yesterday_kWh[3];
for (uint32_t i = 0; i < Energy->phase_count; i++) {
energy_yesterday_kWh[i] = Energy->Settings.energy_yesterday_kWh[i];
@@ -898,16 +917,19 @@ void ResponseCmndEnergyTotalYesterdayToday(void) {
}
}
- Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"),
+ Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s"),
XdrvMailbox.command,
- EnergyFormat(value_chr, Energy->total, Settings->flag2.energy_resolution),
- EnergyFormat(value2_chr, energy_yesterday_kWh, Settings->flag2.energy_resolution),
- EnergyFormat(value3_chr, Energy->daily_kWh, Settings->flag2.energy_resolution));
+ EnergyFmt(Energy->total, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s"),
+ EnergyFmt(energy_yesterday_kWh, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY "\":%s"),
+ EnergyFmt(Energy->daily_kWh, Settings->flag2.energy_resolution));
if (Energy->local_energy_active_export) {
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"),
- EnergyFormat(value_chr, Energy->export_active, Settings->flag2.energy_resolution));
+ EnergyFmt(Energy->export_active, Settings->flag2.energy_resolution));
}
ResponseJsonEndEnd();
+ EnergyFmtFree();
}
void CmndEnergyDisplay(void) {
@@ -1345,6 +1367,7 @@ void EnergyDrvInit(void) {
EnergySettingsLoad(0);
EnergyRtcSettingsLoad();
+ EnergyFmtFree();
// Energy->voltage_common = false;
// Energy->frequency_common = false;
// Energy->use_overtemp = false;
@@ -1399,17 +1422,19 @@ void EnergySnsInit(void) {
}
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_SNS1[] PROGMEM =
- "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}"
- "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}"
+const char HTTP_ENERGY_POWERUSAGE_APPARENT[] PROGMEM =
+ "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}";
+const char HTTP_ENERGY_POWERUSAGE_REACTIVE[] PROGMEM =
+ "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}";
+const char HTTP_ENERGY_POWER_FACTOR[] PROGMEM =
"{s}" D_POWER_FACTOR "{m}%s{e}";
-
-const char HTTP_ENERGY_SNS2[] PROGMEM =
- "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
- "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
+const char HTTP_ENERGY_TODAY[] PROGMEM =
+ "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
+const char HTTP_ENERGY_YESTERDAY[] PROGMEM =
+ "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
+const char HTTP_ENERGY_TOTAL[] PROGMEM =
"{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = | , {m} = | , {e} = |
-
-const char HTTP_ENERGY_SNS3[] PROGMEM =
+const char HTTP_ENERGY_EXPORT_ACTIVE[] PROGMEM =
"{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
#endif // USE_WEBSERVER
@@ -1490,34 +1515,31 @@ void EnergyShow(bool json) {
energy_tariff = true;
}
- char value_chr[GUISZ]; // Used by EnergyFormatIndex
- char value2_chr[GUISZ];
- char value3_chr[GUISZ];
-
if (json) {
bool show_energy_period = (0 == TasmotaGlobal.tele_period);
ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s"),
GetDateAndTime(DT_ENERGY).c_str(),
- EnergyFormat(value_chr, Energy->total, Settings->flag2.energy_resolution, 2));
+ EnergyFmt(Energy->total, Settings->flag2.energy_resolution, 2));
if (energy_tariff) {
ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL D_CMND_TARIFF "\":%s"),
- EnergyFormat(value_chr, energy_usage_kWh, Settings->flag2.energy_resolution, 6));
+ EnergyFmt(energy_usage_kWh, Settings->flag2.energy_resolution, 6));
}
- ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"),
- EnergyFormat(value_chr, energy_yesterday_kWh, Settings->flag2.energy_resolution, 2),
- EnergyFormat(value2_chr, Energy->daily_kWh, Settings->flag2.energy_resolution, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s"),
+ EnergyFmt(energy_yesterday_kWh, Settings->flag2.energy_resolution, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY "\":%s"),
+ EnergyFmt(Energy->daily_kWh, Settings->flag2.energy_resolution, 2));
/*
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
if (!isnan(Energy->import_active[0])) {
ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s"),
- EnergyFormat(value_chr, Energy->import_active, Settings->flag2.energy_resolution));
+ EnergyFmt(Energy->import_active, Settings->flag2.energy_resolution));
if (energy_tariff) {
ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT D_CMND_TARIFF "\":%s"),
- EnergyFormat(value_chr, energy_return_kWh, Settings->flag2.energy_resolution, 6));
+ EnergyFmt(energy_return_kWh, Settings->flag2.energy_resolution, 6));
}
}
#endif // SDM630_IMPORT || SDM72_IMPEXP
@@ -1525,13 +1547,15 @@ void EnergyShow(bool json) {
if (!isnan(Energy->export_active[0])) {
uint32_t single = (!isnan(Energy->export_active[1]) && !isnan(Energy->export_active[2])) ? 0 : 1;
- ResponseAppend_P(PSTR(",\"" D_JSON_TODAY_SUM_IMPORT "\":%s,\"" D_JSON_TODAY_SUM_EXPORT "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s"),
- EnergyFormat(value_chr, &Energy->daily_sum_import_balanced, Settings->flag2.energy_resolution, 1),
- EnergyFormat(value2_chr, &Energy->daily_sum_export_balanced, Settings->flag2.energy_resolution, 1),
- EnergyFormat(value3_chr, Energy->export_active, Settings->flag2.energy_resolution, single));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY_SUM_IMPORT "\":%s"),
+ EnergyFmt(&Energy->daily_sum_import_balanced, Settings->flag2.energy_resolution, 1));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TODAY_SUM_EXPORT "\":%s"),
+ EnergyFmt(&Energy->daily_sum_export_balanced, Settings->flag2.energy_resolution, 1));
+ ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"),
+ EnergyFmt(Energy->export_active, Settings->flag2.energy_resolution, single));
if (energy_tariff) {
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT D_CMND_TARIFF "\":%s"),
- EnergyFormat(value_chr, energy_return_kWh, Settings->flag2.energy_resolution, 6));
+ EnergyFmt(energy_return_kWh, Settings->flag2.energy_resolution, 6));
}
}
@@ -1542,30 +1566,32 @@ void EnergyShow(bool json) {
Energy->period_kWh[i] = RtcEnergySettings.energy_today_kWh[i];
}
ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"),
- EnergyFormat(value_chr, energy_period, Settings->flag2.wattage_resolution));
+ EnergyFmt(energy_period, Settings->flag2.wattage_resolution));
}
ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"),
- EnergyFormat(value_chr, Energy->active_power, Settings->flag2.wattage_resolution));
+ EnergyFmt(Energy->active_power, Settings->flag2.wattage_resolution));
if (!Energy->type_dc) {
if (Energy->current_available && Energy->voltage_available) {
- ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"),
- EnergyFormat(value_chr, apparent_power, Settings->flag2.wattage_resolution),
- EnergyFormat(value2_chr, reactive_power, Settings->flag2.wattage_resolution),
- EnergyFormat(value3_chr, power_factor, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s"),
+ EnergyFmt(apparent_power, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_REACTIVE_POWERUSAGE "\":%s"),
+ EnergyFmt(reactive_power, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_POWERFACTOR "\":%s"),
+ EnergyFmt(power_factor, 2));
}
if (!isnan(Energy->frequency[0])) {
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"),
- EnergyFormat(value_chr, Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
+ EnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
}
}
if (Energy->voltage_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"),
- EnergyFormat(value_chr, Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
+ EnergyFmt(Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
}
if (Energy->current_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"),
- EnergyFormat(value_chr, Energy->current, Settings->flag2.current_resolution));
+ EnergyFmt(Energy->current, Settings->flag2.current_resolution));
}
XnrgCall(FUNC_JSON_APPEND);
ResponseJsonEnd();
@@ -1667,39 +1693,40 @@ void EnergyShow(bool json) {
// {s} | Head1 | | Head2 | | Head3 | | Head4 | | {e}
WSContentSend_P(PSTR("{t}{s} | | ")); // First column is empty ({t} = , {s} = )
bool no_label = (1 == Energy->phase_count);
+ char number[4];
for (uint32_t i = 0; i < Energy->gui_count; i++) {
WSContentSend_P(PSTR(" | %s%s | | "),
(no_label) ? "" : (label_o) ? "O" : "L",
- (no_label) ? "" : itoa(relays[Energy->gui_offset +i], value_chr, 10));
+ (no_label) ? "" : itoa(relays[Energy->gui_offset +i], number, 10));
}
WSContentSend_P(PSTR("{e}")); // Last column is units ({e} = |
)
#endif // USE_ENERGY_COLUMN_GUI
if (Energy->voltage_available) {
- WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFormat(value_chr, Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
+ WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFmt(Energy->voltage, Settings->flag2.voltage_resolution, voltage_common));
}
if (!Energy->type_dc) {
if (!isnan(Energy->frequency[0])) {
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"),
- WebEnergyFormat(value_chr, Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
+ WebEnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common));
}
}
if (Energy->current_available) {
- WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFormat(value_chr, Energy->current, Settings->flag2.current_resolution));
+ WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFmt(Energy->current, Settings->flag2.current_resolution));
}
- WSContentSend_PD(HTTP_SNS_POWER, WebEnergyFormat(value_chr, Energy->active_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_SNS_POWER, WebEnergyFmt(Energy->active_power, Settings->flag2.wattage_resolution));
if (!Energy->type_dc) {
if (Energy->current_available && Energy->voltage_available) {
- WSContentSend_PD(HTTP_ENERGY_SNS1, WebEnergyFormat(value_chr, apparent_power, Settings->flag2.wattage_resolution),
- WebEnergyFormat(value2_chr, reactive_power, Settings->flag2.wattage_resolution),
- WebEnergyFormat(value3_chr, power_factor, 2));
+ WSContentSend_PD(HTTP_ENERGY_POWERUSAGE_APPARENT, WebEnergyFmt(apparent_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_ENERGY_POWERUSAGE_REACTIVE, WebEnergyFmt(reactive_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_ENERGY_POWER_FACTOR, WebEnergyFmt(power_factor, 2));
}
}
- WSContentSend_PD(HTTP_ENERGY_SNS2, WebEnergyFormat(value_chr, Energy->daily_kWh, Settings->flag2.energy_resolution, 2),
- WebEnergyFormat(value2_chr, energy_yesterday_kWh, Settings->flag2.energy_resolution, 2),
- WebEnergyFormat(value3_chr, Energy->total, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_TODAY, WebEnergyFmt(Energy->daily_kWh, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_YESTERDAY, WebEnergyFmt(energy_yesterday_kWh, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_TOTAL, WebEnergyFmt(Energy->total, Settings->flag2.energy_resolution, 2));
if (!isnan(Energy->export_active[0])) {
uint32_t single = (!isnan(Energy->export_active[1]) && !isnan(Energy->export_active[2])) ? 2 : 1;
- WSContentSend_PD(HTTP_ENERGY_SNS3, WebEnergyFormat(value_chr, Energy->export_active, Settings->flag2.energy_resolution, single));
+ WSContentSend_PD(HTTP_ENERGY_EXPORT_ACTIVE, WebEnergyFmt(Energy->export_active, Settings->flag2.energy_resolution, single));
}
#ifdef USE_ENERGY_COLUMN_GUI
@@ -1710,6 +1737,7 @@ void EnergyShow(bool json) {
#endif // USE_WEBSERVER
}
}
+ EnergyFmtFree();
}
#ifdef USE_WEBSERVER
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino b/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino
index 5a02108eb..fd4e99cf7 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino
@@ -60,6 +60,7 @@
#define D_CMND_I2CSTRETCH "I2CStretch"
#define D_CMND_I2CCLOCK "I2CClock"
#define D_CMND_SERBUFF "SerBufSize"
+#define D_CMND_SOSET "SOSet"
const char kDebugCommands[] PROGMEM = "|" // No prefix
D_CMND_MEMDUMP "|" D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|"
@@ -77,8 +78,9 @@ const char kDebugCommands[] PROGMEM = "|" // No prefix
#endif
D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|"
#ifdef USE_I2C
- D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK
+ D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK "|"
#endif
+ D_CMND_SOSET
;
void (* const DebugCommand[])(void) PROGMEM = {
@@ -97,8 +99,9 @@ void (* const DebugCommand[])(void) PROGMEM = {
#endif
&CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump,
#ifdef USE_I2C
- &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock
+ &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock,
#endif
+ &CmndSoSet
};
uint32_t CPU_loops = 0;
@@ -209,23 +212,41 @@ extern "C" {
extern cont_t* g_pcont;
}
-void DebugFreeMem(void)
-{
+void DebugFreeMem(void) {
register uint32_t *sp asm("a1");
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data);
}
+uint32_t FreeStack(void) {
+ register uint32_t *sp asm("a1");
+ return 4 * (sp - g_pcont->stack);
+}
+
+void AddLogMem(const char* function) {
+ register uint32_t *sp asm("a1");
+ AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "== %s FreeRam %d, FreeStack %d"), function, ESP.getFreeHeap(), 4 * (sp - g_pcont->stack));
+}
+
#endif // ESP8266
#ifdef ESP32
-void DebugFreeMem(void)
-{
+void DebugFreeMem(void) {
register uint8_t *sp asm("a1");
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), sp - pxTaskGetStackStart(NULL), XdrvMailbox.data);
}
+uint32_t FreeStack(void) {
+ register uint8_t *sp asm("a1");
+ return sp - pxTaskGetStackStart(NULL);
+}
+
+void AddLogMem(const char* function) {
+ register uint8_t *sp asm("a1");
+ AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "== %s FreeRam %d, FreeStack %d"), function, ESP.getFreeHeap(), sp - pxTaskGetStackStart(NULL));
+}
+
#endif // ESP8266 - ESP32
/*******************************************************************************************/
@@ -724,6 +745,52 @@ void CmndI2cClock(void)
}
#endif // USE_I2C
+void CmndSoSet(void) {
+ // Set option data as 32-bit hex value
+ // SoSet1 0x5400401B
+ if ((XdrvMailbox.index >= 1) && (XdrvMailbox.index <= 5)) {
+ uint32_t option = XdrvMailbox.index;
+ uint32_t data;
+ switch (option) {
+ case 1:
+ data = Settings->flag.data; // SetOption0 .. 31
+ break;
+ case 2:
+ data = Settings->flag3.data; // SetOption50 .. 81
+ break;
+ case 3:
+ data = Settings->flag4.data; // SetOption82 .. 113
+ break;
+ case 4:
+ data = Settings->flag5.data; // SetOption114 .. 145
+ break;
+ case 5:
+ data = Settings->flag6.data; // SetOption146 .. 177
+ }
+ if (XdrvMailbox.data_len > 0) {
+ char *p;
+ data = strtoul(XdrvMailbox.data, &p, 0); // decimal, octal (0) or hex (0x)
+ switch (option) {
+ case 1:
+ Settings->flag.data = data; // SetOption0 .. 31
+ break;
+ case 2:
+ Settings->flag3.data = data; // SetOption50 .. 81
+ break;
+ case 3:
+ Settings->flag4.data = data; // SetOption82 .. 113
+ break;
+ case 4:
+ Settings->flag5.data = data; // SetOption114 .. 145
+ break;
+ case 5: Settings->flag6.data = data; // SetOption146 .. 177
+ }
+// TasmotaGlobal.restart_flag = 2; // Activate some SetOptions
+ }
+ Response_P(PSTR("{\"%s%d\":\"%08X\"}"), XdrvMailbox.command, XdrvMailbox.index, data);
+ }
+}
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino
index 66dc60856..b13ad4fbd 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino
@@ -2300,14 +2300,12 @@ void SSPMEnergyShow(bool json) {
WSContentSend_PD(HTTP_SNS_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[0], Settings->flag2.voltage_resolution, indirect, offset, count));
WSContentSend_PD(HTTP_SNS_CURRENT, SSPMEnergyFormat(value_chr, Sspm->current[0], Settings->flag2.current_resolution, indirect, offset, count));
WSContentSend_PD(HTTP_SNS_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[0], Settings->flag2.wattage_resolution, indirect, offset, count));
- char valu2_chr[SSPM_SIZE];
- char valu3_chr[SSPM_SIZE];
- WSContentSend_PD(HTTP_ENERGY_SNS1, SSPMEnergyFormat(value_chr, Sspm->apparent_power[0], Settings->flag2.wattage_resolution, indirect, offset, count),
- SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[0], Settings->flag2.wattage_resolution, indirect, offset, count),
- SSPMEnergyFormat(valu3_chr, Sspm->power_factor[0], 2, indirect, offset, count));
- WSContentSend_PD(HTTP_ENERGY_SNS2, SSPMEnergyFormat(value_chr, Sspm->energy_today[0], Settings->flag2.energy_resolution, indirect, offset, count),
- SSPMEnergyFormat(valu2_chr, Sspm->Settings.energy_yesterday[0], Settings->flag2.energy_resolution, indirect, offset, count),
- SSPMEnergyFormat(valu3_chr, Sspm->energy_total[0], Settings->flag2.energy_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_ENERGY_POWERUSAGE_APPARENT, SSPMEnergyFormat(value_chr, Sspm->apparent_power[0], Settings->flag2.wattage_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_ENERGY_POWERUSAGE_REACTIVE, SSPMEnergyFormat(value_chr, Sspm->reactive_power[0], Settings->flag2.wattage_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_ENERGY_POWER_FACTOR, SSPMEnergyFormat(value_chr, Sspm->power_factor[0], 2, indirect, offset, count));
+ WSContentSend_PD(HTTP_ENERGY_TODAY, SSPMEnergyFormat(value_chr, Sspm->energy_today[0], Settings->flag2.energy_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_ENERGY_YESTERDAY, SSPMEnergyFormat(value_chr, Sspm->Settings.energy_yesterday[0], Settings->flag2.energy_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_ENERGY_TOTAL, SSPMEnergyFormat(value_chr, Sspm->energy_total[0], Settings->flag2.energy_resolution, indirect, offset, count));
WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR
}
#endif // USE_WEBSERVER
diff --git a/tasmota/tasmota_xnrg_energy/xnrg_08_sdm120.ino b/tasmota/tasmota_xnrg_energy/xnrg_08_sdm120.ino
index e3c5b9b76..99b5b0804 100644
--- a/tasmota/tasmota_xnrg_energy/xnrg_08_sdm120.ino
+++ b/tasmota/tasmota_xnrg_energy/xnrg_08_sdm120.ino
@@ -204,55 +204,32 @@ void Sdm220Reset(void)
}
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_SDM220[] PROGMEM =
- "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"
- "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"
+const char HTTP_ENERGY_SDM220_IMPORT_REACTIVE[] PROGMEM =
+ "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}";
+const char HTTP_ENERGY_SDM220_EXPORT_REACTIVE[] PROGMEM =
+ "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}";
+const char HTTP_ENERGY_SDM220_PHASE_ANGLE[] PROGMEM =
"{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}";
#endif // USE_WEBSERVER
-/*
void Sdm220Show(bool json) {
if (isnan(Sdm120.import_active)) { return; }
- char import_active_chr[FLOATSZ];
- dtostrfd(Sdm120.import_active, Settings->flag2.energy_resolution, import_active_chr);
- char import_reactive_chr[FLOATSZ];
- dtostrfd(Sdm120.import_reactive, Settings->flag2.energy_resolution, import_reactive_chr);
- char export_reactive_chr[FLOATSZ];
- dtostrfd(Sdm120.export_reactive, Settings->flag2.energy_resolution, export_reactive_chr);
- char phase_angle_chr[FLOATSZ];
- dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr);
-
if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"),
- import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr);
+ ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s"),
+ EnergyFmt(&Sdm120.import_active, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_REACTIVE "\":%s"),
+ EnergyFmt(&Sdm120.import_reactive, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_REACTIVE "\":%s"),
+ EnergyFmt(&Sdm120.export_reactive, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_PHASE_ANGLE "\":%s"),
+ EnergyFmt(&Sdm120.phase_angle, 2));
#ifdef USE_WEBSERVER
} else {
- WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr);
-#endif // USE_WEBSERVER
- }
-}
-*/
+ WSContentSend_PD(HTTP_ENERGY_SDM220_IMPORT_REACTIVE, WebEnergyFmt(&Sdm120.import_reactive, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_SDM220_EXPORT_REACTIVE, WebEnergyFmt(&Sdm120.export_reactive, Settings->flag2.energy_resolution, 2));
+ WSContentSend_PD(HTTP_ENERGY_SDM220_PHASE_ANGLE, WebEnergyFmt(&Sdm120.phase_angle, 2));
-void Sdm220Show(bool json) {
- if (isnan(Sdm120.import_active)) { return; }
-
- char value_chr[GUISZ];
- char value2_chr[GUISZ];
- char value3_chr[GUISZ];
- char value4_chr[GUISZ];
-
- if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"),
- EnergyFormat(value_chr, &Sdm120.import_active, Settings->flag2.energy_resolution),
- EnergyFormat(value2_chr, &Sdm120.import_reactive, Settings->flag2.energy_resolution),
- EnergyFormat(value3_chr, &Sdm120.export_reactive, Settings->flag2.energy_resolution),
- EnergyFormat(value4_chr, &Sdm120.phase_angle, 2));
-#ifdef USE_WEBSERVER
- } else {
- WSContentSend_PD(HTTP_ENERGY_SDM220, WebEnergyFormat(value_chr, &Sdm120.import_reactive, Settings->flag2.energy_resolution, 2),
- WebEnergyFormat(value2_chr, &Sdm120.export_reactive, Settings->flag2.energy_resolution, 2),
- WebEnergyFormat(value3_chr, &Sdm120.phase_angle, 2));
#endif // USE_WEBSERVER
}
}
diff --git a/tasmota/tasmota_xnrg_energy/xnrg_13_fif_le01mr.ino b/tasmota/tasmota_xnrg_energy/xnrg_13_fif_le01mr.ino
index 5be6cc2b2..d68bd6a9b 100644
--- a/tasmota/tasmota_xnrg_energy/xnrg_13_fif_le01mr.ino
+++ b/tasmota/tasmota_xnrg_energy/xnrg_13_fif_le01mr.ino
@@ -237,43 +237,22 @@ void FifLEReset(void)
}
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_LE01MR[] PROGMEM =
- "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
- "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"
- ;
+const char HTTP_ENERGY_LE01MR_TOTAL_ACTIVE[] PROGMEM =
+ "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
+const char HTTP_ENERGY_LE01MR_TOTAL_REACTIVE[] PROGMEM =
+ "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}";
#endif // USE_WEBSERVER
-/*
void FifLEShow(bool json) {
- char total_reactive_chr[FLOATSZ];
- dtostrfd(Le01mr.total_reactive, Settings->flag2.energy_resolution, total_reactive_chr);
- char total_active_chr[FLOATSZ];
- dtostrfd(Le01mr.total_active, Settings->flag2.energy_resolution, total_active_chr);
-
if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"),
- total_active_chr, total_reactive_chr);
+ ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s"),
+ EnergyFmt(&Le01mr.total_active, Settings->flag2.energy_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_REACTIVE "\":%s"),
+ EnergyFmt(&Le01mr.total_reactive, Settings->flag2.energy_resolution));
#ifdef USE_WEBSERVER
} else {
- WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr);
-#endif // USE_WEBSERVER
- }
-}
-*/
-
-void FifLEShow(bool json) {
- char value_chr[GUISZ];
- char value2_chr[GUISZ];
-
- if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"),
- EnergyFormat(value_chr, &Le01mr.total_active, Settings->flag2.energy_resolution),
- EnergyFormat(value2_chr, &Le01mr.total_reactive, Settings->flag2.energy_resolution));
-#ifdef USE_WEBSERVER
- } else {
- WSContentSend_PD(HTTP_ENERGY_LE01MR, WebEnergyFormat(value_chr, &Le01mr.total_active, Settings->flag2.energy_resolution),
- WebEnergyFormat(value2_chr, &Le01mr.total_reactive, Settings->flag2.energy_resolution));
-
+ WSContentSend_PD(HTTP_ENERGY_LE01MR_TOTAL_ACTIVE, WebEnergyFmt(&Le01mr.total_active, Settings->flag2.energy_resolution));
+ WSContentSend_PD(HTTP_ENERGY_LE01MR_TOTAL_REACTIVE, WebEnergyFmt(&Le01mr.total_reactive, Settings->flag2.energy_resolution));
#endif // USE_WEBSERVER
}
}
diff --git a/tasmota/tasmota_xnrg_energy/xnrg_18_sdm72.ino b/tasmota/tasmota_xnrg_energy/xnrg_18_sdm72.ino
index b058b09c0..69095ad81 100644
--- a/tasmota/tasmota_xnrg_energy/xnrg_18_sdm72.ino
+++ b/tasmota/tasmota_xnrg_energy/xnrg_18_sdm72.ino
@@ -177,26 +177,24 @@ void Sdm72Show(bool json) {
*/
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_SDM72[] PROGMEM =
- "{s}" D_EXPORT_POWER "{m}%s" D_UNIT_WATT "{e}"
+const char HTTP_ENERGY_SDM72_EXPORT_POWER[] PROGMEM =
+ "{s}" D_EXPORT_POWER "{m}%s" D_UNIT_WATT "{e}";
+const char HTTP_ENERGY_SDM72_IMPORT_POWER[] PROGMEM =
"{s}" D_IMPORT_POWER "{m}%s" D_UNIT_WATT "{e}";
#endif // USE_WEBSERVER
void Sdm72Show(bool json) {
if (isnan(Sdm72.total_active)) { return; }
- char value_chr[GUISZ];
- char value2_chr[GUISZ];
-
if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_POWER "\":%s,\"" D_JSON_IMPORT_POWER "\":%s"),
- EnergyFormat(value_chr, &Sdm72.export_power, Settings->flag2.wattage_resolution),
- EnergyFormat(value2_chr, &Sdm72.import_power, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_POWER "\":%s"),
+ EnergyFmt(&Sdm72.export_power, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_POWER "\":%s"),
+ EnergyFmt(&Sdm72.import_power, Settings->flag2.wattage_resolution));
#ifdef USE_WEBSERVER
} else {
- WSContentSend_PD(HTTP_ENERGY_SDM72, WebEnergyFormat(value_chr, &Sdm72.export_power, Settings->flag2.wattage_resolution),
- WebEnergyFormat(value2_chr, &Sdm72.import_power, Settings->flag2.wattage_resolution));
-
+ WSContentSend_PD(HTTP_ENERGY_SDM72_EXPORT_POWER, WebEnergyFmt(&Sdm72.export_power, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_ENERGY_SDM72_IMPORT_POWER, WebEnergyFmt(&Sdm72.import_power, Settings->flag2.wattage_resolution));
#endif // USE_WEBSERVER
}
}
diff --git a/tasmota/tasmota_xnrg_energy/xnrg_21_sdm230.ino b/tasmota/tasmota_xnrg_energy/xnrg_21_sdm230.ino
index f851b8110..c8c166d46 100644
--- a/tasmota/tasmota_xnrg_energy/xnrg_21_sdm230.ino
+++ b/tasmota/tasmota_xnrg_energy/xnrg_21_sdm230.ino
@@ -217,47 +217,27 @@ void Sdm230Reset(void)
#ifdef SDM230_MORE_REGS
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_SDM230[] PROGMEM =
- "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"
- "{s}" D_MAX_POWER "{m}%s " D_UNIT_WATT "{e}"
+const char HTTP_ENERGY_SDM230_PHASE_ANGLE[] PROGMEM =
+ "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}";
+const char HTTP_ENERGY_SDM230_MAX_POWER[] PROGMEM =
+ "{s}" D_MAX_POWER "{m}%s " D_UNIT_WATT "{e}";
+const char HTTP_ENERGY_SDM230_RESETTABLE_TOTAL_ACTIVE[] PROGMEM =
"{s}" D_RESETTABLE_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
#endif // USE_WEBSERVER
-/*
void Sdm230Show(bool json) {
- char phase_angle_chr[FLOATSZ];
- dtostrfd(Sdm230.phase_angle, 2, phase_angle_chr);
- char maximum_demand_chr[FLOATSZ];
- dtostrfd(Sdm230.maximum_total_demand_power_active, Settings->flag2.wattage_resolution, maximum_demand_chr);
- char resettable_energy_chr[FLOATSZ];
- dtostrfd(Sdm230.resettable_total_energy, Settings->flag2.energy_resolution, resettable_energy_chr);
-
if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_POWERMAX "\":%s,\"" D_JSON_RESETTABLE_TOTAL_ACTIVE "\":%s"),
- phase_angle_chr, maximum_demand_chr, resettable_energy_chr);
+ ResponseAppend_P(PSTR(",\"" D_JSON_PHASE_ANGLE "\":%s"),
+ EnergyFmt(&Sdm230.phase_angle, 2));
+ ResponseAppend_P(PSTR(",\"" D_JSON_POWERMAX "\":%s"),
+ EnergyFmt(&Sdm230.maximum_total_demand_power_active, Settings->flag2.wattage_resolution));
+ ResponseAppend_P(PSTR(",\"" D_JSON_RESETTABLE_TOTAL_ACTIVE "\":%s"),
+ EnergyFmt(&Sdm230.resettable_total_energy, Settings->flag2.energy_resolution));
#ifdef USE_WEBSERVER
} else {
- WSContentSend_PD(HTTP_ENERGY_SDM230, phase_angle_chr, maximum_demand_chr, resettable_energy_chr);
-#endif // USE_WEBSERVER
- }
-}
-*/
-
-void Sdm230Show(bool json) {
- char value_chr[GUISZ];
- char value2_chr[GUISZ];
- char value3_chr[GUISZ];
-
- if (json) {
- ResponseAppend_P(PSTR(",\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_POWERMAX "\":%s,\"" D_JSON_RESETTABLE_TOTAL_ACTIVE "\":%s"),
- EnergyFormat(value_chr, &Sdm230.phase_angle, 2),
- EnergyFormat(value2_chr, &Sdm230.maximum_total_demand_power_active, Settings->flag2.wattage_resolution),
- EnergyFormat(value3_chr, &Sdm230.resettable_total_energy, Settings->flag2.energy_resolution));
-#ifdef USE_WEBSERVER
- } else {
- WSContentSend_PD(HTTP_ENERGY_SDM230, WebEnergyFormat(value_chr, &Sdm230.phase_angle, 2),
- WebEnergyFormat(value2_chr, &Sdm230.maximum_total_demand_power_active, Settings->flag2.wattage_resolution),
- WebEnergyFormat(value3_chr, &Sdm230.resettable_total_energy, Settings->flag2.energy_resolution));
+ WSContentSend_PD(HTTP_ENERGY_SDM230_PHASE_ANGLE, WebEnergyFmt(&Sdm230.phase_angle, 2));
+ WSContentSend_PD(HTTP_ENERGY_SDM230_MAX_POWER, WebEnergyFmt(&Sdm230.maximum_total_demand_power_active, Settings->flag2.wattage_resolution));
+ WSContentSend_PD(HTTP_ENERGY_SDM230_RESETTABLE_TOTAL_ACTIVE, WebEnergyFmt(&Sdm230.resettable_total_energy, Settings->flag2.energy_resolution));
#endif // USE_WEBSERVER
}
}
diff --git a/tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino b/tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino
index 0a6cdac0a..0c1f688fb 100644
--- a/tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino
+++ b/tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino
@@ -746,14 +746,13 @@ const char HTTP_ADE7880_CURRENT[] PROGMEM = "{s}" D_CURRENT_NEUTRAL "{m}%s " D_U
#endif // USE_WEBSERVER
void Ade7880Show(bool json) {
- char value_chr[GUISZ];
if (json) {
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT_NEUTRAL "\":%s"),
- EnergyFormat(value_chr, &Ade7880.neutral_current, Settings->flag2.current_resolution, 1));
+ EnergyFmt(&Ade7880.neutral_current, Settings->flag2.current_resolution, 1));
#ifdef USE_WEBSERVER
} else {
- WSContentSend_PD(HTTP_ADE7880_CURRENT, WebEnergyFormat(value_chr, &Ade7880.neutral_current, Settings->flag2.current_resolution, 1));
+ WSContentSend_PD(HTTP_ADE7880_CURRENT, WebEnergyFmt(&Ade7880.neutral_current, Settings->flag2.current_resolution, 1));
#endif // USE_WEBSERVER
}
}
diff --git a/tasmota/tasmota_xnrg_energy/xnrg_29_modbus.ino b/tasmota/tasmota_xnrg_energy/xnrg_29_modbus.ino
index 8dde49a5a..29b4eaf10 100644
--- a/tasmota/tasmota_xnrg_energy/xnrg_29_modbus.ino
+++ b/tasmota/tasmota_xnrg_energy/xnrg_29_modbus.ino
@@ -799,7 +799,6 @@ uint32_t EnergyModbusResolution(uint32_t resolution) {
}
void EnergyModbusShow(bool json) {
- char value_chr[GUISZ];
float values[ENERGY_MAX_PHASES];
for (uint32_t i = 0; i < NrgMbsParam.user_adds; i++) {
uint32_t reg_index = NRG_MBS_MAX_REGS + i;
@@ -829,15 +828,14 @@ void EnergyModbusShow(bool json) {
#ifdef ENERGY_MODBUS_DEBUG_SHOW
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: resolution %d -> %d"), NrgMbsUser[i].resolution, resolution);
#endif
-
if (json) {
- ResponseAppend_P(PSTR(",\"%s\":%s"), NrgMbsUser[i].json_name, EnergyFormat(value_chr, values, resolution, single));
+ ResponseAppend_P(PSTR(",\"%s\":%s"), NrgMbsUser[i].json_name, EnergyFmt(values, resolution, single));
#ifdef USE_WEBSERVER
} else {
if (strlen(NrgMbsUser[i].gui_name)) { // Skip empty GUI names
WSContentSend_PD(PSTR("{s}%s{m}%s %s{e}"),
NrgMbsUser[i].gui_name,
- WebEnergyFormat(value_chr, values, resolution, single),
+ WebEnergyFmt(values, resolution, single),
NrgMbsUser[i].gui_unit);
}
#endif // USE_WEBSERVER