Add ZHA entities for snzb06p (#107379)

* Updating zha component to add entities for snzb06p

Sonoff snzb06p presence detector needs some custom entities.

* Updating ZCL_INIT_ATTRS for sonoff specific attrs

* updating cluster name due to change in quirk
pull/108721/head
Peter Hall 2024-01-24 00:31:32 +11:00 committed by GitHub
parent 5dbcdfc6fb
commit 701404fa0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 91 additions and 1 deletions

View File

@ -13,3 +13,10 @@ def is_hue_motion_sensor(cluster_handler: ClusterHandler) -> bool:
"SML003",
"SML004",
)
def is_sonoff_presence_sensor(cluster_handler: ClusterHandler) -> bool:
"""Return true if the manufacturer and model match known Sonoff sensor models."""
return cluster_handler.cluster.endpoint.manufacturer in (
"SONOFF",
) and cluster_handler.cluster.endpoint.model in ("SNZB-06P",)

View File

@ -423,3 +423,11 @@ class IkeaRemote(ClusterHandler):
)
class XiaomiVibrationAQ1ClusterHandler(MultistateInput):
"""Xiaomi DoorLock Cluster is in fact a MultiStateInput Cluster."""
@registries.CLUSTER_HANDLER_ONLY_CLUSTERS.register(0xFC11)
@registries.ZIGBEE_CLUSTER_HANDLER_REGISTRY.register(0xFC11)
class SonoffPresenceSenor(ClusterHandler):
"""SonoffPresenceSensor cluster handler."""
ZCL_INIT_ATTRS = {"last_illumination_state": True}

View File

@ -14,7 +14,7 @@ from ..const import (
REPORT_CONFIG_MIN_INT,
)
from . import AttrReportConfig, ClusterHandler
from .helpers import is_hue_motion_sensor
from .helpers import is_hue_motion_sensor, is_sonoff_presence_sensor
if TYPE_CHECKING:
from ..endpoint import Endpoint
@ -69,6 +69,10 @@ class OccupancySensing(ClusterHandler):
if is_hue_motion_sensor(self):
self.ZCL_INIT_ATTRS = self.ZCL_INIT_ATTRS.copy()
self.ZCL_INIT_ATTRS["sensitivity"] = True
if is_sonoff_presence_sensor(self):
self.ZCL_INIT_ATTRS = self.ZCL_INIT_ATTRS.copy()
self.ZCL_INIT_ATTRS["ultrasonic_o_to_u_delay"] = True
self.ZCL_INIT_ATTRS["ultrasonic_u_to_o_threshold"] = True
@registries.ZIGBEE_CLUSTER_HANDLER_REGISTRY.register(

View File

@ -20,6 +20,7 @@ from .core.const import (
CLUSTER_HANDLER_COLOR,
CLUSTER_HANDLER_INOVELLI,
CLUSTER_HANDLER_LEVEL,
CLUSTER_HANDLER_OCCUPANCY,
CLUSTER_HANDLER_THERMOSTAT,
SIGNAL_ADD_ENTITIES,
SIGNAL_ATTR_UPDATED,
@ -966,3 +967,21 @@ class ThermostatLocalTempCalibration(ZHANumberConfigurationEntity):
_attr_mode: NumberMode = NumberMode.SLIDER
_attr_native_unit_of_measurement: str = UnitOfTemperature.CELSIUS
_attr_icon: str = ICONS[0]
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names=CLUSTER_HANDLER_OCCUPANCY, models={"SNZB-06P"}
)
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class SonoffPresenceSenorTimeout(ZHANumberConfigurationEntity):
"""Configuration of Sonoff sensor presence detection timeout."""
_unique_id_suffix = "presence_detection_timeout"
_attr_entity_category = EntityCategory.CONFIG
_attr_native_min_value: int = 15
_attr_native_max_value: int = 60
_attribute_name = "ultrasonic_o_to_u_delay"
_attr_translation_key: str = "presence_detection_timeout"
_attr_mode: NumberMode = NumberMode.BOX
_attr_icon: str = "mdi:timer-edit"

View File

@ -25,6 +25,7 @@ from .core.const import (
CLUSTER_HANDLER_HUE_OCCUPANCY,
CLUSTER_HANDLER_IAS_WD,
CLUSTER_HANDLER_INOVELLI,
CLUSTER_HANDLER_OCCUPANCY,
CLUSTER_HANDLER_ON_OFF,
SIGNAL_ADD_ENTITIES,
SIGNAL_ATTR_UPDATED,
@ -652,3 +653,23 @@ class AqaraThermostatPreset(ZCLEnumSelectEntity):
_attribute_name = "preset"
_enum = AqaraThermostatPresetMode
_attr_translation_key: str = "preset"
class SonoffPresenceDetectionSensitivityEnum(types.enum8):
"""Enum for detection sensitivity select entity."""
Low = 0x01
Medium = 0x02
High = 0x03
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names=CLUSTER_HANDLER_OCCUPANCY, models={"SNZB-06P"}
)
class SonoffPresenceDetectionSensitivity(ZCLEnumSelectEntity):
"""Entity to set the detection sensitivity of the Sonoff SNZB-06P."""
_unique_id_suffix = "detection_sensitivity"
_attribute_name = "ultrasonic_u_to_o_threshold"
_enum = SonoffPresenceDetectionSensitivityEnum
_attr_translation_key: str = "detection_sensitivity"

View File

@ -1214,3 +1214,25 @@ class AqaraSmokeDensityDbm(Sensor):
_attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT
_attr_icon: str = "mdi:google-circles-communities"
_attr_suggested_display_precision: int = 3
class SonoffIlluminationStates(types.enum8):
"""Enum for displaying last Illumination state."""
Dark = 0x00
Light = 0x01
@MULTI_MATCH(cluster_handler_names="sonoff_manufacturer", models={"SNZB-06P"})
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class SonoffPresenceSenorIlluminationStatus(Sensor):
"""Sensor that displays the illumination status the last time peresence was detected."""
_attribute_name = "last_illumination_state"
_unique_id_suffix = "last_illumination"
_attr_translation_key: str = "last_illumination_state"
_attr_icon: str = "mdi:theme-light-dark"
def formatter(self, value: int) -> int | float | None:
"""Numeric pass-through formatter."""
return SonoffIlluminationStates(value).name

View File

@ -727,6 +727,9 @@
},
"local_temperature_calibration": {
"name": "Local temperature offset"
},
"presence_detection_timeout": {
"name": "Presence detection timeout"
}
},
"select": {
@ -792,6 +795,9 @@
},
"decoupled_mode": {
"name": "Decoupled mode"
},
"detection_sensitivity": {
"name": "Detection Sensitivity"
}
},
"sensor": {
@ -869,6 +875,9 @@
},
"smoke_density": {
"name": "Smoke density"
},
"last_illumination_state": {
"name": "Last illumination state"
}
},
"switch": {