mirror of
https://github.com/home-assistant/core.git
synced 2025-07-11 15:27:08 +00:00
Fix ZHA startup failure with the Konke button (#92144)
* Ensure devices with bad cluster subclasses do not prevent startup * Explicitly unit test an affected SML001 device * Do not use invalid `hue_occupancy` attribute name * Actually remove `hue_occupancy` * Bump ZHA dependencies
This commit is contained in:
parent
cdbffee781
commit
9d0dd0b784
@ -22,6 +22,7 @@ from .core import discovery
|
|||||||
from .core.const import (
|
from .core.const import (
|
||||||
CLUSTER_HANDLER_ACCELEROMETER,
|
CLUSTER_HANDLER_ACCELEROMETER,
|
||||||
CLUSTER_HANDLER_BINARY_INPUT,
|
CLUSTER_HANDLER_BINARY_INPUT,
|
||||||
|
CLUSTER_HANDLER_HUE_OCCUPANCY,
|
||||||
CLUSTER_HANDLER_OCCUPANCY,
|
CLUSTER_HANDLER_OCCUPANCY,
|
||||||
CLUSTER_HANDLER_ON_OFF,
|
CLUSTER_HANDLER_ON_OFF,
|
||||||
CLUSTER_HANDLER_ZONE,
|
CLUSTER_HANDLER_ZONE,
|
||||||
@ -130,6 +131,11 @@ class Occupancy(BinarySensor):
|
|||||||
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.OCCUPANCY
|
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.OCCUPANCY
|
||||||
|
|
||||||
|
|
||||||
|
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_HUE_OCCUPANCY)
|
||||||
|
class HueOccupancy(Occupancy):
|
||||||
|
"""ZHA Hue occupancy."""
|
||||||
|
|
||||||
|
|
||||||
@STRICT_MATCH(cluster_handler_names=CLUSTER_HANDLER_ON_OFF)
|
@STRICT_MATCH(cluster_handler_names=CLUSTER_HANDLER_ON_OFF)
|
||||||
class Opening(BinarySensor):
|
class Opening(BinarySensor):
|
||||||
"""ZHA OnOff BinarySensor."""
|
"""ZHA OnOff BinarySensor."""
|
||||||
|
@ -347,7 +347,7 @@ class OnOffClientClusterHandler(ClientClusterHandler):
|
|||||||
class OnOffClusterHandler(ClusterHandler):
|
class OnOffClusterHandler(ClusterHandler):
|
||||||
"""Cluster handler for the OnOff Zigbee cluster."""
|
"""Cluster handler for the OnOff Zigbee cluster."""
|
||||||
|
|
||||||
ON_OFF = 0
|
ON_OFF = general.OnOff.attributes_by_name["on_off"].id
|
||||||
REPORT_CONFIG = (AttrReportConfig(attr="on_off", config=REPORT_CONFIG_IMMEDIATE),)
|
REPORT_CONFIG = (AttrReportConfig(attr="on_off", config=REPORT_CONFIG_IMMEDIATE),)
|
||||||
ZCL_INIT_ATTRS = {
|
ZCL_INIT_ATTRS = {
|
||||||
"start_up_on_off": True,
|
"start_up_on_off": True,
|
||||||
@ -374,6 +374,15 @@ class OnOffClusterHandler(ClusterHandler):
|
|||||||
if self.cluster.endpoint.model == "TS011F":
|
if self.cluster.endpoint.model == "TS011F":
|
||||||
self.ZCL_INIT_ATTRS["child_lock"] = True
|
self.ZCL_INIT_ATTRS["child_lock"] = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def matches(cls, cluster: zigpy.zcl.Cluster, endpoint: Endpoint) -> bool:
|
||||||
|
"""Filter the cluster match for specific devices."""
|
||||||
|
return not (
|
||||||
|
cluster.endpoint.device.manufacturer == "Konke"
|
||||||
|
and cluster.endpoint.device.model
|
||||||
|
in ("3AFE280100510001", "3AFE170100510001")
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def on_off(self) -> bool | None:
|
def on_off(self) -> bool | None:
|
||||||
"""Return cached value of on/off attribute."""
|
"""Return cached value of on/off attribute."""
|
||||||
|
@ -78,6 +78,7 @@ CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT = "electrical_measurement"
|
|||||||
CLUSTER_HANDLER_EVENT_RELAY = "event_relay"
|
CLUSTER_HANDLER_EVENT_RELAY = "event_relay"
|
||||||
CLUSTER_HANDLER_FAN = "fan"
|
CLUSTER_HANDLER_FAN = "fan"
|
||||||
CLUSTER_HANDLER_HUMIDITY = "humidity"
|
CLUSTER_HANDLER_HUMIDITY = "humidity"
|
||||||
|
CLUSTER_HANDLER_HUE_OCCUPANCY = "philips_occupancy"
|
||||||
CLUSTER_HANDLER_SOIL_MOISTURE = "soil_moisture"
|
CLUSTER_HANDLER_SOIL_MOISTURE = "soil_moisture"
|
||||||
CLUSTER_HANDLER_LEAF_WETNESS = "leaf_wetness"
|
CLUSTER_HANDLER_LEAF_WETNESS = "leaf_wetness"
|
||||||
CLUSTER_HANDLER_IAS_ACE = "ias_ace"
|
CLUSTER_HANDLER_IAS_ACE = "ias_ace"
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
"zigpy_znp"
|
"zigpy_znp"
|
||||||
],
|
],
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"bellows==0.35.1",
|
"bellows==0.35.2",
|
||||||
"pyserial==3.5",
|
"pyserial==3.5",
|
||||||
"pyserial-asyncio==0.6",
|
"pyserial-asyncio==0.6",
|
||||||
"zha-quirks==0.0.97",
|
"zha-quirks==0.0.98",
|
||||||
"zigpy-deconz==0.21.0",
|
"zigpy-deconz==0.21.0",
|
||||||
"zigpy==0.55.0",
|
"zigpy==0.55.0",
|
||||||
"zigpy-xbee==0.18.0",
|
"zigpy-xbee==0.18.0",
|
||||||
|
@ -20,9 +20,9 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
|
|
||||||
from .core import discovery
|
from .core import discovery
|
||||||
from .core.const import (
|
from .core.const import (
|
||||||
|
CLUSTER_HANDLER_HUE_OCCUPANCY,
|
||||||
CLUSTER_HANDLER_IAS_WD,
|
CLUSTER_HANDLER_IAS_WD,
|
||||||
CLUSTER_HANDLER_INOVELLI,
|
CLUSTER_HANDLER_INOVELLI,
|
||||||
CLUSTER_HANDLER_OCCUPANCY,
|
|
||||||
CLUSTER_HANDLER_ON_OFF,
|
CLUSTER_HANDLER_ON_OFF,
|
||||||
DATA_ZHA,
|
DATA_ZHA,
|
||||||
SIGNAL_ADD_ENTITIES,
|
SIGNAL_ADD_ENTITIES,
|
||||||
@ -367,7 +367,7 @@ class HueV1MotionSensitivities(types.enum8):
|
|||||||
|
|
||||||
|
|
||||||
@CONFIG_DIAGNOSTIC_MATCH(
|
@CONFIG_DIAGNOSTIC_MATCH(
|
||||||
cluster_handler_names=CLUSTER_HANDLER_OCCUPANCY,
|
cluster_handler_names=CLUSTER_HANDLER_HUE_OCCUPANCY,
|
||||||
manufacturers={"Philips", "Signify Netherlands B.V."},
|
manufacturers={"Philips", "Signify Netherlands B.V."},
|
||||||
models={"SML001"},
|
models={"SML001"},
|
||||||
)
|
)
|
||||||
@ -390,7 +390,7 @@ class HueV2MotionSensitivities(types.enum8):
|
|||||||
|
|
||||||
|
|
||||||
@CONFIG_DIAGNOSTIC_MATCH(
|
@CONFIG_DIAGNOSTIC_MATCH(
|
||||||
cluster_handler_names=CLUSTER_HANDLER_OCCUPANCY,
|
cluster_handler_names=CLUSTER_HANDLER_HUE_OCCUPANCY,
|
||||||
manufacturers={"Philips", "Signify Netherlands B.V."},
|
manufacturers={"Philips", "Signify Netherlands B.V."},
|
||||||
models={"SML002", "SML003", "SML004"},
|
models={"SML002", "SML003", "SML004"},
|
||||||
)
|
)
|
||||||
|
@ -428,7 +428,7 @@ beautifulsoup4==4.11.1
|
|||||||
# beewi_smartclim==0.0.10
|
# beewi_smartclim==0.0.10
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
bellows==0.35.1
|
bellows==0.35.2
|
||||||
|
|
||||||
# homeassistant.components.bmw_connected_drive
|
# homeassistant.components.bmw_connected_drive
|
||||||
bimmer_connected==0.13.0
|
bimmer_connected==0.13.0
|
||||||
@ -2709,7 +2709,7 @@ zeroconf==0.58.2
|
|||||||
zeversolar==0.3.1
|
zeversolar==0.3.1
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.97
|
zha-quirks==0.0.98
|
||||||
|
|
||||||
# homeassistant.components.zhong_hong
|
# homeassistant.components.zhong_hong
|
||||||
zhong_hong_hvac==1.0.9
|
zhong_hong_hvac==1.0.9
|
||||||
|
@ -361,7 +361,7 @@ base36==0.1.1
|
|||||||
beautifulsoup4==4.11.1
|
beautifulsoup4==4.11.1
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
bellows==0.35.1
|
bellows==0.35.2
|
||||||
|
|
||||||
# homeassistant.components.bmw_connected_drive
|
# homeassistant.components.bmw_connected_drive
|
||||||
bimmer_connected==0.13.0
|
bimmer_connected==0.13.0
|
||||||
@ -1964,7 +1964,7 @@ zeroconf==0.58.2
|
|||||||
zeversolar==0.3.1
|
zeversolar==0.3.1
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.97
|
zha-quirks==0.0.98
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-deconz==0.21.0
|
zigpy-deconz==0.21.0
|
||||||
|
@ -240,6 +240,15 @@ def zigpy_device_mock(zigpy_app_controller):
|
|||||||
):
|
):
|
||||||
common.patch_cluster(cluster)
|
common.patch_cluster(cluster)
|
||||||
|
|
||||||
|
if attributes is not None:
|
||||||
|
for ep_id, clusters in attributes.items():
|
||||||
|
for cluster_name, attrs in clusters.items():
|
||||||
|
cluster = getattr(device.endpoints[ep_id], cluster_name)
|
||||||
|
|
||||||
|
for name, value in attrs.items():
|
||||||
|
attr_id = cluster.find_attribute(name).id
|
||||||
|
cluster._attr_cache[attr_id] = value
|
||||||
|
|
||||||
return device
|
return device
|
||||||
|
|
||||||
return _mock_dev
|
return _mock_dev
|
||||||
|
@ -10,16 +10,26 @@ from zigpy.const import (
|
|||||||
SIG_MODEL,
|
SIG_MODEL,
|
||||||
SIG_NODE_DESC,
|
SIG_NODE_DESC,
|
||||||
)
|
)
|
||||||
from zigpy.profiles import zha
|
from zigpy.profiles import zha, zll
|
||||||
|
from zigpy.types import Bool, uint8_t
|
||||||
from zigpy.zcl.clusters.closures import DoorLock
|
from zigpy.zcl.clusters.closures import DoorLock
|
||||||
from zigpy.zcl.clusters.general import (
|
from zigpy.zcl.clusters.general import (
|
||||||
Basic,
|
Basic,
|
||||||
Groups,
|
Groups,
|
||||||
Identify,
|
Identify,
|
||||||
|
LevelControl,
|
||||||
MultistateInput,
|
MultistateInput,
|
||||||
|
OnOff,
|
||||||
Ota,
|
Ota,
|
||||||
|
PowerConfiguration,
|
||||||
Scenes,
|
Scenes,
|
||||||
)
|
)
|
||||||
|
from zigpy.zcl.clusters.lighting import Color
|
||||||
|
from zigpy.zcl.clusters.measurement import (
|
||||||
|
IlluminanceMeasurement,
|
||||||
|
OccupancySensing,
|
||||||
|
TemperatureMeasurement,
|
||||||
|
)
|
||||||
|
|
||||||
DEV_SIG_CLUSTER_HANDLERS = "cluster_handlers"
|
DEV_SIG_CLUSTER_HANDLERS = "cluster_handlers"
|
||||||
DEV_SIG_DEV_NO = "device_no"
|
DEV_SIG_DEV_NO = "device_no"
|
||||||
@ -5373,4 +5383,156 @@ DEVICES = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
DEV_SIG_DEV_NO: 100,
|
||||||
|
SIG_MANUFACTURER: "Konke",
|
||||||
|
SIG_MODEL: "3AFE170100510001",
|
||||||
|
SIG_NODE_DESC: b"\x02@\x80\x02\x10RR\x00\x00,R\x00\x00",
|
||||||
|
SIG_ENDPOINTS: {
|
||||||
|
1: {
|
||||||
|
PROFILE_ID: 260,
|
||||||
|
DEVICE_TYPE: zha.DeviceType.ON_OFF_OUTPUT,
|
||||||
|
INPUT_CLUSTERS: [
|
||||||
|
Basic.cluster_id,
|
||||||
|
PowerConfiguration.cluster_id,
|
||||||
|
Identify.cluster_id,
|
||||||
|
Groups.cluster_id,
|
||||||
|
Scenes.cluster_id,
|
||||||
|
OnOff.cluster_id,
|
||||||
|
],
|
||||||
|
OUTPUT_CLUSTERS: [
|
||||||
|
Identify.cluster_id,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DEV_SIG_EVT_CLUSTER_HANDLERS: [],
|
||||||
|
DEV_SIG_ENT_MAP: {
|
||||||
|
("button", "00:11:22:33:44:55:66:77-1-3"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["identify"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "ZHAIdentifyButton",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "button.konke_3afe170100510001_identify",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-1-1"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["power"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "Battery",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.konke_3afe170100510001_battery",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-1-0-rssi"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["basic"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "RSSISensor",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.konke_3afe170100510001_rssi",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-1-0-lqi"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["basic"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "LQISensor",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.konke_3afe170100510001_lqi",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DEV_SIG_DEV_NO: 101,
|
||||||
|
SIG_MANUFACTURER: "Philips",
|
||||||
|
SIG_MODEL: "SML001",
|
||||||
|
SIG_NODE_DESC: b"\x02@\x80\x0b\x10Y?\x00\x00\x00?\x00\x00",
|
||||||
|
SIG_ENDPOINTS: {
|
||||||
|
1: {
|
||||||
|
PROFILE_ID: zll.PROFILE_ID,
|
||||||
|
DEVICE_TYPE: zll.DeviceType.ON_OFF_SENSOR,
|
||||||
|
INPUT_CLUSTERS: [Basic.cluster_id],
|
||||||
|
OUTPUT_CLUSTERS: [
|
||||||
|
Basic.cluster_id,
|
||||||
|
Identify.cluster_id,
|
||||||
|
Groups.cluster_id,
|
||||||
|
Scenes.cluster_id,
|
||||||
|
OnOff.cluster_id,
|
||||||
|
LevelControl.cluster_id,
|
||||||
|
Color.cluster_id,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
PROFILE_ID: zha.PROFILE_ID,
|
||||||
|
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
|
||||||
|
INPUT_CLUSTERS: [
|
||||||
|
Basic.cluster_id,
|
||||||
|
PowerConfiguration.cluster_id,
|
||||||
|
Identify.cluster_id,
|
||||||
|
IlluminanceMeasurement.cluster_id,
|
||||||
|
TemperatureMeasurement.cluster_id,
|
||||||
|
OccupancySensing.cluster_id,
|
||||||
|
],
|
||||||
|
OUTPUT_CLUSTERS: [
|
||||||
|
Ota.cluster_id,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DEV_SIG_ATTRIBUTES: {
|
||||||
|
2: {
|
||||||
|
"basic": {
|
||||||
|
"trigger_indicator": Bool(False),
|
||||||
|
},
|
||||||
|
"philips_occupancy": {
|
||||||
|
"sensitivity": uint8_t(1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DEV_SIG_EVT_CLUSTER_HANDLERS: [
|
||||||
|
"1:0x0005",
|
||||||
|
"1:0x0006",
|
||||||
|
"1:0x0008",
|
||||||
|
"1:0x0300",
|
||||||
|
"2:0x0019",
|
||||||
|
],
|
||||||
|
DEV_SIG_ENT_MAP: {
|
||||||
|
("button", "00:11:22:33:44:55:66:77-2-3"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["identify"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "ZHAIdentifyButton",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "button.philips_sml001_identify",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-2-1"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["power"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "Battery",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.philips_sml001_battery",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-1-0-rssi"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["basic"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "RSSISensor",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.philips_sml001_rssi",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-1-0-lqi"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["basic"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "LQISensor",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.philips_sml001_lqi",
|
||||||
|
},
|
||||||
|
("binary_sensor", "00:11:22:33:44:55:66:77-1-6"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["on_off"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "Motion",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "binary_sensor.philips_sml001_motion",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-2-1024"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["illuminance"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "Illuminance",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.philips_sml001_illuminance",
|
||||||
|
},
|
||||||
|
("binary_sensor", "00:11:22:33:44:55:66:77-2-1030"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["philips_occupancy"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "HueOccupancy",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "binary_sensor.philips_sml001_occupancy",
|
||||||
|
},
|
||||||
|
("sensor", "00:11:22:33:44:55:66:77-2-1026"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["temperature"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "Temperature",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "sensor.philips_sml001_temperature",
|
||||||
|
},
|
||||||
|
("switch", "00:11:22:33:44:55:66:77-2-0-trigger_indicator"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["basic"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "HueMotionTriggerIndicatorSwitch",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "switch.philips_sml001_led_trigger_indicator",
|
||||||
|
},
|
||||||
|
("select", "00:11:22:33:44:55:66:77-2-1030-motion_sensitivity"): {
|
||||||
|
DEV_SIG_CLUSTER_HANDLERS: ["philips_occupancy"],
|
||||||
|
DEV_SIG_ENT_MAP_CLASS: "HueV1MotionSensitivity",
|
||||||
|
DEV_SIG_ENT_MAP_ID: "select.philips_sml001_hue_motion_sensitivity",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user