Bypass zwave_js config validation if driver not ready (#83410)
parent
048553cd02
commit
1cfd292075
|
@ -4,6 +4,7 @@ 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.const import ConfigurationValueType
|
||||
from zwave_js_server.model.node import Node
|
||||
from zwave_js_server.model.value import ConfigurationValue
|
||||
|
@ -12,7 +13,7 @@ from homeassistant.config_entries import ConfigEntryState
|
|||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import DATA_CLIENT, DOMAIN
|
||||
|
||||
NODE_STATUSES = ["asleep", "awake", "dead", "alive"]
|
||||
|
||||
|
@ -66,4 +67,9 @@ def async_bypass_dynamic_config_validation(hass: HomeAssistant, device_id: str)
|
|||
),
|
||||
None,
|
||||
)
|
||||
return not entry
|
||||
if not entry:
|
||||
return True
|
||||
|
||||
# The driver may not be ready when the config entry is loaded.
|
||||
client: ZwaveClient = hass.data[DOMAIN][entry.entry_id][DATA_CLIENT]
|
||||
return client.driver is None
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
"""Helpers for Z-Wave JS custom triggers."""
|
||||
from zwave_js_server.client import Client as ZwaveClient
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import ATTR_DEVICE_ID, ATTR_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from ..const import ATTR_CONFIG_ENTRY_ID, DOMAIN
|
||||
from ..const import ATTR_CONFIG_ENTRY_ID, DATA_CLIENT, DOMAIN
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -19,9 +21,8 @@ def async_bypass_dynamic_config_validation(
|
|||
ent_reg = er.async_get(hass)
|
||||
trigger_devices = config.get(ATTR_DEVICE_ID, [])
|
||||
trigger_entities = config.get(ATTR_ENTITY_ID, [])
|
||||
return any(
|
||||
entry.state != ConfigEntryState.LOADED
|
||||
and (
|
||||
for entry in hass.config_entries.async_entries(DOMAIN):
|
||||
if entry.state != ConfigEntryState.LOADED and (
|
||||
entry.entry_id == config.get(ATTR_CONFIG_ENTRY_ID)
|
||||
or any(
|
||||
device.id in trigger_devices
|
||||
|
@ -31,6 +32,12 @@ def async_bypass_dynamic_config_validation(
|
|||
entity.entity_id in trigger_entities
|
||||
for entity in er.async_entries_for_config_entry(ent_reg, entry.entry_id)
|
||||
)
|
||||
)
|
||||
for entry in hass.config_entries.async_entries(DOMAIN)
|
||||
)
|
||||
):
|
||||
return True
|
||||
|
||||
# The driver may not be ready when the config entry is loaded.
|
||||
client: ZwaveClient = hass.data[DOMAIN][entry.entry_id][DATA_CLIENT]
|
||||
if client.driver is None:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
|
|
@ -1080,6 +1080,74 @@ async def test_if_value_updated_value_fires(
|
|||
)
|
||||
|
||||
|
||||
async def test_value_updated_value_no_driver(
|
||||
hass, client, lock_schlage_be469, integration, calls
|
||||
):
|
||||
"""Test zwave_js.value_updated.value trigger with missing driver."""
|
||||
node: Node = lock_schlage_be469
|
||||
dev_reg = async_get_dev_reg(hass)
|
||||
device = async_entries_for_config_entry(dev_reg, integration.entry_id)[0]
|
||||
driver = client.driver
|
||||
client.driver = None
|
||||
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
automation.DOMAIN,
|
||||
{
|
||||
automation.DOMAIN: [
|
||||
{
|
||||
"trigger": {
|
||||
"platform": "device",
|
||||
"domain": DOMAIN,
|
||||
"device_id": device.id,
|
||||
"type": "zwave_js.value_updated.value",
|
||||
"command_class": CommandClass.DOOR_LOCK.value,
|
||||
"property": "latchStatus",
|
||||
"property_key": None,
|
||||
"endpoint": None,
|
||||
"from": "open",
|
||||
},
|
||||
"action": {
|
||||
"service": "test.automation",
|
||||
"data_template": {
|
||||
"some": (
|
||||
"zwave_js.value_updated.value - "
|
||||
"{{ trigger.platform}} - "
|
||||
"{{ trigger.previous_value }}"
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client.driver = driver
|
||||
|
||||
# No trigger as automation failed to setup.
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": node.node_id,
|
||||
"args": {
|
||||
"commandClassName": "Door Lock",
|
||||
"commandClass": 98,
|
||||
"endpoint": 0,
|
||||
"property": "latchStatus",
|
||||
"newValue": "closed",
|
||||
"prevValue": "open",
|
||||
"propertyName": "latchStatus",
|
||||
},
|
||||
},
|
||||
)
|
||||
node.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
|
||||
async def test_get_trigger_capabilities_value_updated_value(
|
||||
hass, client, lock_schlage_be469, integration
|
||||
):
|
||||
|
|
|
@ -385,6 +385,65 @@ async def test_zwave_js_value_updated_bypass_dynamic_validation_no_nodes(
|
|||
assert len(no_value_filter) == 0
|
||||
|
||||
|
||||
async def test_zwave_js_value_updated_bypass_dynamic_validation_no_driver(
|
||||
hass, client, lock_schlage_be469, integration
|
||||
):
|
||||
"""Test zwave_js.value_updated trigger without driver."""
|
||||
trigger_type = f"{DOMAIN}.value_updated"
|
||||
node: Node = lock_schlage_be469
|
||||
driver = client.driver
|
||||
client.driver = None
|
||||
|
||||
no_value_filter = async_capture_events(hass, "no_value_filter")
|
||||
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
automation.DOMAIN,
|
||||
{
|
||||
automation.DOMAIN: [
|
||||
# no value filter
|
||||
{
|
||||
"trigger": {
|
||||
"platform": trigger_type,
|
||||
"entity_id": SCHLAGE_BE469_LOCK_ENTITY,
|
||||
"command_class": CommandClass.DOOR_LOCK.value,
|
||||
"property": "latchStatus",
|
||||
},
|
||||
"action": {
|
||||
"event": "no_value_filter",
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client.driver = driver
|
||||
|
||||
# Test that no value filter is NOT triggered because automation failed setup
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": node.node_id,
|
||||
"args": {
|
||||
"commandClassName": "Door Lock",
|
||||
"commandClass": 98,
|
||||
"endpoint": 0,
|
||||
"property": "latchStatus",
|
||||
"newValue": "boo",
|
||||
"prevValue": "hiss",
|
||||
"propertyName": "latchStatus",
|
||||
},
|
||||
},
|
||||
)
|
||||
node.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(no_value_filter) == 0
|
||||
|
||||
|
||||
async def test_zwave_js_event(hass, client, lock_schlage_be469, integration):
|
||||
"""Test for zwave_js.event automation trigger."""
|
||||
trigger_type = f"{DOMAIN}.event"
|
||||
|
|
Loading…
Reference in New Issue