diff --git a/zhaquirks/sonoff/mini-zb2gs-l.py b/zhaquirks/sonoff/mini-zb2gs-l.py new file mode 100644 index 0000000000..27e447c2e0 --- /dev/null +++ b/zhaquirks/sonoff/mini-zb2gs-l.py @@ -0,0 +1,59 @@ +"""Sonoff MINI-ZB2GS-L - Zigbee Switch.""" + +from zigpy import types +from zigpy.quirks import CustomCluster +from zigpy.quirks.v2 import QuirkBuilder +import zigpy.types as t +from zigpy.zcl import foundation +from zigpy.zcl.foundation import BaseAttributeDefs, ZCLAttributeDef + + +class SonoffCluster(CustomCluster): + """Custom Sonoff cluster.""" + + cluster_id = 0xFC11 + + manufacturer_id_override = foundation.ZCLHeader.NO_MANUFACTURER_ID + + class AttributeDefs(BaseAttributeDefs): + """Attribute definitions.""" + + external_trigger_mode = ZCLAttributeDef( + id=0x0016, + type=t.uint8_t, + ) + detach_relay = ZCLAttributeDef( + id=0x0019, + type=t.bitmap8, + ) + + +class SonoffExternalSwitchTriggerType(types.enum8): + """extern switch trigger type.""" + + Edge_trigger = 0x00 + Pulse_trigger = 0x01 + Normally_off_follow_trigger = 0x02 + Normally_on_follow_trigger = 0x82 + + +( + QuirkBuilder("SONOFF", "MINI-ZB2GS-L") + .replaces(SonoffCluster) + .enum( + SonoffCluster.AttributeDefs.external_trigger_mode.name, + SonoffExternalSwitchTriggerType, + SonoffCluster.cluster_id, + translation_key="external_trigger_mode", + fallback_name="External trigger mode", + ) + .switch( + SonoffCluster.AttributeDefs.detach_relay.name, + SonoffCluster.cluster_id, + off_value=0, + on_value=1, + translation_key="detach_relay", + fallback_name="Detach relay", + ) + .add_to_registry() +) diff --git a/zhaquirks/sonoff/mini-zb2gs.py b/zhaquirks/sonoff/mini-zb2gs.py new file mode 100644 index 0000000000..8f4b040b4d --- /dev/null +++ b/zhaquirks/sonoff/mini-zb2gs.py @@ -0,0 +1,112 @@ +"""Sonoff MINI-ZB2GS - Zigbee Switch.""" + +from zigpy import types +from zigpy.quirks import CustomCluster +from zigpy.quirks.v2 import QuirkBuilder +import zigpy.types as t +from zigpy.zcl import foundation +from zigpy.zcl.foundation import BaseAttributeDefs, ZCLAttributeDef + + +class SonoffCluster(CustomCluster): + """Custom Sonoff cluster.""" + + cluster_id = 0xFC11 + manufacturer_id_override = foundation.ZCLHeader.NO_MANUFACTURER_ID + + class AttributeDefs(BaseAttributeDefs): + """Attribute definitions.""" + + external_trigger_mode = ZCLAttributeDef( + id=0x0016, + type=t.uint8_t, + ) + detach_relay = ZCLAttributeDef( + id=0x0019, + type=t.bitmap8, + ) + # 添加turbo模式属性 + turbo_mode = ZCLAttributeDef( + id=0x0012, + type=t.int16s, + ) + # 添加network_led属性 + network_led = ZCLAttributeDef( + id=0x0001, + type=t.Bool, + ) + + +class SonoffExternalSwitchTriggerType(types.enum8): + """extern switch trigger type.""" + + Edge_trigger = 0x00 + Pulse_trigger = 0x01 + Normally_off_follow_trigger = 0x02 + Normally_on_follow_trigger = 0x82 + + +class SonoffDetachRelayType(types.enum8): + """detach relay type.""" + + ALL_CH_DETACH_RELAY_CLOSE = 0x00 + JUST_CH1_ENABLE_DETACH_RELAY = 0x01 + JUST_CH2_ENABLE_DETACH_RELAY = 0x02 + CH1_AND_CH2_ENABLE_DETACH_RELAY = 0x03 + + +# 定义turbo模式的枚举类型 +class SonoffTurboModeType(types.enum16): + """turbo mode type.""" + + NORMAL_MODE = 0x0009 # 9 + TURBO_MODE = 0x0014 # 20 + + +( + QuirkBuilder("SONOFF", "MINI-ZB2GS") + .replaces(SonoffCluster, endpoint_id=1) + .replaces(SonoffCluster, endpoint_id=2) + .enum( + SonoffCluster.AttributeDefs.external_trigger_mode.name, + SonoffExternalSwitchTriggerType, + SonoffCluster.cluster_id, + translation_key="external_trigger_mode", + fallback_name="External trigger mode", + endpoint_id=1, + ) + .enum( + SonoffCluster.AttributeDefs.detach_relay.name, + SonoffDetachRelayType, + SonoffCluster.cluster_id, + translation_key="detach_relay", + fallback_name="Detach relay", + endpoint_id=1, + ) + .enum( + SonoffCluster.AttributeDefs.external_trigger_mode.name, + SonoffExternalSwitchTriggerType, + SonoffCluster.cluster_id, + translation_key="external_trigger_mode", + fallback_name="External trigger mode", + endpoint_id=2, + ) + # 添加turbo模式实体 + .enum( + SonoffCluster.AttributeDefs.turbo_mode.name, + SonoffTurboModeType, + SonoffCluster.cluster_id, + translation_key="turbo_mode", + fallback_name="Turbo mode", + endpoint_id=1, + ) + # 添加network_led实体 + .switch( + SonoffCluster.AttributeDefs.network_led.name, + SonoffCluster.cluster_id, + translation_key="network_led", + fallback_name="Network LED", + endpoint_id=1, + ) + .add_to_registry() +) diff --git a/zhaquirks/sonoff/snzb02dr2.py b/zhaquirks/sonoff/snzb02dr2.py new file mode 100644 index 0000000000..102cfc71fe --- /dev/null +++ b/zhaquirks/sonoff/snzb02dr2.py @@ -0,0 +1,147 @@ +"""Sonoff SNZB-02WD - Zigbee IP65 LCD smart temperature humidity sensor.""" + +from zigpy.quirks import CustomCluster +from zigpy.quirks.v2 import NumberDeviceClass, QuirkBuilder +from zigpy.quirks.v2.homeassistant import PERCENTAGE, UnitOfTemperature +import zigpy.types as t +from zigpy.zcl import foundation +from zigpy.zcl.foundation import BaseAttributeDefs, DataTypeId, ZCLAttributeDef + + +class TemperatureUnit(t.enum16): + """Temperature unit.""" + + Celsius = 0 + Fahrenheit = 1 + + +class CustomSonoffCluster(CustomCluster): + """Sonoff custom cluster.""" + + cluster_id = 0xFC11 + manufacturer_id_override: t.uint16_t = foundation.ZCLHeader.NO_MANUFACTURER_ID + + class AttributeDefs(BaseAttributeDefs): + """Attribute definitions.""" + + comfort_temperature_max = ZCLAttributeDef( + id=0x0003, + type=t.int16s, + ) + + comfort_temperature_min = ZCLAttributeDef( + id=0x0004, + type=t.int16s, + ) + + comfort_humidity_min = ZCLAttributeDef( + id=0x0005, + type=t.uint16_t, + ) + + comfort_humidity_max = ZCLAttributeDef( + id=0x0006, + type=t.uint16_t, + ) + + temperature_unit = ZCLAttributeDef( + id=0x0007, + type=TemperatureUnit, + zcl_type=DataTypeId.uint16, + ) + + temperature_offset = ZCLAttributeDef( + id=0x2003, + type=t.int16s, + ) + + humidity_offset = ZCLAttributeDef( + id=0x2004, + type=t.int16s, + ) + + +( + QuirkBuilder("SONOFF", "SNZB-02DR2") + .replaces(CustomSonoffCluster) + .number( + CustomSonoffCluster.AttributeDefs.comfort_temperature_min.name, + CustomSonoffCluster.cluster_id, + min_value=-10, + max_value=60, + step=0.1, + device_class=NumberDeviceClass.TEMPERATURE, + unit=UnitOfTemperature.CELSIUS, + multiplier=0.01, + translation_key="comfort_temperature_min", + fallback_name="Comfort temperature min", + ) + .number( + CustomSonoffCluster.AttributeDefs.comfort_temperature_max.name, + CustomSonoffCluster.cluster_id, + min_value=-10, + max_value=60, + step=0.1, + device_class=NumberDeviceClass.TEMPERATURE, + unit=UnitOfTemperature.CELSIUS, + multiplier=0.01, + translation_key="comfort_temperature_max", + fallback_name="Comfort temperature max", + ) + .number( + CustomSonoffCluster.AttributeDefs.comfort_humidity_min.name, + CustomSonoffCluster.cluster_id, + min_value=5, + max_value=95, + step=0.1, + device_class=NumberDeviceClass.HUMIDITY, + unit=PERCENTAGE, + multiplier=0.01, + translation_key="comfort_humidity_min", + fallback_name="Comfort humidity min", + ) + .number( + CustomSonoffCluster.AttributeDefs.comfort_humidity_max.name, + CustomSonoffCluster.cluster_id, + min_value=5, + max_value=95, + step=0.1, + device_class=NumberDeviceClass.HUMIDITY, + unit=PERCENTAGE, + multiplier=0.01, + translation_key="comfort_humidity_max", + fallback_name="Comfort humidity max", + ) + .enum( + CustomSonoffCluster.AttributeDefs.temperature_unit.name, + TemperatureUnit, + CustomSonoffCluster.cluster_id, + translation_key="display_unit", + fallback_name="Display unit", + ) + .number( + CustomSonoffCluster.AttributeDefs.temperature_offset.name, + CustomSonoffCluster.cluster_id, + min_value=-50, + max_value=50, + step=0.1, + device_class=NumberDeviceClass.TEMPERATURE, + unit=UnitOfTemperature.CELSIUS, + multiplier=0.01, + translation_key="temperature_offset", + fallback_name="Temperature offset", + ) + .number( + CustomSonoffCluster.AttributeDefs.humidity_offset.name, + CustomSonoffCluster.cluster_id, + min_value=-50, + max_value=50, + step=0.1, + device_class=NumberDeviceClass.HUMIDITY, + unit=PERCENTAGE, + multiplier=0.01, + translation_key="humidity_offset", + fallback_name="Humidity offset", + ) + .add_to_registry() +)