From cbe990806ef9fcb4749e592c343aa56d282be6c9 Mon Sep 17 00:00:00 2001 From: CyrilP <5814027+CyrilP@users.noreply.github.com> Date: Fri, 1 Mar 2024 19:45:55 +0100 Subject: [PATCH] File mode debug (#56) * fix Warnings introduced in HA 2024.2 * remove buggy error log * implement file-mode debugging --- .ruff.toml | 8 ++--- .../deltadore_tydom/ha_entities.py | 18 +++++++++++ custom_components/deltadore_tydom/hub.py | 10 ++++++- .../deltadore_tydom/tydom/MessageHandler.py | 5 +++- .../deltadore_tydom/tydom/tydom_client.py | 30 +++++++++++++++++-- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 0903c4c..aa49637 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -2,7 +2,7 @@ target-version = "py310" -select = [ +lint.select = [ "B007", # Loop control variable {name} not used within loop body "B014", # Exception handler with duplicate exception "C", # complexity @@ -26,7 +26,7 @@ select = [ "W", # pycodestyle ] -ignore = [ +lint.ignore = [ "D202", # No blank lines allowed after function docstring "D203", # 1 blank line required before class docstring "D213", # Multi-line docstring summary should start at the second line @@ -38,8 +38,8 @@ ignore = [ "E731", # do not assign a lambda expression, use a def ] -[flake8-pytest-style] +[lint.flake8-pytest-style] fixture-parentheses = false -[mccabe] +[lint.mccabe] max-complexity = 25 diff --git a/custom_components/deltadore_tydom/ha_entities.py b/custom_components/deltadore_tydom/ha_entities.py index be79615..c49e31d 100644 --- a/custom_components/deltadore_tydom/ha_entities.py +++ b/custom_components/deltadore_tydom/ha_entities.py @@ -34,6 +34,7 @@ from homeassistant.components.light import LightEntity from homeassistant.components.lock import LockEntity from homeassistant.components.update import UpdateEntity, UpdateEntityFeature, UpdateDeviceClass +from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity, CodeFormat from .tydom.tydom_devices import ( Tydom, @@ -47,6 +48,7 @@ TydomGate, TydomGarage, TydomLight, + TydomAlarm, ) from .const import DOMAIN, LOGGER @@ -817,3 +819,19 @@ def device_info(self) -> DeviceInfo: "name": self.name, } +class HaAlarm(AlarmControlPanelEntity, HAEntity): + """Representation of an Alarm.""" + + should_poll = False + supported_features = 0 + code_format = CodeFormat.NUMBER + sensor_classes = {} + + def __init__(self, device: TydomAlarm, hass) -> None: + """Initialize the sensor.""" + self.hass = hass + self._device = device + self._device._ha_device = self + self._attr_unique_id = f"{self._device.device_id}_cover" + self._attr_name = self._device.device_name + self._registered_sensors = [] diff --git a/custom_components/deltadore_tydom/hub.py b/custom_components/deltadore_tydom/hub.py index 38b2129..061f269 100644 --- a/custom_components/deltadore_tydom/hub.py +++ b/custom_components/deltadore_tydom/hub.py @@ -31,6 +31,7 @@ HaGate, HaGarage, HaLight, + HaAlarm, ) from .const import LOGGER @@ -107,7 +108,8 @@ async def get_tydom_credentials( async def test_credentials(self) -> None: """Validate credentials.""" connection = await self._tydom_client.async_connect() - await connection.close() + if hasattr(connection, "close"): + await connection.close() def ready(self) -> bool: """Check if we're ready to work.""" @@ -234,6 +236,12 @@ async def create_ha_device(self, device): self.add_sensor_callback(ha_device.get_sensors()) case TydomAlarm(): LOGGER.debug("Create alarm %s", device.device_id) + ha_device = HaAlarm(device, self._hass) + if self.add_light_callback is not None: + self.add_light_callback([ha_device]) + + if self.add_sensor_callback is not None: + self.add_sensor_callback(ha_device.get_sensors()) LOGGER.error("Alarm Not implemented yet.") case _: LOGGER.error( diff --git a/custom_components/deltadore_tydom/tydom/MessageHandler.py b/custom_components/deltadore_tydom/tydom/MessageHandler.py index edfb4b7..1f94f4f 100644 --- a/custom_components/deltadore_tydom/tydom/MessageHandler.py +++ b/custom_components/deltadore_tydom/tydom/MessageHandler.py @@ -73,6 +73,9 @@ def get_http_request_line(data) -> str: async def incoming_triage(self, bytes_str): """Identify message type and dispatch the result.""" + if bytes_str is None: + return None + incoming = None # Find Uri-Origin in header if available @@ -187,7 +190,7 @@ async def parse_response(self, incoming, uri_origin, http_request_line): return await self.parse_msg_info(parsed) except Exception as e: - LOGGER.error("Error on parsing tydom response (%s)", e) + LOGGER.error("Error on parsing tydom response (%s)", data) LOGGER.exception("Error on parsing tydom response") traceback.print_exception(e) LOGGER.debug("Incoming data parsed with success") diff --git a/custom_components/deltadore_tydom/tydom/tydom_client.py b/custom_components/deltadore_tydom/tydom/tydom_client.py index a263c9a..70968ec 100644 --- a/custom_components/deltadore_tydom/tydom/tydom_client.py +++ b/custom_components/deltadore_tydom/tydom/tydom_client.py @@ -41,6 +41,11 @@ class TydomClientApiClientAuthenticationError(TydomClientApiClientError): proxy = None +# For debugging with traces +file_mode = False +file_lines = None +file_index = 0 +file_name = "/config/traces.txt" class TydomClient: """Tydom API Client.""" @@ -89,6 +94,8 @@ async def async_get_credentials( session: ClientSession, email: str, password: str, macaddress: str ): """Get tydom credentials from Delta Dore.""" + if file_mode: + return "dummyPassword" try: async with async_timeout.timeout(10): response = await session.request( @@ -176,6 +183,13 @@ async def async_get_credentials( async def async_connect(self) -> ClientWebSocketResponse: """Connect to the Tydom API.""" + global file_lines, file_mode, file_name + if file_mode: + file = open(file_name) + file_lines = file.readlines() + + return None + http_headers = { "Connection": "Upgrade", "Upgrade": "websocket", @@ -281,6 +295,18 @@ async def listen_tydom(self, connection: ClientWebSocketResponse): async def consume_messages(self): """Read and parse incomming messages.""" + global file_lines, file_mode, file_index + if file_mode: + if (len(file_lines) > file_index): + incoming = file_lines[file_index].replace("\\r", '\x0d').replace("\\n", "\x0a") + incoming_bytes_str = incoming.encode("utf-8") + file_index += 1 + LOGGER.info("Incomming message - message : %s", incoming_bytes_str) + else: + await asyncio.sleep(10) + return None + await asyncio.sleep(1) + return await self._message_handler.incoming_triage(incoming_bytes_str) try: if self._connection.closed: await self._connection.close() @@ -362,8 +388,8 @@ async def send_message(self, method, msg): method, msg if "pwd" not in msg else "***", ) - - await self.send_bytes(a_bytes) + if not file_mode: + await self.send_bytes(a_bytes) # ########################