1 """Generic Z-Wave Entity Class."""
3 from __future__
import annotations
5 from collections.abc
import Sequence
8 from zwave_js_server.const
import NodeStatus
9 from zwave_js_server.exceptions
import BaseZwaveJSServerError
10 from zwave_js_server.model.driver
import Driver
11 from zwave_js_server.model.value
import (
25 from .const
import DOMAIN, EVENT_VALUE_UPDATED, LOGGER
26 from .discovery
import ZwaveDiscoveryInfo
27 from .helpers
import get_device_id, get_unique_id, get_valueless_base_unique_id
29 EVENT_VALUE_REMOVED =
"value removed"
35 """Generic Entity Class for a Z-Wave Device."""
37 _attr_should_poll =
False
38 _attr_has_entity_name =
True
41 self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
43 """Initialize a generic Z-Wave device entity."""
50 if self.
infoinfo.additional_value_ids_to_watch:
52 self.
infoinfo.additional_value_ids_to_watch
58 if self.
infoinfo.entity_registry_enabled_default
is False:
60 if self.
infoinfo.entity_category
is not None:
62 if self.
infoinfo.assumed_state:
71 """Call when one of the watched values change.
73 To be overridden by platforms needing this event.
82 await self.info.node.async_poll_value(value_or_id)
83 except BaseZwaveJSServerError
as err:
84 LOGGER.error(
"Error while refreshing value %s: %s", value_or_id, err)
88 if not refresh_all_values:
92 "Refreshing primary value %s for %s, "
93 "state update may be delayed for devices on battery"
95 self.
infoinfo.primary_value,
105 "Refreshing values %s for %s, state update may be delayed for "
113 """Call when entity is added."""
126 f
"{get_valueless_base_unique_id(self.driver, self.info.node)}_"
137 f
"{get_valueless_base_unique_id(self.driver, self.info.node)}_"
138 "remove_entity_on_interview_started"
144 for status_event
in (EVENT_ALIVE, EVENT_DEAD):
152 f
"{DOMAIN}_{self.unique_id}_poll_value",
159 include_value_name: bool =
False,
160 alternate_value_name: str |
None =
None,
161 additional_info: Sequence[str |
None] |
None =
None,
162 name_prefix: str |
None =
None,
164 """Generate entity name."""
165 primary_value = self.
infoinfo.primary_value
168 hasattr(self,
"entity_description")
169 and self.entity_description
170 and self.entity_description.name
171 and self.entity_description.name
is not UNDEFINED
173 name = self.entity_description.name
176 name = f
"{name_prefix} {name}".strip()
179 if alternate_value_name:
180 value_name = alternate_value_name
181 elif include_value_name:
183 primary_value.metadata.label
184 or primary_value.property_key_name
185 or primary_value.property_name
189 name = f
"{name} {value_name}".strip()
191 if additional_info := [item
for item
in (additional_info
or [])
if item]:
192 name = f
"{name} {' '.join(additional_info)}"
196 if primary_value.endpoint
is not None and any(
199 primary_value.command_class,
200 primary_value.property_,
201 endpoint=endpoint_idx,
202 property_key=primary_value.property_key,
204 in self.
infoinfo.node.values
205 for endpoint_idx
in range(primary_value.endpoint)
207 name += f
" ({primary_value.endpoint})"
213 """Return entity availability."""
215 self.
driverdriver.client.connected
217 and self.
infoinfo.node.status != NodeStatus.DEAD
222 """Call when node status changes to alive or dead.
224 Should not be overridden by subclasses.
230 """Call when a value associated with our node changes.
232 Should not be overridden by subclasses.
234 value_id = event_data[
"value"].value_id
239 value = self.
infoinfo.node.values[value_id]
242 "[%s] Value %s/%s changed to: %s",
245 value.property_key_name,
254 """Call when a value associated with our node is removed.
256 Should not be overridden by subclasses.
258 value_id = event_data[
"value"].value_id
260 if value_id != self.
infoinfo.primary_value.value_id:
264 "[%s] Primary value %s is being removed",
274 value_property: str | int,
275 command_class: int |
None =
None,
276 endpoint: int |
None =
None,
277 value_property_key: int | str |
None =
None,
278 add_to_watched_value_ids: bool =
True,
279 check_all_endpoints: bool =
False,
280 ) -> ZwaveValue |
None:
281 """Return specific ZwaveValue on this ZwaveNode."""
284 if command_class
is None:
285 command_class = self.
infoinfo.primary_value.command_class
287 endpoint = self.
infoinfo.primary_value.endpoint
290 value_id = get_value_id_str(
295 property_key=value_property_key,
297 return_value = self.
infoinfo.node.values.get(value_id)
301 if return_value
is None and check_all_endpoints:
302 for endpoint_idx
in self.
infoinfo.node.endpoints:
303 if endpoint_idx != self.
infoinfo.primary_value.endpoint:
304 value_id = get_value_id_str(
308 endpoint=endpoint_idx,
309 property_key=value_property_key,
311 return_value = self.
infoinfo.node.values.get(value_id)
319 and add_to_watched_value_ids
328 options: dict |
None =
None,
329 wait_for_result: bool |
None =
None,
330 ) -> SetValueResult |
None:
331 """Set value on node."""
333 return await self.
infoinfo.node.async_set_value(
334 value, new_value, options=options, wait_for_result=wait_for_result
336 except BaseZwaveJSServerError
as err:
338 f
"Unable to set value {value.value_id}: {err}"
None _value_changed(self, dict event_data)
None on_value_update(self)
str generate_name(self, bool include_value_name=False, str|None alternate_value_name=None, Sequence[str|None]|None additional_info=None, str|None name_prefix=None)
None async_added_to_hass(self)
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
SetValueResult|None _async_set_value(self, ZwaveValue value, Any new_value, dict|None options=None, bool|None wait_for_result=None)
_attr_entity_registry_enabled_default
None _value_removed(self, dict event_data)
None _node_status_alive_or_dead(self, dict event_data)
None _async_poll_value(self, str|ZwaveValue value_or_id)
None async_poll_value(self, bool refresh_all_values)
ZwaveValue|None get_zwave_value(self, str|int value_property, int|None command_class=None, int|None endpoint=None, int|str|None value_property_key=None, bool add_to_watched_value_ids=True, bool check_all_endpoints=False)
None async_write_ha_state(self)
None async_on_remove(self, CALLBACK_TYPE func)
None async_remove(self, *bool force_remove=False)
bool add(self, _T matcher)
str get_device_id(ServerInfoMessage server_info, MatterEndpoint endpoint)
str get_unique_id(dict[str, Any] data)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)