"""Tuya TS201 temperature, humidity and optional illumination sensors.""" from typing import Final from zigpy.profiles import zha from zigpy.profiles.zha import DeviceType from zigpy.quirks import CustomCluster, CustomDevice import zigpy.types as t from zigpy.zcl.clusters.general import Basic, Identify, Ota, PowerConfiguration, Time from zigpy.zcl.clusters.measurement import ( IlluminanceMeasurement, RelativeHumidity, TemperatureMeasurement, ) from zigpy.zcl.foundation import BaseAttributeDefs, ZCLAttributeDef from zigpy.zdo.types import NodeDescriptor from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, NODE_DESCRIPTOR, OUTPUT_CLUSTERS, PROFILE_ID, ) class ValueAlarm(t.enum8): """Temperature and humidity alarm values.""" ALARM_OFF = 0x02 MAX_ALARM_ON = 0x01 MIN_ALARM_ON = 0x00 class TuyaTemperatureHumidityAlarmCluster(CustomCluster): """Tuya temperature and humidity alarm cluster (0xE002).""" name = "Tuya Temperature and Humidity Alarm Cluster" cluster_id = 0xE002 class AttributeDefs(BaseAttributeDefs): """Attribute definitions.""" # Alarm settings alarm_temperature_max: Final = ZCLAttributeDef( id=0xD00A, type=t.uint16_t, is_manufacturer_specific=True ) alarm_temperature_min: Final = ZCLAttributeDef( id=0xD00B, type=t.uint16_t, is_manufacturer_specific=True ) alarm_humidity_max: Final = ZCLAttributeDef( id=0xD00C, type=t.uint16_t, is_manufacturer_specific=True ) alarm_humidity_min: Final = ZCLAttributeDef( id=0xD00E, type=t.uint16_t, is_manufacturer_specific=True ) # Alarm information alarm_humidity: Final = ZCLAttributeDef( id=0xD00F, type=ValueAlarm, is_manufacturer_specific=True ) temperature_humidity: Final = ZCLAttributeDef( id=0xD006, type=ValueAlarm, is_manufacturer_specific=True ) # Unknown unknown: Final = ZCLAttributeDef( id=0xD010, type=t.uint8_t, is_manufacturer_specific=True ) class NeoTemperatureHumidtyIlluminanceSensor(CustomDevice): """Neo temperature, humidity and illumination sensor.""" signature = { # MODELS_INFO: [("_TZ3000_qaaysllp", "TS0201")], ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: DeviceType.LIGHT_SENSOR, INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, IlluminanceMeasurement.cluster_id, TuyaTemperatureHumidityAlarmCluster.cluster_id, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, }, } replacement = { ENDPOINTS: { 1: { INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, IlluminanceMeasurement.cluster_id, TuyaTemperatureHumidityAlarmCluster, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: DeviceType.TEMPERATURE_SENSOR, INPUT_CLUSTERS: [ Basic.cluster_id, TemperatureMeasurement.cluster_id, RelativeHumidity.cluster_id, ], }, }, } class ZemismartTemperatureHumidtySensor(CustomDevice): """Zemismart temperature and humidity sensor.""" signature = { # MODELS_INFO: [("_TZ3000_lfa05ajd", "TS0201")], ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR, INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, Identify.cluster_id, RelativeHumidity.cluster_id, TemperatureMeasurement.cluster_id, 0xEEFF, # Unknown ], OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id], } }, } replacement = { NODE_DESCRIPTOR: NodeDescriptor( 0x02, 0x40, 0x80, 0x1037, 0x7F, 0x0064, 0x2C00, 0x0064, 0x00, # Forcing capability 0x80 instead of 0x84 so AC Power = false ), ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR, INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, Identify.cluster_id, RelativeHumidity.cluster_id, TemperatureMeasurement.cluster_id, ], OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id], } }, } class RelativeHumidityX10(CustomCluster, RelativeHumidity): """Handles invalid humidity values.""" def _update_attribute(self, attrid, value): # x10 factor in measured_value`(attrid=0) if attrid == 0: value = value * 10 super()._update_attribute(attrid, value) class MoesTemperatureHumidtySensorWithScreen(CustomDevice): """Moes temperature and humidity sensor with screen.""" signature = { # ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: DeviceType.TEMPERATURE_SENSOR, INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, Identify.cluster_id, TemperatureMeasurement.cluster_id, RelativeHumidity.cluster_id, TuyaTemperatureHumidityAlarmCluster.cluster_id, ], OUTPUT_CLUSTERS: [ Identify.cluster_id, Time.cluster_id, Ota.cluster_id, ], }, }, } replacement = { ENDPOINTS: { 1: { INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, Identify.cluster_id, TemperatureMeasurement.cluster_id, RelativeHumidityX10, TuyaTemperatureHumidityAlarmCluster, ], OUTPUT_CLUSTERS: [ Identify.cluster_id, Time.cluster_id, Ota.cluster_id, ], }, }, }