22
33from __future__ import annotations
44
5+ from abc import ABC , abstractmethod
56import asyncio
67import contextlib
78from dataclasses import dataclass
@@ -66,11 +67,64 @@ class SirenEntityInfo(BaseEntityInfo):
6667 supported_features : SirenEntityFeature
6768
6869
70+ class BaseSiren (PlatformEntity , ABC ):
71+ """Abstract base class for ZHA siren entities."""
72+
73+ PLATFORM = Platform .SIREN
74+
75+ _attr_is_on : bool = False
76+ _attr_available_tones : dict [int , str ]
77+ _attr_supported_features : SirenEntityFeature
78+
79+ @property
80+ def state (self ) -> dict [str , Any ]:
81+ """Get the state of the siren."""
82+ response = super ().state
83+ response ["state" ] = self .is_on
84+ return response
85+
86+ @property
87+ def is_on (self ) -> bool :
88+ """Return true if the entity is on."""
89+ return self ._attr_is_on
90+
91+ @property
92+ def available_tones (self ) -> dict [int , str ]:
93+ """Return available tones."""
94+ return self ._attr_available_tones
95+
96+ @property
97+ def supported_features (self ) -> SirenEntityFeature :
98+ """Return supported features."""
99+ return self ._attr_supported_features
100+
101+ @functools .cached_property
102+ def info_object (self ) -> SirenEntityInfo :
103+ """Return representation of the siren."""
104+ return SirenEntityInfo (
105+ ** super ().info_object .__dict__ ,
106+ available_tones = self .available_tones ,
107+ supported_features = self .supported_features ,
108+ )
109+
110+ @abstractmethod
111+ async def async_turn_on (
112+ self ,
113+ duration : int | None = None ,
114+ tone : int | None = None ,
115+ volume_level : int | None = None ,
116+ ) -> None :
117+ """Turn on siren."""
118+
119+ @abstractmethod
120+ async def async_turn_off (self ) -> None :
121+ """Turn off siren."""
122+
123+
69124@register_entity (IasWd .cluster_id )
70- class Siren (PlatformEntity ):
125+ class Siren (BaseSiren ):
71126 """Representation of a ZHA siren."""
72127
73- PLATFORM = Platform .SIREN
74128 _attr_fallback_name : str = "Siren"
75129 _attr_primary_weight = 4
76130
@@ -120,36 +174,14 @@ def __init__(
120174 WARNING_DEVICE_MODE_FIRE_PANIC : "Fire Panic" ,
121175 WARNING_DEVICE_MODE_EMERGENCY_PANIC : "Emergency Panic" ,
122176 }
123- self ._attr_is_on : bool = False
124177 self ._off_listener : asyncio .TimerHandle | None = None
125178
126- @functools .cached_property
127- def info_object (self ) -> SirenEntityInfo :
128- """Return representation of the siren."""
129- return SirenEntityInfo (
130- ** super ().info_object .__dict__ ,
131- available_tones = self ._attr_available_tones ,
132- supported_features = self ._attr_supported_features ,
133- )
134-
135- @property
136- def state (self ) -> dict [str , Any ]:
137- """Get the state of the siren."""
138- response = super ().state
139- response ["state" ] = self .is_on
140- return response
141-
142- @property
143- def supported_features (self ) -> SirenEntityFeature :
144- """Return supported features."""
145- return self ._attr_supported_features
146-
147- @property
148- def is_on (self ) -> bool :
149- """Return true if the entity is on."""
150- return self ._attr_is_on
151-
152- async def async_turn_on (self , ** kwargs : Any ) -> None :
179+ async def async_turn_on (
180+ self ,
181+ duration : int | None = None ,
182+ tone : int | None = None ,
183+ volume_level : int | None = None ,
184+ ) -> None :
153185 """Turn on siren."""
154186 if self ._off_listener :
155187 self ._off_listener .cancel ()
@@ -181,12 +213,12 @@ async def async_turn_on(self, **kwargs: Any) -> None:
181213 if strobe_level_cache is not None
182214 else WARNING_DEVICE_STROBE_HIGH
183215 )
184- if ( duration := kwargs . get ( ATTR_DURATION )) is not None :
216+ if duration is not None :
185217 siren_duration = duration
186- if ( tone := kwargs . get ( ATTR_TONE )) is not None :
218+ if tone is not None :
187219 siren_tone = tone
188- if ( level := kwargs . get ( ATTR_VOLUME_LEVEL )) is not None :
189- siren_level = int (level )
220+ if volume_level is not None :
221+ siren_level = int (volume_level )
190222 await self ._cluster_handler .issue_start_warning (
191223 mode = siren_tone ,
192224 warning_duration = siren_duration ,
@@ -202,7 +234,7 @@ async def async_turn_on(self, **kwargs: Any) -> None:
202234 self ._tracked_handles .append (self ._off_listener )
203235 self .maybe_emit_state_changed_event ()
204236
205- async def async_turn_off (self , ** kwargs : Any ) -> None : # pylint: disable=unused-argument
237+ async def async_turn_off (self ) -> None :
206238 """Turn off siren."""
207239 await self ._cluster_handler .issue_start_warning (
208240 mode = WARNING_DEVICE_MODE_STOP , strobe = WARNING_DEVICE_STROBE_NO
0 commit comments