Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore unavailable entities when creating zwave_js device actions list #64184

Merged
merged 4 commits into from Jan 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 14 additions & 4 deletions homeassistant/components/zwave_js/device_action.py
Expand Up @@ -21,6 +21,7 @@
CONF_DOMAIN,
CONF_ENTITY_ID,
CONF_TYPE,
STATE_UNAVAILABLE,
)
from homeassistant.core import Context, HomeAssistant
from homeassistant.exceptions import HomeAssistantError
Expand Down Expand Up @@ -172,7 +173,17 @@ async def async_get_actions(hass: HomeAssistant, device_id: str) -> list[dict]:

meter_endpoints: dict[int, dict[str, Any]] = defaultdict(dict)

for entry in entity_registry.async_entries_for_device(registry, device_id):
for entry in entity_registry.async_entries_for_device(
registry, device_id, include_disabled_entities=False
):
# If an entry is unavailable, it is possible that the underlying value
# is no longer valid. Additionally, if an entry is disabled, its
# underlying value is not being monitored by HA so we shouldn't allow
# actions against it.
if (
state := hass.states.get(entry.entity_id)
) and state.state == STATE_UNAVAILABLE:
continue
entity_action = {**base_action, CONF_ENTITY_ID: entry.entity_id}
actions.append({**entity_action, CONF_TYPE: SERVICE_REFRESH_VALUE})
if entry.domain == LOCK_DOMAIN:
Expand All @@ -187,10 +198,9 @@ async def async_get_actions(hass: HomeAssistant, device_id: str) -> list[dict]:
value_id = entry.unique_id.split(".")[1]
# If this unique ID doesn't have a value ID, we know it is the node status
# sensor which doesn't have any relevant actions
if re.match(VALUE_ID_REGEX, value_id):
value = node.values[value_id]
else:
if not re.match(VALUE_ID_REGEX, value_id):
continue
value = node.values[value_id]
# If the value has the meterType CC specific value, we can add a reset_meter
# action for it
if CC_SPECIFIC_METER_TYPE in value.metadata.cc_specific:
Expand Down
23 changes: 23 additions & 0 deletions tests/components/zwave_js/test_device_action.py
Expand Up @@ -12,6 +12,7 @@
from homeassistant.components.zwave_js import DOMAIN, device_action
from homeassistant.components.zwave_js.helpers import get_device_id
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, device_registry
Expand Down Expand Up @@ -588,3 +589,25 @@ async def test_failure_scenarios(
)
== {}
)


async def test_unavailable_entity_actions(
hass: HomeAssistant,
client: Client,
lock_schlage_be469: Node,
integration: ConfigEntry,
) -> None:
"""Test unavailable entities are not included in actions list."""
entity_id_unavailable = "binary_sensor.touchscreen_deadbolt_home_security_intrusion"
hass.states.async_set(entity_id_unavailable, STATE_UNAVAILABLE, force_update=True)
await hass.async_block_till_done()
node = lock_schlage_be469
dev_reg = device_registry.async_get(hass)
device = dev_reg.async_get_device({get_device_id(client, node)})
assert device
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device.id
)
assert not any(
action.get("entity_id") == entity_id_unavailable for action in actions
)