From f31b903fab8832e471000ce6fa31ebb1bdb533e6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Aug 2019 17:01:12 +0200 Subject: [PATCH] Bump version to 6.6.0.8 * Add Tuya Energy monitoring by Shantur Rathore * Add phase 1 Domoticz P1 Smart Meter support using energy sensors handled by xdrv_03_energy.ino based on an idea by pablozg * Add commands Tariff1 0..23 (start Off-Peak hour), Tariff2 0..23 (start Standard hour) and Tariff3 0/1 (Saturday and Sunday Off-Peak) --- sonoff/_changelog.ino | 5 +++ sonoff/settings.h | 8 ++-- sonoff/settings.ino | 15 +++++++- sonoff/sonoff.h | 6 ++- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_03_energy.ino | 78 +++++++++++++++++++++++++++++++++++---- 6 files changed, 100 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c592b7abf..422ef4f9d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ /*********************************************************************************************\ + * 6.6.0.8 20190827 + * Add Tuya Energy monitoring by Shantur Rathore + * Add phase 1 Domoticz P1 Smart Meter support using energy sensors handled by xdrv_03_energy.ino based on an idea by pablozg + * Add commands Tariff1 0..23 (start Off-Peak hour), Tariff2 0..23 (start Standard hour) and Tariff3 0/1 (Saturday and Sunday Off-Peak) + * * 6.6.0.7 20190825 * Expand Settings area to 4k for future use * diff --git a/sonoff/settings.h b/sonoff/settings.h index 1c4ccd1a5..591c4ff35 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -83,7 +83,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM uint32_t tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. - uint32_t spare20 : 1; + uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF uint32_t spare21 : 1; uint32_t spare22 : 1; uint32_t spare23 : 1; @@ -179,7 +179,7 @@ typedef union { typedef struct { uint32_t usage1_kWhtotal; - uint32_t usage2_kWhtotal; + uint32_t usage1_kWhtoday; uint32_t return1_kWhtotal; uint32_t return2_kWhtotal; uint32_t last_usage_kWhtotal; @@ -367,8 +367,10 @@ struct SYSCFG { uint16_t web_refresh; // 7CC char mems[MAX_RULE_MEMS][10]; // 7CE char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b + uint8_t data8[32]; // E00 + uint16_t data16[16]; // E20 - uint8_t free_e00[512]; // E00 + uint8_t free_e20[448]; // E40 // FFF last location } Settings; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 158b92319..3eed18d1b 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -128,6 +128,15 @@ #ifndef TUYA_DIMMER_MAX #define TUYA_DIMMER_MAX 100 #endif +#ifndef ENERGY_TARIFF1_HOUR +#define ENERGY_TARIFF1_HOUR 23 // Start hour "nighttime" or "off-peak" tariff +#endif +#ifndef ENERGY_TARIFF2_HOUR +#define ENERGY_TARIFF2_HOUR 7 // Start hour "daytime" or "standard" tariff +#endif +#ifndef ENERGY_TARIFF_WEEKEND +#define ENERGY_TARIFF_WEEKEND 1 // 0 = No difference in weekend, 1 = off-peak during weekend +#endif enum WebColors { COL_TEXT, COL_BACKGROUND, COL_FORM, @@ -1070,13 +1079,17 @@ void SettingsDelta(void) } if (Settings.version < 0x06060007) { memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); - + } + if (Settings.version < 0x06060008) { // Move current tuya dimmer range to the new param. if (Settings.flag3.tuya_dimmer_range_255) { Settings.param[P_TUYA_DIMMER_MAX] = 100; } else { Settings.param[P_TUYA_DIMMER_MAX] = 255; } + Settings.param[P_ENERGY_TARIFF1] = ENERGY_TARIFF1_HOUR; + Settings.param[P_ENERGY_TARIFF2] = ENERGY_TARIFF2_HOUR; + Settings.flag3.energy_weekend = ENERGY_TARIFF_WEEKEND; } Settings.version = VERSION; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index c31f1196a..818a42408 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -231,8 +231,10 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 - P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_TUYA_RELAYS, P_OVER_TEMP, P_TUYA_DIMMER_MAX, P_TUYA_VOLTAGE_ID, P_TUYA_CURRENT_ID, P_TUYA_POWER_ID, // SetOption39 .. SetOption46 +enum SettingsParamIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 + P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42 + P_TUYA_DIMMER_MAX, P_TUYA_VOLTAGE_ID, P_TUYA_CURRENT_ID, P_TUYA_POWER_ID, // SetOption43 .. SetOption46 + P_ENERGY_TARIFF1, P_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 29d2a455a..e216004be 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060007; +const uint32_t VERSION = 0x06060008; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 37fc8f6d5..13345fc2c 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -22,20 +22,21 @@ * Energy \*********************************************************************************************/ -#define XDRV_03 3 -#define XSNS_03 3 +#define XDRV_03 3 +#define XSNS_03 3 //#define USE_ENERGY_MARGIN_DETECTION // #define USE_ENERGY_POWER_LIMIT -#define ENERGY_NONE 0 -#define ENERGY_WATCHDOG 4 // Allow up to 4 seconds before deciding no valid data present +#define ENERGY_NONE 0 +#define ENERGY_WATCHDOG 4 // Allow up to 4 seconds before deciding no valid data present #include #define D_CMND_POWERCAL "PowerCal" #define D_CMND_VOLTAGECAL "VoltageCal" #define D_CMND_CURRENTCAL "CurrentCal" +#define D_CMND_TARIFF "Tariff" enum EnergyCommands { CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, @@ -52,7 +53,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_ENERGYRESET "|" D_CMND_TARIFF ; void (* const EnergyCommand[])(void) PROGMEM = { &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, @@ -65,7 +66,7 @@ void (* const EnergyCommand[])(void) PROGMEM = { &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, #endif // USE_ENERGY_POWER_LIMIT #endif // USE_ENERGY_MARGIN_DETECTION - &CmndEnergyReset }; + &CmndEnergyReset, &CmndTariff }; struct ENERGY { float voltage = 0; // 123.1 V @@ -78,10 +79,12 @@ struct ENERGY { float start_energy = 0; // 12345.12345 kWh total previous float daily = 0; // 123.123 kWh - float total = 0; // 12345.12345 kWh + float total = 0; // 12345.12345 kWh tariff 1 + 2 + float total1 = 0; // 12345.12345 kWh tariff 1 - off-peak unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily + unsigned long kWhtoday1; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily uint8_t fifth_second = 0; @@ -126,9 +129,21 @@ void EnergyUpdateToday(void) Energy.kWhtoday_delta -= (delta * 1000); Energy.kWhtoday += delta; } + uint32_t energy_diff = Energy.kWhtoday - RtcSettings.energy_kWhtoday; + RtcSettings.energy_kWhtoday = Energy.kWhtoday; Energy.daily = (float)Energy.kWhtoday / 100000; Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000; + + if ((RtcTime.hour < Settings.param[P_ENERGY_TARIFF2]) || // Tarrif1 = Off-Peak + (RtcTime.hour >= Settings.param[P_ENERGY_TARIFF1]) || + (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || + (RtcTime.day_of_week == 7))) + ) { + Energy.kWhtoday1 += energy_diff; + RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1; + Energy.total1 = (float)(RtcSettings.energy_usage.usage1_kWhtotal + Energy.kWhtoday1) / 100000; + } } /*********************************************************************************************/ @@ -146,9 +161,15 @@ void Energy200ms(void) if (RtcTime.valid) { if (LocalTime() == Midnight()) { Settings.energy_kWhyesterday = Energy.kWhtoday; + Settings.energy_kWhtotal += Energy.kWhtoday; RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; Energy.kWhtoday = 0; + + Settings.energy_usage.usage1_kWhtotal += Energy.kWhtoday1; + RtcSettings.energy_usage.usage1_kWhtotal = Settings.energy_usage.usage1_kWhtotal; + Energy.kWhtoday1 = 0; + Energy.kWhtoday_delta = 0; Energy.period = Energy.kWhtoday; EnergyUpdateToday(); @@ -171,9 +192,14 @@ void Energy200ms(void) void EnergySaveState(void) { Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; + Settings.energy_kWhtoday = Energy.kWhtoday; RtcSettings.energy_kWhtoday = Energy.kWhtoday; Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Settings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1; + RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1; + Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; } #ifdef USE_ENERGY_MARGIN_DETECTION @@ -409,6 +435,19 @@ void CmndEnergyReset(void) break; } } + + if (Energy.kWhtoday1 > Energy.kWhtoday) { + Energy.kWhtoday1 = Energy.kWhtoday; + } + if (Settings.energy_usage.usage1_kWhtoday > Settings.energy_kWhtoday) { + Settings.energy_usage.usage1_kWhtoday = Settings.energy_kWhtoday; + RtcSettings.energy_usage.usage1_kWhtoday = Settings.energy_kWhtoday; + } + if (Settings.energy_usage.usage1_kWhtotal > Settings.energy_kWhtotal) { + Settings.energy_usage.usage1_kWhtotal = Settings.energy_kWhtotal; + RtcSettings.energy_usage.usage1_kWhtotal = Settings.energy_kWhtotal; + } + char energy_total_chr[33]; dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); char energy_daily_chr[33]; @@ -421,6 +460,23 @@ void CmndEnergyReset(void) } } +void CmndTariff(void) +{ + // Tariff1 23 + // Tariff2 7 + // Tariff3 0/1 + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { + Settings.param[P_ENERGY_TARIFF1 + XdrvMailbox.index -1] = XdrvMailbox.payload; + } + } + else if (XdrvMailbox.index == 3) { + Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; + } + Response_P(PSTR("{\"%s\":{\"Off-Peak\":%d,\"Standard\":%d,\"Weekend\":\"%s\"}}"), + XdrvMailbox.command, Settings.param[P_ENERGY_TARIFF1], Settings.param[P_ENERGY_TARIFF2], GetStateText(Settings.flag3.energy_weekend)); +} + void CmndPowerCal(void) { Energy.command_code = CMND_POWERCAL; @@ -623,6 +679,7 @@ void EnergySnsInit(void) if (energy_flg) { Energy.kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0; + Energy.kWhtoday1 = (RtcSettingsValid()) ? RtcSettings.energy_usage.usage1_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_usage.usage1_kWhtoday : 0; Energy.kWhtoday_delta = 0; Energy.period = Energy.kWhtoday; EnergyUpdateToday(); @@ -736,6 +793,13 @@ void EnergyShow(bool json) if (show_energy_period) { // Only send if telemetry dtostrfd(Energy.total * 1000, 1, energy_total_chr); DomoticzSensorPowerEnergy((int)Energy.active_power, energy_total_chr); // PowerUsage, EnergyToday + + dtostrfd((Energy.total - Energy.total1) * 1000, 1, energy_total_chr); // Tariff2 + char energy_total1_chr[33]; + dtostrfd(Energy.total1 * 1000, 1, energy_total1_chr); // Tariff1 + char energy_non[2] = "0"; + DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power, 0); + if (Energy.voltage_available) { DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage }