Skip to content

Commit

Permalink
Improve @service (#1869)
Browse files Browse the repository at this point in the history
* Move @service

* Fix

* Fix message

* Extract performance logger

* Align encoding

* Update json_rpc.py

* Improve service error message
  • Loading branch information
SukramJ authored Nov 21, 2024
1 parent 8294c20 commit edf8ecb
Show file tree
Hide file tree
Showing 27 changed files with 221 additions and 208 deletions.
9 changes: 8 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# Version 2024.11.8 (2024-11-21)

- Add missing @service annotations
- Add performance measurement to @service
- Don't re-raise exception on internal services
- Move @service
- Remove @service from abstract methods

# Version 2024.11.7 (2024-11-19)

- Set state_uncertain on value write
-

# Version 2024.11.6 (2024-11-19)

Expand Down
4 changes: 2 additions & 2 deletions hahomematic/caches/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def get_address_id(self, address: str) -> str:
async def _get_all_rooms(self) -> dict[str, set[str]]:
"""Get all rooms, if available."""
if client := self._central.primary_client:
return await client.get_all_rooms() # type: ignore[no-any-return]
return await client.get_all_rooms()
return {}

def get_device_rooms(self, device_address: str) -> set[str]:
Expand All @@ -203,7 +203,7 @@ def get_channel_rooms(self, channel_address: str) -> set[str]:
async def _get_all_functions(self) -> dict[str, set[str]]:
"""Get all functions, if available."""
if client := self._central.primary_client:
return await client.get_all_functions() # type: ignore[no-any-return]
return await client.get_all_functions()
return {}

def get_function_text(self, address: str) -> str | None:
Expand Down
4 changes: 2 additions & 2 deletions hahomematic/caches/persistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
from hahomematic import central as hmcu
from hahomematic.const import (
CACHE_PATH,
DEFAULT_ENCODING,
FILE_DEVICES,
FILE_PARAMSETS,
INIT_DATETIME,
UTF8,
DataOperationResult,
DeviceDescription,
ParameterData,
Expand Down Expand Up @@ -106,7 +106,7 @@ async def load(self) -> DataOperationResult:
def _load() -> DataOperationResult:
with open(
file=os.path.join(self._cache_dir, self._filename),
encoding=DEFAULT_ENCODING,
encoding=UTF8,
) as fptr:
data = orjson.loads(fptr.read())
if (converted_hash := hash_sha256(value=data)) == self.last_hash_saved:
Expand Down
10 changes: 2 additions & 8 deletions hahomematic/caches/visibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@
from typing import Any, Final

from hahomematic import central as hmcu, support as hms
from hahomematic.const import (
CLICK_EVENTS,
DEFAULT_ENCODING,
UN_IGNORE_WILDCARD,
Parameter,
ParamsetKey,
)
from hahomematic.const import CLICK_EVENTS, UN_IGNORE_WILDCARD, UTF8, Parameter, ParamsetKey
from hahomematic.model.custom import get_required_parameters
from hahomematic.support import element_matches_key, reduce_args

Expand Down Expand Up @@ -713,7 +707,7 @@ def _load() -> None:
self._storage_folder,
_FILE_CUSTOM_UN_IGNORE_PARAMETERS,
),
encoding=DEFAULT_ENCODING,
encoding=UTF8,
) as fptr:
for file_line in fptr.readlines():
if "#" not in file_line:
Expand Down
12 changes: 7 additions & 5 deletions hahomematic/central/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
ProxyInitState,
SystemInformation,
)
from hahomematic.decorators import service
from hahomematic.exceptions import (
BaseHomematicException,
HaHomematicConfigException,
Expand All @@ -75,13 +76,12 @@
from hahomematic.model import create_data_points_and_events
from hahomematic.model.custom import CustomDataPoint, create_custom_data_points
from hahomematic.model.data_point import BaseParameterDataPoint, CallbackDataPoint
from hahomematic.model.decorators import info_property, service
from hahomematic.model.decorators import info_property
from hahomematic.model.device import Device
from hahomematic.model.event import GenericEvent
from hahomematic.model.generic import GenericDataPoint
from hahomematic.model.hub import GenericHubDataPoint, GenericSysvarDataPoint, Hub, ProgramDpButton
from hahomematic.model.support import PayloadMixin
from hahomematic.performance import measure_execution_time
from hahomematic.support import (
check_config,
get_channel_no,
Expand Down Expand Up @@ -917,7 +917,7 @@ async def add_new_devices(
interface_id=interface_id, device_descriptions=device_descriptions
)

@measure_execution_time
@service(measure_performance=True)
async def _add_new_devices(
self, interface_id: str, device_descriptions: tuple[DeviceDescription, ...]
) -> None:
Expand Down Expand Up @@ -1163,18 +1163,20 @@ def set_last_event_dt(self, interface_id: str) -> None:
async def execute_program(self, pid: str) -> bool:
"""Execute a program on CCU / Homegear."""
if client := self.primary_client:
return await client.execute_program(pid=pid) # type: ignore[no-any-return]
return await client.execute_program(pid=pid)
return False

@service(re_raise=False)
async def fetch_sysvar_data(self, scheduled: bool) -> None:
"""Fetch sysvar data for the hub."""
await self._hub.fetch_sysvar_data(scheduled=scheduled)

@service(re_raise=False)
async def fetch_program_data(self, scheduled: bool) -> None:
"""Fetch program data for the hub."""
await self._hub.fetch_program_data(scheduled=scheduled)

@measure_execution_time
@service(measure_performance=True)
async def load_and_refresh_data_point_data(
self,
interface: Interface,
Expand Down
53 changes: 19 additions & 34 deletions hahomematic/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@
SystemInformation,
SystemVariableData,
)
from hahomematic.decorators import measure_execution_time, service
from hahomematic.exceptions import BaseHomematicException, ClientException, NoConnectionException
from hahomematic.model.decorators import service
from hahomematic.model.device import Device
from hahomematic.model.support import convert_value
from hahomematic.performance import measure_execution_time
from hahomematic.support import (
build_headers,
build_xml_rpc_uri,
Expand Down Expand Up @@ -294,15 +293,14 @@ async def stop(self) -> None:
await self._proxy_read.stop()

@abstractmethod
@service()
async def fetch_all_device_data(self) -> None:
"""Fetch all device data from CCU."""

@abstractmethod
@service()
async def fetch_device_details(self) -> None:
"""Fetch names from backend."""

@service(re_raise=False, no_raise_return=False)
async def is_connected(self) -> bool:
"""
Perform actions required for connectivity check.
Expand Down Expand Up @@ -364,44 +362,36 @@ async def check_connection_availability(self, handle_ping_pong: bool) -> bool:
"""Send ping to CCU to generate PONG event."""

@abstractmethod
@service()
async def execute_program(self, pid: str) -> bool:
"""Execute a program on CCU / Homegear.."""

@abstractmethod
@service()
async def set_system_variable(self, name: str, value: Any) -> bool:
"""Set a system variable on CCU / Homegear."""

@abstractmethod
@service()
async def delete_system_variable(self, name: str) -> bool:
"""Delete a system variable from CCU / Homegear."""

@abstractmethod
@service()
async def get_system_variable(self, name: str) -> str:
"""Get single system variable from CCU / Homegear."""

@abstractmethod
@service(re_raise=False, no_raise_return=())
async def get_all_system_variables(
self, include_internal: bool
) -> tuple[SystemVariableData, ...]:
"""Get all system variables from CCU / Homegear."""

@abstractmethod
@service(re_raise=False, no_raise_return=())
async def get_all_programs(self, include_internal: bool) -> tuple[ProgramData, ...]:
"""Get all programs, if available."""

@abstractmethod
@service(re_raise=False, no_raise_return={})
async def get_all_rooms(self) -> dict[str, set[str]]:
"""Get all rooms, if available."""

@abstractmethod
@service(re_raise=False, no_raise_return={})
async def get_all_functions(self) -> dict[str, set[str]]:
"""Get all functions, if available."""

Expand Down Expand Up @@ -555,8 +545,7 @@ async def get_value(
f"GET_VALUE failed with for: {channel_address}/{parameter}/{paramset_key}: {reduce_args(args=ex.args)}"
) from ex

@measure_execution_time
@service()
@service(measure_performance=True)
async def _set_value(
self,
channel_address: str,
Expand Down Expand Up @@ -653,6 +642,7 @@ def _write_temporary_value(self, data_point_key_values: set[DP_KEY_VALUE]) -> No
):
data_point.write_temporary_value(value=value)

@service(re_raise=False, no_raise_return=set())
async def set_value(
self,
channel_address: str,
Expand Down Expand Up @@ -708,8 +698,7 @@ async def get_paramset(
f"GET_PARAMSET failed with for {address}/{paramset_key}: {reduce_args(args=ex.args)}"
) from ex

@measure_execution_time
@service()
@service(measure_performance=True)
async def put_paramset(
self,
channel_address: str,
Expand Down Expand Up @@ -872,7 +861,7 @@ def _get_parameter_type(
return parameter_data["TYPE"]
return None

@service()
@service(re_raise=False)
async def fetch_paramset_description(
self, channel_address: str, paramset_key: ParamsetKey
) -> None:
Expand All @@ -889,7 +878,7 @@ async def fetch_paramset_description(
paramset_description=paramset_description,
)

@service()
@service(re_raise=False)
async def fetch_paramset_descriptions(self, device_description: DeviceDescription) -> None:
"""Fetch paramsets for provided device description."""
data = await self.get_paramset_descriptions(device_description=device_description)
Expand Down Expand Up @@ -956,8 +945,7 @@ async def has_program_ids(self, channel_hmid: str) -> bool:
"""Return if a channel has program ids."""
return False

@measure_execution_time
@service(re_raise=False)
@service(re_raise=False, measure_performance=True)
async def list_devices(self) -> tuple[DeviceDescription, ...] | None:
"""List devices of homematic backend."""
try:
Expand Down Expand Up @@ -1006,7 +994,7 @@ async def update_device_firmware(self, device_address: str) -> bool:
return result
return False

@service()
@service(re_raise=False)
async def update_paramset_descriptions(self, device_address: str) -> None:
"""Update paramsets descriptions for provided device_address."""
if not self.central.device_descriptions.get_device_descriptions(
Expand Down Expand Up @@ -1052,8 +1040,7 @@ def supports_ping_pong(self) -> bool:
"""Return the supports_ping_pong info of the backend."""
return True

@measure_execution_time
@service()
@service(re_raise=False, measure_performance=True)
async def fetch_device_details(self) -> None:
"""Get all names via JSON-RPS and store in data.NAMES."""
if json_result := await self._json_rpc_client.get_device_details():
Expand Down Expand Up @@ -1083,8 +1070,7 @@ async def fetch_device_details(self) -> None:
else:
_LOGGER.debug("FETCH_DEVICE_DETAILS: Unable to fetch device details via JSON-RPC")

@measure_execution_time
@service()
@service(re_raise=False, measure_performance=True)
async def fetch_all_device_data(self) -> None:
"""Fetch all device data from CCU."""
try:
Expand All @@ -1105,12 +1091,14 @@ async def fetch_all_device_data(self) -> None:
interface_event_type=InterfaceEventType.FETCH_DATA,
data={EventKey.AVAILABLE: False},
)
raise

_LOGGER.debug(
"FETCH_ALL_DEVICE_DATA: Unable to get all device data via JSON-RPC RegaScript for interface %s",
self.interface,
)

@service(re_raise=False, no_raise_return=False)
async def check_connection_availability(self, handle_ping_pong: bool) -> bool:
"""Check if _proxy is still initialized."""
try:
Expand Down Expand Up @@ -1155,8 +1143,7 @@ async def report_value_usage(self, address: str, value_id: str, ref_counter: int
f"REPORT_VALUE_USAGE failed with: {address}/{value_id}/{ref_counter}: {reduce_args(args=ex.args)}"
) from ex

@measure_execution_time
@service()
@service(measure_performance=True)
async def set_system_variable(self, name: str, value: Any) -> bool:
"""Set a system variable on CCU / Homegear."""
return await self._json_rpc_client.set_system_variable(name=name, value=value)
Expand Down Expand Up @@ -1314,8 +1301,7 @@ async def get_value(
f"GET_VALUE failed with for: {channel_address}/{parameter}/{paramset_key}: {reduce_args(args=ex.args)}"
) from ex

@measure_execution_time
@service(re_raise=False)
@service(re_raise=False, measure_performance=True)
async def list_devices(self) -> tuple[DeviceDescription, ...] | None:
"""List devices of homematic backend."""
try:
Expand Down Expand Up @@ -1440,13 +1426,12 @@ def supports_ping_pong(self) -> bool:
"""Return the supports_ping_pong info of the backend."""
return False

@measure_execution_time
@service(re_raise=False)
async def fetch_all_device_data(self) -> None:
"""Fetch all device data from CCU."""
return

@measure_execution_time
@service()
@service(re_raise=False, measure_performance=True)
async def fetch_device_details(self) -> None:
"""Get all names from metadata (Homegear)."""
_LOGGER.debug("FETCH_DEVICE_DETAILS: Fetching names via Metadata")
Expand All @@ -1466,6 +1451,7 @@ async def fetch_device_details(self) -> None:
address,
)

@service(re_raise=False, no_raise_return=False)
async def check_connection_availability(self, handle_ping_pong: bool) -> bool:
"""Check if proxy is still initialized."""
try:
Expand All @@ -1487,8 +1473,7 @@ async def execute_program(self, pid: str) -> bool:
"""Execute a program on Homegear."""
return True

@measure_execution_time
@service()
@service(measure_performance=True)
async def set_system_variable(self, name: str, value: Any) -> bool:
"""Set a system variable on CCU / Homegear."""
try:
Expand Down
Loading

0 comments on commit edf8ecb

Please sign in to comment.