-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathaircube.py
More file actions
187 lines (167 loc) · 6.6 KB
/
Copy pathaircube.py
File metadata and controls
187 lines (167 loc) · 6.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""StuckAtPrototype AirCube air quality monitor quirk for ZHA.
This single file is compatible with both old and new Home Assistant:
* Modern HA (zigpy >= 0.65.1, i.e. HA >= ~2024.8):
Full quirks v2 support. Exposes eCO2, tVOC and AQI sensors from the
custom 0xFC01 cluster plus a Brightness number on the Analog Output
cluster.
* Old HA (zigpy < 0.65, e.g. HA 2024.1.x):
`zigpy.quirks.v2` does not exist yet, so importing QuirkBuilder raises
ImportError and the whole quirk fails to load. We fall back to a classic
v1 quirk so the module imports cleanly and the device is named correctly.
IMPORTANT: on these old ZHA versions there is no supported way to turn
custom-cluster (0xFC01) attributes into entities -- eCO2/tVOC/AQI will
NOT appear until HA is updated to a version with quirks v2, or the values
are read over BLE via the firmware's BTHome broadcaster. Temperature,
humidity and brightness still work on old HA because they use standard
Zigbee clusters and are discovered automatically.
"""
from zigpy.quirks import CustomCluster
from zigpy.zcl.foundation import ZCLAttributeDef
import zigpy.types as t
class AirQualityCluster(CustomCluster):
"""AirCube custom air quality cluster (0xFC01) — read-only sensors."""
cluster_id = 0xFC01
name = "AirCube Air Quality"
ep_attribute = "aircube_air_quality"
class AttributeDefs(CustomCluster.AttributeDefs):
eco2 = ZCLAttributeDef(
id=0x0000, type=t.uint16_t, is_manufacturer_specific=False
)
etvoc = ZCLAttributeDef(
id=0x0001, type=t.uint16_t, is_manufacturer_specific=False
)
aqi = ZCLAttributeDef(
id=0x0002, type=t.uint16_t, is_manufacturer_specific=False
)
ANALOG_OUTPUT_CLUSTER_ID = 0x000D
# ---------------------------------------------------------------------------
# Detect whether this HA/zigpy version supports the quirks v2 API.
# ---------------------------------------------------------------------------
try:
from zigpy.quirks.v2 import QuirkBuilder
from zigpy.quirks.v2.homeassistant import EntityType
try:
from zigpy.quirks.v2.homeassistant.sensor import (
SensorDeviceClass,
SensorStateClass,
)
except ImportError:
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorStateClass,
)
_HAS_QUIRKS_V2 = True
except ImportError:
_HAS_QUIRKS_V2 = False
if _HAS_QUIRKS_V2:
# -----------------------------------------------------------------------
# Modern HA: full quirks v2 definition.
# -----------------------------------------------------------------------
(
QuirkBuilder("StuckAtPrototype", "AirCube")
.replaces(AirQualityCluster, endpoint_id=10)
.sensor(
AirQualityCluster.AttributeDefs.eco2.name,
AirQualityCluster.cluster_id,
endpoint_id=10,
unit="ppm",
translation_key="equivalent_co2",
state_class=SensorStateClass.MEASUREMENT,
fallback_name="Equivalent CO2",
)
.sensor(
AirQualityCluster.AttributeDefs.etvoc.name,
AirQualityCluster.cluster_id,
endpoint_id=10,
unit="ppb",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
state_class=SensorStateClass.MEASUREMENT,
fallback_name="tVOC",
)
.sensor(
AirQualityCluster.AttributeDefs.aqi.name,
AirQualityCluster.cluster_id,
endpoint_id=10,
state_class=SensorStateClass.MEASUREMENT,
translation_key="voc_level",
fallback_name="VOC Level",
)
.number(
"present_value",
ANALOG_OUTPUT_CLUSTER_ID,
endpoint_id=10,
min_value=0,
max_value=100,
step=1,
mode="slider",
entity_type=EntityType.STANDARD,
translation_key="brightness",
fallback_name="Brightness",
)
.add_to_registry()
)
else:
# -----------------------------------------------------------------------
# Old HA (no quirks v2): classic v1 fallback.
#
# This keeps the module importable (stops the ImportError crash) and names
# the device. Temperature, humidity and brightness are exposed by ZHA's
# standard discovery. The eCO2/tVOC/AQI values on cluster 0xFC01 cannot be
# surfaced as entities on this ZHA version -- update HA, or read them over
# BLE (BTHome), for those.
# -----------------------------------------------------------------------
from zigpy.quirks import CustomDevice
from zigpy.profiles import zha
from zigpy.zcl.clusters.general import AnalogOutput, Basic, Identify
from zigpy.zcl.clusters.measurement import (
RelativeHumidity,
TemperatureMeasurement,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
)
class AirCube(CustomDevice):
"""AirCube v1 quirk for HA versions without quirks v2."""
signature = {
MODELS_INFO: [("StuckAtPrototype", "AirCube")],
ENDPOINTS: {
# <SimpleDescriptor endpoint=10 profile=260 device_type=770
# input_clusters=[0, 3, 13, 1026, 1029, 64513]
# output_clusters=[]>
10: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Identify.cluster_id,
AnalogOutput.cluster_id,
TemperatureMeasurement.cluster_id,
RelativeHumidity.cluster_id,
AirQualityCluster.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
},
}
replacement = {
ENDPOINTS: {
10: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
INPUT_CLUSTERS: [
Basic,
Identify,
AnalogOutput,
TemperatureMeasurement,
RelativeHumidity,
AirQualityCluster,
],
OUTPUT_CLUSTERS: [],
},
},
}