From 95286791fe85f0f684364df93803e378ed0a3ce5 Mon Sep 17 00:00:00 2001 From: Oleksandr Kapshuk Date: Wed, 1 Dec 2021 14:17:02 +0200 Subject: [PATCH] Add tuya zndb device category (#59477) --- homeassistant/components/tuya/base.py | 14 ++ homeassistant/components/tuya/const.py | 6 +- homeassistant/components/tuya/sensor.py | 282 ++++++++++++++++-------- homeassistant/components/tuya/switch.py | 14 +- 4 files changed, 225 insertions(+), 91 deletions(-) diff --git a/homeassistant/components/tuya/base.py b/homeassistant/components/tuya/base.py index f7b4453fea8..928899940f4 100644 --- a/homeassistant/components/tuya/base.py +++ b/homeassistant/components/tuya/base.py @@ -89,6 +89,20 @@ class EnumTypeData: return cls(**json.loads(data)) +@dataclass +class ElectricityTypeData: + """Electricity Type Data.""" + + electriccurrent: str | None = None + power: str | None = None + voltage: str | None = None + + @classmethod + def from_json(cls, data: str) -> ElectricityTypeData: + """Load JSON string and return a ElectricityTypeData object.""" + return cls(**json.loads(data.lower())) + + class TuyaEntity(Entity): """Tuya base device.""" diff --git a/homeassistant/components/tuya/const.py b/homeassistant/components/tuya/const.py index e551c6a5229..dd229011c2a 100644 --- a/homeassistant/components/tuya/const.py +++ b/homeassistant/components/tuya/const.py @@ -205,6 +205,7 @@ class DPCode(str, Enum): FILTER_RESET = "filter_reset" # Filter (cartridge) reset FLOODLIGHT_LIGHTNESS = "floodlight_lightness" FLOODLIGHT_SWITCH = "floodlight_switch" + FORWARD_ENERGY_TOTAL = "forward_energy_total" GAS_SENSOR_STATE = "gas_sensor_state" GAS_SENSOR_STATUS = "gas_sensor_status" GAS_SENSOR_VALUE = "gas_sensor_value" @@ -234,6 +235,9 @@ class DPCode(str, Enum): PERCENT_STATE = "percent_state" PERCENT_STATE_2 = "percent_state_2" PERCENT_STATE_3 = "percent_state_3" + PHASE_A = "phase_a" + PHASE_B = "phase_b" + PHASE_C = "phase_c" PIR = "pir" # Motion sensor PM1 = "pm1" PM10 = "pm10" @@ -401,7 +405,7 @@ UNITS = ( ), UnitOfMeasurement( unit=ENERGY_KILO_WATT_HOUR, - aliases={"kwh", "kilowatt-hour"}, + aliases={"kwh", "kilowatt-hour", "kW·h"}, device_classes={DEVICE_CLASS_ENERGY}, ), UnitOfMeasurement( diff --git a/homeassistant/components/tuya/sensor.py b/homeassistant/components/tuya/sensor.py index b09d0ca905f..4ba7fb461c3 100644 --- a/homeassistant/components/tuya/sensor.py +++ b/homeassistant/components/tuya/sensor.py @@ -1,6 +1,7 @@ """Support for Tuya sensors.""" from __future__ import annotations +from dataclasses import dataclass from typing import cast from tuya_iot import TuyaDevice, TuyaDeviceManager @@ -9,6 +10,7 @@ from tuya_iot.device import TuyaDeviceStatusRange from homeassistant.components.sensor import ( DEVICE_CLASS_BATTERY, STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, SensorEntity, SensorEntityDescription, ) @@ -17,6 +19,7 @@ from homeassistant.const import ( DEVICE_CLASS_CO, DEVICE_CLASS_CO2, DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_PM1, @@ -27,8 +30,11 @@ from homeassistant.const import ( DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, DEVICE_CLASS_VOLTAGE, + ELECTRIC_CURRENT_AMPERE, + ELECTRIC_POTENTIAL_VOLT, ENTITY_CATEGORY_DIAGNOSTIC, PERCENTAGE, + POWER_KILO_WATT, ) from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -36,7 +42,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from . import HomeAssistantTuyaData -from .base import EnumTypeData, IntegerTypeData, TuyaEntity +from .base import ElectricityTypeData, EnumTypeData, IntegerTypeData, TuyaEntity from .const import ( DEVICE_CLASS_TUYA_STATUS, DEVICE_CLASS_UNITS, @@ -46,9 +52,17 @@ from .const import ( UnitOfMeasurement, ) + +@dataclass +class TuyaSensorEntityDescription(SensorEntityDescription): + """Describes Tuya sensor entity.""" + + subkey: str | None = None + + # Commonly used battery sensors, that are re-used in the sensors down below. -BATTERY_SENSORS: tuple[SensorEntityDescription, ...] = ( - SensorEntityDescription( +BATTERY_SENSORS: tuple[TuyaSensorEntityDescription, ...] = ( + TuyaSensorEntityDescription( key=DPCode.BATTERY_PERCENTAGE, name="Battery", native_unit_of_measurement=PERCENTAGE, @@ -56,20 +70,20 @@ BATTERY_SENSORS: tuple[SensorEntityDescription, ...] = ( state_class=STATE_CLASS_MEASUREMENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.BATTERY_STATE, name="Battery State", icon="mdi:battery", entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.BATTERY_VALUE, name="Battery", device_class=DEVICE_CLASS_BATTERY, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VA_BATTERY, name="Battery", device_class=DEVICE_CLASS_BATTERY, @@ -82,23 +96,23 @@ BATTERY_SENSORS: tuple[SensorEntityDescription, ...] = ( # default status set of each category (that don't have a set instruction) # end up being a sensor. # https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq -SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { +SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = { # Smart Kettle # https://developer.tuya.com/en/docs/iot/fbh?id=K9gf484m21yq7 "bh": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Current Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT_F, name="Current Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.STATUS, name="Status", device_class=DEVICE_CLASS_TUYA_STATUS, @@ -107,19 +121,19 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # CO2 Detector # https://developer.tuya.com/en/docs/iot/categoryco2bj?id=Kaiuz3wes7yuy "co2bj": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.HUMIDITY_VALUE, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO2_VALUE, name="Carbon Dioxide", device_class=DEVICE_CLASS_CO2, @@ -130,7 +144,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # CO Detector # https://developer.tuya.com/en/docs/iot/categorycobj?id=Kaiuz3u1j6q1v "cobj": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO_VALUE, name="Carbon Monoxide", device_class=DEVICE_CLASS_CO, @@ -141,101 +155,76 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Air Quality Monitor # No specification on Tuya portal "hjjcy": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.HUMIDITY_VALUE, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO2_VALUE, name="Carbon Dioxide", device_class=DEVICE_CLASS_CO2, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CH2O_VALUE, name="Formaldehyde", state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VOC_VALUE, name="Volatile Organic Compound", device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PM25_VALUE, name="Particulate Matter 2.5 µm", device_class=DEVICE_CLASS_PM25, state_class=STATE_CLASS_MEASUREMENT, ), ), - # Switch - # https://developer.tuya.com/en/docs/iot/s?id=K9gf7o5prgf7s - "kg": ( - SensorEntityDescription( - key=DPCode.CUR_CURRENT, - name="Current", - device_class=DEVICE_CLASS_CURRENT, - state_class=STATE_CLASS_MEASUREMENT, - entity_registry_enabled_default=False, - ), - SensorEntityDescription( - key=DPCode.CUR_POWER, - name="Power", - device_class=DEVICE_CLASS_POWER, - state_class=STATE_CLASS_MEASUREMENT, - entity_registry_enabled_default=False, - ), - SensorEntityDescription( - key=DPCode.CUR_VOLTAGE, - name="Voltage", - device_class=DEVICE_CLASS_VOLTAGE, - state_class=STATE_CLASS_MEASUREMENT, - entity_registry_enabled_default=False, - ), - ), # Formaldehyde Detector # Note: Not documented "jqbj": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO2_VALUE, name="Carbon Dioxide", device_class=DEVICE_CLASS_CO2, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VOC_VALUE, name="Volatile Organic Compound", device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PM25_VALUE, name="Particulate Matter 2.5 µm", device_class=DEVICE_CLASS_PM25, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VA_HUMIDITY, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VA_TEMPERATURE, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CH2O_VALUE, name="Formaldehyde", state_class=STATE_CLASS_MEASUREMENT, @@ -245,40 +234,65 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Methane Detector # https://developer.tuya.com/en/docs/iot/categoryjwbj?id=Kaiuz40u98lkm "jwbj": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CH4_SENSOR_VALUE, name="Methane", state_class=STATE_CLASS_MEASUREMENT, ), *BATTERY_SENSORS, ), + # Switch + # https://developer.tuya.com/en/docs/iot/s?id=K9gf7o5prgf7s + "kg": ( + TuyaSensorEntityDescription( + key=DPCode.CUR_CURRENT, + name="Current", + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + entity_registry_enabled_default=False, + ), + TuyaSensorEntityDescription( + key=DPCode.CUR_POWER, + name="Power", + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + entity_registry_enabled_default=False, + ), + TuyaSensorEntityDescription( + key=DPCode.CUR_VOLTAGE, + name="Voltage", + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + entity_registry_enabled_default=False, + ), + ), # Luminance Sensor # https://developer.tuya.com/en/docs/iot/categoryldcg?id=Kaiuz3n7u69l8 "ldcg": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.BRIGHT_STATE, name="Luminosity", icon="mdi:brightness-6", ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.BRIGHT_VALUE, name="Luminosity", device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.HUMIDITY_VALUE, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO2_VALUE, name="Carbon Dioxide", device_class=DEVICE_CLASS_CO2, @@ -295,48 +309,48 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # PM2.5 Sensor # https://developer.tuya.com/en/docs/iot/categorypm25?id=Kaiuz3qof3yfu "pm2.5": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PM25_VALUE, name="Particulate Matter 2.5 µm", device_class=DEVICE_CLASS_PM25, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CH2O_VALUE, name="Formaldehyde", state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VOC_VALUE, name="Volatile Organic Compound", device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO2_VALUE, name="Carbon Dioxide", device_class=DEVICE_CLASS_CO2, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.HUMIDITY_VALUE, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PM1, name="Particulate Matter 1.0 µm", device_class=DEVICE_CLASS_PM1, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PM10, name="Particulate Matter 10.0 µm", device_class=DEVICE_CLASS_PM10, @@ -347,7 +361,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Heater # https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm "qn": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.WORK_POWER, name="Power", device_class=DEVICE_CLASS_POWER, @@ -357,7 +371,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Gas Detector # https://developer.tuya.com/en/docs/iot/categoryrqbj?id=Kaiuz3d162ubw "rqbj": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.GAS_SENSOR_VALUE, icon="mdi:gas-cylinder", device_class=STATE_CLASS_MEASUREMENT, @@ -373,19 +387,19 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Smart Camera # https://developer.tuya.com/en/docs/iot/categorysp?id=Kaiuz35leyo12 "sp": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.SENSOR_TEMPERATURE, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.SENSOR_HUMIDITY, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.WIRELESS_ELECTRICITY, name="Battery", device_class=DEVICE_CLASS_BATTERY, @@ -393,42 +407,44 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { state_class=STATE_CLASS_MEASUREMENT, ), ), + # Fingerbot + "szjqr": BATTERY_SENSORS, # Solar Light # https://developer.tuya.com/en/docs/iot/tynd?id=Kaof8j02e1t98 "tyndj": BATTERY_SENSORS, # Volatile Organic Compound Sensor # Note: Undocumented in cloud API docs, based on test device "voc": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CO2_VALUE, name="Carbon Dioxide", device_class=DEVICE_CLASS_CO2, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PM25_VALUE, name="Particulate Matter 2.5 µm", device_class=DEVICE_CLASS_PM25, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.CH2O_VALUE, name="Formaldehyde", state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.HUMIDITY_VALUE, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VOC_VALUE, name="Volatile Organic Compound", device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, @@ -439,31 +455,31 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Temperature and Humidity Sensor # https://developer.tuya.com/en/docs/iot/categorywsdcg?id=Kaiuz3hinij34 "wsdcg": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VA_TEMPERATURE, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.TEMP_CURRENT, name="Temperature", device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.VA_HUMIDITY, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.HUMIDITY_VALUE, name="Humidity", device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.BRIGHT_VALUE, name="Luminosity", device_class=DEVICE_CLASS_ILLUMINANCE, @@ -474,7 +490,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Pressure Sensor # https://developer.tuya.com/en/docs/iot/categoryylcg?id=Kaiuz3kc2e4gm "ylcg": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.PRESSURE_VALUE, device_class=DEVICE_CLASS_PRESSURE, state_class=STATE_CLASS_MEASUREMENT, @@ -484,7 +500,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Smoke Detector # https://developer.tuya.com/en/docs/iot/categoryywbj?id=Kaiuz3f6sf952 "ywbj": ( - SensorEntityDescription( + TuyaSensorEntityDescription( key=DPCode.SMOKE_SENSOR_VALUE, name="Smoke Amount", icon="mdi:smoke-detector", @@ -496,8 +512,88 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { # Vibration Sensor # https://developer.tuya.com/en/docs/iot/categoryzd?id=Kaiuz3a5vrzno "zd": BATTERY_SENSORS, - # Fingerbot - "szjqr": BATTERY_SENSORS, + # Smart Electricity Meter + # https://developer.tuya.com/en/docs/iot/smart-meter?id=Kaiuz4gv6ack7 + "zndb": ( + TuyaSensorEntityDescription( + key=DPCode.FORWARD_ENERGY_TOTAL, + name="Total Energy", + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_A, + name="Phase A Current", + device_class=DEVICE_CLASS_CURRENT, + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + state_class=STATE_CLASS_MEASUREMENT, + subkey="electriccurrent", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_A, + name="Phase A Power", + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=POWER_KILO_WATT, + subkey="power", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_A, + name="Phase A Voltage", + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + subkey="voltage", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_B, + name="Phase B Current", + device_class=DEVICE_CLASS_CURRENT, + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + state_class=STATE_CLASS_MEASUREMENT, + subkey="electriccurrent", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_B, + name="Phase B Power", + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=POWER_KILO_WATT, + subkey="power", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_B, + name="Phase B Voltage", + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + subkey="voltage", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_C, + name="Phase C Current", + device_class=DEVICE_CLASS_CURRENT, + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + state_class=STATE_CLASS_MEASUREMENT, + subkey="electriccurrent", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_C, + name="Phase C Power", + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=POWER_KILO_WATT, + subkey="power", + ), + TuyaSensorEntityDescription( + key=DPCode.PHASE_C, + name="Phase C Voltage", + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + subkey="voltage", + ), + ), } # Socket (duplicate of `kg`) @@ -545,6 +641,8 @@ async def async_setup_entry( class TuyaSensorEntity(TuyaEntity, SensorEntity): """Tuya Sensor Entity.""" + entity_description: TuyaSensorEntityDescription + _status_range: TuyaDeviceStatusRange | None = None _type_data: IntegerTypeData | EnumTypeData | None = None _uom: UnitOfMeasurement | None = None @@ -553,12 +651,14 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity): self, device: TuyaDevice, device_manager: TuyaDeviceManager, - description: SensorEntityDescription, + description: TuyaSensorEntityDescription, ) -> None: """Init Tuya sensor.""" super().__init__(device, device_manager) self.entity_description = description - self._attr_unique_id = f"{super().unique_id}{description.key}" + self._attr_unique_id = ( + f"{super().unique_id}{description.key}{description.subkey or ''}" + ) if status_range := device.status_range.get(description.key): self._status_range = cast(TuyaDeviceStatusRange, status_range) @@ -614,6 +714,7 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity): "Integer", "String", "Enum", + "Json", ): return None @@ -636,5 +737,12 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity): ): return None + # Get subkey value from Json string. + if self._status_range.type == "Json": + if self.entity_description.subkey is None: + return None + values = ElectricityTypeData.from_json(value) + return getattr(values, self.entity_description.subkey) + # Valid string or enum value return value diff --git a/homeassistant/components/tuya/switch.py b/homeassistant/components/tuya/switch.py index 97361a5c2c7..acc6e2e57e0 100644 --- a/homeassistant/components/tuya/switch.py +++ b/homeassistant/components/tuya/switch.py @@ -385,6 +385,14 @@ SWITCHES: dict[str, tuple[SwitchEntityDescription, ...]] = { entity_category=ENTITY_CATEGORY_CONFIG, ), ), + # Fingerbot + "szjqr": ( + SwitchEntityDescription( + key=DPCode.SWITCH, + name="Switch", + icon="mdi:cursor-pointer", + ), + ), # IoT Switch? # Note: Undocumented "tdq": ( @@ -449,12 +457,12 @@ SWITCHES: dict[str, tuple[SwitchEntityDescription, ...]] = { entity_category=ENTITY_CATEGORY_CONFIG, ), ), - # Fingerbot - "szjqr": ( + # Smart Electricity Meter + # https://developer.tuya.com/en/docs/iot/smart-meter?id=Kaiuz4gv6ack7 + "zndb": ( SwitchEntityDescription( key=DPCode.SWITCH, name="Switch", - icon="mdi:cursor-pointer", ), ), }