|
| 1 | + """Device handler for Bosch RBSH-RTH0-ZB-EU thermostat.""" |
| 2 | + |
| 3 | +from typing import Any, Final |
| 4 | + |
| 5 | +from zigpy.device import Device |
| 6 | +from zigpy.profiles import zha |
| 7 | +from zigpy.quirks import CustomCluster |
| 8 | +from zigpy.quirks.registry import DeviceRegistry |
| 9 | +from zigpy.quirks.v2 import ( |
| 10 | + CustomDeviceV2, |
| 11 | + add_to_registry_v2, |
| 12 | +) |
| 13 | +from zigpy.quirks.v2.homeassistant.number import NumberDeviceClass |
| 14 | +import zigpy.types as t |
| 15 | +from zigpy.zcl import ClusterType |
| 16 | +from zigpy.zcl.clusters.hvac import Thermostat, UserInterface |
| 17 | +from zigpy.zcl.foundation import BaseAttributeDefs, ZCLAttributeDef, ZCLCommandDef |
| 18 | + |
| 19 | +"""Bosch specific thermostat attribute ids.""" |
| 20 | +OPERATING_MODE_ATTR_ID = 0x4007 |
| 21 | +VALVE_POSITION_ATTR_ID = 0x4020 |
| 22 | +WINDOW_OPEN_ATTR_ID = 0x4042 |
| 23 | +BOOST_ATTR_ID = 0x4043 |
| 24 | + |
| 25 | +"""Bosch specific user interface attribute ids.""" |
| 26 | +SCREEN_TIMEOUT_ATTR_ID = 0x403a |
| 27 | +SCREEN_BRIGHTNESS_ATTR_ID = 0x403b |
| 28 | + |
| 29 | +"""Bosh operating mode attribute values.""" |
| 30 | +class BoschOperatingMode(t.enum8): |
| 31 | + Schedule = 0x00 |
| 32 | + Manual = 0x01 |
| 33 | + Pause = 0x05 |
| 34 | + |
| 35 | +"""Bosch thermostat preset.""" |
| 36 | +class BoschPreset(t.enum8): |
| 37 | + Normal = 0x00 |
| 38 | + Boost = 0x01 |
| 39 | + |
| 40 | +"""Binary attribute (window open) value.""" |
| 41 | +class State(t.enum8): |
| 42 | + Off = 0x00 |
| 43 | + On = 0x01 |
| 44 | + |
| 45 | +class BoschThermostatCluster(CustomCluster, Thermostat): |
| 46 | + """Bosch thermostat cluster.""" |
| 47 | + |
| 48 | + class AttributeDefs(Thermostat.AttributeDefs): |
| 49 | + operating_mode = ZCLAttributeDef( |
| 50 | + id=t.uint16_t(OPERATING_MODE_ATTR_ID), |
| 51 | + type=BoschOperatingMode, |
| 52 | + is_manufacturer_specific=True, |
| 53 | + ) |
| 54 | + |
| 55 | + pi_heating_demand = ZCLAttributeDef( |
| 56 | + id=t.uint16_t(VALVE_POSITION_ATTR_ID), |
| 57 | + # Values range from 0-100 |
| 58 | + type=t.enum8, |
| 59 | + is_manufacturer_specific=True, |
| 60 | + ) |
| 61 | + |
| 62 | + window_open = ZCLAttributeDef( |
| 63 | + id=t.uint16_t(WINDOW_OPEN_ATTR_ID), |
| 64 | + type=State, |
| 65 | + is_manufacturer_specific=True, |
| 66 | + ) |
| 67 | + |
| 68 | + boost = ZCLAttributeDef( |
| 69 | + id=t.uint16_t(BOOST_ATTR_ID), |
| 70 | + type=BoschPreset, |
| 71 | + is_manufacturer_specific=True, |
| 72 | + ) |
| 73 | + |
| 74 | + |
| 75 | +class BoschUserInterfaceCluster(CustomCluster, UserInterface): |
| 76 | + """Bosch UserInterface cluster.""" |
| 77 | + |
| 78 | + class AttributeDefs(UserInterface.AttributeDefs): |
| 79 | + display_ontime = ZCLAttributeDef( |
| 80 | + id=t.uint16_t(SCREEN_TIMEOUT_ATTR_ID), |
| 81 | + # Usable values range from 5-30 |
| 82 | + type=t.enum8, |
| 83 | + is_manufacturer_specific=True, |
| 84 | + ) |
| 85 | + |
| 86 | + display_brightness = ZCLAttributeDef( |
| 87 | + id=t.uint16_t(SCREEN_BRIGHTNESS_ATTR_ID), |
| 88 | + # Values range from 0-10 |
| 89 | + type=t.enum8, |
| 90 | + is_manufacturer_specific=True, |
| 91 | + ) |
| 92 | + |
| 93 | + |
| 94 | +class BoschThermostat(CustomDeviceV2): |
| 95 | + """Bosch thermostat custom device.""" |
| 96 | + |
| 97 | +( |
| 98 | + add_to_registry_v2( |
| 99 | + "Bosch", "RBSH-RTH0-ZB-EU" |
| 100 | + ) |
| 101 | + .device_class(BoschThermostat) |
| 102 | + .replaces(BoschThermostatCluster) |
| 103 | + .replaces(BoschUserInterfaceCluster) |
| 104 | + # Operating mode: controlled automatically through Thermostat.system_mode (HAVC mode). |
| 105 | + .enum( |
| 106 | + BoschThermostatCluster.AttributeDefs.operating_mode.name, |
| 107 | + BoschOperatingMode, |
| 108 | + BoschThermostatCluster.cluster_id, |
| 109 | + translation_key="switch_mode" |
| 110 | + ) |
| 111 | + # Preset - normal/boost. |
| 112 | + .enum( |
| 113 | + BoschThermostatCluster.AttributeDefs.boost.name, |
| 114 | + BoschPreset, |
| 115 | + BoschThermostatCluster.cluster_id, |
| 116 | + translation_key="preset" |
| 117 | + ) |
| 118 | + # Window open switch: manually set or through an automation. |
| 119 | + .switch( |
| 120 | + BoschThermostatCluster.AttributeDefs.window_open.name, |
| 121 | + BoschThermostatCluster.cluster_id, |
| 122 | + translation_key="window_detection" |
| 123 | + ) |
| 124 | + # Display time-out |
| 125 | + .number( |
| 126 | + BoschUserInterfaceCluster.AttributeDefs.display_ontime.name, |
| 127 | + BoschUserInterfaceCluster.cluster_id, |
| 128 | + min_value=5, |
| 129 | + max_value=30, |
| 130 | + step=1, |
| 131 | + translation_key="on_off_transition_time" |
| 132 | + ) |
| 133 | + # Display brightness |
| 134 | + .number( |
| 135 | + BoschUserInterfaceCluster.AttributeDefs.display_brightness.name, |
| 136 | + BoschUserInterfaceCluster.cluster_id, |
| 137 | + min_value=0, |
| 138 | + max_value=10, |
| 139 | + step=1, |
| 140 | + translation_key="backlight_mode" |
| 141 | + ) |
| 142 | +) |
0 commit comments