Add split total energy

This commit is contained in:
Theo Arends 2021-10-02 18:29:05 +02:00
parent de75cd4c40
commit c4bb190e82
18 changed files with 150 additions and 180 deletions

View File

@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file.
## [Unreleased] - Development
## [9.5.0.9]
### Added
- Command ``SetOption129 1`` to enable split total energy results (#13030)
- Commands ``EnergyTotal<phase>``, ``EnergyToday<phase>`` and ``EnergyYesterday<phase>`` to (re)set energy values
- Commands ``EnergyUsage`` and ``EnergyExport`` to (re)set energy usage and export values
### Breaking Changed
- ESP32 LVGL updated to v8.0.2
### Changed
- Removed command ``EnergyReset`` as it is replaced by new commands
## [9.5.0.8] 20210927
### Added
- Command ``WebGetConfig <url>`` if ``#define USE_WEBGETCONFIG`` is enabled to restore/init configuration from external webserver (#13034)

View File

@ -110,6 +110,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
- Command ``WebGetConfig <url>`` if ``#define USE_WEBGETCONFIG`` is enabled to restore/init configuration from external webserver [#13034](https://github.com/arendst/Tasmota/issues/13034)
- Command ``WebQuery <url> GET|POST|PUT|PATCH [<headers>] <body>`` to extent HTTP requests [#13209](https://github.com/arendst/Tasmota/issues/13209)
- Commands ``EnergyTotal<phase>``, ``EnergyToday<phase>`` and ``EnergyYesterday<phase>`` to (re)set energy values
- Commands ``EnergyUsage`` and ``EnergyExport`` to (re)set energy usage and export values
- Optional IP filter to command ``TCPStart`` [#12806](https://github.com/arendst/Tasmota/issues/12806)
- Neopool commands ``NPPHRes``, ``NPCLRes`` and ``NPIonRes`` [#12813](https://github.com/arendst/Tasmota/issues/12813)
- Support for second DNS server
@ -145,6 +146,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
### Changed
- Move firmware binaries to https://github.com/arendst/Tasmota-firmware/tree/main/release-firmware
- Removed command ``EnergyReset`` as it is replaced by new commands
- IRremoteESP8266 library from v2.7.18 to v2.7.20
- NeoPixelBus library from v2.6.3 to v2.6.7
- Message ``Upload buffer miscompare`` into ``Not enough space``

View File

@ -432,10 +432,11 @@
#define D_CMND_VOLTAGEHIGH "VoltageHigh"
#define D_CMND_CURRENTLOW "CurrentLow"
#define D_CMND_CURRENTHIGH "CurrentHigh"
#define D_CMND_ENERGYRESET "EnergyReset"
#define D_CMND_ENERGYTODAY "EnergyToday"
#define D_CMND_ENERGYYESTERDAY "EnergyYesterday"
#define D_CMND_ENERGYTOTAL "EnergyTotal"
#define D_CMND_ENERGYUSAGE "EnergyUsage"
#define D_CMND_ENERGYEXPORT "EnergyExport"
#define D_CMND_POWERSET "PowerSet"
#define D_CMND_VOLTAGESET "VoltageSet"
#define D_CMND_CURRENTSET "CurrentSet"

View File

@ -56,7 +56,7 @@ const char kEnergyCommands[] PROGMEM = "|" // No prefix
D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|"
#endif // USE_ENERGY_POWER_LIMIT
#endif // USE_ENERGY_MARGIN_DETECTION
D_CMND_ENERGYRESET "|" D_CMND_ENERGYTODAY "|" D_CMND_ENERGYYESTERDAY "|" D_CMND_ENERGYTOTAL "|" D_CMND_TARIFF;
D_CMND_ENERGYTODAY "|" D_CMND_ENERGYYESTERDAY "|" D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYUSAGE "|" D_CMND_ENERGYEXPORT "|" D_CMND_TARIFF;
void (* const EnergyCommand[])(void) PROGMEM = {
&CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, &CmndFrequencyCal,
@ -69,7 +69,7 @@ void (* const EnergyCommand[])(void) PROGMEM = {
&CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow,
#endif // USE_ENERGY_POWER_LIMIT
#endif // USE_ENERGY_MARGIN_DETECTION
&CmndEnergyReset, &CmndEnergyToday, &CmndEnergyYesterday, &CmndEnergyTotal, &CmndTariff};
&CmndEnergyToday, &CmndEnergyYesterday, &CmndEnergyTotal, &CmndEnergyUsage, &CmndEnergyExport, &CmndTariff};
const char kEnergyPhases[] PROGMEM = "|%*_f / %*_f|%*_f / %*_f / %*_f||[%*_f,%*_f]|[%*_f,%*_f,%*_f]";
@ -81,9 +81,7 @@ struct ENERGY {
float reactive_power[ENERGY_MAX_PHASES]; // 123.1 VAr
float power_factor[ENERGY_MAX_PHASES]; // 0.12
float frequency[ENERGY_MAX_PHASES]; // 123.1 Hz
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
float import_active[ENERGY_MAX_PHASES]; // 123.123 kWh
#endif // SDM630_IMPORT || SDM72_IMPEXP
float export_active[ENERGY_MAX_PHASES]; // 123.123 kWh
float start_energy[ENERGY_MAX_PHASES]; // 12345.12345 kWh total previous
float daily[ENERGY_MAX_PHASES]; // 123.123 kWh
@ -200,6 +198,7 @@ void EnergyUpdateToday(void) {
Energy.total_sum = 0.0;
Energy.yesterday_sum = 0.0;
Energy.daily_sum = 0.0;
for (uint32_t i = 0; i < Energy.phase_count; i++) {
if (Energy.kWhtoday_delta[i] > 1000) {
uint32_t delta = Energy.kWhtoday_delta[i] / 1000;
@ -246,28 +245,29 @@ void EnergyUpdateToday(void) {
}
}
void EnergyUpdateTotal(float value, bool kwh, uint32_t phase = 0);
void EnergyUpdateTotal(float value, bool kwh, uint32_t phase)
{
// AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total %4_f %sWh"), &value, (kwh) ? "k" : "");
void EnergyUpdateTotal(void) {
// Provide total import active energy as float Energy.import_active[phase] in kWh: 98Wh = 0.098kWh
uint32_t multiplier = (kwh) ? 100000 : 100; // kWh or Wh to deca milli Wh
for (uint32_t i = 0; i < Energy.phase_count; i++) {
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: EnergyTotal[%d] %4_f kWh"), i, &Energy.import_active[i]);
if (0 == Energy.start_energy[phase] || (value < Energy.start_energy[phase])) {
Energy.start_energy[phase] = value; // Init after restart and handle roll-over if any
}
else if (value != Energy.start_energy[phase]) {
Energy.kWhtoday[phase] = (unsigned long)((value - Energy.start_energy[phase]) * multiplier);
if (0 == Energy.start_energy[i] || (Energy.import_active[i] < Energy.start_energy[i])) {
Energy.start_energy[i] = Energy.import_active[i]; // Init after restart and handle roll-over if any
}
else if (Energy.import_active[i] != Energy.start_energy[i]) {
Energy.kWhtoday[i] = (uint32_t)((Energy.import_active[i] - Energy.start_energy[i]) * 100000);
}
if ((Energy.total[i] < (Energy.import_active[i] - 0.01)) && // We subtract a little offset to avoid continuous updates
Settings->flag3.hardware_energy_total) { // SetOption72 - Enable hardware energy total counter as reference (#6561)
RtcSettings.energy_kWhtotal_ph[i] = (unsigned long)((Energy.import_active[i] * 100000) - Energy.kWhtoday_offset[i] - Energy.kWhtoday[i]);
Settings->energy_kWhtotal_ph[i] = RtcSettings.energy_kWhtotal_ph[i];
Energy.total[i] = (float)(RtcSettings.energy_kWhtotal_ph[i] + Energy.kWhtoday_offset[i] + Energy.kWhtoday[i]) / 100000;
Settings->energy_kWhtotal_time = (!Energy.kWhtoday_offset[i]) ? LocalTime() : Midnight();
// AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value"));
}
}
if ((Energy.total[phase] < (value - 0.01)) && // We subtract a little offset to avoid continuous updates
Settings->flag3.hardware_energy_total) { // SetOption72 - Enable hardware energy total counter as reference (#6561)
RtcSettings.energy_kWhtotal_ph[phase] = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset[phase] - Energy.kWhtoday[phase]);
Settings->energy_kWhtotal_ph[phase] = RtcSettings.energy_kWhtotal_ph[phase];
Energy.total[phase] = (float)(RtcSettings.energy_kWhtotal_ph[phase] + Energy.kWhtoday_offset[phase] + Energy.kWhtoday[phase]) / 100000;
Settings->energy_kWhtotal_time = (!Energy.kWhtoday_offset[phase]) ? LocalTime() : Midnight();
// AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value"));
}
EnergyUpdateToday();
}
@ -589,50 +589,7 @@ void EnergyCommandCalResponse(uint32_t nvalue) {
ResponseCmndNumber(nvalue);
}
void CmndEnergyReset(void) {
uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values);
values[0] *= 100;
if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) {
if (params > 0) {
switch (XdrvMailbox.index) {
case 4:
// Reset energy_usage.usage totals
RtcSettings.energy_usage.usage1_kWhtotal = values[0];
if (params > 1) {
RtcSettings.energy_usage.usage2_kWhtotal = values[1] * 100;
}
Settings->energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
Settings->energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal;
break;
case 5:
// Reset energy_usage.return totals
RtcSettings.energy_usage.return1_kWhtotal = values[0];
if (params > 1) {
RtcSettings.energy_usage.return2_kWhtotal = values[1] * 100;
}
Settings->energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal;
Settings->energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal;
break;
}
}
}
float usage1_kWhtotal = (float)Settings->energy_usage.usage1_kWhtotal / 100000;
float usage2_kWhtotal = (float)Settings->energy_usage.usage2_kWhtotal / 100000;
float return1_kWhtotal = (float)Settings->energy_usage.return1_kWhtotal / 100000;
float return2_kWhtotal = (float)Settings->energy_usage.return2_kWhtotal / 100000;
Response_P(PSTR("{\"%s\":{\"" D_JSON_USAGE "\":[%*_f,%*_f],\"" D_JSON_EXPORT "\":[%*_f,%*_f]}}"),
XdrvMailbox.command,
Settings->flag2.energy_resolution, &usage1_kWhtotal,
Settings->flag2.energy_resolution, &usage2_kWhtotal,
Settings->flag2.energy_resolution, &return1_kWhtotal,
Settings->flag2.energy_resolution, &return2_kWhtotal);
}
void CmndEnergyResponse(void) {
void ResponseCmndEnergyTotalYesterdayToday(void) {
char value_chr[FLOATSZ * ENERGY_MAX_PHASES]; // Used by EnergyFormatIndex
char value2_chr[FLOATSZ * ENERGY_MAX_PHASES];
char value3_chr[FLOATSZ * ENERGY_MAX_PHASES];
@ -653,12 +610,11 @@ void CmndEnergyResponse(void) {
void CmndEnergyTotal(void) {
uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values);
values[0] *= 100;
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Energy.phase_count) && (params > 0)) {
uint32_t phase = XdrvMailbox.index -1;
// Reset Energy Total
RtcSettings.energy_kWhtotal_ph[phase] = values[0];
RtcSettings.energy_kWhtotal_ph[phase] = values[0] * 100;
Settings->energy_kWhtotal_ph[phase] = RtcSettings.energy_kWhtotal_ph[phase];
if (params > 1) {
Settings->energy_kWhtotal_time = values[1];
@ -667,33 +623,31 @@ void CmndEnergyTotal(void) {
}
RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total[phase] * 1000);
}
CmndEnergyResponse();
ResponseCmndEnergyTotalYesterdayToday();
}
void CmndEnergyYesterday(void) {
uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values);
values[0] *= 100;
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Energy.phase_count) && (params > 0)) {
uint32_t phase = XdrvMailbox.index -1;
// Reset Energy Yesterday
Settings->energy_kWhyesterday_ph[phase] = values[0];
Settings->energy_kWhyesterday_ph[phase] = values[0] * 100;
if (params > 1) {
Settings->energy_kWhtotal_time = values[1];
}
}
CmndEnergyResponse();
ResponseCmndEnergyTotalYesterdayToday();
}
void CmndEnergyToday(void) {
uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values);
values[0] *= 100;
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Energy.phase_count) && (params > 0)) {
uint32_t phase = XdrvMailbox.index -1;
// Reset Energy Today
Energy.kWhtoday_offset[phase] = values[0];
Energy.kWhtoday_offset[phase] = values[0] * 100;
Energy.kWhtoday[phase] = 0;
Energy.kWhtoday_delta[phase] = 0;
Energy.start_energy[phase] = 0;
@ -704,13 +658,55 @@ void CmndEnergyToday(void) {
if (params > 1) {
Settings->energy_kWhtotal_time = values[1];
}
else {
if (!RtcSettings.energy_kWhtotal_ph[phase] && !Energy.kWhtoday_offset[phase]) {
Settings->energy_kWhtotal_time = LocalTime();
}
else if (!RtcSettings.energy_kWhtotal_ph[phase] && !Energy.kWhtoday_offset[phase]) {
Settings->energy_kWhtotal_time = LocalTime();
}
}
CmndEnergyResponse();
ResponseCmndEnergyTotalYesterdayToday();
}
void ResponseCmndEnergyUsageExport(void) {
float usage1_kWhtotal = (float)Settings->energy_usage.usage1_kWhtotal / 100000;
float usage2_kWhtotal = (float)Settings->energy_usage.usage2_kWhtotal / 100000;
float return1_kWhtotal = (float)Settings->energy_usage.return1_kWhtotal / 100000;
float return2_kWhtotal = (float)Settings->energy_usage.return2_kWhtotal / 100000;
Response_P(PSTR("{\"%s\":{\"" D_JSON_USAGE "\":[%*_f,%*_f],\"" D_JSON_EXPORT "\":[%*_f,%*_f]}}"),
XdrvMailbox.command,
Settings->flag2.energy_resolution, &usage1_kWhtotal,
Settings->flag2.energy_resolution, &usage2_kWhtotal,
Settings->flag2.energy_resolution, &return1_kWhtotal,
Settings->flag2.energy_resolution, &return2_kWhtotal);
}
void CmndEnergyUsage(void) {
uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values);
if (params > 0) {
// Reset energy_usage.usage totals
RtcSettings.energy_usage.usage1_kWhtotal = values[0] * 100;
if (params > 1) {
RtcSettings.energy_usage.usage2_kWhtotal = values[1] * 100;
}
Settings->energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
Settings->energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal;
}
ResponseCmndEnergyUsageExport();
}
void CmndEnergyExport(void) {
uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values);
if (params > 0) {
// Reset energy_usage.return totals
RtcSettings.energy_usage.return1_kWhtotal = values[0] * 100;
if (params > 1) {
RtcSettings.energy_usage.return2_kWhtotal = values[1] * 100;
}
Settings->energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal;
Settings->energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal;
}
ResponseCmndEnergyUsageExport();
}
void CmndTariff(void) {
@ -960,9 +956,6 @@ void EnergyDrvInit(void) {
Energy.reactive_power[phase] = NAN;
Energy.power_factor[phase] = NAN;
Energy.frequency[phase] = NAN;
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
Energy.import_active[phase] = NAN;
#endif // SDM630_IMPORT || SDM72_IMPEXP
Energy.export_active[phase] = NAN;
}
Energy.phase_count = 1; // Number of phases active
@ -1024,11 +1017,6 @@ const char HTTP_ENERGY_SNS2[] PROGMEM =
const char HTTP_ENERGY_SNS3[] PROGMEM =
"{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
const char HTTP_ENERGY_SNS4[] PROGMEM =
"{s}" D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
#endif // SDM630_IMPORT || SDM72_IMPEXP
#endif // USE_WEBSERVER
void EnergyShow(bool json) {
@ -1119,6 +1107,7 @@ void EnergyShow(bool json) {
EnergyFormatSum(value_chr, energy_yesterday_ph, Settings->flag2.energy_resolution, json),
EnergyFormatSum(value2_chr, Energy.daily, Settings->flag2.energy_resolution, json));
/*
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
if (!isnan(Energy.import_active[0])) {
ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s"),
@ -1129,6 +1118,7 @@ void EnergyShow(bool json) {
}
}
#endif // SDM630_IMPORT || SDM72_IMPEXP
*/
if (!isnan(Energy.export_active[0])) {
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"),
@ -1243,12 +1233,6 @@ void EnergyShow(bool json) {
if (!isnan(Energy.export_active[0])) {
WSContentSend_PD(HTTP_ENERGY_SNS3, EnergyFormat(value_chr, Energy.export_active, Settings->flag2.energy_resolution, json));
}
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
if (!isnan(Energy.import_active[0])) {
WSContentSend_PD(HTTP_ENERGY_SNS4, EnergyFormat(value_chr, Energy.import_active, Settings->flag2.energy_resolution, json));
}
#endif // SDM630_IMPORT || SDM72_IMPEXP
XnrgCall(FUNC_WEB_SENSOR);
#endif // USE_WEBSERVER
}

View File

@ -891,8 +891,9 @@ void TuyaProcessStatePacket(void) {
Tuya.lastPowerCheckTime = Rtc.utc_time;
}
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER_TOTAL) {
EnergyUpdateTotal((float)packetValue / 100,true);
Energy.import_active[0] = (float)packetValue / 100;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Total_Power=%d"), Tuya.buffer[dpidStart], packetValue);
EnergyUpdateTotal();
}
#endif // USE_ENERGY_SENSOR
}

View File

@ -60,8 +60,8 @@ TasmotaSerial *PzemSerial = nullptr;
/*********************************************************************************************/
struct PZEM {
float energy = 0;
float last_energy = 0;
// float energy = 0;
// float last_energy = 0;
uint8_t send_retry = 0;
uint8_t read_state = 0; // Set address
uint8_t phase = 0;
@ -192,20 +192,11 @@ void PzemEvery250ms(void)
Energy.active_power[Pzem.phase] = value;
break;
case 4: // Total energy as 99999Wh
/*
Pzem.energy += value;
Energy.import_active[Pzem.phase] = value / 1000.0; // 99.999kWh
if (Pzem.phase == Energy.phase_count -1) {
if (Pzem.energy > Pzem.last_energy) { // Handle missed phase
if (TasmotaGlobal.uptime > PZEM_STABILIZE) {
EnergyUpdateTotal(Pzem.energy, false);
}
Pzem.last_energy = Pzem.energy;
if (TasmotaGlobal.uptime > PZEM_STABILIZE) {
EnergyUpdateTotal();
}
Pzem.energy = 0;
}
*/
if (TasmotaGlobal.uptime > PZEM_STABILIZE) {
EnergyUpdateTotal(value, false, Pzem.phase);
}
break;
}

View File

@ -77,22 +77,11 @@ void PzemAcEverySecond(void)
Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W
Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
/*
PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
Energy.import_active[PzemAc.phase] = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]) / 1000.0; // 4294967.295 kWh
if (PzemAc.phase == Energy.phase_count -1) {
if (PzemAc.energy > PzemAc.last_energy) { // Handle missed phase
if (TasmotaGlobal.uptime > PZEM_AC_STABILIZE) {
EnergyUpdateTotal(PzemAc.energy, false);
}
PzemAc.last_energy = PzemAc.energy;
if (TasmotaGlobal.uptime > PZEM_AC_STABILIZE) {
EnergyUpdateTotal();
}
PzemAc.energy = 0;
}
*/
float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
if (TasmotaGlobal.uptime > PZEM_AC_STABILIZE) {
EnergyUpdateTotal(energy, false, PzemAc.phase);
}
}
}

View File

@ -74,21 +74,11 @@ void PzemDcEverySecond(void)
Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
/*
PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
Energy.import_active[PzemDc.channel] = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]) / 1000.0; // 4294967.295 kWh
if (PzemDc.channel == Energy.phase_count -1) {
if (PzemDc.energy > PzemDc.last_energy) { // Handle missed channel
if (TasmotaGlobal.uptime > PZEM_DC_STABILIZE) {
EnergyUpdateTotal(PzemDc.energy, false);
}
PzemDc.last_energy = PzemDc.energy;
if (TasmotaGlobal.uptime > PZEM_DC_STABILIZE) {
EnergyUpdateTotal();
}
PzemDc.energy = 0;
}
*/
float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
if (TasmotaGlobal.uptime > PZEM_DC_STABILIZE) {
EnergyUpdateTotal(energy, false, PzemDc.channel);
}
}
}

View File

@ -161,7 +161,8 @@ void SDM120Every250ms(void)
Sdm120.start_address_count = sdm120_table; // No extended registers available
}
}
EnergyUpdateTotal(Sdm120.total_active, true); // 484.708 kWh
Energy.import_active[0] = Sdm120.total_active; // 484.708 kWh
EnergyUpdateTotal(); // 484.708 kWh
}
}
} // end data ready

View File

@ -75,9 +75,8 @@ void Dds2382EverySecond(void)
offset = 19;
}
Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW
float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496.729 kW
EnergyUpdateTotal(import_active, true); // 484.708 kWh
Energy.import_active[0] = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496.729 kW
EnergyUpdateTotal(); // 484.708 kWh
}
} // end data ready

View File

@ -60,11 +60,11 @@ const uint16_t sdm630_start_addresses[] {
0x0160, // + + + kWh Phase 1 export active energy
0x0162, // + + + kWh Phase 2 export active energy
0x0164, // + + + kWh Phase 3 export active energy
#ifdef SDM630_IMPORT
//#ifdef SDM630_IMPORT
0x015A, // + + + kWh Phase 1 import active energy
0x015C, // + + + kWh Phase 2 import active energy
0x015E, // + + + kWh Phase 3 import active energy
#endif // SDM630_IMPORT
//#endif // SDM630_IMPORT
0x0156 // + + + kWh Total active energy
};
@ -179,7 +179,6 @@ void SDM630Every250ms(void)
break;
case 19:
#ifdef SDM630_IMPORT
Energy.import_active[0] = value;
break;
@ -192,8 +191,8 @@ void SDM630Every250ms(void)
break;
case 22:
#endif // SDM630_IMPORT
EnergyUpdateTotal(value, true);
// Energy.import_active[0] = value;
EnergyUpdateTotal();
break;
}

View File

@ -49,7 +49,6 @@ const uint16_t Ddsu666_start_addresses[] {
};
struct DDSU666 {
float import_active = NAN;
uint8_t read_state = 0;
uint8_t send_retry = 0;
} Ddsu666;
@ -106,7 +105,7 @@ void DDSU666Every250ms(void)
break;
case 6:
Ddsu666.import_active = value; // 478.492 kWh
Energy.import_active[0] = value; // 478.492 kWh
break;
case 7:
@ -118,7 +117,7 @@ void DDSU666Every250ms(void)
if (Ddsu666.read_state == 8) {
Ddsu666.read_state = 0;
EnergyUpdateTotal(Ddsu666.import_active, true); // 484.708 kWh
EnergyUpdateTotal(); // 484.708 kWh
}
}
} // end data ready

View File

@ -100,7 +100,6 @@ struct SOLAXX1 {
float dc2_voltage = 0;
float dc1_current = 0;
float dc2_current = 0;
uint32_t energy_total = 0;
uint32_t runtime_total = 0;
float dc1_power = 0;
float dc2_power = 0;
@ -272,7 +271,7 @@ void solaxX1250MSecond(void) // Every 250 milliseconds
Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; // AC Frequency
Energy.active_power[0] = (float)((value[27] << 8) | value[28]); // AC Power
//temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used
solaxX1.energy_total = ((value[31] << 24) | (value[32] << 16) | (value[33] << 8) | value[34]); // Energy Total
Energy.import_active[0] = (float)((value[31] << 24) | (value[32] << 16) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total
solaxX1.runtime_total = ((value[35] << 24) | (value[36] << 16) | (value[37] << 8) | value[38]); // Work Time Total
solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); // Work mode
//temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V
@ -287,7 +286,7 @@ void solaxX1250MSecond(void) // Every 250 milliseconds
solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current;
solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current;
EnergyUpdateTotal((float)solaxX1.energy_total * 0.1f, true); // 484.708 kWh
EnergyUpdateTotal(); // 484.708 kWh
}
} else { // end hasAddress
// check address confirmation from inverter
@ -365,7 +364,7 @@ void solaxX1250MSecond(void) // Every 250 milliseconds
solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0;
solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0;
//solaxX1.energy_today = solaxX1.energy_total = solaxX1.runtime_total = 0;
//solaxX1.energy_today = solaxX1.runtime_total = 0;
} else {
if (protocolStatus.queryOfflineSend) {
protocolStatus.status = 0b00001000; // queryOffline

View File

@ -181,7 +181,8 @@ void FifLEEvery250ms(void)
break;
case 7:
Le01mr.total_active = value_buff * 0.01f; // [kWh]
Energy.import_active[0] = value_buff * 0.01f; // [kWh]
Le01mr.total_active = Energy.import_active[0] // Useless
break;
case 8:
@ -193,7 +194,7 @@ void FifLEEvery250ms(void)
if (Le01mr.read_state == Le01mr.start_address_count) {
Le01mr.read_state = 0;
EnergyUpdateTotal(Le01mr.total_active, true);
EnergyUpdateTotal();
}
}
} // end data ready

View File

@ -113,7 +113,7 @@ const char kTarifName[] PROGMEM =
// tariff values for standard mode
#define TELEINFO_STD_TARIFF_BASE PSTR("BASE")
#define TELEINFO_STD_TARIFF_HC PSTR("HEURE CREUSE")
#define TELEINFO_STD_TARIFF_HP PSTR("HEURE PLEINE")
#define TELEINFO_STD_TARIFF_HP PSTR("HEURE PLEINE")
// Label used to do some post processing and/or calculation
@ -122,7 +122,7 @@ enum TInfoLabel{
LABEL_ADCO, LABEL_ADSC,
LABEL_HCHC, LABEL_HCHP, LABEL_EAST, LABEL_EASF01, LABEL_EASF02,
LABEL_OPTARIF, LABEL_NGTF, LABEL_ISOUSC, LABEL_PREF, LABEL_PTEC, LABEL_LTARF, LABEL_NTARF,
LABEL_PAPP, LABEL_SINSTS, LABEL_IINST, LABEL_IINST1, LABEL_IINST2, LABEL_IINST3, LABEL_IRMS1, LABEL_IRMS2, LABEL_IRMS3,
LABEL_PAPP, LABEL_SINSTS, LABEL_IINST, LABEL_IINST1, LABEL_IINST2, LABEL_IINST3, LABEL_IRMS1, LABEL_IRMS2, LABEL_IRMS3,
LABEL_TENSION, LABEL_URMS1, LABEL_URMS2, LABEL_URMS3,
LABEL_IMAX, LABEL_IMAX1, LABEL_IMAX2, LABEL_IMAX3, LABEL_PMAX, LABEL_SMAXSN,
LABEL_DEMAIN,
@ -139,12 +139,12 @@ const char kLabel[] PROGMEM =
"|DEMAIN"
;
// Blacklisted label from telemetry
// Blacklisted label from telemetry
// Each label shoud be enclosed by pipe
const char kLabelBlacklist[]
const char kLabelBlacklist[]
// declared as progmem for ESP8266 just crash and reset on strstr()
#ifndef ESP8266
PROGMEM
PROGMEM
#endif
=
"|PJOURF+1"
@ -246,7 +246,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
float volt = (float) atoi(me->value);
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s=%s, now %d"), me->name, me->value, (int) volt);
if ( ilabel == LABEL_URMS2) {
if ( ilabel == LABEL_URMS2) {
Energy.voltage[1] = volt;
} else if ( ilabel == LABEL_URMS3) {
Energy.voltage[2] = volt;
@ -256,7 +256,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
}
// Current I phase 1 to 3
else if (ilabel == LABEL_IINST
else if (ilabel == LABEL_IINST
|| ilabel == LABEL_IINST1 || ilabel == LABEL_IRMS1
|| ilabel == LABEL_IINST2 || ilabel == LABEL_IRMS2
|| ilabel == LABEL_IINST3 || ilabel == LABEL_IRMS3 )
@ -355,7 +355,8 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total);
}
EnergyUpdateTotal(total/1000.0f, true);
Energy.import_active[0] = total/1000.0f;
EnergyUpdateTotal();
}
// Wh total index (standard)
@ -363,7 +364,8 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
{
uint32_t total = atoi(me->value);
if (contrat != CONTRAT_BAS) {
EnergyUpdateTotal(total/1000.0f, true);
Energy.import_active[0] = total/1000.0f;
EnergyUpdateTotal();
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total);
}
}
@ -372,7 +374,8 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
else if ( ilabel == LABEL_EASF01)
{
if (contrat == CONTRAT_BAS) {
EnergyUpdateTotal(atoi(me->value)/1000.0f, true);
Energy.import_active[0] = atoi(me->value)/1000.0f;
EnergyUpdateTotal();
}
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u"), atoi(me->value));
}
@ -534,7 +537,7 @@ void NewFrameCallback(struct _ValueList * me)
// send teleinfo full frame or only changed data
bool hasData = ResponseAppendTInfo(' ', Settings->teleinfo.raw_report_changed ? false : true );
ResponseJsonEndEnd();
// Publish adding ADCO serial number into the topic
// Need setOption4 to be enabled
// No need to send empty payload
@ -643,7 +646,7 @@ void TInfoInit(void)
AddLog(LOG_LEVEL_INFO, PSTR("TIC: Raw mode enabled"));
if (raw_skip) {
AddLog(LOG_LEVEL_INFO, PSTR("TIC: Sending only one frame over %d "), raw_skip+1);
}
}
}
}
}
@ -667,7 +670,7 @@ bool TInfoCmd(void) {
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: len %d, data '%s'"), XdrvMailbox.data_len, XdrvMailbox.data ? XdrvMailbox.data : "null" );
// Just "EnergyConfig" no more parameter
// Show Teleinfo configuration
// Show Teleinfo configuration
if (XdrvMailbox.data_len == 0) {
char mode_name[MAX_TINFO_COMMAND_NAME];
@ -676,7 +679,7 @@ bool TInfoCmd(void) {
int index_raw = Settings->teleinfo.raw_send ? CMND_TELEINFO_RAW_FULL : CMND_TELEINFO_RAW_DISABLE;
if (Settings->teleinfo.raw_send && Settings->teleinfo.raw_report_changed) {
index_raw = CMND_TELEINFO_RAW_CHANGE;
}
}
// Get the mode and raw name
GetTextIndexed(mode_name, MAX_TINFO_COMMAND_NAME, index_mode, kTInfo_Commands);
GetTextIndexed(raw_name, MAX_TINFO_COMMAND_NAME, index_raw, kTInfo_Commands);
@ -685,7 +688,7 @@ bool TInfoCmd(void) {
serviced = true;
// At least "EnergyConfig xyz" plus one space and one (or more) char
// At least "EnergyConfig xyz" plus one space and one (or more) char
// so "EnergyConfig 0" or "EnergyConfig Teleinfo Standard"
} else if (XdrvMailbox.data_len) {
// Now point on parameter
@ -722,7 +725,7 @@ bool TInfoCmd(void) {
if ( (tinfo_mode==TINFO_MODE_STANDARD && command_code==CMND_TELEINFO_HISTORIQUE) ||
(tinfo_mode==TINFO_MODE_HISTORIQUE && command_code==CMND_TELEINFO_STANDARD) ) {
// Cleanup Serial not sure it will works since
// Cleanup Serial not sure it will works since
// there is no end() or close() on tasmotaserial class
if (TInfoSerial) {
TInfoSerial->flush();
@ -730,7 +733,7 @@ bool TInfoCmd(void) {
free(TInfoSerial);
}
// Change mode
// Change mode
Settings->teleinfo.mode_standard = command_code == CMND_TELEINFO_STANDARD ? 1 : 0;
AddLog(LOG_LEVEL_INFO, PSTR("TIC: '%s' mode"), mode_name);
@ -746,10 +749,10 @@ bool TInfoCmd(void) {
}
break;
case CMND_TELEINFO_RAW_DISABLE:
case CMND_TELEINFO_RAW_FULL:
case CMND_TELEINFO_RAW_DISABLE:
case CMND_TELEINFO_RAW_FULL:
case CMND_TELEINFO_RAW_CHANGE: {
// Enable all RAW frame send
char raw_name[MAX_TINFO_COMMAND_NAME];
@ -899,7 +902,7 @@ void TInfoShow(bool json)
else
{
char name[33];
char value[33];
char value[33];
int percent;
if (isousc) {
@ -916,7 +919,7 @@ void TInfoShow(bool json)
// Hue from 128 (green) to 0 (red) so reversed from percent
hue = changeUIntScale(100-percent, 0, 100, 0, 128);
HsToRgb(hue, 128, &red, &green, &blue);
snprintf_P(phase_color, sizeof(phase_color), PSTR("#%02X%02X%02X"), red, green, blue);
snprintf_P(phase_color, sizeof(phase_color), PSTR("#%02X%02X%02X"), red, green, blue);
WSContentSend_P(HTTP_ENERGY_LOAD_BAR, phase_color, percent, percent);
}
}

View File

@ -166,10 +166,11 @@ void IEM3000Every250ms(void)
case 10:
#ifdef IEM3000_IEM3155
EnergyUpdateTotal(value, true);
Energy.import_active[0] = value;
#else
EnergyUpdateTotal(value64 * 0.001f, true); // 1125 => 1.125
Energy.import_active[0] = value64 * 0.001f; // 1125 => 1.125
#endif
EnergyUpdateTotal();
break;
}

View File

@ -163,7 +163,8 @@ void WE517Every250ms(void)
break;
case 16:
EnergyUpdateTotal(value, true);
Energy.import_active[0] = value;
EnergyUpdateTotal();
break;
}

View File

@ -112,7 +112,8 @@ void Sdm72Every250ms(void)
++Sdm72.read_state %= nitems(sdm72_register);
if (0 == Sdm72.read_state && !isnan(Sdm72.total_active)) {
EnergyUpdateTotal(Sdm72.total_active, true);
Energy.import_active[0] = Sdm72.total_active;
EnergyUpdateTotal();
}
}
} // end data ready