Skip to content

Commit

Permalink
Cleanup API, reduce visibility (#81)
Browse files Browse the repository at this point in the history
* add manufacturer to const, remove entry_id

* Cleanup API, reduce visibility

* Add setValue to client
  • Loading branch information
SukramJ authored Dec 22, 2021
1 parent 8c5b163 commit bf8acb8
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 238 deletions.
4 changes: 4 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Version 0.2.0 (2021-12-22)
- Cleanup API, reduce visibility
- Add setValue to client

Version 0.1.2 (2021-12-21)
- Rotate device identifier

Expand Down
3 changes: 1 addition & 2 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,12 @@ def hacallback(self, eventtype, event_data):
async def example_run(self):
self.central = CentralConfig(
name="ccu-dev",
entry_id="123",
loop=asyncio.get_running_loop(),
xml_rpc_server=register_xml_rpc_server(),
host=CCU_HOST,
username=CCU_USERNAME,
password=CCU_PASSWORD,
enable_virtual_channels=True,
option_enable_virtual_channels=True,
).get_central()

# For testing we set a short INIT_TIMEOUT
Expand Down
6 changes: 2 additions & 4 deletions example_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,21 @@ def hacallback(self, eventtype, event_data):
async def example_run(self):
self.central_1 = CentralConfig(
name="ccu-dev",
entry_id="123",
loop=asyncio.get_running_loop(),
xml_rpc_server=register_xml_rpc_server(),
host=CCU_HOST,
username=CCU_USERNAME,
password=CCU_PASSWORD,
enable_virtual_channels=True,
option_enable_virtual_channels=True,
).get_central()
self.central_2 = CentralConfig(
name="ccu-2-dev",
entry_id="456",
loop=asyncio.get_running_loop(),
xml_rpc_server=register_xml_rpc_server(),
host=CCU_HOST,
username=CCU_USERNAME,
password=CCU_PASSWORD,
enable_virtual_channels=True,
option_enable_virtual_channels=True,
).get_central()

# For testing we set a short INIT_TIMEOUT
Expand Down
100 changes: 76 additions & 24 deletions hahomematic/central_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,21 @@
FILE_DEVICES,
FILE_NAMES,
FILE_PARAMSETS,
HA_DOMAIN,
HM_VIRTUAL_REMOTE_HM,
HM_VIRTUAL_REMOTE_HMIP,
LOCALHOST,
MANUFACTURER,
HmPlatform,
)
from hahomematic.data import INSTANCES
from hahomematic.device import HmDevice, create_devices
from hahomematic.entity import BaseEntity, GenericEntity
import hahomematic.helpers
from hahomematic.helpers import get_device_address, get_device_channel
from hahomematic.hub import HmDummyHub, HmHub
from hahomematic.json_rpc_client import JsonRpcAioHttpClient
from hahomematic.proxy import NoConnection
from hahomematic.xml_rpc_proxy import NoConnection
import hahomematic.xml_rpc_server as xml_rpc

_LOGGER = logging.getLogger(__name__)
Expand All @@ -55,23 +58,15 @@ def __init__(self, central_config: CentralConfig):
self.central_config: CentralConfig = central_config

self.instance_name: str = self.central_config.name
self.entry_id: str = self.central_config.entry_id
self._available: bool = True
self._loop: asyncio.AbstractEventLoop = self.central_config.loop
self._xml_rpc_server: xml_rpc.XMLRPCServer = self.central_config.xml_rpc_server
self._xml_rpc_server: xml_rpc.XmlRpcServer = self.central_config.xml_rpc_server
self._xml_rpc_server.register_central(self)
self.enable_virtual_channels: bool = self.central_config.enable_virtual_channels
self.host: str = self.central_config.host
self.option_enable_virtual_channels: bool = (
self.central_config.option_enable_virtual_channels
)
self._model: str | None = None
self._primary_client: hm_client.Client | None = None
self.json_port: int | None = self.central_config.json_port
self.password: str | None = self.central_config.password
self.username: str | None = None
if self.password is not None:
self.username = self.central_config.username
self.tls: bool = self.central_config.tls
self.verify_tls: bool = self.central_config.verify_tls
self.client_session: ClientSession | None = self.central_config.client_session

# Caches for CCU data
self.paramsets: ParamsetCache = ParamsetCache(central=self)
Expand Down Expand Up @@ -99,7 +94,7 @@ def __init__(self, central_config: CentralConfig):
# Signature: (event_type, event_data)
self.callback_ha_event: Callable | None = None

self.json_rpc_session: JsonRpcAioHttpClient = JsonRpcAioHttpClient(
self._json_rpc_session: JsonRpcAioHttpClient = JsonRpcAioHttpClient(
central_config=self.central_config
)

Expand All @@ -116,7 +111,7 @@ def create_hub(self) -> HmHub | HmDummyHub:
else:
hub = HmHub(
self,
use_entities=self.central_config.enable_sensors_for_system_variables,
use_entities=self.central_config.option_enable_sensors_for_system_variables,
)
return hub

Expand Down Expand Up @@ -146,6 +141,23 @@ def version(self) -> str | None:
return client.version
return None

@property
def device_url(self) -> str:
"""Return the device_url of the backend."""
return self.central_config.device_url

@property
def device_info(self) -> dict[str, Any]:
"""Return central specific attributes."""
return {
"identifiers": {(HA_DOMAIN, self.instance_name)},
"name": self.instance_name,
"manufacturer": MANUFACTURER,
"model": self.model,
"sw_version": self.version,
"device_url": self.device_url,
}

@property
def local_ip(self) -> str:
"""Return the local ip of the xmlrpc_server."""
Expand All @@ -156,6 +168,11 @@ def local_port(self) -> int:
"""Return the local port of the xmlrpc_server."""
return self._xml_rpc_server.local_port

@property
def json_rpc_session(self) -> JsonRpcAioHttpClient:
"""Return the json_rpc_session."""
return self._json_rpc_session

@property
def loop(self) -> asyncio.AbstractEventLoop:
"""Return the loop for async operations."""
Expand Down Expand Up @@ -209,6 +226,14 @@ async def stop(self) -> None:
_LOGGER.debug("CentralUnit.stop: Removing instance")
del INSTANCES[self.instance_name]

def create_task(self, target: Awaitable) -> None:
"""Add task to the executor pool."""
self.loop.call_soon_threadsafe(self.async_create_task, target)

def async_create_task(self, target: Awaitable) -> asyncio.Task:
"""Create a task from within the event loop. This method must be run in the event loop."""
return self.loop.create_task(target)

def run_coroutine(self, coro: Coroutine) -> Any:
"""call coroutine from sync"""
return asyncio.run_coroutine_threadsafe(coro, self.loop).result()
Expand Down Expand Up @@ -304,6 +329,21 @@ async def get_install_mode(self, interface_id: str) -> int:
return int(await client.get_install_mode())
return 0

async def set_value(
self,
interface_id: str,
address: str,
value_key: str,
value: Any,
rx_mode: str | None = None,
) -> None:
""""Set single value on paramset VALUES."""

if client := self.get_primary_client(interface_id):
await client.set_value(
address=address, value_key=value_key, value=value, rx_mode=rx_mode
)

async def put_paramset(
self,
interface_id: str,
Expand Down Expand Up @@ -371,8 +411,9 @@ def get_primary_client(
except IndexError as err:
message = f"Can't resolve interface for {self.instance_name}: {interface_id}"
_LOGGER.warning(message)
raise hm_client.ClientException(message) from err
raise hahomematic.helpers.ClientException(message) from err
else:
client: hm_client.Client | None = None
for client in self.clients.values():
if client.get_virtual_remote():
self._primary_client = client
Expand Down Expand Up @@ -490,9 +531,8 @@ class CentralConfig:

def __init__(
self,
entry_id: str,
loop: asyncio.AbstractEventLoop,
xml_rpc_server: xml_rpc.XMLRPCServer,
xml_rpc_server: xml_rpc.XmlRpcServer,
name: str,
host: str = LOCALHOST,
username: str = DEFAULT_USERNAME,
Expand All @@ -501,13 +541,12 @@ def __init__(
verify_tls: bool = DEFAULT_VERIFY_TLS,
client_session: ClientSession | None = None,
callback_host: str | None = None,
callback_port: str | None = None,
callback_port: int | None = None,
json_port: int | None = None,
json_tls: bool = DEFAULT_TLS,
enable_virtual_channels: bool = False,
enable_sensors_for_system_variables: bool = False,
option_enable_virtual_channels: bool = False,
option_enable_sensors_for_system_variables: bool = False,
):
self.entry_id = entry_id
self.loop = loop
self.xml_rpc_server = xml_rpc_server
self.name = name
Expand All @@ -521,8 +560,21 @@ def __init__(
self.callback_port = callback_port
self.json_port = json_port
self.json_tls = json_tls
self.enable_virtual_channels = enable_virtual_channels
self.enable_sensors_for_system_variables = enable_sensors_for_system_variables
self.option_enable_virtual_channels = option_enable_virtual_channels
self.option_enable_sensors_for_system_variables = (
option_enable_sensors_for_system_variables
)

@property
def device_url(self) -> str:
"""Return the required url."""
url = "http://"
if self.json_tls:
url = "https://"
url = f"{url}{self.host}"
if self.json_port:
url = f"{url}:{self.json_port}"
return f"{url}"

def get_central(self) -> CentralUnit:
"""Identify the used client."""
Expand Down
Loading

0 comments on commit bf8acb8

Please sign in to comment.