mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Remove Knocki triggers on runtime (#120452)
* Bump Knocki to 0.2.0 * Remove triggers on runtime in Knocki * Fix
This commit is contained in:
parent
82b8b73b8a
commit
59959141af
@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from knocki import EventType, KnockiClient
|
||||
from knocki import Event, EventType, KnockiClient
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_TOKEN, Platform
|
||||
@ -30,6 +30,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: KnockiConfigEntry) -> bo
|
||||
client.register_listener(EventType.CREATED, coordinator.add_trigger)
|
||||
)
|
||||
|
||||
async def _refresh_coordinator(_: Event) -> None:
|
||||
await coordinator.async_refresh()
|
||||
|
||||
entry.async_on_unload(
|
||||
client.register_listener(EventType.DELETED, _refresh_coordinator)
|
||||
)
|
||||
|
||||
entry.runtime_data = coordinator
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
from knocki import Event, KnockiClient, KnockiConnectionError, Trigger
|
||||
|
||||
from homeassistant.components.event import DOMAIN as EVENT_DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import DOMAIN, LOGGER
|
||||
@ -19,12 +21,20 @@ class KnockiCoordinator(DataUpdateCoordinator[dict[int, Trigger]]):
|
||||
name=DOMAIN,
|
||||
)
|
||||
self.client = client
|
||||
self._known_triggers: set[tuple[str, int]] = set()
|
||||
|
||||
async def _async_update_data(self) -> dict[int, Trigger]:
|
||||
try:
|
||||
triggers = await self.client.get_triggers()
|
||||
except KnockiConnectionError as exc:
|
||||
raise UpdateFailed from exc
|
||||
current_triggers = {
|
||||
(trigger.device_id, trigger.details.trigger_id) for trigger in triggers
|
||||
}
|
||||
removed_triggers = self._known_triggers - current_triggers
|
||||
for trigger in removed_triggers:
|
||||
await self._delete_device(trigger)
|
||||
self._known_triggers = current_triggers
|
||||
return {trigger.details.trigger_id: trigger for trigger in triggers}
|
||||
|
||||
def add_trigger(self, event: Event) -> None:
|
||||
@ -32,3 +42,16 @@ class KnockiCoordinator(DataUpdateCoordinator[dict[int, Trigger]]):
|
||||
self.async_set_updated_data(
|
||||
{**self.data, event.payload.details.trigger_id: event.payload}
|
||||
)
|
||||
self._known_triggers.add(
|
||||
(event.payload.device_id, event.payload.details.trigger_id)
|
||||
)
|
||||
|
||||
async def _delete_device(self, trigger: tuple[str, int]) -> None:
|
||||
"""Delete a device from the coordinator."""
|
||||
device_id, trigger_id = trigger
|
||||
entity_registry = er.async_get(self.hass)
|
||||
entity_entry = entity_registry.async_get_entity_id(
|
||||
EVENT_DOMAIN, DOMAIN, f"{device_id}_{trigger_id}"
|
||||
)
|
||||
if entity_entry:
|
||||
entity_registry.async_remove(entity_entry)
|
||||
|
30
tests/components/knocki/fixtures/more_triggers.json
Normal file
30
tests/components/knocki/fixtures/more_triggers.json
Normal file
@ -0,0 +1,30 @@
|
||||
[
|
||||
{
|
||||
"device": "KNC1-W-00000214",
|
||||
"gesture": "d060b870-15ba-42c9-a932-2d2951087152",
|
||||
"details": {
|
||||
"description": "Eeee",
|
||||
"name": "Aaaa",
|
||||
"id": 31
|
||||
},
|
||||
"type": "homeassistant",
|
||||
"user": "7a4d5bf9-01b1-413b-bb4d-77728e931dcc",
|
||||
"updatedAt": 1716378013721,
|
||||
"createdAt": 1716378013721,
|
||||
"id": "1a050b25-7fed-4e0e-b5af-792b8b4650de"
|
||||
},
|
||||
{
|
||||
"device": "KNC1-W-00000214",
|
||||
"gesture": "d060b870-15ba-42c9-a932-2d2951087152",
|
||||
"details": {
|
||||
"description": "Eeee",
|
||||
"name": "Bbbb",
|
||||
"id": 32
|
||||
},
|
||||
"type": "homeassistant",
|
||||
"user": "7a4d5bf9-01b1-413b-bb4d-77728e931dcc",
|
||||
"updatedAt": 1716378013721,
|
||||
"createdAt": 1716378013721,
|
||||
"id": "1a050b25-7fed-4e0e-b5af-792b8b4650de"
|
||||
}
|
||||
]
|
@ -1,6 +1,6 @@
|
||||
"""Tests for the Knocki event platform."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Awaitable, Callable
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from knocki import Event, EventType, Trigger, TriggerDetails
|
||||
@ -89,10 +89,39 @@ async def test_adding_runtime_entities(
|
||||
assert not hass.states.get("event.knc1_w_00000214_aaaa")
|
||||
|
||||
add_trigger_function: Callable[[Event], None] = (
|
||||
mock_knocki_client.register_listener.call_args[0][1]
|
||||
mock_knocki_client.register_listener.call_args_list[0][0][1]
|
||||
)
|
||||
trigger = Trigger.from_dict(load_json_array_fixture("triggers.json", DOMAIN)[0])
|
||||
|
||||
add_trigger_function(Event(EventType.CREATED, trigger))
|
||||
|
||||
assert hass.states.get("event.knc1_w_00000214_aaaa") is not None
|
||||
|
||||
|
||||
async def test_removing_runtime_entities(
|
||||
hass: HomeAssistant,
|
||||
mock_knocki_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test we can create devices on runtime."""
|
||||
mock_knocki_client.get_triggers.return_value = [
|
||||
Trigger.from_dict(trigger)
|
||||
for trigger in load_json_array_fixture("more_triggers.json", DOMAIN)
|
||||
]
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert hass.states.get("event.knc1_w_00000214_aaaa") is not None
|
||||
assert hass.states.get("event.knc1_w_00000214_bbbb") is not None
|
||||
|
||||
remove_trigger_function: Callable[[Event], Awaitable[None]] = (
|
||||
mock_knocki_client.register_listener.call_args_list[1][0][1]
|
||||
)
|
||||
trigger = Trigger.from_dict(load_json_array_fixture("triggers.json", DOMAIN)[0])
|
||||
|
||||
mock_knocki_client.get_triggers.return_value = [trigger]
|
||||
|
||||
await remove_trigger_function(Event(EventType.DELETED, trigger))
|
||||
|
||||
assert hass.states.get("event.knc1_w_00000214_aaaa") is not None
|
||||
assert hass.states.get("event.knc1_w_00000214_bbbb") is None
|
||||
|
Loading…
x
Reference in New Issue
Block a user