Skip to content

Commit 47fc054

Browse files
committed
Add config_entries subscribe method
1 parent fce15b6 commit 47fc054

4 files changed

Lines changed: 55 additions & 5 deletions

File tree

homeassistant_api/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
from .base import BaseModel
44
from .config_entries import (
55
ConfigEntry,
6+
ConfigEntryChange,
67
ConfigEntryDisabler,
8+
ConfigEntryEvent,
79
ConfigEntryState,
810
ConfigFlowContext,
911
ConfigSubEntry,
@@ -45,4 +47,6 @@
4547
"ConfigEntryState",
4648
"ConfigEntry",
4749
"ConfigSubEntry",
50+
"ConfigEntryChange",
51+
"ConfigEntryEvent",
4852
)

homeassistant_api/models/config_entries.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,16 @@ class ConfigSubEntry(BaseModel):
143143
subentry_type: str
144144
title: str
145145
unique_id: Optional[str]
146+
147+
148+
class ConfigEntryChange(str, Enum):
149+
"""What was changed in a config entry."""
150+
151+
ADDED = "added"
152+
REMOVED = "removed"
153+
UPDATED = "updated"
154+
155+
156+
class ConfigEntryEvent(BaseModel):
157+
type: Optional[ConfigEntryChange]
158+
entry: ConfigEntry

homeassistant_api/models/websocket.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""A module defining the responses we expect from the websocket API."""
22

3-
from typing import Any, Literal, Optional, Union
3+
from typing import Any, List, Literal, Optional, Union
44

55
from homeassistant_api.utils import JSONType
66

77
from .base import BaseModel, DatetimeIsoField
8+
from .config_entries import ConfigEntryEvent
89
from .states import Context
910

1011
__all__ = (
@@ -99,4 +100,4 @@ class EventResponse(BaseModel):
99100

100101
id: int
101102
type: Literal["event"]
102-
event: Union[FiredEvent, FiredTrigger, TemplateEvent]
103+
event: Union[FiredEvent, FiredTrigger, TemplateEvent, List[ConfigEntryEvent]]

homeassistant_api/websocket.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from homeassistant_api.models import (
77
ConfigEntry,
8+
ConfigEntryEvent,
89
ConfigSubEntry,
910
DisableEnableResult,
1011
Domain,
@@ -287,7 +288,38 @@ def get_config_entries(
287288
)
288289
)
289290

290-
# TODO: config_entries/subscribe
291+
def _subscribe_config_entries(self) -> int:
292+
"""
293+
Subscribe to config entry flows.
294+
295+
Sends command :code:`{"type": "config_entries/subscribe"}`.
296+
"""
297+
298+
return self.recv(self.send("config_entries/subscribe")).id
299+
300+
@contextlib.contextmanager
301+
def listen_config_entries(
302+
self, disconnect_client: bool = True
303+
) -> Generator[Generator[ConfigEntryEvent, None, None], None, None]:
304+
"""
305+
Listen to all config entry flow events.
306+
307+
For example:
308+
309+
.. code-block:: python
310+
311+
with ws_client.listen_config_entries() as flows:
312+
for i, flow in zip(range(2), flows): # to only wait for two flows to be received
313+
print(flow)
314+
"""
315+
subscription = self._subscribe_config_entries()
316+
cast(Generator[ConfigEntryEvent, None, None], self._wait_for(subscription))
317+
# There is no "unsubscribe" method available for these events.
318+
# Provide the ability to "unsubscribe" by disconnecting and reconnecting the Websocket client.
319+
if disconnect_client:
320+
logger.info("Reloading Websocket Client. Undefined behavior may occur.")
321+
self.__exit__(None, None, None)
322+
self.__enter__()
291323

292324
# UNTESTED
293325
def get_entry_subentries(self, entry_id: str) -> Tuple[ConfigSubEntry, ...]:
@@ -468,14 +500,14 @@ def _subscribe_trigger(self, trigger: str, **trigger_fields) -> int:
468500

469501
def _wait_for(
470502
self, subscription_id: int
471-
) -> Generator[Union[FiredEvent, FiredTrigger], None, None]:
503+
) -> Generator[Union[FiredEvent, FiredTrigger, ConfigEntryEvent], None, None]:
472504
"""
473505
An iterator that waits for events of a certain type.
474506
"""
475507
while True:
476508
yield cast(
477509
Union[
478-
FiredEvent, FiredTrigger
510+
FiredEvent, FiredTrigger, ConfigEntryEvent
479511
], # we can cast this because TemplateEvent is only used for rendering templates
480512
cast(EventResponse, self.recv(subscription_id)).event,
481513
)

0 commit comments

Comments
 (0)