diff --git a/src/homematicip/AbstractRunner.py b/src/homematicip/AbstractRunner.py new file mode 100644 index 00000000..b38ddeaa --- /dev/null +++ b/src/homematicip/AbstractRunner.py @@ -0,0 +1,33 @@ +import abc +import asyncio +from typing import Any + + +class AbstractRunner(abc.ABC): + """Abstract runner.""" + + @abc.abstractmethod + async def async_initialize_runner(self): + """Initialize the runner with the model and the context.""" + pass + + @abc.abstractmethod + async def async_initialize_runner_without_init_model(self): + """Initialize just the context and connection. Use async_get_current_state to get the current state.""" + pass + + @abc.abstractmethod + async def async_listening_for_updates(self): + """Start listening for updates from the homematicip access point. This method will not return.""" + pass + + @abc.abstractmethod + async def async_get_current_state(self): + """Return the current state of the homematicip access point.""" + pass + + @property + @abc.abstractmethod + def rest_connection(self): + """Return the rest connection.""" + pass diff --git a/src/homematicip/cli/hmip.py b/src/homematicip/cli/hmip.py index 4df64aa8..001f059e 100644 --- a/src/homematicip/cli/hmip.py +++ b/src/homematicip/cli/hmip.py @@ -35,7 +35,7 @@ async def get_initialized_runner(including_model: bool = True) -> Runner: config.level, config.log_file ) - r = Runner(_config=config) + r = Runner(config=config) if including_model: await r.async_initialize_runner() diff --git a/src/homematicip/events/event_types.py b/src/homematicip/events/event_types.py index 39066d4d..1046d6ae 100644 --- a/src/homematicip/events/event_types.py +++ b/src/homematicip/events/event_types.py @@ -2,6 +2,8 @@ class EventType(Enum): + """Events thrown by the HomematicIP Cloud API. These are handled in HmipEventHandler. + Don't use these outside of the homematicip_rest_api package.""" CLIENT_ADDED = auto() CLIENT_CHANGED = auto() CLIENT_REMOVED = auto() @@ -16,6 +18,8 @@ class EventType(Enum): class ModelUpdateEvent(Enum): + """Model Update Events are thrown by the HmipEventHandler when the model is updated. + Subscribe to these Events in EventManager.""" ITEM_REMOVED = auto() ITEM_UPDATED = auto() - ITEM_CREATED = auto() \ No newline at end of file + ITEM_CREATED = auto() diff --git a/src/homematicip/runner.py b/src/homematicip/runner.py index db3a9cbf..25667769 100644 --- a/src/homematicip/runner.py +++ b/src/homematicip/runner.py @@ -3,6 +3,7 @@ import json import logging +from homematicip.AbstractRunner import AbstractRunner from homematicip.auth import Auth from homematicip.configuration.config import PersistentConfig, Config from homematicip.configuration.config_io import ConfigIO @@ -23,14 +24,14 @@ @dataclass(kw_only=True) -class Runner: +class Runner(AbstractRunner): model: Model = None event_manager: EventManager = None external_loop: asyncio.AbstractEventLoop = None _connection_context: ConnectionContext = None _rest_connection: RestConnection = None - _config: Config = None + config: Config = None def __post_init__(self): if self.event_manager is None: @@ -41,21 +42,21 @@ def __post_init__(self): def _ensure_config(self): """Ensure that a configuration is set. If not, try to load it from well-known locations.""" - if self._config is None: + if self.config is None: config = ConfigIO.find_config_in_well_known_locations() if config is None: raise ValueError("No configuration set via set_config() and no configuration found in well-known " "locations.") - self._config = Config.from_persistent_config(config) + self.config = Config.from_persistent_config(config) - if self._config.accesspoint_id is None or self._config.auth_token is None: + if self.config.accesspoint_id is None or self.config.auth_token is None: raise ValueError("Invalid configuration. Accesspoint ID and Auth Token must be set.") def _initialize_connection_context(self) -> ConnectionContext: """Initialize the connection context with the given configuration. """ self._ensure_config() - return ConnectionContext.create(self._config.accesspoint_id, self._config.lookup_url, self._config.auth_token) + return ConnectionContext.create(self.config.accesspoint_id, self.config.lookup_url, self.config.auth_token) async def async_initialize_runner(self): self._connection_context = self._initialize_connection_context() diff --git a/tests/test_runner.py b/tests/test_runner.py index b8836519..7c94dbd8 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -9,7 +9,7 @@ def test_initalize_connection_context(mocker, config: PersistentConfig): mocked_lookup_urls = mocker.patch('homematicip.connection.rest_connection.ConnectionUrlResolver.lookup_urls') mocked_lookup_urls.return_value = url_result - runner = Runner(_config=config) + runner = Runner(config=config) context = runner._initialize_connection_context() assert context.accesspoint_id == config.accesspoint_id @@ -24,7 +24,7 @@ async def test_runner_get_current_state(mocker, sample_data_complete, config, co mocked_rest_call = mocker.patch("homematicip.connection.rest_connection.RestConnection.async_post") mocked_rest_call.return_value = RestResult(status=200, json=sample_data_complete) - runner = Runner(_config=config, _connection_context=connection_context, + runner = Runner(config=config, _connection_context=connection_context, _rest_connection=RestConnection(connection_context)) result = await runner.async_get_current_state() @@ -42,7 +42,7 @@ async def test_runner_async_run_home(mocker, sample_data_complete, config, conne mocked_listening = mocker.patch("homematicip.runner.Runner.async_listening_for_updates") mocked_listening.result = True - runner = Runner(_config=config, _connection_context=connection_context, + runner = Runner(config=config, _connection_context=connection_context, _rest_connection=RestConnection(connection_context)) await runner.async_initialize_runner()