Use Z-Wave notification event enums in binary sensor (#151236)

This commit is contained in:
Martin Hjelmare
2025-08-27 19:06:38 +02:00
committed by GitHub
parent f583dfe532
commit abb59f2233

View File

@@ -3,11 +3,15 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import TYPE_CHECKING, cast
from zwave_js_server.const import CommandClass from zwave_js_server.const import CommandClass
from zwave_js_server.const.command_class.lock import DOOR_STATUS_PROPERTY from zwave_js_server.const.command_class.lock import DOOR_STATUS_PROPERTY
from zwave_js_server.const.command_class.notification import ( from zwave_js_server.const.command_class.notification import (
CC_SPECIFIC_NOTIFICATION_TYPE, CC_SPECIFIC_NOTIFICATION_TYPE,
NotificationEvent,
NotificationType,
SmokeAlarmNotificationEvent,
) )
from zwave_js_server.model.driver import Driver from zwave_js_server.model.driver import Driver
@@ -60,8 +64,8 @@ NOTIFICATION_GAS = "18"
class NotificationZWaveJSEntityDescription(BinarySensorEntityDescription): class NotificationZWaveJSEntityDescription(BinarySensorEntityDescription):
"""Represent a Z-Wave JS binary sensor entity description.""" """Represent a Z-Wave JS binary sensor entity description."""
not_states: set[str] = field(default_factory=lambda: {"0"}) not_states: set[NotificationEvent | int] = field(default_factory=lambda: {0})
states: tuple[str, ...] | None = None states: set[NotificationEvent | int] | None = None
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
@@ -122,13 +126,13 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 2: Carbon Monoxide - State Id's 1 and 2 # NotificationType 2: Carbon Monoxide - State Id's 1 and 2
key=NOTIFICATION_CARBON_MONOOXIDE, key=NOTIFICATION_CARBON_MONOOXIDE,
states=("1", "2"), states={1, 2},
device_class=BinarySensorDeviceClass.CO, device_class=BinarySensorDeviceClass.CO,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 2: Carbon Monoxide - State Id 4, 5, 7 # NotificationType 2: Carbon Monoxide - State Id 4, 5, 7
key=NOTIFICATION_CARBON_MONOOXIDE, key=NOTIFICATION_CARBON_MONOOXIDE,
states=("4", "5", "7"), states={4, 5, 7},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -140,13 +144,13 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 3: Carbon Dioxide - State Id's 1 and 2 # NotificationType 3: Carbon Dioxide - State Id's 1 and 2
key=NOTIFICATION_CARBON_DIOXIDE, key=NOTIFICATION_CARBON_DIOXIDE,
states=("1", "2"), states={1, 2},
device_class=BinarySensorDeviceClass.GAS, device_class=BinarySensorDeviceClass.GAS,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 3: Carbon Dioxide - State Id's 4, 5, 7 # NotificationType 3: Carbon Dioxide - State Id's 4, 5, 7
key=NOTIFICATION_CARBON_DIOXIDE, key=NOTIFICATION_CARBON_DIOXIDE,
states=("4", "5", "7"), states={4, 5, 7},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -158,13 +162,13 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 4: Heat - State Id's 1, 2, 5, 6 (heat/underheat) # NotificationType 4: Heat - State Id's 1, 2, 5, 6 (heat/underheat)
key=NOTIFICATION_HEAT, key=NOTIFICATION_HEAT,
states=("1", "2", "5", "6"), states={1, 2, 5, 6},
device_class=BinarySensorDeviceClass.HEAT, device_class=BinarySensorDeviceClass.HEAT,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 4: Heat - State ID's 8, A, B # NotificationType 4: Heat - State ID's 8, A, B
key=NOTIFICATION_HEAT, key=NOTIFICATION_HEAT,
states=("8", "10", "11"), states={8, 10, 11},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -176,13 +180,13 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 5: Water - State Id's 1, 2, 3, 4, 6, 7, 8, 9, 0A # NotificationType 5: Water - State Id's 1, 2, 3, 4, 6, 7, 8, 9, 0A
key=NOTIFICATION_WATER, key=NOTIFICATION_WATER,
states=("1", "2", "3", "4", "6", "7", "8", "9", "10"), states={1, 2, 3, 4, 6, 7, 8, 9, 10},
device_class=BinarySensorDeviceClass.MOISTURE, device_class=BinarySensorDeviceClass.MOISTURE,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 5: Water - State Id's B # NotificationType 5: Water - State Id's B
key=NOTIFICATION_WATER, key=NOTIFICATION_WATER,
states=("11",), states={11},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -194,54 +198,54 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 6: Access Control - State Id's 1, 2, 3, 4 (Lock) # NotificationType 6: Access Control - State Id's 1, 2, 3, 4 (Lock)
key=NOTIFICATION_ACCESS_CONTROL, key=NOTIFICATION_ACCESS_CONTROL,
states=("1", "2", "3", "4"), states={1, 2, 3, 4},
device_class=BinarySensorDeviceClass.LOCK, device_class=BinarySensorDeviceClass.LOCK,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 6: Access Control - State Id's 11 (Lock jammed) # NotificationType 6: Access Control - State Id's 11 (Lock jammed)
key=NOTIFICATION_ACCESS_CONTROL, key=NOTIFICATION_ACCESS_CONTROL,
states=("11",), states={11},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 6: Access Control - State Id 22 (door/window open) # NotificationType 6: Access Control - State Id 22 (door/window open)
key=NOTIFICATION_ACCESS_CONTROL, key=NOTIFICATION_ACCESS_CONTROL,
not_states={"23"}, not_states={23},
states=("22",), states={22},
device_class=BinarySensorDeviceClass.DOOR, device_class=BinarySensorDeviceClass.DOOR,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 7: Home Security - State Id's 1, 2 (intrusion) # NotificationType 7: Home Security - State Id's 1, 2 (intrusion)
key=NOTIFICATION_HOME_SECURITY, key=NOTIFICATION_HOME_SECURITY,
states=("1", "2"), states={1, 2},
device_class=BinarySensorDeviceClass.SAFETY, device_class=BinarySensorDeviceClass.SAFETY,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 7: Home Security - State Id's 3, 4, 9 (tampering) # NotificationType 7: Home Security - State Id's 3, 4, 9 (tampering)
key=NOTIFICATION_HOME_SECURITY, key=NOTIFICATION_HOME_SECURITY,
states=("3", "4", "9"), states={3, 4, 9},
device_class=BinarySensorDeviceClass.TAMPER, device_class=BinarySensorDeviceClass.TAMPER,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 7: Home Security - State Id's 5, 6 (glass breakage) # NotificationType 7: Home Security - State Id's 5, 6 (glass breakage)
key=NOTIFICATION_HOME_SECURITY, key=NOTIFICATION_HOME_SECURITY,
states=("5", "6"), states={5, 6},
device_class=BinarySensorDeviceClass.SAFETY, device_class=BinarySensorDeviceClass.SAFETY,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 7: Home Security - State Id's 7, 8 (motion) # NotificationType 7: Home Security - State Id's 7, 8 (motion)
key=NOTIFICATION_HOME_SECURITY, key=NOTIFICATION_HOME_SECURITY,
states=("7", "8"), states={7, 8},
device_class=BinarySensorDeviceClass.MOTION, device_class=BinarySensorDeviceClass.MOTION,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 8: Power Management - # NotificationType 8: Power Management -
# State Id's 2, 3 (Mains status) # State Id's 2, 3 (Mains status)
key=NOTIFICATION_POWER_MANAGEMENT, key=NOTIFICATION_POWER_MANAGEMENT,
not_states={"2"}, not_states={2},
states=("3",), states={3},
device_class=BinarySensorDeviceClass.PLUG, device_class=BinarySensorDeviceClass.PLUG,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -249,7 +253,7 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
# NotificationType 8: Power Management - # NotificationType 8: Power Management -
# State Id's 6, 7, 8, 9 (power status) # State Id's 6, 7, 8, 9 (power status)
key=NOTIFICATION_POWER_MANAGEMENT, key=NOTIFICATION_POWER_MANAGEMENT,
states=("6", "7", "8", "9"), states={6, 7, 8, 9},
device_class=BinarySensorDeviceClass.SAFETY, device_class=BinarySensorDeviceClass.SAFETY,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -257,39 +261,39 @@ NOTIFICATION_SENSOR_MAPPINGS: tuple[NotificationZWaveJSEntityDescription, ...] =
# NotificationType 8: Power Management - # NotificationType 8: Power Management -
# State Id's 10, 11, 17 (Battery maintenance status) # State Id's 10, 11, 17 (Battery maintenance status)
key=NOTIFICATION_POWER_MANAGEMENT, key=NOTIFICATION_POWER_MANAGEMENT,
states=("10", "11", "17"), states={10, 11, 17},
device_class=BinarySensorDeviceClass.BATTERY, device_class=BinarySensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 9: System - State Id's 1, 2, 3, 4, 6, 7 # NotificationType 9: System - State Id's 1, 2, 3, 4, 6, 7
key=NOTIFICATION_SYSTEM, key=NOTIFICATION_SYSTEM,
states=("1", "2", "3", "4", "6", "7"), states={1, 2, 3, 4, 6, 7},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 10: Emergency - State Id's 1, 2, 3 # NotificationType 10: Emergency - State Id's 1, 2, 3
key=NOTIFICATION_EMERGENCY, key=NOTIFICATION_EMERGENCY,
states=("1", "2", "3"), states={1, 2, 3},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 14: Siren # NotificationType 14: Siren
key=NOTIFICATION_SIREN, key=NOTIFICATION_SIREN,
states=("1",), states={1},
device_class=BinarySensorDeviceClass.SOUND, device_class=BinarySensorDeviceClass.SOUND,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 18: Gas - State Id's 1, 2, 3, 4 # NotificationType 18: Gas - State Id's 1, 2, 3, 4
key=NOTIFICATION_GAS, key=NOTIFICATION_GAS,
states=("1", "2", "3", "4"), states={1, 2, 3, 4},
device_class=BinarySensorDeviceClass.GAS, device_class=BinarySensorDeviceClass.GAS,
), ),
NotificationZWaveJSEntityDescription( NotificationZWaveJSEntityDescription(
# NotificationType 18: Gas - State Id 6 # NotificationType 18: Gas - State Id 6
key=NOTIFICATION_GAS, key=NOTIFICATION_GAS,
states=("6",), states={6},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -386,10 +390,10 @@ async def async_setup_entry(
config_entry, driver, info, state_key, info.entity_description config_entry, driver, info, state_key, info.entity_description
) )
for state_key in info.primary_value.metadata.states for state_key in info.primary_value.metadata.states
if state_key not in info.entity_description.not_states if int(state_key) not in info.entity_description.not_states
and ( and (
not info.entity_description.states not info.entity_description.states
or state_key in info.entity_description.states or int(state_key) in info.entity_description.states
) )
) )
elif isinstance(info, NewZwaveDiscoveryInfo): elif isinstance(info, NewZwaveDiscoveryInfo):
@@ -400,6 +404,8 @@ async def async_setup_entry(
return return
# Get all sensors from Notification CC states # Get all sensors from Notification CC states
for state_key in info.primary_value.metadata.states: for state_key in info.primary_value.metadata.states:
if TYPE_CHECKING:
state_key = cast(str, state_key)
# ignore idle key (0) # ignore idle key (0)
if state_key == "0": if state_key == "0":
continue continue
@@ -413,13 +419,15 @@ async def async_setup_entry(
== info.primary_value.metadata.cc_specific[ == info.primary_value.metadata.cc_specific[
CC_SPECIFIC_NOTIFICATION_TYPE CC_SPECIFIC_NOTIFICATION_TYPE
] ]
) and (not description.states or state_key in description.states): ) and (
not description.states or int(state_key) in description.states
):
notification_description = description notification_description = description
break break
if ( if (
notification_description notification_description
and state_key in notification_description.not_states and int(state_key) in notification_description.not_states
): ):
continue continue
entities.append( entities.append(
@@ -571,14 +579,22 @@ DISCOVERY_SCHEMAS: list[NewZWaveDiscoverySchema] = [
CommandClass.NOTIFICATION, CommandClass.NOTIFICATION,
}, },
type={ValueType.NUMBER}, type={ValueType.NUMBER},
any_available_states_keys={1, 2}, any_available_states_keys={
any_available_cc_specific={(CC_SPECIFIC_NOTIFICATION_TYPE, 1)}, SmokeAlarmNotificationEvent.SENSOR_STATUS_SMOKE_DETECTED_LOCATION_PROVIDED,
SmokeAlarmNotificationEvent.SENSOR_STATUS_SMOKE_DETECTED,
},
any_available_cc_specific={
(CC_SPECIFIC_NOTIFICATION_TYPE, NotificationType.SMOKE_ALARM)
},
), ),
allow_multi=True, allow_multi=True,
entity_description=NotificationZWaveJSEntityDescription( entity_description=NotificationZWaveJSEntityDescription(
# NotificationType 1: Smoke Alarm - State Id's 1 and 2 - Smoke detected # NotificationType 1: Smoke Alarm - State Id's 1 and 2 - Smoke detected
key=NOTIFICATION_SMOKE_ALARM, key=NOTIFICATION_SMOKE_ALARM,
states=("1", "2"), states={
SmokeAlarmNotificationEvent.SENSOR_STATUS_SMOKE_DETECTED_LOCATION_PROVIDED,
SmokeAlarmNotificationEvent.SENSOR_STATUS_SMOKE_DETECTED,
},
device_class=BinarySensorDeviceClass.SMOKE, device_class=BinarySensorDeviceClass.SMOKE,
), ),
entity_class=ZWaveNotificationBinarySensor, entity_class=ZWaveNotificationBinarySensor,
@@ -590,14 +606,26 @@ DISCOVERY_SCHEMAS: list[NewZWaveDiscoverySchema] = [
CommandClass.NOTIFICATION, CommandClass.NOTIFICATION,
}, },
type={ValueType.NUMBER}, type={ValueType.NUMBER},
any_available_states_keys={4, 5, 7, 8}, any_available_states_keys={
any_available_cc_specific={(CC_SPECIFIC_NOTIFICATION_TYPE, 1)}, SmokeAlarmNotificationEvent.MAINTENANCE_STATUS_REPLACEMENT_REQUIRED,
SmokeAlarmNotificationEvent.MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE,
SmokeAlarmNotificationEvent.PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION,
SmokeAlarmNotificationEvent.DUST_IN_DEVICE_STATUS_MAINTENANCE_REQUIRED_DUST_IN_DEVICE,
},
any_available_cc_specific={
(CC_SPECIFIC_NOTIFICATION_TYPE, NotificationType.SMOKE_ALARM)
},
), ),
allow_multi=True, allow_multi=True,
entity_description=NotificationZWaveJSEntityDescription( entity_description=NotificationZWaveJSEntityDescription(
# NotificationType 1: Smoke Alarm - State Id's 4, 5, 7, 8 # NotificationType 1: Smoke Alarm - State Id's 4, 5, 7, 8
key=NOTIFICATION_SMOKE_ALARM, key=NOTIFICATION_SMOKE_ALARM,
states=("4", "5", "7", "8"), states={
SmokeAlarmNotificationEvent.MAINTENANCE_STATUS_REPLACEMENT_REQUIRED,
SmokeAlarmNotificationEvent.MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE,
SmokeAlarmNotificationEvent.PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION,
SmokeAlarmNotificationEvent.DUST_IN_DEVICE_STATUS_MAINTENANCE_REQUIRED_DUST_IN_DEVICE,
},
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
@@ -610,7 +638,9 @@ DISCOVERY_SCHEMAS: list[NewZWaveDiscoverySchema] = [
CommandClass.NOTIFICATION, CommandClass.NOTIFICATION,
}, },
type={ValueType.NUMBER}, type={ValueType.NUMBER},
any_available_cc_specific={(CC_SPECIFIC_NOTIFICATION_TYPE, 1)}, any_available_cc_specific={
(CC_SPECIFIC_NOTIFICATION_TYPE, NotificationType.SMOKE_ALARM)
},
), ),
allow_multi=True, allow_multi=True,
entity_description=NotificationZWaveJSEntityDescription( entity_description=NotificationZWaveJSEntityDescription(
@@ -618,12 +648,12 @@ DISCOVERY_SCHEMAS: list[NewZWaveDiscoverySchema] = [
key=NOTIFICATION_SMOKE_ALARM, key=NOTIFICATION_SMOKE_ALARM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
not_states={ not_states={
"1", SmokeAlarmNotificationEvent.SENSOR_STATUS_SMOKE_DETECTED_LOCATION_PROVIDED,
"2", SmokeAlarmNotificationEvent.SENSOR_STATUS_SMOKE_DETECTED,
"4", SmokeAlarmNotificationEvent.MAINTENANCE_STATUS_REPLACEMENT_REQUIRED,
"5", SmokeAlarmNotificationEvent.MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE,
"7", SmokeAlarmNotificationEvent.PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION,
"8", SmokeAlarmNotificationEvent.DUST_IN_DEVICE_STATUS_MAINTENANCE_REQUIRED_DUST_IN_DEVICE,
}, },
), ),
entity_class=ZWaveNotificationBinarySensor, entity_class=ZWaveNotificationBinarySensor,