From 231a1ba1371c545703e4efd879b106ef7c4ff623 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 27 Aug 2019 10:50:34 +0100 Subject: [PATCH] Tuya Serial: Add support for power metering Capable Tuya serial devices send power metering data over serial interface. User needs to identify the ids of all power metering functions and set as SetOption44 -> Voltage SetOption45 -> Current SetOption46 -> Power --- sonoff/sonoff.h | 2 +- sonoff/support_command.ino | 3 +++ sonoff/xdrv_16_tuyadimmer.ino | 44 +++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 8bc215c69..c31f1196a 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -232,7 +232,7 @@ 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, // SetOption39 .. SetOption43 + 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 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/support_command.ino b/sonoff/support_command.ino index f897e8d80..bd07643e9 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -654,6 +654,9 @@ void CmndSetoption(void) #endif #ifdef USE_TUYA_DIMMER case P_TUYA_RELAYS: + case P_TUYA_POWER_ID: + case P_TUYA_CURRENT_ID: + case P_TUYA_VOLTAGE_ID: case P_TUYA_DIMMER_MAX: restart_flag = 2; // Need a restart to update GUI break; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 513abf1b4..85a4083d6 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -21,13 +21,12 @@ #ifdef USE_TUYA_DIMMER #define XDRV_16 16 +#define XNRG_08 8 #ifndef TUYA_DIMMER_ID #define TUYA_DIMMER_ID 0 #endif -#define TUYA_POWER_ID 1 - #define TUYA_CMD_HEARTBEAT 0x00 #define TUYA_CMD_QUERY_PRODUCT 0x01 #define TUYA_CMD_MCU_CONF 0x02 @@ -55,6 +54,7 @@ struct TUYA { uint8_t data_len = 0; // Data lenght of command int8_t wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() uint8_t heartbeat_timer = 0; // 10 second heartbeat timer for tuya module + uint32_t lastPowerCheckTime = 0; // Time when last power was checked char *buffer = nullptr; // Serial receive buffer int byte_counter = 0; // Index in serial receive buffer @@ -228,6 +228,25 @@ void TuyaPacketProcess(void) } } } + + if (Settings.param[P_TUYA_VOLTAGE_ID] == Tuya.buffer[6]) { + Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Settings.param[P_TUYA_VOLTAGE_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + } else if (Settings.param[P_TUYA_CURRENT_ID] == Tuya.buffer[6]) { + Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Settings.param[P_TUYA_CURRENT_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + } else if (Settings.param[P_TUYA_POWER_ID] == Tuya.buffer[6]) { + Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Settings.param[P_TUYA_POWER_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + + if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) { + Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; + EnergyUpdateToday(); + } + Tuya.lastPowerCheckTime = Rtc.utc_time; + } else if (Settings.param[P_TUYA_DIMMER_ID] != Tuya.buffer[6]){ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Unknown ID=%d"), Tuya.buffer[6]); + } } break; @@ -440,5 +459,26 @@ bool Xdrv16(uint8_t function) return result; } +/*********************************************************************************************\ + * Energy Interface +\*********************************************************************************************/ + +int Xnrg08(uint8_t function) +{ + int result = 0; + if (FUNC_PRE_INIT == function) { + if (Settings.param[P_TUYA_POWER_ID] != 0) { + energy_flg = XNRG_08; + } + if (Settings.param[P_TUYA_CURRENT_ID] == 0) { + Energy.current_available = false; + } + if (Settings.param[P_TUYA_VOLTAGE_ID] == 0) { + Energy.voltage_available = false; + } + } + return result; +} + #endif // USE_TUYA_DIMMER #endif // USE_LIGHT