Bump zwave-js-server-python to 0.50.1 (#94760)
* Bump zwave-js-server-python to 0.50.0 * handle additional upstream changes * Additional changes * fix tests * Convert two similar functions to be one function * Fix docstring * Remove conditional pydantic import * Revert scope change * Bump zwave-js-server-python * Set default return value for command * Remove line breaks * Add coverage
This commit is contained in:
parent
2841cbbed2
commit
5d3d66e47d
28 changed files with 171 additions and 128 deletions
|
@ -9,7 +9,7 @@ from typing import Any
|
||||||
|
|
||||||
from async_timeout import timeout
|
from async_timeout import timeout
|
||||||
from zwave_js_server.client import Client as ZwaveClient
|
from zwave_js_server.client import Client as ZwaveClient
|
||||||
from zwave_js_server.const import CommandClass
|
from zwave_js_server.const import CommandClass, RemoveNodeReason
|
||||||
from zwave_js_server.exceptions import BaseZwaveJSServerError, InvalidServerVersion
|
from zwave_js_server.exceptions import BaseZwaveJSServerError, InvalidServerVersion
|
||||||
from zwave_js_server.model.driver import Driver
|
from zwave_js_server.model.driver import Driver
|
||||||
from zwave_js_server.model.node import Node as ZwaveNode
|
from zwave_js_server.model.node import Node as ZwaveNode
|
||||||
|
@ -398,13 +398,13 @@ class ControllerEvents:
|
||||||
def async_on_node_removed(self, event: dict) -> None:
|
def async_on_node_removed(self, event: dict) -> None:
|
||||||
"""Handle node removed event."""
|
"""Handle node removed event."""
|
||||||
node: ZwaveNode = event["node"]
|
node: ZwaveNode = event["node"]
|
||||||
replaced: bool = event.get("replaced", False)
|
reason: RemoveNodeReason = event["reason"]
|
||||||
# grab device in device registry attached to this node
|
# grab device in device registry attached to this node
|
||||||
dev_id = get_device_id(self.driver_events.driver, node)
|
dev_id = get_device_id(self.driver_events.driver, node)
|
||||||
device = self.dev_reg.async_get_device(identifiers={dev_id})
|
device = self.dev_reg.async_get_device(identifiers={dev_id})
|
||||||
# We assert because we know the device exists
|
# We assert because we know the device exists
|
||||||
assert device
|
assert device
|
||||||
if replaced:
|
if reason in (RemoveNodeReason.REPLACED, RemoveNodeReason.PROXY_REPLACED):
|
||||||
self.discovered_value_ids.pop(device.id, None)
|
self.discovered_value_ids.pop(device.id, None)
|
||||||
|
|
||||||
async_dispatcher_send(
|
async_dispatcher_send(
|
||||||
|
|
|
@ -1138,6 +1138,7 @@ async def websocket_remove_node(
|
||||||
node = event["node"]
|
node = event["node"]
|
||||||
node_details = {
|
node_details = {
|
||||||
"node_id": node.node_id,
|
"node_id": node.node_id,
|
||||||
|
"reason": event["reason"],
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.send_message(
|
connection.send_message(
|
||||||
|
|
|
@ -507,8 +507,9 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
|
||||||
# Please use Dry and Fan HVAC modes instead.
|
# Please use Dry and Fan HVAC modes instead.
|
||||||
if preset_mode_value in (ThermostatMode.DRY, ThermostatMode.FAN):
|
if preset_mode_value in (ThermostatMode.DRY, ThermostatMode.FAN):
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
"Dry and Fan preset modes are deprecated and will be removed in Home Assistant 2024.2. "
|
"Dry and Fan preset modes are deprecated and will be removed in Home "
|
||||||
"Please use the corresponding Dry and Fan HVAC modes instead"
|
"Assistant 2024.2. Please use the corresponding Dry and Fan HVAC "
|
||||||
|
"modes instead"
|
||||||
)
|
)
|
||||||
async_create_issue(
|
async_create_issue(
|
||||||
self.hass,
|
self.hass,
|
||||||
|
|
|
@ -54,9 +54,8 @@ from .device_automation_helpers import (
|
||||||
CONF_SUBTYPE,
|
CONF_SUBTYPE,
|
||||||
VALUE_ID_REGEX,
|
VALUE_ID_REGEX,
|
||||||
generate_config_parameter_subtype,
|
generate_config_parameter_subtype,
|
||||||
get_config_parameter_value_schema,
|
|
||||||
)
|
)
|
||||||
from .helpers import async_get_node_from_device_id
|
from .helpers import async_get_node_from_device_id, get_value_state_schema
|
||||||
|
|
||||||
ACTION_TYPES = {
|
ACTION_TYPES = {
|
||||||
SERVICE_CLEAR_LOCK_USERCODE,
|
SERVICE_CLEAR_LOCK_USERCODE,
|
||||||
|
@ -357,7 +356,7 @@ async def async_get_action_capabilities(
|
||||||
property_key=config[ATTR_CONFIG_PARAMETER_BITMASK],
|
property_key=config[ATTR_CONFIG_PARAMETER_BITMASK],
|
||||||
endpoint=config[ATTR_ENDPOINT],
|
endpoint=config[ATTR_ENDPOINT],
|
||||||
)
|
)
|
||||||
value_schema = get_config_parameter_value_schema(node, value_id)
|
value_schema = get_value_state_schema(node.values[value_id])
|
||||||
if value_schema is None:
|
if value_schema is None:
|
||||||
return {}
|
return {}
|
||||||
return {"extra_fields": vol.Schema({vol.Required(ATTR_VALUE): value_schema})}
|
return {"extra_fields": vol.Schema({vol.Required(ATTR_VALUE): value_schema})}
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
"""Provides helpers for Z-Wave JS device automations."""
|
"""Provides helpers for Z-Wave JS device automations."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import cast
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
from zwave_js_server.client import Client as ZwaveClient
|
from zwave_js_server.client import Client as ZwaveClient
|
||||||
from zwave_js_server.const import ConfigurationValueType
|
|
||||||
from zwave_js_server.model.node import Node
|
|
||||||
from zwave_js_server.model.value import ConfigurationValue
|
from zwave_js_server.model.value import ConfigurationValue
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
@ -23,24 +18,6 @@ CONF_VALUE_ID = "value_id"
|
||||||
VALUE_ID_REGEX = r"([0-9]+-[0-9]+-[0-9]+-).+"
|
VALUE_ID_REGEX = r"([0-9]+-[0-9]+-[0-9]+-).+"
|
||||||
|
|
||||||
|
|
||||||
def get_config_parameter_value_schema(node: Node, value_id: str) -> vol.Schema | None:
|
|
||||||
"""Get the extra fields schema for a config parameter value."""
|
|
||||||
config_value = cast(ConfigurationValue, node.values[value_id])
|
|
||||||
min_ = config_value.metadata.min
|
|
||||||
max_ = config_value.metadata.max
|
|
||||||
|
|
||||||
if config_value.configuration_value_type in (
|
|
||||||
ConfigurationValueType.RANGE,
|
|
||||||
ConfigurationValueType.MANUAL_ENTRY,
|
|
||||||
):
|
|
||||||
return vol.All(vol.Coerce(int), vol.Range(min=min_, max=max_))
|
|
||||||
|
|
||||||
if config_value.configuration_value_type == ConfigurationValueType.ENUMERATED:
|
|
||||||
return vol.In({int(k): v for k, v in config_value.metadata.states.items()})
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def generate_config_parameter_subtype(config_value: ConfigurationValue) -> str:
|
def generate_config_parameter_subtype(config_value: ConfigurationValue) -> str:
|
||||||
"""Generate the config parameter name used in a device automation subtype."""
|
"""Generate the config parameter name used in a device automation subtype."""
|
||||||
parameter = str(config_value.property_)
|
parameter = str(config_value.property_)
|
||||||
|
|
|
@ -31,11 +31,11 @@ from .device_automation_helpers import (
|
||||||
NODE_STATUSES,
|
NODE_STATUSES,
|
||||||
async_bypass_dynamic_config_validation,
|
async_bypass_dynamic_config_validation,
|
||||||
generate_config_parameter_subtype,
|
generate_config_parameter_subtype,
|
||||||
get_config_parameter_value_schema,
|
|
||||||
)
|
)
|
||||||
from .helpers import (
|
from .helpers import (
|
||||||
async_get_node_from_device_id,
|
async_get_node_from_device_id,
|
||||||
check_type_schema_map,
|
check_type_schema_map,
|
||||||
|
get_value_state_schema,
|
||||||
get_zwave_value_from_config,
|
get_zwave_value_from_config,
|
||||||
remove_keys_with_empty_values,
|
remove_keys_with_empty_values,
|
||||||
)
|
)
|
||||||
|
@ -209,7 +209,7 @@ async def async_get_condition_capabilities(
|
||||||
# Add additional fields to the automation trigger UI
|
# Add additional fields to the automation trigger UI
|
||||||
if config[CONF_TYPE] == CONFIG_PARAMETER_TYPE:
|
if config[CONF_TYPE] == CONFIG_PARAMETER_TYPE:
|
||||||
value_id = config[CONF_VALUE_ID]
|
value_id = config[CONF_VALUE_ID]
|
||||||
value_schema = get_config_parameter_value_schema(node, value_id)
|
value_schema = get_value_state_schema(node.values[value_id])
|
||||||
if value_schema is None:
|
if value_schema is None:
|
||||||
return {}
|
return {}
|
||||||
return {"extra_fields": vol.Schema({vol.Required(ATTR_VALUE): value_schema})}
|
return {"extra_fields": vol.Schema({vol.Required(ATTR_VALUE): value_schema})}
|
||||||
|
|
|
@ -7,8 +7,9 @@ from typing import Any
|
||||||
from zwave_js_server.client import Client
|
from zwave_js_server.client import Client
|
||||||
from zwave_js_server.const import CommandClass
|
from zwave_js_server.const import CommandClass
|
||||||
from zwave_js_server.dump import dump_msgs
|
from zwave_js_server.dump import dump_msgs
|
||||||
from zwave_js_server.model.node import Node, NodeDataType
|
from zwave_js_server.model.node import Node
|
||||||
from zwave_js_server.model.value import ValueDataType
|
from zwave_js_server.model.value import ValueDataType
|
||||||
|
from zwave_js_server.util.node import dump_node_state
|
||||||
|
|
||||||
from homeassistant.components.diagnostics import REDACTED
|
from homeassistant.components.diagnostics import REDACTED
|
||||||
from homeassistant.components.diagnostics.util import async_redact_data
|
from homeassistant.components.diagnostics.util import async_redact_data
|
||||||
|
@ -54,13 +55,20 @@ def optionally_redact_value_of_zwave_value(zwave_value: ValueDataType) -> ValueD
|
||||||
return zwave_value
|
return zwave_value
|
||||||
|
|
||||||
|
|
||||||
def redact_node_state(node_state: NodeDataType) -> NodeDataType:
|
def redact_node_state(node_state: dict) -> dict:
|
||||||
"""Redact node state."""
|
"""Redact node state."""
|
||||||
redacted_state: NodeDataType = deepcopy(node_state)
|
redacted_state: dict = deepcopy(node_state)
|
||||||
redacted_state["values"] = [
|
# dump_msgs returns values in a list but dump_node_state returns them in a dict
|
||||||
optionally_redact_value_of_zwave_value(zwave_value)
|
if isinstance(node_state["values"], list):
|
||||||
for zwave_value in node_state["values"]
|
redacted_state["values"] = [
|
||||||
]
|
optionally_redact_value_of_zwave_value(zwave_value)
|
||||||
|
for zwave_value in node_state["values"]
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
redacted_state["values"] = {
|
||||||
|
value_id: optionally_redact_value_of_zwave_value(zwave_value)
|
||||||
|
for value_id, zwave_value in node_state["values"].items()
|
||||||
|
}
|
||||||
return redacted_state
|
return redacted_state
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,8 +137,8 @@ async def async_get_config_entry_diagnostics(
|
||||||
handshake_msgs = msgs[:-1]
|
handshake_msgs = msgs[:-1]
|
||||||
network_state = msgs[-1]
|
network_state = msgs[-1]
|
||||||
network_state["result"]["state"]["nodes"] = [
|
network_state["result"]["state"]["nodes"] = [
|
||||||
redact_node_state(async_redact_data(node, KEYS_TO_REDACT))
|
redact_node_state(async_redact_data(node_data, KEYS_TO_REDACT))
|
||||||
for node in network_state["result"]["state"]["nodes"]
|
for node_data in network_state["result"]["state"]["nodes"]
|
||||||
]
|
]
|
||||||
return {"messages": [*handshake_msgs, network_state]}
|
return {"messages": [*handshake_msgs, network_state]}
|
||||||
|
|
||||||
|
@ -148,7 +156,9 @@ async def async_get_device_diagnostics(
|
||||||
node = driver.controller.nodes[node_id]
|
node = driver.controller.nodes[node_id]
|
||||||
entities = get_device_entities(hass, node, config_entry, device)
|
entities = get_device_entities(hass, node, config_entry, device)
|
||||||
assert client.version
|
assert client.version
|
||||||
node_state = redact_node_state(async_redact_data(node.data, KEYS_TO_REDACT))
|
node_state = redact_node_state(
|
||||||
|
async_redact_data(dump_node_state(node), KEYS_TO_REDACT)
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"versionInfo": {
|
"versionInfo": {
|
||||||
"driverVersion": client.version.driver_version,
|
"driverVersion": client.version.driver_version,
|
||||||
|
|
|
@ -1108,7 +1108,7 @@ def async_discover_single_value(
|
||||||
def async_discover_single_configuration_value(
|
def async_discover_single_configuration_value(
|
||||||
value: ConfigurationValue,
|
value: ConfigurationValue,
|
||||||
) -> Generator[ZwaveDiscoveryInfo, None, None]:
|
) -> Generator[ZwaveDiscoveryInfo, None, None]:
|
||||||
"""Run discovery on a single ZWave configuration value and return matching schema info."""
|
"""Run discovery on single Z-Wave configuration value and return schema matches."""
|
||||||
if value.metadata.writeable and value.metadata.readable:
|
if value.metadata.writeable and value.metadata.readable:
|
||||||
if value.configuration_value_type == ConfigurationValueType.ENUMERATED:
|
if value.configuration_value_type == ConfigurationValueType.ENUMERATED:
|
||||||
yield ZwaveDiscoveryInfo(
|
yield ZwaveDiscoveryInfo(
|
||||||
|
@ -1125,36 +1125,29 @@ def async_discover_single_configuration_value(
|
||||||
ConfigurationValueType.RANGE,
|
ConfigurationValueType.RANGE,
|
||||||
ConfigurationValueType.MANUAL_ENTRY,
|
ConfigurationValueType.MANUAL_ENTRY,
|
||||||
):
|
):
|
||||||
if value.metadata.type == ValueType.BOOLEAN or (
|
yield ZwaveDiscoveryInfo(
|
||||||
value.metadata.min == 0 and value.metadata.max == 1
|
node=value.node,
|
||||||
):
|
primary_value=value,
|
||||||
yield ZwaveDiscoveryInfo(
|
assumed_state=False,
|
||||||
node=value.node,
|
platform=Platform.NUMBER,
|
||||||
primary_value=value,
|
platform_hint="config_parameter",
|
||||||
assumed_state=False,
|
platform_data=None,
|
||||||
platform=Platform.SWITCH,
|
additional_value_ids_to_watch=set(),
|
||||||
platform_hint="config_parameter",
|
entity_registry_enabled_default=False,
|
||||||
platform_data=None,
|
)
|
||||||
additional_value_ids_to_watch=set(),
|
elif value.configuration_value_type == ConfigurationValueType.BOOLEAN:
|
||||||
entity_registry_enabled_default=False,
|
yield ZwaveDiscoveryInfo(
|
||||||
)
|
node=value.node,
|
||||||
else:
|
primary_value=value,
|
||||||
yield ZwaveDiscoveryInfo(
|
assumed_state=False,
|
||||||
node=value.node,
|
platform=Platform.SWITCH,
|
||||||
primary_value=value,
|
platform_hint="config_parameter",
|
||||||
assumed_state=False,
|
platform_data=None,
|
||||||
platform=Platform.NUMBER,
|
additional_value_ids_to_watch=set(),
|
||||||
platform_hint="config_parameter",
|
entity_registry_enabled_default=False,
|
||||||
platform_data=None,
|
)
|
||||||
additional_value_ids_to_watch=set(),
|
|
||||||
entity_registry_enabled_default=False,
|
|
||||||
)
|
|
||||||
elif not value.metadata.writeable and value.metadata.readable:
|
elif not value.metadata.writeable and value.metadata.readable:
|
||||||
if value.metadata.type == ValueType.BOOLEAN or (
|
if value.configuration_value_type == ConfigurationValueType.BOOLEAN:
|
||||||
value.metadata.min == 0
|
|
||||||
and value.metadata.max == 1
|
|
||||||
and not value.metadata.states
|
|
||||||
):
|
|
||||||
yield ZwaveDiscoveryInfo(
|
yield ZwaveDiscoveryInfo(
|
||||||
node=value.node,
|
node=value.node,
|
||||||
primary_value=value,
|
primary_value=value,
|
||||||
|
|
|
@ -7,7 +7,11 @@ from typing import Any
|
||||||
from zwave_js_server.const import NodeStatus
|
from zwave_js_server.const import NodeStatus
|
||||||
from zwave_js_server.exceptions import BaseZwaveJSServerError
|
from zwave_js_server.exceptions import BaseZwaveJSServerError
|
||||||
from zwave_js_server.model.driver import Driver
|
from zwave_js_server.model.driver import Driver
|
||||||
from zwave_js_server.model.value import Value as ZwaveValue, get_value_id_str
|
from zwave_js_server.model.value import (
|
||||||
|
SetValueResult,
|
||||||
|
Value as ZwaveValue,
|
||||||
|
get_value_id_str,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
@ -70,9 +74,9 @@ class ZWaveBaseEntity(Entity):
|
||||||
|
|
||||||
async def _async_poll_value(self, value_or_id: str | ZwaveValue) -> None:
|
async def _async_poll_value(self, value_or_id: str | ZwaveValue) -> None:
|
||||||
"""Poll a value."""
|
"""Poll a value."""
|
||||||
# We log an error instead of raising an exception because this service call occurs
|
# We log an error instead of raising an exception because this service call
|
||||||
# in a separate task and we don't want to raise the exception in that separate task
|
# occurs in a separate task and we don't want to raise the exception in that
|
||||||
# because it is confusing to the user.
|
# separate task because it is confusing to the user.
|
||||||
try:
|
try:
|
||||||
await self.info.node.async_poll_value(value_or_id)
|
await self.info.node.async_poll_value(value_or_id)
|
||||||
except BaseZwaveJSServerError as err:
|
except BaseZwaveJSServerError as err:
|
||||||
|
@ -312,7 +316,7 @@ class ZWaveBaseEntity(Entity):
|
||||||
new_value: Any,
|
new_value: Any,
|
||||||
options: dict | None = None,
|
options: dict | None = None,
|
||||||
wait_for_result: bool | None = None,
|
wait_for_result: bool | None = None,
|
||||||
) -> bool | None:
|
) -> SetValueResult | None:
|
||||||
"""Set value on node."""
|
"""Set value on node."""
|
||||||
try:
|
try:
|
||||||
return await self.info.node.async_set_value(
|
return await self.info.node.async_set_value(
|
||||||
|
|
|
@ -252,7 +252,7 @@ def async_get_node_from_entity_id(
|
||||||
entity_entry = ent_reg.async_get(entity_id)
|
entity_entry = ent_reg.async_get(entity_id)
|
||||||
|
|
||||||
if entity_entry is None or entity_entry.platform != DOMAIN:
|
if entity_entry is None or entity_entry.platform != DOMAIN:
|
||||||
raise ValueError(f"Entity {entity_id} is not a valid {DOMAIN} entity.")
|
raise ValueError(f"Entity {entity_id} is not a valid {DOMAIN} entity")
|
||||||
|
|
||||||
# Assert for mypy, safe because we know that zwave_js entities are always
|
# Assert for mypy, safe because we know that zwave_js entities are always
|
||||||
# tied to a device
|
# tied to a device
|
||||||
|
@ -414,9 +414,7 @@ def copy_available_params(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_value_state_schema(
|
def get_value_state_schema(value: ZwaveValue) -> vol.Schema | None:
|
||||||
value: ZwaveValue,
|
|
||||||
) -> vol.Schema | None:
|
|
||||||
"""Return device automation schema for a config entry."""
|
"""Return device automation schema for a config entry."""
|
||||||
if isinstance(value, ConfigurationValue):
|
if isinstance(value, ConfigurationValue):
|
||||||
min_ = value.metadata.min
|
min_ = value.metadata.min
|
||||||
|
@ -427,6 +425,9 @@ def get_value_state_schema(
|
||||||
):
|
):
|
||||||
return vol.All(vol.Coerce(int), vol.Range(min=min_, max=max_))
|
return vol.All(vol.Coerce(int), vol.Range(min=min_, max=max_))
|
||||||
|
|
||||||
|
if value.configuration_value_type == ConfigurationValueType.BOOLEAN:
|
||||||
|
return vol.Coerce(bool)
|
||||||
|
|
||||||
if value.configuration_value_type == ConfigurationValueType.ENUMERATED:
|
if value.configuration_value_type == ConfigurationValueType.ENUMERATED:
|
||||||
return vol.In({int(k): v for k, v in value.metadata.states.items()})
|
return vol.In({int(k): v for k, v in value.metadata.states.items()})
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["zwave_js_server"],
|
"loggers": ["zwave_js_server"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"requirements": ["pyserial==3.5", "zwave-js-server-python==0.49.0"],
|
"requirements": ["pyserial==3.5", "zwave-js-server-python==0.50.1"],
|
||||||
"usb": [
|
"usb": [
|
||||||
{
|
{
|
||||||
"vid": "0658",
|
"vid": "0658",
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from zwave_js_server.client import Client as ZwaveClient
|
from zwave_js_server.client import Client as ZwaveClient
|
||||||
from zwave_js_server.const import CommandClass, CommandStatus
|
from zwave_js_server.const import SET_VALUE_SUCCESS, CommandClass, CommandStatus
|
||||||
from zwave_js_server.exceptions import FailedZWaveCommand, SetValueFailed
|
from zwave_js_server.exceptions import FailedZWaveCommand, SetValueFailed
|
||||||
from zwave_js_server.model.endpoint import Endpoint
|
from zwave_js_server.model.endpoint import Endpoint
|
||||||
from zwave_js_server.model.node import Node as ZwaveNode
|
from zwave_js_server.model.node import Node as ZwaveNode
|
||||||
|
@ -39,12 +39,6 @@ from .helpers import (
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SET_VALUE_FAILED_EXC = SetValueFailed(
|
|
||||||
"Unable to set value, refer to "
|
|
||||||
"https://zwave-js.github.io/node-zwave-js/#/api/node?id=setvalue for "
|
|
||||||
"possible reasons"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def parameter_name_does_not_need_bitmask(
|
def parameter_name_does_not_need_bitmask(
|
||||||
val: dict[str, int | str | list[str]]
|
val: dict[str, int | str | list[str]]
|
||||||
|
@ -538,16 +532,20 @@ class ZWaveServices:
|
||||||
nodes_list = list(nodes)
|
nodes_list = list(nodes)
|
||||||
# multiple set_values my fail so we will track the entire list
|
# multiple set_values my fail so we will track the entire list
|
||||||
set_value_failed_nodes_list: list[ZwaveNode | Endpoint] = []
|
set_value_failed_nodes_list: list[ZwaveNode | Endpoint] = []
|
||||||
for node_, success in get_valid_responses_from_results(nodes_list, results):
|
set_value_failed_error_list: list[SetValueFailed] = []
|
||||||
if success is False:
|
for node_, result in get_valid_responses_from_results(nodes_list, results):
|
||||||
# If we failed to set a value, add node to SetValueFailed exception list
|
if result and result.status not in SET_VALUE_SUCCESS:
|
||||||
|
# If we failed to set a value, add node to exception list
|
||||||
set_value_failed_nodes_list.append(node_)
|
set_value_failed_nodes_list.append(node_)
|
||||||
|
set_value_failed_error_list.append(
|
||||||
|
SetValueFailed(f"{result.status} {result.message}")
|
||||||
|
)
|
||||||
|
|
||||||
# Add the SetValueFailed exception to the results and the nodes to the node
|
# Add the exception to the results and the nodes to the node list. No-op if
|
||||||
# list. No-op if there are no SetValueFailed exceptions
|
# no set value commands failed
|
||||||
raise_exceptions_from_results(
|
raise_exceptions_from_results(
|
||||||
(*nodes_list, *set_value_failed_nodes_list),
|
(*nodes_list, *set_value_failed_nodes_list),
|
||||||
(*results, *([SET_VALUE_FAILED_EXC] * len(set_value_failed_nodes_list))),
|
(*results, *set_value_failed_error_list),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_multicast_set_value(self, service: ServiceCall) -> None:
|
async def async_multicast_set_value(self, service: ServiceCall) -> None:
|
||||||
|
@ -611,7 +609,7 @@ class ZWaveServices:
|
||||||
new_value = str(new_value)
|
new_value = str(new_value)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
success = await async_multicast_set_value(
|
result = await async_multicast_set_value(
|
||||||
client=client,
|
client=client,
|
||||||
new_value=new_value,
|
new_value=new_value,
|
||||||
value_data=value,
|
value_data=value,
|
||||||
|
@ -621,10 +619,10 @@ class ZWaveServices:
|
||||||
except FailedZWaveCommand as err:
|
except FailedZWaveCommand as err:
|
||||||
raise HomeAssistantError("Unable to set value via multicast") from err
|
raise HomeAssistantError("Unable to set value via multicast") from err
|
||||||
|
|
||||||
if success is False:
|
if result.status not in SET_VALUE_SUCCESS:
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
"Unable to set value via multicast"
|
"Unable to set value via multicast"
|
||||||
) from SetValueFailed
|
) from SetValueFailed(f"{result.status} {result.message}")
|
||||||
|
|
||||||
async def async_ping(self, service: ServiceCall) -> None:
|
async def async_ping(self, service: ServiceCall) -> None:
|
||||||
"""Ping node(s)."""
|
"""Ping node(s)."""
|
||||||
|
|
|
@ -2785,7 +2785,7 @@ zigpy==0.56.4
|
||||||
zm-py==0.5.2
|
zm-py==0.5.2
|
||||||
|
|
||||||
# homeassistant.components.zwave_js
|
# homeassistant.components.zwave_js
|
||||||
zwave-js-server-python==0.49.0
|
zwave-js-server-python==0.50.1
|
||||||
|
|
||||||
# homeassistant.components.zwave_me
|
# homeassistant.components.zwave_me
|
||||||
zwave-me-ws==0.4.3
|
zwave-me-ws==0.4.3
|
||||||
|
|
|
@ -2049,7 +2049,7 @@ zigpy-znp==0.11.4
|
||||||
zigpy==0.56.4
|
zigpy==0.56.4
|
||||||
|
|
||||||
# homeassistant.components.zwave_js
|
# homeassistant.components.zwave_js
|
||||||
zwave-js-server-python==0.49.0
|
zwave-js-server-python==0.50.1
|
||||||
|
|
||||||
# homeassistant.components.zwave_me
|
# homeassistant.components.zwave_me
|
||||||
zwave-me-ws==0.4.3
|
zwave-me-ws==0.4.3
|
||||||
|
|
|
@ -687,6 +687,9 @@ def mock_client_fixture(
|
||||||
|
|
||||||
client.version = VersionInfo.from_message(version_state)
|
client.version = VersionInfo.from_message(version_state)
|
||||||
client.ws_server_url = "ws://test:3000/zjs"
|
client.ws_server_url = "ws://test:3000/zjs"
|
||||||
|
client.async_send_command.return_value = {
|
||||||
|
"result": {"success": True, "status": 255}
|
||||||
|
}
|
||||||
|
|
||||||
yield client
|
yield client
|
||||||
|
|
||||||
|
|
|
@ -270,5 +270,5 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"replaced": false
|
"reason": 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,14 +276,16 @@ async def test_subscribe_node_status(
|
||||||
msg = await ws_client.receive_json()
|
msg = await ws_client.receive_json()
|
||||||
assert msg["success"]
|
assert msg["success"]
|
||||||
|
|
||||||
node.data["ready"] = True
|
new_node_data = deepcopy(multisensor_6_state)
|
||||||
|
new_node_data["ready"] = True
|
||||||
|
|
||||||
event = Event(
|
event = Event(
|
||||||
"ready",
|
"ready",
|
||||||
{
|
{
|
||||||
"source": "node",
|
"source": "node",
|
||||||
"event": "ready",
|
"event": "ready",
|
||||||
"nodeId": node.node_id,
|
"nodeId": node.node_id,
|
||||||
"nodeState": node.data,
|
"nodeState": new_node_data,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
node.receive_event(event)
|
node.receive_event(event)
|
||||||
|
@ -1715,7 +1717,7 @@ async def test_remove_node(
|
||||||
assert len(client.async_send_command.call_args_list) == 1
|
assert len(client.async_send_command.call_args_list) == 1
|
||||||
assert client.async_send_command.call_args[0][0] == {
|
assert client.async_send_command.call_args[0][0] == {
|
||||||
"command": "controller.begin_exclusion",
|
"command": "controller.begin_exclusion",
|
||||||
"strategy": 0,
|
"options": {"strategy": 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test FailedZWaveCommand is caught
|
# Test FailedZWaveCommand is caught
|
||||||
|
|
|
@ -731,6 +731,8 @@ async def test_thermostat_raise_repair_issue_and_warning_when_setting_dry_preset
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test raise of repair issue and warning when setting Dry preset."""
|
"""Test raise of repair issue and warning when setting Dry preset."""
|
||||||
|
client.async_send_command.return_value = {"result": {"status": 1}}
|
||||||
|
|
||||||
state = hass.states.get(CLIMATE_AIDOO_HVAC_UNIT_ENTITY)
|
state = hass.states.get(CLIMATE_AIDOO_HVAC_UNIT_ENTITY)
|
||||||
assert state
|
assert state
|
||||||
|
|
||||||
|
@ -765,6 +767,7 @@ async def test_thermostat_raise_repair_issue_and_warning_when_setting_fan_preset
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test raise of repair issue and warning when setting Fan preset."""
|
"""Test raise of repair issue and warning when setting Fan preset."""
|
||||||
|
client.async_send_command.return_value = {"result": {"status": 1}}
|
||||||
state = hass.states.get(CLIMATE_AIDOO_HVAC_UNIT_ENTITY)
|
state = hass.states.get(CLIMATE_AIDOO_HVAC_UNIT_ENTITY)
|
||||||
assert state
|
assert state
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ async def test_window_cover(
|
||||||
assert args["value"]
|
assert args["value"]
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test stop after opening
|
# Test stop after opening
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -265,6 +266,7 @@ async def test_fibaro_fgr222_shutter_cover(
|
||||||
assert args["value"] == 99
|
assert args["value"] == 99
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test closing tilts
|
# Test closing tilts
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -286,6 +288,7 @@ async def test_fibaro_fgr222_shutter_cover(
|
||||||
assert args["value"] == 0
|
assert args["value"] == 0
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test setting tilt position
|
# Test setting tilt position
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -365,6 +368,7 @@ async def test_aeotec_nano_shutter_cover(
|
||||||
assert args["value"]
|
assert args["value"]
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test stop after opening
|
# Test stop after opening
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
|
|
@ -125,7 +125,13 @@ async def test_device_diagnostics(
|
||||||
entity["entity_id"] == "test.unrelated_entity"
|
entity["entity_id"] == "test.unrelated_entity"
|
||||||
for entity in diagnostics_data["entities"]
|
for entity in diagnostics_data["entities"]
|
||||||
)
|
)
|
||||||
assert diagnostics_data["state"] == multisensor_6.data
|
assert diagnostics_data["state"] == {
|
||||||
|
**multisensor_6.data,
|
||||||
|
"values": {id: val.data for id, val in multisensor_6.values.items()},
|
||||||
|
"endpoints": {
|
||||||
|
str(idx): endpoint.data for idx, endpoint in multisensor_6.endpoints.items()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_device_diagnostics_error(hass: HomeAssistant, integration) -> None:
|
async def test_device_diagnostics_error(hass: HomeAssistant, integration) -> None:
|
||||||
|
@ -230,7 +236,11 @@ async def test_device_diagnostics_secret_value(
|
||||||
"""Find ultraviolet property value in data."""
|
"""Find ultraviolet property value in data."""
|
||||||
return next(
|
return next(
|
||||||
val
|
val
|
||||||
for val in data["values"]
|
for val in (
|
||||||
|
data["values"]
|
||||||
|
if isinstance(data["values"], list)
|
||||||
|
else data["values"].values()
|
||||||
|
)
|
||||||
if val["commandClass"] == CommandClass.SENSOR_MULTILEVEL
|
if val["commandClass"] == CommandClass.SENSOR_MULTILEVEL
|
||||||
and val["property"] == PROPERTY_ULTRAVIOLET
|
and val["property"] == PROPERTY_ULTRAVIOLET
|
||||||
)
|
)
|
||||||
|
|
|
@ -171,6 +171,7 @@ async def test_zooz_zen72(
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
NUMBER_DOMAIN,
|
NUMBER_DOMAIN,
|
||||||
SERVICE_SET_VALUE,
|
SERVICE_SET_VALUE,
|
||||||
|
@ -256,6 +257,7 @@ async def test_indicator_test(
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state == STATE_OFF
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
SWITCH_DOMAIN,
|
SWITCH_DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
|
|
@ -231,6 +231,7 @@ async def test_configurable_speeds_fan(
|
||||||
async def get_zwave_speed_from_percentage(percentage):
|
async def get_zwave_speed_from_percentage(percentage):
|
||||||
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"fan",
|
"fan",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
|
@ -356,6 +357,7 @@ async def test_ge_12730_fan(hass: HomeAssistant, client, ge_12730, integration)
|
||||||
async def get_zwave_speed_from_percentage(percentage):
|
async def get_zwave_speed_from_percentage(percentage):
|
||||||
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"fan",
|
"fan",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
|
@ -448,6 +450,7 @@ async def test_inovelli_lzw36(
|
||||||
async def get_zwave_speed_from_percentage(percentage):
|
async def get_zwave_speed_from_percentage(percentage):
|
||||||
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"fan",
|
"fan",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
|
@ -518,6 +521,7 @@ async def test_inovelli_lzw36(
|
||||||
assert state.attributes[ATTR_PERCENTAGE] is None
|
assert state.attributes[ATTR_PERCENTAGE] is None
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"fan",
|
"fan",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
|
@ -553,6 +557,7 @@ async def test_leviton_zw4sf_fan(
|
||||||
async def get_zwave_speed_from_percentage(percentage):
|
async def get_zwave_speed_from_percentage(percentage):
|
||||||
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"fan",
|
"fan",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
|
@ -951,6 +956,7 @@ async def test_honeywell_39358_fan(
|
||||||
async def get_zwave_speed_from_percentage(percentage):
|
async def get_zwave_speed_from_percentage(percentage):
|
||||||
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"fan",
|
"fan",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
"""Test the Z-Wave JS helpers module."""
|
"""Test the Z-Wave JS helpers module."""
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.zwave_js.helpers import (
|
from homeassistant.components.zwave_js.helpers import (
|
||||||
async_get_node_status_sensor_entity_id,
|
async_get_node_status_sensor_entity_id,
|
||||||
async_get_nodes_from_area_id,
|
async_get_nodes_from_area_id,
|
||||||
|
get_value_state_schema,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import area_registry as ar, device_registry as dr
|
from homeassistant.helpers import area_registry as ar, device_registry as dr
|
||||||
|
@ -22,3 +25,14 @@ async def test_async_get_nodes_from_area_id(hass: HomeAssistant) -> None:
|
||||||
area_reg = ar.async_get(hass)
|
area_reg = ar.async_get(hass)
|
||||||
area = area_reg.async_create("test")
|
area = area_reg.async_create("test")
|
||||||
assert not async_get_nodes_from_area_id(hass, area.id)
|
assert not async_get_nodes_from_area_id(hass, area.id)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_value_state_schema_boolean_config_value(
|
||||||
|
hass: HomeAssistant, client, aeon_smart_switch_6
|
||||||
|
) -> None:
|
||||||
|
"""Test get_value_state_schema for boolean config value."""
|
||||||
|
schema_validator = get_value_state_schema(
|
||||||
|
aeon_smart_switch_6.values["102-112-0-255"]
|
||||||
|
)
|
||||||
|
assert isinstance(schema_validator, vol.Coerce)
|
||||||
|
assert schema_validator.type == bool
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ async def test_node_removed(
|
||||||
event = {
|
event = {
|
||||||
"source": "controller",
|
"source": "controller",
|
||||||
"event": "node added",
|
"event": "node added",
|
||||||
"node": node.data,
|
"node": multisensor_6_state,
|
||||||
"result": {},
|
"result": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,7 +1014,7 @@ async def test_node_removed(
|
||||||
old_device = dev_reg.async_get_device(identifiers={(DOMAIN, device_id)})
|
old_device = dev_reg.async_get_device(identifiers={(DOMAIN, device_id)})
|
||||||
assert old_device.id
|
assert old_device.id
|
||||||
|
|
||||||
event = {"node": node, "replaced": False}
|
event = {"node": node, "reason": 0}
|
||||||
|
|
||||||
client.driver.controller.emit("node removed", event)
|
client.driver.controller.emit("node removed", event)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -1047,14 +1047,14 @@ async def test_replace_same_node(
|
||||||
|
|
||||||
assert hass.states.get(AIR_TEMPERATURE_SENSOR)
|
assert hass.states.get(AIR_TEMPERATURE_SENSOR)
|
||||||
|
|
||||||
# A replace node event has the extra field "replaced" set to True
|
# A replace node event has the extra field "reason"
|
||||||
# to distinguish it from an exclusion
|
# to distinguish it from an exclusion
|
||||||
event = Event(
|
event = Event(
|
||||||
type="node removed",
|
type="node removed",
|
||||||
data={
|
data={
|
||||||
"source": "controller",
|
"source": "controller",
|
||||||
"event": "node removed",
|
"event": "node removed",
|
||||||
"replaced": True,
|
"reason": 3,
|
||||||
"node": multisensor_6_state,
|
"node": multisensor_6_state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1139,8 +1139,8 @@ async def test_replace_different_node(
|
||||||
"""Test when a node is replaced with a different node."""
|
"""Test when a node is replaced with a different node."""
|
||||||
dev_reg = dr.async_get(hass)
|
dev_reg = dr.async_get(hass)
|
||||||
node_id = multisensor_6.node_id
|
node_id = multisensor_6.node_id
|
||||||
hank_binary_switch_state = deepcopy(hank_binary_switch_state)
|
state = deepcopy(hank_binary_switch_state)
|
||||||
hank_binary_switch_state["nodeId"] = node_id
|
state["nodeId"] = node_id
|
||||||
|
|
||||||
device_id = f"{client.driver.controller.home_id}-{node_id}"
|
device_id = f"{client.driver.controller.home_id}-{node_id}"
|
||||||
multisensor_6_device_id = (
|
multisensor_6_device_id = (
|
||||||
|
@ -1148,9 +1148,9 @@ async def test_replace_different_node(
|
||||||
f"{multisensor_6.product_type}:{multisensor_6.product_id}"
|
f"{multisensor_6.product_type}:{multisensor_6.product_id}"
|
||||||
)
|
)
|
||||||
hank_device_id = (
|
hank_device_id = (
|
||||||
f"{device_id}-{hank_binary_switch_state['manufacturerId']}:"
|
f"{device_id}-{state['manufacturerId']}:"
|
||||||
f"{hank_binary_switch_state['productType']}:"
|
f"{state['productType']}:"
|
||||||
f"{hank_binary_switch_state['productId']}"
|
f"{state['productId']}"
|
||||||
)
|
)
|
||||||
|
|
||||||
device = dev_reg.async_get_device(identifiers={(DOMAIN, device_id)})
|
device = dev_reg.async_get_device(identifiers={(DOMAIN, device_id)})
|
||||||
|
@ -1171,7 +1171,7 @@ async def test_replace_different_node(
|
||||||
data={
|
data={
|
||||||
"source": "controller",
|
"source": "controller",
|
||||||
"event": "node removed",
|
"event": "node removed",
|
||||||
"replaced": True,
|
"reason": 3,
|
||||||
"node": multisensor_6_state,
|
"node": multisensor_6_state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1228,7 +1228,7 @@ async def test_replace_different_node(
|
||||||
"source": "node",
|
"source": "node",
|
||||||
"event": "ready",
|
"event": "ready",
|
||||||
"nodeId": node_id,
|
"nodeId": node_id,
|
||||||
"nodeState": hank_binary_switch_state,
|
"nodeState": state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
client.driver.receive_event(event)
|
client.driver.receive_event(event)
|
||||||
|
@ -1345,7 +1345,7 @@ async def test_disabled_node_status_entity_on_node_replaced(
|
||||||
data={
|
data={
|
||||||
"source": "controller",
|
"source": "controller",
|
||||||
"event": "node removed",
|
"event": "node removed",
|
||||||
"replaced": True,
|
"reason": 3,
|
||||||
"node": zp3111_state,
|
"node": zp3111_state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -414,6 +414,7 @@ async def test_bulk_set_config_parameters(
|
||||||
identifiers={get_device_id(client.driver, multisensor_6)}
|
identifiers={get_device_id(client.driver, multisensor_6)}
|
||||||
)
|
)
|
||||||
assert device
|
assert device
|
||||||
|
|
||||||
# Test setting config parameter by property and property_key
|
# Test setting config parameter by property and property_key
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -875,7 +876,9 @@ async def test_set_value(
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test that when a command fails we raise an exception
|
# Test that when a command fails we raise an exception
|
||||||
client.async_send_command.return_value = {"success": False}
|
client.async_send_command.return_value = {
|
||||||
|
"result": {"status": 2, "message": "test"}
|
||||||
|
}
|
||||||
|
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
|
@ -924,7 +927,6 @@ async def test_set_value_string(
|
||||||
hass: HomeAssistant, client, climate_danfoss_lc_13, lock_schlage_be469, integration
|
hass: HomeAssistant, client, climate_danfoss_lc_13, lock_schlage_be469, integration
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test set_value service converts number to string when needed."""
|
"""Test set_value service converts number to string when needed."""
|
||||||
client.async_send_command.return_value = {"success": True}
|
|
||||||
|
|
||||||
# Test that number gets converted to a string when needed
|
# Test that number gets converted to a string when needed
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
|
@ -1240,7 +1242,9 @@ async def test_multicast_set_value(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test that when a command is unsuccessful we raise an exception
|
# Test that when a command is unsuccessful we raise an exception
|
||||||
client.async_send_command.return_value = {"success": False}
|
client.async_send_command.return_value = {
|
||||||
|
"result": {"status": 2, "message": "test"}
|
||||||
|
}
|
||||||
|
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
|
@ -1381,7 +1385,7 @@ async def test_multicast_set_value_string(
|
||||||
integration,
|
integration,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test multicast_set_value service converts number to string when needed."""
|
"""Test multicast_set_value service converts number to string when needed."""
|
||||||
client.async_send_command.return_value = {"success": True}
|
client.async_send_command.return_value = {"result": {"status": 255}}
|
||||||
|
|
||||||
# Test that number gets converted to a string when needed
|
# Test that number gets converted to a string when needed
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
|
|
|
@ -63,6 +63,8 @@ async def test_switch(
|
||||||
state = hass.states.get(SWITCH_ENTITY)
|
state = hass.states.get(SWITCH_ENTITY)
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
|
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test turning off
|
# Test turning off
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"switch", "turn_off", {"entity_id": SWITCH_ENTITY}, blocking=True
|
"switch", "turn_off", {"entity_id": SWITCH_ENTITY}, blocking=True
|
||||||
|
|
|
@ -1158,7 +1158,7 @@ async def test_server_reconnect_event(
|
||||||
data={
|
data={
|
||||||
"source": "controller",
|
"source": "controller",
|
||||||
"event": "node removed",
|
"event": "node removed",
|
||||||
"replaced": False,
|
"reason": 0,
|
||||||
"node": lock_schlage_be469_state,
|
"node": lock_schlage_be469_state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1238,7 +1238,7 @@ async def test_server_reconnect_value_updated(
|
||||||
data={
|
data={
|
||||||
"source": "controller",
|
"source": "controller",
|
||||||
"event": "node removed",
|
"event": "node removed",
|
||||||
"replaced": False,
|
"reason": 0,
|
||||||
"node": lock_schlage_be469_state,
|
"node": lock_schlage_be469_state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -264,6 +264,8 @@ async def test_update_entity_ha_not_running(
|
||||||
"""Test update occurs only after HA is running."""
|
"""Test update occurs only after HA is running."""
|
||||||
await hass.async_stop()
|
await hass.async_stop()
|
||||||
|
|
||||||
|
client.async_send_command.return_value = {"updates": []}
|
||||||
|
|
||||||
entry = MockConfigEntry(domain="zwave_js", data={"url": "ws://test.org"})
|
entry = MockConfigEntry(domain="zwave_js", data={"url": "ws://test.org"})
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
@ -341,7 +343,9 @@ async def test_update_entity_progress(
|
||||||
assert attrs[ATTR_LATEST_VERSION] == "11.2.4"
|
assert attrs[ATTR_LATEST_VERSION] == "11.2.4"
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
client.async_send_command.return_value = {"success": False}
|
client.async_send_command.return_value = {
|
||||||
|
"result": {"status": 2, "success": False, "reInterview": False}
|
||||||
|
}
|
||||||
|
|
||||||
# Test successful install call without a version
|
# Test successful install call without a version
|
||||||
install_task = hass.async_create_task(
|
install_task = hass.async_create_task(
|
||||||
|
@ -437,7 +441,9 @@ async def test_update_entity_install_failed(
|
||||||
assert attrs[ATTR_LATEST_VERSION] == "11.2.4"
|
assert attrs[ATTR_LATEST_VERSION] == "11.2.4"
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
client.async_send_command.return_value = {"success": False}
|
client.async_send_command.return_value = {
|
||||||
|
"result": {"status": 2, "success": False, "reInterview": False}
|
||||||
|
}
|
||||||
|
|
||||||
# Test install call - we expect it to finish fail
|
# Test install call - we expect it to finish fail
|
||||||
install_task = hass.async_create_task(
|
install_task = hass.async_create_task(
|
||||||
|
@ -577,6 +583,7 @@ async def test_update_entity_delay(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test update occurs on a delay after HA starts."""
|
"""Test update occurs on a delay after HA starts."""
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
client.async_send_command.return_value = {"updates": []}
|
||||||
await hass.async_stop()
|
await hass.async_stop()
|
||||||
|
|
||||||
entry = MockConfigEntry(domain="zwave_js", data={"url": "ws://test.org"})
|
entry = MockConfigEntry(domain="zwave_js", data={"url": "ws://test.org"})
|
||||||
|
@ -710,7 +717,9 @@ async def test_update_entity_full_restore_data_update_available(
|
||||||
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
||||||
assert state.attributes[ATTR_LATEST_VERSION] == "11.2.4"
|
assert state.attributes[ATTR_LATEST_VERSION] == "11.2.4"
|
||||||
|
|
||||||
client.async_send_command.return_value = {"success": True}
|
client.async_send_command.return_value = {
|
||||||
|
"result": {"status": 255, "success": True, "reInterview": False}
|
||||||
|
}
|
||||||
|
|
||||||
# Test successful install call without a version
|
# Test successful install call without a version
|
||||||
install_task = hass.async_create_task(
|
install_task = hass.async_create_task(
|
||||||
|
|
Loading…
Add table
Reference in a new issue