parent
43c2f0284a
commit
f6600c7dda
4
.gitignore
vendored
4
.gitignore
vendored
@ -169,6 +169,7 @@ pip-selfcheck.json
|
|||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
# User-specific stuff
|
# User-specific stuff
|
||||||
|
.idea/
|
||||||
.idea/**/workspace.xml
|
.idea/**/workspace.xml
|
||||||
.idea/**/tasks.xml
|
.idea/**/tasks.xml
|
||||||
.idea/**/usage.statistics.xml
|
.idea/**/usage.statistics.xml
|
||||||
@ -240,3 +241,6 @@ fabric.properties
|
|||||||
# Android studio 3.1+ serialized cache file
|
# Android studio 3.1+ serialized cache file
|
||||||
.idea/caches/build_file_checksums.ser
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
# local config test
|
||||||
|
options.json
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
name: "Fritz!Box Temperature Sync"
|
name: "Fritz!Box Temperature Sync"
|
||||||
description: "Sync Fritz!DECT thermostat temperatures with other sensors in Home Assistant"
|
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"
|
slug: "fritz_temp_sync"
|
||||||
homeassistant_api: true
|
homeassistant_api: true
|
||||||
arch:
|
arch:
|
||||||
@ -12,6 +14,7 @@ arch:
|
|||||||
options:
|
options:
|
||||||
fritzbox:
|
fritzbox:
|
||||||
url: "http://fritz.box"
|
url: "http://fritz.box"
|
||||||
|
username: null
|
||||||
password: null
|
password: null
|
||||||
mappings:
|
mappings:
|
||||||
- sensor: null
|
- sensor: null
|
||||||
@ -20,6 +23,7 @@ options:
|
|||||||
schema:
|
schema:
|
||||||
fritzbox:
|
fritzbox:
|
||||||
url: url
|
url: url
|
||||||
|
username: "str?"
|
||||||
password: str
|
password: str
|
||||||
mappings:
|
mappings:
|
||||||
- sensor: str
|
- sensor: str
|
||||||
|
@ -801,8 +801,8 @@ class FritzBox:
|
|||||||
else:
|
else:
|
||||||
logging.info("Already logged in")
|
logging.info("Already logged in")
|
||||||
|
|
||||||
def login(self, user: str = None) -> bool:
|
def login(self) -> bool:
|
||||||
logging.info(f"Login user {user} to Fritz!Box")
|
logging.info(f"Login user {self.user} to Fritz!Box")
|
||||||
challenge = None
|
challenge = None
|
||||||
r = self.session.get(f"{self.url}/{self._endpoints['login']}")
|
r = self.session.get(f"{self.url}/{self._endpoints['login']}")
|
||||||
xml = ET.fromstring(r.text)
|
xml = ET.fromstring(r.text)
|
||||||
@ -811,12 +811,12 @@ class FritzBox:
|
|||||||
self.sid = elem.text
|
self.sid = elem.text
|
||||||
elif elem.tag == "Challenge":
|
elif elem.tag == "Challenge":
|
||||||
challenge = elem.text
|
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:
|
for user_elem in elem:
|
||||||
if "fritz" in user_elem.text:
|
if "fritz" in user_elem.text:
|
||||||
user = 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$"):
|
if challenge.startswith("2$"):
|
||||||
response = self._calc_challenge_v2(challenge)
|
response = self._calc_challenge_v2(challenge)
|
||||||
@ -824,7 +824,7 @@ class FritzBox:
|
|||||||
response = self._calc_challenge_v1(challenge)
|
response = self._calc_challenge_v1(challenge)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"username": user,
|
"username": self.user,
|
||||||
"response": response
|
"response": response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import logging
|
|||||||
from asyncio import Queue, Task, Event, Lock
|
from asyncio import Queue, Task, Event, Lock
|
||||||
from typing import Callable, Dict, Optional
|
from typing import Callable, Dict, Optional
|
||||||
import websockets
|
import websockets
|
||||||
|
from websockets.exceptions import InvalidStatusCode
|
||||||
|
|
||||||
|
|
||||||
class HomeAssistantAPI:
|
class HomeAssistantAPI:
|
||||||
@ -25,10 +26,21 @@ class HomeAssistantAPI:
|
|||||||
self.response_lock: Lock = Lock()
|
self.response_lock: Lock = Lock()
|
||||||
|
|
||||||
async def connect(self):
|
async def connect(self):
|
||||||
self.ws = await websockets.connect(self.url)
|
retries = 5
|
||||||
self.sender = asyncio.create_task(self.sending())
|
while True:
|
||||||
await self.auth()
|
try:
|
||||||
self.receiver = asyncio.create_task(self.receiving())
|
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):
|
async def wait_for_close(self):
|
||||||
await self.ws.wait_closed()
|
await self.ws.wait_closed()
|
||||||
@ -79,9 +91,9 @@ class HomeAssistantAPI:
|
|||||||
logging.error("Authentication error: Not required")
|
logging.error("Authentication error: Not required")
|
||||||
await self.exit_loop()
|
await self.exit_loop()
|
||||||
response = {
|
response = {
|
||||||
"type": "auth",
|
"type": "auth",
|
||||||
"access_token": self.token
|
"access_token": self.token
|
||||||
}
|
}
|
||||||
await self.sending_queue.put(response)
|
await self.sending_queue.put(response)
|
||||||
msg = json.loads(await self.ws.recv())
|
msg = json.loads(await self.ws.recv())
|
||||||
if msg["type"] == "auth_invalid":
|
if msg["type"] == "auth_invalid":
|
||||||
|
@ -90,7 +90,11 @@ config = json.load(open(config_path))
|
|||||||
logging.debug(config)
|
logging.debug(config)
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
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"
|
supervisor_url = "ws://supervisor/core/websocket"
|
||||||
ha = HomeAssistantAPI(os.environ["SUPERVISOR_TOKEN"], supervisor_url)
|
ha = HomeAssistantAPI(os.environ["SUPERVISOR_TOKEN"], supervisor_url)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user