I found something interesting by “brute-forcing” the Zigbee clusters/attributes:
Cluster 0xfc7e
/ 64638
provides a measurement in the range of 0-500:
[INFO] Get attr: {'id': 1, 'ieee': '38:5c:fb:ff:fe:c7:1c:a1', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 0}
[INFO] Response: {'id': 1, 'type': 'result', 'success': True, 'result': '202.0'}
[INFO] Get attr: {'id': 2, 'ieee': '38:5c:fb:ff:fe:c7:1c:a1', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 1}
[INFO] Response: {'id': 2, 'type': 'result', 'success': True, 'result': '0.0'}
[INFO] Get attr: {'id': 3, 'ieee': '38:5c:fb:ff:fe:c7:1c:a1', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 2}
[INFO] Response: {'id': 3, 'type': 'result', 'success': True, 'result': '500.0'}
[INFO] Get attr: {'id': 4, 'ieee': '94:34:69:ff:fe:c1:df:9c', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 0}
[INFO] Response: {'id': 4, 'type': 'result', 'success': True, 'result': '239.0'}
[INFO] Get attr: {'id': 5, 'ieee': '94:34:69:ff:fe:c1:df:9c', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 1}
[INFO] Response: {'id': 5, 'type': 'result', 'success': True, 'result': '0.0'}
[INFO] Get attr: {'id': 6, 'ieee': '94:34:69:ff:fe:c1:df:9c', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 2}
[INFO] Response: {'id': 6, 'type': 'result', 'success': True, 'result': '500.0'}
[INFO] Get attr: {'id': 7, 'ieee': '94:34:69:ff:fe:86:a7:41', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 0}
[INFO] Response: {'id': 7, 'type': 'result', 'success': True, 'result': '69.0'}
[INFO] Get attr: {'id': 8, 'ieee': '94:34:69:ff:fe:86:a7:41', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 1}
[INFO] Response: {'id': 8, 'type': 'result', 'success': True, 'result': '0.0'}
[INFO] Get attr: {'id': 9, 'ieee': '94:34:69:ff:fe:86:a7:41', 'endpoint_id': 1, 'cluster_id': 64638, 'cluster_type': 'in', 'attribute': 2}
[INFO] Response: {'id': 9, 'type': 'result', 'success': True, 'result': '500.0'}
Output from all three sensors. Attribute 0 is the current measurement, attribute 1 is the lower bound, and attribute 2 is the upper bound.
Yes! This is the tVOC measurement. The reading goes up and down in conjunction with the tVOC “trend display” on the unit itself when I spray some body spray into the room.
Now I only need to figure out how to get Home Assistant to understand this as an Entity
The Sensirion SEN54 sensor module inside VINDSTYRKA reports a “VOC index” on a scale of 0-500, which matches the bounds reported by the attribute.
So it looks like we’re getting the processed value directly from the sensor: https://sensirion.com/media/documents/02232963/6294E043/Info_Note_VOC_Index.pdf