mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +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 __future__ import annotations
|
||||||
|
|
||||||
from knocki import EventType, KnockiClient
|
from knocki import Event, EventType, KnockiClient
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_TOKEN, Platform
|
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)
|
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
|
entry.runtime_data = coordinator
|
||||||
|
|
||||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
from knocki import Event, KnockiClient, KnockiConnectionError, Trigger
|
from knocki import Event, KnockiClient, KnockiConnectionError, Trigger
|
||||||
|
|
||||||
|
from homeassistant.components.event import DOMAIN as EVENT_DOMAIN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import DOMAIN, LOGGER
|
from .const import DOMAIN, LOGGER
|
||||||
@ -19,12 +21,20 @@ class KnockiCoordinator(DataUpdateCoordinator[dict[int, Trigger]]):
|
|||||||
name=DOMAIN,
|
name=DOMAIN,
|
||||||
)
|
)
|
||||||
self.client = client
|
self.client = client
|
||||||
|
self._known_triggers: set[tuple[str, int]] = set()
|
||||||
|
|
||||||
async def _async_update_data(self) -> dict[int, Trigger]:
|
async def _async_update_data(self) -> dict[int, Trigger]:
|
||||||
try:
|
try:
|
||||||
triggers = await self.client.get_triggers()
|
triggers = await self.client.get_triggers()
|
||||||
except KnockiConnectionError as exc:
|
except KnockiConnectionError as exc:
|
||||||
raise UpdateFailed from 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}
|
return {trigger.details.trigger_id: trigger for trigger in triggers}
|
||||||
|
|
||||||
def add_trigger(self, event: Event) -> None:
|
def add_trigger(self, event: Event) -> None:
|
||||||
@ -32,3 +42,16 @@ class KnockiCoordinator(DataUpdateCoordinator[dict[int, Trigger]]):
|
|||||||
self.async_set_updated_data(
|
self.async_set_updated_data(
|
||||||
{**self.data, event.payload.details.trigger_id: event.payload}
|
{**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."""
|
"""Tests for the Knocki event platform."""
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Awaitable, Callable
|
||||||
from unittest.mock import AsyncMock
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from knocki import Event, EventType, Trigger, TriggerDetails
|
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")
|
assert not hass.states.get("event.knc1_w_00000214_aaaa")
|
||||||
|
|
||||||
add_trigger_function: Callable[[Event], None] = (
|
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])
|
trigger = Trigger.from_dict(load_json_array_fixture("triggers.json", DOMAIN)[0])
|
||||||
|
|
||||||
add_trigger_function(Event(EventType.CREATED, trigger))
|
add_trigger_function(Event(EventType.CREATED, trigger))
|
||||||
|
|
||||||
assert hass.states.get("event.knc1_w_00000214_aaaa") is not None
|
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