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
This commit is contained in:
Shantur Rathore 2019-08-27 10:50:34 +01:00
parent 579f68cf2f
commit 231a1ba137
3 changed files with 46 additions and 3 deletions

View File

@ -232,7 +232,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED };
enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; 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 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 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}; 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};

View File

@ -654,6 +654,9 @@ void CmndSetoption(void)
#endif #endif
#ifdef USE_TUYA_DIMMER #ifdef USE_TUYA_DIMMER
case P_TUYA_RELAYS: case P_TUYA_RELAYS:
case P_TUYA_POWER_ID:
case P_TUYA_CURRENT_ID:
case P_TUYA_VOLTAGE_ID:
case P_TUYA_DIMMER_MAX: case P_TUYA_DIMMER_MAX:
restart_flag = 2; // Need a restart to update GUI restart_flag = 2; // Need a restart to update GUI
break; break;

View File

@ -21,13 +21,12 @@
#ifdef USE_TUYA_DIMMER #ifdef USE_TUYA_DIMMER
#define XDRV_16 16 #define XDRV_16 16
#define XNRG_08 8
#ifndef TUYA_DIMMER_ID #ifndef TUYA_DIMMER_ID
#define TUYA_DIMMER_ID 0 #define TUYA_DIMMER_ID 0
#endif #endif
#define TUYA_POWER_ID 1
#define TUYA_CMD_HEARTBEAT 0x00 #define TUYA_CMD_HEARTBEAT 0x00
#define TUYA_CMD_QUERY_PRODUCT 0x01 #define TUYA_CMD_QUERY_PRODUCT 0x01
#define TUYA_CMD_MCU_CONF 0x02 #define TUYA_CMD_MCU_CONF 0x02
@ -55,6 +54,7 @@ struct TUYA {
uint8_t data_len = 0; // Data lenght of command uint8_t data_len = 0; // Data lenght of command
int8_t wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() 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 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 char *buffer = nullptr; // Serial receive buffer
int byte_counter = 0; // Index in 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; break;
@ -440,5 +459,26 @@ bool Xdrv16(uint8_t function)
return result; 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_TUYA_DIMMER
#endif // USE_LIGHT #endif // USE_LIGHT