diff --git a/CHANGELOG.md b/CHANGELOG.md index 014b13aa3..a84be6f50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Support for Sonoff MS01 soil moisture sensor (#15335) - Support for daisy chaining MAX7219 displays (#15345) +- Command ``EnergyExportActive`` to (p)reset energy export active for supported devices. Currently ADE7880 only (#13515) ### Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 00240dc5d..ee8b4152f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -106,6 +106,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo ## Changelog v11.1.0.1 ### Added +- Command ``EnergyExportActive`` to (p)reset energy export active for supported devices. Currently ADE7880 only [#13515](https://github.com/arendst/Tasmota/issues/13515) - Support for Sonoff MS01 soil moisture sensor [#15335](https://github.com/arendst/Tasmota/issues/15335) - Support for daisy chaining MAX7219 displays [#15345](https://github.com/arendst/Tasmota/issues/15345) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 47bcce2ae..c2f94c48a 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -444,6 +444,7 @@ #define D_CMND_ENERGYTOTAL "EnergyTotal" #define D_CMND_ENERGYUSAGE "EnergyUsage" #define D_CMND_ENERGYEXPORT "EnergyExport" +#define D_CMND_ENERGYEXPORTACTIVE "EnergyExportActive" #define D_CMND_POWERSET "PowerSet" #define D_CMND_VOLTAGESET "VoltageSet" #define D_CMND_CURRENTSET "CurrentSet" diff --git a/tasmota/settings.h b/tasmota/settings.h index f53be14d6..e2b5be2ac 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -779,10 +779,11 @@ typedef struct { uint8_t tcp_config; // F5F uint8_t light_step_pixels; // F60 - uint8_t free_f61[39]; // F61 - Decrement if adding new Setting variables just above and below + uint8_t free_f61[27]; // F61 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below + int32_t energy_kWhexport_ph[3]; // F7C uint32_t eth_ipv4_address[5]; // F88 uint32_t energy_kWhtotal; // F9C SBitfield1 sbflag1; // FA0 @@ -837,8 +838,9 @@ typedef struct { int32_t energy_kWhtoday_ph[3]; // 2D8 int32_t energy_kWhtotal_ph[3]; // 2E4 + int32_t energy_kWhexport_ph[3]; // 2F0 - // 2F0 - 2FF free locations + uint8_t free_2fc[4]; // 2FC } TRtcSettings; TRtcSettings RtcSettings; #ifdef ESP32 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 1b4c2763c..2670bd63d 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -47,6 +47,7 @@ void RtcSettingsSave(void) { for (uint32_t i = 0; i < 3; i++) { RtcSettings.energy_kWhtoday_ph[i] = Settings->energy_kWhtoday_ph[i]; RtcSettings.energy_kWhtotal_ph[i] = Settings->energy_kWhtotal_ph[i]; + RtcSettings.energy_kWhexport_ph[i] = Settings->energy_kWhexport_ph[i]; } RtcSettings.energy_usage = Settings->energy_usage; for (uint32_t i = 0; i < MAX_COUNTERS; i++) { diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index ff665caf7..d66b76b93 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -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_ENERGYTODAY "|" D_CMND_ENERGYYESTERDAY "|" D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYUSAGE "|" D_CMND_ENERGYEXPORT "|" D_CMND_TARIFF; + D_CMND_ENERGYTODAY "|" D_CMND_ENERGYYESTERDAY "|" D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYEXPORTACTIVE "|" 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 - &CmndEnergyToday, &CmndEnergyYesterday, &CmndEnergyTotal, &CmndEnergyUsage, &CmndEnergyExport, &CmndTariff}; + &CmndEnergyToday, &CmndEnergyYesterday, &CmndEnergyTotal, &CmndEnergyExportActive, &CmndEnergyUsage, &CmndEnergyExport, &CmndTariff}; struct ENERGY { float voltage[ENERGY_MAX_PHASES]; // 123.1 V @@ -105,6 +105,7 @@ struct ENERGY { bool voltage_available; // Enable if voltage is measured bool current_available; // Enable if current is measured + bool local_energy_active_export; // Enable if support for storing energy_active bool type_dc; bool power_on; @@ -243,6 +244,13 @@ void EnergyUpdateToday(void) { int32_t delta = Energy.kWhtoday_delta[i] / 1000; Energy.kWhtoday_delta[i] -= (delta * 1000); Energy.kWhtoday[i] += delta; + + if (delta < 0) { // Export energy + RtcSettings.energy_kWhexport_ph[i] += (delta *-1); + if (Energy.local_energy_active_export) { + Energy.export_active[i] = (float)(RtcSettings.energy_kWhexport_ph[i]) / 100000; + } + } } RtcSettings.energy_kWhtoday_ph[i] = Energy.kWhtoday_offset[i] + Energy.kWhtoday[i]; @@ -338,6 +346,8 @@ void Energy200ms(void) RtcSettings.energy_kWhtotal_ph[i] += RtcSettings.energy_kWhtoday_ph[i]; Settings->energy_kWhtotal_ph[i] = RtcSettings.energy_kWhtotal_ph[i]; + Settings->energy_kWhexport_ph[i] = RtcSettings.energy_kWhexport_ph[i]; + Energy.period[i] -= RtcSettings.energy_kWhtoday_ph[i]; // this becomes a large unsigned, effectively a negative for EnergyShow calculation Energy.kWhtoday[i] = 0; Energy.kWhtoday_offset[i] = 0; @@ -369,6 +379,7 @@ void EnergySaveState(void) for (uint32_t i = 0; i < 3; i++) { Settings->energy_kWhtoday_ph[i] = RtcSettings.energy_kWhtoday_ph[i]; Settings->energy_kWhtotal_ph[i] = RtcSettings.energy_kWhtotal_ph[i]; + Settings->energy_kWhexport_ph[i] = RtcSettings.energy_kWhexport_ph[i]; } Settings->energy_usage = RtcSettings.energy_usage; @@ -629,13 +640,21 @@ void ResponseCmndEnergyTotalYesterdayToday(void) { for (uint32_t i = 0; i < Energy.phase_count; i++) { energy_yesterday_ph[i] = (float)Settings->energy_kWhyesterday_ph[i] / 100000; Energy.total[i] = (float)(RtcSettings.energy_kWhtotal_ph[i] + Energy.kWhtoday_offset[i] + Energy.kWhtoday[i]) / 100000; + if (Energy.local_energy_active_export) { + Energy.export_active[i] = (float)(RtcSettings.energy_kWhexport_ph[i]) / 100000; + } } - Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), + Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%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)); + if (Energy.local_energy_active_export) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), + EnergyFormat(value_chr, Energy.export_active, Settings->flag2.energy_resolution)); + } + ResponseJsonEndEnd(); } void CmndEnergyTotal(void) { @@ -671,6 +690,7 @@ void CmndEnergyYesterday(void) { } ResponseCmndEnergyTotalYesterdayToday(); } + void CmndEnergyToday(void) { uint32_t values[2] = { 0 }; uint32_t params = ParseParameters(2, values); @@ -696,6 +716,26 @@ void CmndEnergyToday(void) { ResponseCmndEnergyTotalYesterdayToday(); } +void CmndEnergyExportActive(void) { + if (Energy.local_energy_active_export) { + // EnergyExportActive1 24 + // EnergyExportActive1 24,1650111291 + uint32_t values[2] = { 0 }; + uint32_t params = ParseParameters(2, values); + + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Energy.phase_count) && (params > 0)) { + uint32_t phase = XdrvMailbox.index -1; + // Reset Energy Export Active + RtcSettings.energy_kWhexport_ph[phase] = values[0] * 100; + Settings->energy_kWhexport_ph[phase] = RtcSettings.energy_kWhexport_ph[phase]; + if (params > 1) { + Settings->energy_kWhtotal_time = values[1]; + } + } + ResponseCmndEnergyTotalYesterdayToday(); + } +} + void ResponseCmndEnergyUsageExport(void) { float usage1_kWhtotal = (float)Settings->energy_usage.usage1_kWhtotal / 100000; float usage2_kWhtotal = (float)Settings->energy_usage.usage2_kWhtotal / 100000; @@ -1032,6 +1072,9 @@ void EnergySnsInit(void) // Energy.kWhtoday_ph[i] = 0; // Energy.kWhtoday_delta[i] = 0; Energy.period[i] = Energy.kWhtoday_offset[i]; + if (Energy.local_energy_active_export) { + Energy.export_active[i] = 0; + } } EnergyUpdateToday(); ticker_energy.attach_ms(200, Energy200ms); diff --git a/tasmota/xnrg_23_ade7880.ino b/tasmota/xnrg_23_ade7880.ino index 9ff070c8c..2bdf9f486 100644 --- a/tasmota/xnrg_23_ade7880.ino +++ b/tasmota/xnrg_23_ade7880.ino @@ -635,6 +635,7 @@ void Ade7880DrvInit(void) { Energy.phase_count = 3; // Three phases // Settings->flag5.energy_phase = 1; // SetOption129 - (Energy) Show phase information // Energy.use_overtemp = true; // Use global temperature for overtemp detection + Energy.local_energy_active_export = true; TasmotaGlobal.energy_driver = XNRG_23; } }