1717 PowerConfiguration ,
1818)
1919from zigpy .zcl .clusters .homeautomation import ElectricalMeasurement
20+ from zigpy .zcl .clusters .manufacturer_specific import ManufacturerSpecificCluster
2021from zigpy .zcl .clusters .measurement import (
2122 IlluminanceMeasurement ,
2223 PressureMeasurement ,
6667STATE = "state"
6768TEMPERATURE = "temperature"
6869TEMPERATURE_MEASUREMENT = "temperature_measurement"
70+ TVOC_MEASUREMENT = "tvoc_measurement"
6971TEMPERATURE_REPORTED = "temperature_reported"
7072POWER_REPORTED = "power_reported"
7173CONSUMPTION_REPORTED = "consumption_reported"
7274VOLTAGE_REPORTED = "voltage_reported"
7375ILLUMINANCE_MEASUREMENT = "illuminance_measurement"
7476ILLUMINANCE_REPORTED = "illuminance_reported"
7577XIAOMI_AQARA_ATTRIBUTE = 0xFF01
78+ XIAOMI_AQARA_ATTRIBUTE_E1 = 0x00F7
7679XIAOMI_ATTR_3 = "X-attrib-3"
7780XIAOMI_ATTR_4 = "X-attrib-4"
7881XIAOMI_ATTR_5 = "X-attrib-5"
@@ -110,10 +113,8 @@ class XiaomiQuickInitDevice(XiaomiCustomDevice, QuickInitDevice):
110113 """Xiaomi devices eligible for QuickInit."""
111114
112115
113- class BasicCluster (CustomCluster , Basic ):
114- """Xiaomi basic cluster implementation."""
115-
116- cluster_id = Basic .cluster_id
116+ class XiaomiCluster (CustomCluster ):
117+ """Xiaomi cluster implementation."""
117118
118119 def _iter_parse_attr_report (
119120 self , data : bytes
@@ -125,7 +126,12 @@ def _iter_parse_attr_report(
125126 attr_type , data = t .uint8_t .deserialize (data )
126127
127128 if (
128- attr_id not in (XIAOMI_AQARA_ATTRIBUTE , XIAOMI_MIJA_ATTRIBUTE )
129+ attr_id
130+ not in (
131+ XIAOMI_AQARA_ATTRIBUTE ,
132+ XIAOMI_MIJA_ATTRIBUTE ,
133+ XIAOMI_AQARA_ATTRIBUTE_E1 ,
134+ )
129135 or attr_type != 0x42 # "Character String"
130136 ):
131137 # Assume other attributes are reported correctly
@@ -199,20 +205,17 @@ def deserialize(self, data):
199205 return super ().deserialize (hdr .serialize () + fixed_data )
200206
201207 def _update_attribute (self , attrid , value ):
202- if attrid == XIAOMI_AQARA_ATTRIBUTE :
208+ if attrid in ( XIAOMI_AQARA_ATTRIBUTE , XIAOMI_AQARA_ATTRIBUTE_E1 ) :
203209 attributes = self ._parse_aqara_attributes (value )
204210 super ()._update_attribute (attrid , value )
205- if (
206- MODEL in self ._attr_cache
207- and self ._attr_cache [MODEL ] == "lumi.sensor_switch.aq2"
208- ):
211+ if self .endpoint .device .model == "lumi.sensor_switch.aq2" :
209212 if value == b"\x04 !\xa8 C\n !\x00 \x00 " :
210213 self .listener_event (ZHA_SEND_EVENT , COMMAND_TRIPLE , [])
211214 elif attrid == XIAOMI_MIJA_ATTRIBUTE :
212215 attributes = self ._parse_mija_attributes (value )
213216 else :
214217 super ()._update_attribute (attrid , value )
215- if attrid == 0x0005 :
218+ if attrid == MODEL :
216219 # 0x0005 = model attribute.
217220 # Xiaomi sensors send the model attribute when their reset button is
218221 # pressed quickly."""
@@ -266,6 +269,10 @@ def _update_attribute(self, attrid, value):
266269 self .endpoint .device .illuminance_bus .listener_event (
267270 ILLUMINANCE_REPORTED , attributes [ILLUMINANCE_MEASUREMENT ]
268271 )
272+ if TVOC_MEASUREMENT in attributes :
273+ self .endpoint .voc_level .update_attribute (
274+ 0x0000 , attributes [TVOC_MEASUREMENT ]
275+ )
269276
270277 def _parse_aqara_attributes (self , value ):
271278 """Parse non standard attributes."""
@@ -279,29 +286,29 @@ def _parse_aqara_attributes(self, value):
279286 10 : PATH ,
280287 }
281288
282- if MODEL in self ._attr_cache and self . _attr_cache [ MODEL ] in [
289+ if self .endpoint . device . model in [
283290 "lumi.sensor_ht" ,
284291 "lumi.sens" ,
285292 "lumi.weather" ,
293+ "lumi.airmonitor.acn01" ,
286294 ]:
287295 # Temperature sensors send temperature/humidity/pressure updates trough this
288296 # cluster instead of the respective clusters
289297 attribute_names .update (
290298 {
291299 100 : TEMPERATURE_MEASUREMENT ,
292300 101 : HUMIDITY_MEASUREMENT ,
293- 102 : PRESSURE_MEASUREMENT ,
301+ 102 : TVOC_MEASUREMENT
302+ if self .endpoint .device .model == "lumi.airmonitor.acn01"
303+ else PRESSURE_MEASUREMENT ,
294304 }
295305 )
296- elif MODEL in self ._attr_cache and self . _attr_cache [ MODEL ] in [
306+ elif self .endpoint . device . model in [
297307 "lumi.plug.maus01" ,
298308 "lumi.relay.c2acn01" ,
299309 ]:
300310 attribute_names .update ({149 : CONSUMPTION , 150 : VOLTAGE , 152 : POWER })
301- elif (
302- MODEL in self ._attr_cache
303- and self ._attr_cache [MODEL ] == "lumi.sensor_motion.aq2"
304- ):
311+ elif self .endpoint .device .model == "lumi.sensor_motion.aq2" :
305312 attribute_names .update ({11 : ILLUMINANCE_MEASUREMENT })
306313
307314 result = {}
@@ -340,6 +347,16 @@ def _parse_mija_attributes(self, value):
340347 return attributes
341348
342349
350+ class BasicCluster (XiaomiCluster , Basic ):
351+ """Xiaomi basic cluster implementation."""
352+
353+
354+ class XiaomiAqaraE1Cluster (XiaomiCluster , ManufacturerSpecificCluster ):
355+ """Xiaomi mfg cluster implementation."""
356+
357+ cluster_id = 0xFCC0
358+
359+
343360class BinaryOutputInterlock (CustomCluster , BinaryOutput ):
344361 """Xiaomi binaryoutput cluster with added interlock attribute."""
345362
0 commit comments