Add zwave_js.set_config_parameter service (#46673)
* create zwave_js.set_config_value service * update docstring * PR comments * make proposed changes * handle providing a label for the new value * fix docstring * use new library function * config param endpoint is always 0 * corresponding changes from upstream PR * bug fixes and add tests * create zwave_js.set_config_value service * update docstring * PR comments * make proposed changes * handle providing a label for the new value * fix docstring * use new library function * config param endpoint is always 0 * corresponding changes from upstream PR * bug fixes and add tests * use lambda to avoid extra function * add services description file * bring back the missing selector * move helper functions to helper file for reuse * allow target selector for automation editor * formatting * fix service schema * update docstrings * raise error in service if call to set value is unsuccessful * Update homeassistant/components/zwave_js/services.yaml Co-authored-by: Franck Nijhof <frenck@frenck.nl> * Update homeassistant/components/zwave_js/services.yaml Co-authored-by: Franck Nijhof <frenck@frenck.nl> * Update homeassistant/components/zwave_js/services.yaml Co-authored-by: Franck Nijhof <frenck@frenck.nl> * Update homeassistant/components/zwave_js/services.yaml Co-authored-by: Franck Nijhof <frenck@frenck.nl> * Update homeassistant/components/zwave_js/services.yaml Co-authored-by: Franck Nijhof <frenck@frenck.nl> * Update homeassistant/components/zwave_js/services.yaml Co-authored-by: Franck Nijhof <frenck@frenck.nl> * remove extra param to vol.Optional * switch to set over list for nodes * switch to set over list for nodes Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com> Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
parent
c94968d811
commit
5a3bd30e01
8 changed files with 548 additions and 11 deletions
100
homeassistant/components/zwave_js/helpers.py
Normal file
100
homeassistant/components/zwave_js/helpers.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
"""Helper functions for Z-Wave JS integration."""
|
||||
from typing import List, Tuple, cast
|
||||
|
||||
from zwave_js_server.client import Client as ZwaveClient
|
||||
from zwave_js_server.model.node import Node as ZwaveNode
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.device_registry import async_get as async_get_dev_reg
|
||||
from homeassistant.helpers.entity_registry import async_get as async_get_ent_reg
|
||||
|
||||
from .const import DATA_CLIENT, DOMAIN
|
||||
|
||||
|
||||
@callback
|
||||
def get_device_id(client: ZwaveClient, node: ZwaveNode) -> Tuple[str, str]:
|
||||
"""Get device registry identifier for Z-Wave node."""
|
||||
return (DOMAIN, f"{client.driver.controller.home_id}-{node.node_id}")
|
||||
|
||||
|
||||
@callback
|
||||
def get_home_and_node_id_from_device_id(device_id: Tuple[str, str]) -> List[str]:
|
||||
"""
|
||||
Get home ID and node ID for Z-Wave device registry entry.
|
||||
|
||||
Returns [home_id, node_id]
|
||||
"""
|
||||
return device_id[1].split("-")
|
||||
|
||||
|
||||
@callback
|
||||
def async_get_node_from_device_id(hass: HomeAssistant, device_id: str) -> ZwaveNode:
|
||||
"""
|
||||
Get node from a device ID.
|
||||
|
||||
Raises ValueError if device is invalid or node can't be found.
|
||||
"""
|
||||
device_entry = async_get_dev_reg(hass).async_get(device_id)
|
||||
|
||||
if not device_entry:
|
||||
raise ValueError("Device ID is not valid")
|
||||
|
||||
# Use device config entry ID's to validate that this is a valid zwave_js device
|
||||
# and to get the client
|
||||
config_entry_ids = device_entry.config_entries
|
||||
config_entry_id = next(
|
||||
(
|
||||
config_entry_id
|
||||
for config_entry_id in config_entry_ids
|
||||
if cast(
|
||||
ConfigEntry,
|
||||
hass.config_entries.async_get_entry(config_entry_id),
|
||||
).domain
|
||||
== DOMAIN
|
||||
),
|
||||
None,
|
||||
)
|
||||
if config_entry_id is None or config_entry_id not in hass.data[DOMAIN]:
|
||||
raise ValueError("Device is not from an existing zwave_js config entry")
|
||||
|
||||
client = hass.data[DOMAIN][config_entry_id][DATA_CLIENT]
|
||||
|
||||
# Get node ID from device identifier, perform some validation, and then get the
|
||||
# node
|
||||
identifier = next(
|
||||
(
|
||||
get_home_and_node_id_from_device_id(identifier)
|
||||
for identifier in device_entry.identifiers
|
||||
if identifier[0] == DOMAIN
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
node_id = int(identifier[1]) if identifier is not None else None
|
||||
|
||||
if node_id is None or node_id not in client.driver.controller.nodes:
|
||||
raise ValueError("Device node can't be found")
|
||||
|
||||
return client.driver.controller.nodes[node_id]
|
||||
|
||||
|
||||
@callback
|
||||
def async_get_node_from_entity_id(hass: HomeAssistant, entity_id: str) -> ZwaveNode:
|
||||
"""
|
||||
Get node from an entity ID.
|
||||
|
||||
Raises ValueError if entity is invalid.
|
||||
"""
|
||||
entity_entry = async_get_ent_reg(hass).async_get(entity_id)
|
||||
|
||||
if not entity_entry:
|
||||
raise ValueError("Entity ID is not valid")
|
||||
|
||||
if entity_entry.platform != DOMAIN:
|
||||
raise ValueError("Entity is not from zwave_js integration")
|
||||
|
||||
# Assert for mypy, safe because we know that zwave_js entities are always
|
||||
# tied to a device
|
||||
assert entity_entry.device_id
|
||||
return async_get_node_from_device_id(hass, entity_entry.device_id)
|
Loading…
Add table
Add a link
Reference in a new issue