From f6600c7dda6e6266fba345bb28bc3557d3e2e08e Mon Sep 17 00:00:00 2001 From: Horlabs Date: Mon, 21 Feb 2022 22:30:17 +0100 Subject: [PATCH] Add username to config #3 retry connection to HA --- .gitignore | 4 ++++ fritz_temp_sync/config.yaml | 6 +++++- fritz_temp_sync/fritzbox.py | 10 +++++----- fritz_temp_sync/homeassistant.py | 26 +++++++++++++++++++------- fritz_temp_sync/sync_ha_fb.py | 6 +++++- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index def54fa..7587344 100644 --- a/.gitignore +++ b/.gitignore @@ -169,6 +169,7 @@ pip-selfcheck.json # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff +.idea/ .idea/**/workspace.xml .idea/**/tasks.xml .idea/**/usage.statistics.xml @@ -240,3 +241,6 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser +# local config test +options.json + diff --git a/fritz_temp_sync/config.yaml b/fritz_temp_sync/config.yaml index 9c0155d..7adb578 100755 --- a/fritz_temp_sync/config.yaml +++ b/fritz_temp_sync/config.yaml @@ -1,6 +1,8 @@ name: "Fritz!Box Temperature Sync" description: "Sync Fritz!DECT thermostat temperatures with other sensors in Home Assistant" -version: "0.2.0" +version: "0.3.0" +startup: "application" +stage: "experimental" slug: "fritz_temp_sync" homeassistant_api: true arch: @@ -12,6 +14,7 @@ arch: options: fritzbox: url: "http://fritz.box" + username: null password: null mappings: - sensor: null @@ -20,6 +23,7 @@ options: schema: fritzbox: url: url + username: "str?" password: str mappings: - sensor: str diff --git a/fritz_temp_sync/fritzbox.py b/fritz_temp_sync/fritzbox.py index 21bffae..419bbf4 100755 --- a/fritz_temp_sync/fritzbox.py +++ b/fritz_temp_sync/fritzbox.py @@ -801,8 +801,8 @@ class FritzBox: else: logging.info("Already logged in") - def login(self, user: str = None) -> bool: - logging.info(f"Login user {user} to Fritz!Box") + def login(self) -> bool: + logging.info(f"Login user {self.user} to Fritz!Box") challenge = None r = self.session.get(f"{self.url}/{self._endpoints['login']}") xml = ET.fromstring(r.text) @@ -811,12 +811,12 @@ class FritzBox: self.sid = elem.text elif elem.tag == "Challenge": challenge = elem.text - elif user is None and elem.tag == "Users": + elif self.user is None and elem.tag == "Users": for user_elem in elem: if "fritz" in user_elem.text: user = user_elem.text - assert challenge is not None and user is not None + assert challenge is not None and self.user is not None if challenge.startswith("2$"): response = self._calc_challenge_v2(challenge) @@ -824,7 +824,7 @@ class FritzBox: response = self._calc_challenge_v1(challenge) data = { - "username": user, + "username": self.user, "response": response } diff --git a/fritz_temp_sync/homeassistant.py b/fritz_temp_sync/homeassistant.py index 1f59e31..a8461ca 100755 --- a/fritz_temp_sync/homeassistant.py +++ b/fritz_temp_sync/homeassistant.py @@ -6,6 +6,7 @@ import logging from asyncio import Queue, Task, Event, Lock from typing import Callable, Dict, Optional import websockets +from websockets.exceptions import InvalidStatusCode class HomeAssistantAPI: @@ -25,10 +26,21 @@ class HomeAssistantAPI: self.response_lock: Lock = Lock() async def connect(self): - self.ws = await websockets.connect(self.url) - self.sender = asyncio.create_task(self.sending()) - await self.auth() - self.receiver = asyncio.create_task(self.receiving()) + retries = 5 + while True: + try: + self.ws = await websockets.connect(self.url) + self.sender = asyncio.create_task(self.sending()) + await self.auth() + self.receiver = asyncio.create_task(self.receiving()) + return + except InvalidStatusCode: + if retries > 0: + retries -= 1 + continue + else: + logging.error("Invalid status code while connecting to Home Assistant") + await self.exit_loop() async def wait_for_close(self): await self.ws.wait_closed() @@ -79,9 +91,9 @@ class HomeAssistantAPI: logging.error("Authentication error: Not required") await self.exit_loop() response = { - "type": "auth", - "access_token": self.token - } + "type": "auth", + "access_token": self.token + } await self.sending_queue.put(response) msg = json.loads(await self.ws.recv()) if msg["type"] == "auth_invalid": diff --git a/fritz_temp_sync/sync_ha_fb.py b/fritz_temp_sync/sync_ha_fb.py index 3931c56..a2023d2 100755 --- a/fritz_temp_sync/sync_ha_fb.py +++ b/fritz_temp_sync/sync_ha_fb.py @@ -90,7 +90,11 @@ config = json.load(open(config_path)) logging.debug(config) loop = asyncio.get_event_loop() -fb = FritzBox(config["fritzbox"]["url"], config["fritzbox"]["password"], config["update_timeout"], dry_run=False) +fb = FritzBox(url=config["fritzbox"]["url"], + user=config["fritzbox"]["username"], + password=config["fritzbox"]["password"], + update_timeout=config["update_timeout"], + dry_run=False) supervisor_url = "ws://supervisor/core/websocket" ha = HomeAssistantAPI(os.environ["SUPERVISOR_TOKEN"], supervisor_url)