Bump v12.4.0.3

- Bump v12.4.0.3
- Refactor energy monitoring reducing stack usage and solve inherent exceptions and watchdogs (#18164)
This commit is contained in:
Theo Arends 2023-03-17 21:05:51 +01:00
parent d0f4637611
commit 54a2688cbf
14 changed files with 351 additions and 292 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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_

View File

@ -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("</td>")); // Skip first column
ext_snprintf_P(Energy->value, GUISZ, PSTR("</td>")); // Skip first column
if ((Energy->phase_count > 1) && single) { // Need to set colspan so need new columns
// </td><td colspan='3' style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td colspan='5' style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td colspan='7' style='text-align:right'>1.23</td><td>&nbsp;</td><td>
ext_snprintf_P(result, GUISZ, PSTR("%s<td colspan='%d' style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
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<td colspan='%d' style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
Energy->value, (Energy->phase_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[0]);
} else {
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
for (uint32_t i = 0; i < Energy->phase_count; i++) {
ext_snprintf_P(result, GUISZ, PSTR("%s<td style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
result, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[i]);
ext_snprintf_P(Energy->value, GUISZ, PSTR("%s<td style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
Energy->value, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[i]);
}
}
ext_snprintf_P(result, GUISZ, PSTR("%s<td>"), result);
ext_snprintf_P(Energy->value, GUISZ, PSTR("%s<td>"), 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} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
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("</table><hr/>{t}{s}</th><th></th>")); // First column is empty ({t} = <table style='width:100%'>, {s} = <tr><th>)
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("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
WSContentSend_P(PSTR("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, number, 10));
}
WSContentSend_P(PSTR("<td>{e}")); // Last column is units ({e} = </td></tr>)
#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();
}
/*********************************************************************************************\

View File

@ -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("</td>")); // Skip first column
ext_snprintf_P(Energy->value, GUISZ, PSTR("</td>")); // Skip first column
if ((Energy->gui_count > 1) && single) { // Need to set colspan so need new columns
// </td><td colspan='3' style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td colspan='5' style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td colspan='7' style='text-align:right'>1.23</td><td>&nbsp;</td><td>
ext_snprintf_P(result, GUISZ, PSTR("%s<td colspan='%d' style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
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<td colspan='%d' style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
Energy->value, (Energy->gui_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[Energy->gui_indirect[0]]);
} else {
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
// </td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td style='text-align:right'>1.23</td><td>&nbsp;</td><td>
for (uint32_t i = 0; i < Energy->gui_count; i++) {
ext_snprintf_P(result, GUISZ, PSTR("%s<td style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
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<td style='text-align:%s'>%*_f</td><td>&nbsp;</td>"),
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<td>"), result);
ext_snprintf_P(Energy->value, GUISZ, PSTR("%s<td>"), 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} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
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}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><th>Head4</th><th></th><td>{e}
WSContentSend_P(PSTR("{t}{s}</th><th></th>")); // First column is empty ({t} = <table style='width:100%'>, {s} = <tr><th>)
bool no_label = (1 == Energy->phase_count);
char number[4];
for (uint32_t i = 0; i < Energy->gui_count; i++) {
WSContentSend_P(PSTR("<th style='text-align:center'>%s%s<th></th>"),
(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("<td>{e}")); // Last column is units ({e} = </td></tr>)
#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

View File

@ -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
\*********************************************************************************************/

View File

@ -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("</table><hr/>{t}")); // {t} = <table style='width:100%'> - Define for next FUNC_WEB_SENSOR
}
#endif // USE_WEBSERVER

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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