Compare commits
No commits in common. "master" and "v0.4.3" have entirely different histories.
@ -2,7 +2,8 @@ ARG BUILD_FROM
|
|||||||
FROM $BUILD_FROM
|
FROM $BUILD_FROM
|
||||||
|
|
||||||
# Install requirements for add-on
|
# Install requirements for add-on
|
||||||
RUN apk update && apk add --no-cache python3 py3-pip py3-websockets py3-requests
|
RUN apk update && apk add --no-cache python3 py-pip
|
||||||
|
RUN python3 -m pip install websockets requests
|
||||||
|
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
|
@ -29,4 +29,3 @@ schema:
|
|||||||
- sensor: str
|
- sensor: str
|
||||||
thermostate: str
|
thermostate: str
|
||||||
update_timeout: int
|
update_timeout: int
|
||||||
log_level: "str?"
|
|
||||||
|
@ -42,7 +42,7 @@ class FritzBox:
|
|||||||
|
|
||||||
logging.debug(f"Calculate v2 challenge: {challenge}")
|
logging.debug(f"Calculate v2 challenge: {challenge}")
|
||||||
chall_regex = re.compile(
|
chall_regex = re.compile(
|
||||||
r"2\$(?P<iter1>[0-9a-zA-Z]+)\$(?P<salt1>[0-9a-zA-Z]+)\$(?P<iter2>[0-9a-zA-Z]+)\$(?P<salt2>[0-9a-zA-Z]+)")
|
"2\$(?P<iter1>[0-9a-zA-Z]+)\$(?P<salt1>[0-9a-zA-Z]+)\$(?P<iter2>[0-9a-zA-Z]+)\$(?P<salt2>[0-9a-zA-Z]+)")
|
||||||
|
|
||||||
chall_parts = chall_regex.match(challenge).groupdict()
|
chall_parts = chall_regex.match(challenge).groupdict()
|
||||||
salt1: bytes = bytes.fromhex(chall_parts["salt1"])
|
salt1: bytes = bytes.fromhex(chall_parts["salt1"])
|
||||||
|
@ -1,70 +1,48 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from fritzbox import FritzBox
|
from fritzbox import FritzBox
|
||||||
from homeassistant import HomeAssistantAPI
|
from homeassistant import HomeAssistantAPI
|
||||||
|
import logging
|
||||||
|
import json
|
||||||
|
|
||||||
sensor_mappings = {}
|
sensor_mappings = {}
|
||||||
thermostate_mappings = {}
|
thermostate_mappings = {}
|
||||||
|
|
||||||
|
|
||||||
async def handle_event(idx: int):
|
async def handle_event(idx: int):
|
||||||
global ha, fb
|
|
||||||
logging.debug(f"Wait for events for {idx}")
|
logging.debug(f"Wait for events for {idx}")
|
||||||
|
|
||||||
while event := await ha.events[idx].get():
|
while event := await ha.events[idx].get():
|
||||||
try:
|
try:
|
||||||
entity_id = event["data"]["entity_id"]
|
entity_id = event["data"]["entity_id"]
|
||||||
if (
|
if entity_id in sensor_mappings.keys() or entity_id in thermostate_mappings.keys():
|
||||||
entity_id in sensor_mappings.keys()
|
|
||||||
or entity_id in thermostate_mappings.keys()
|
|
||||||
):
|
|
||||||
state = await ha.get_device_state(entity_id)
|
state = await ha.get_device_state(entity_id)
|
||||||
new_state = event["data"]["new_state"]
|
new_state = event["data"]["new_state"]
|
||||||
logging.info(
|
logging.debug(f"received changed state from {entity_id}")
|
||||||
f"received changed state from {entity_id} {entity_id in thermostate_mappings.keys()} {state['state']} {entity_id in sensor_mappings.keys()}"
|
if entity_id in thermostate_mappings.keys() and state["state"] != "unavailable":
|
||||||
)
|
|
||||||
if (
|
|
||||||
entity_id in thermostate_mappings.keys()
|
|
||||||
and state["state"] != "unavailable"
|
|
||||||
):
|
|
||||||
therm_temp = new_state["attributes"]["current_temperature"]
|
therm_temp = new_state["attributes"]["current_temperature"]
|
||||||
therm_name = new_state["attributes"]["friendly_name"]
|
therm_name = new_state["attributes"]["friendly_name"]
|
||||||
sensor = thermostate_mappings[entity_id]
|
sensor = thermostate_mappings[entity_id]
|
||||||
sensor_state = await ha.get_device_state(sensor)
|
sensor_state = await ha.get_device_state(sensor)
|
||||||
sensor_temp = round(float(sensor_state["state"]) * 2) / 2
|
sensor_temp = round(float(sensor_state["attributes"]["temperature"]) * 2) / 2
|
||||||
logging.info(f"temps: {therm_temp} {sensor_temp}")
|
|
||||||
if therm_temp != sensor_temp:
|
if therm_temp != sensor_temp:
|
||||||
logging.info(
|
logging.info(f"{therm_name}: {therm_temp}\n{sensor}: {sensor_state['attributes']['temperature']} ({sensor_temp})")
|
||||||
f"{therm_name}: {therm_temp}\n{sensor}: {sensor_state['state']} ({sensor_temp})"
|
|
||||||
)
|
|
||||||
fb.correct_offset(therm_name, sensor_temp)
|
fb.correct_offset(therm_name, sensor_temp)
|
||||||
|
|
||||||
elif entity_id in sensor_mappings.keys():
|
elif entity_id in sensor_mappings.keys():
|
||||||
logging.info(f"here {sensor_mappings} {entity_id}")
|
sensor_temp = round(float(new_state["attributes"]["temperature"]) * 2) / 2
|
||||||
logging.info(f"{new_state}")
|
|
||||||
sensor_temp = round(float(new_state["state"]) * 2) / 2
|
|
||||||
logging.info(f"entry: {sensor_mappings[entity_id]}")
|
|
||||||
for thermostate in sensor_mappings[entity_id]:
|
for thermostate in sensor_mappings[entity_id]:
|
||||||
logging.info(thermostate)
|
|
||||||
therm_state = await ha.get_device_state(thermostate)
|
therm_state = await ha.get_device_state(thermostate)
|
||||||
logging.info(f"{thermostate} {therm_state}")
|
|
||||||
if therm_state["state"] == "unavailable":
|
if therm_state["state"] == "unavailable":
|
||||||
continue
|
continue
|
||||||
therm_temp = float(
|
therm_temp = float(therm_state["attributes"]["current_temperature"])
|
||||||
therm_state["attributes"]["current_temperature"]
|
|
||||||
)
|
|
||||||
therm_name = therm_state["attributes"]["friendly_name"]
|
therm_name = therm_state["attributes"]["friendly_name"]
|
||||||
logging.info(f"Temps: {therm_temp} {sensor_temp}")
|
|
||||||
if therm_temp != sensor_temp:
|
if therm_temp != sensor_temp:
|
||||||
logging.info(
|
logging.info(f"{therm_name}: {therm_temp}\n{entity_id}: {new_state['attributes']['temperature']} ({sensor_temp})")
|
||||||
f"{therm_name}: {therm_temp}\n{entity_id}: {new_state['state']} ({sensor_temp})"
|
|
||||||
)
|
|
||||||
fb.correct_offset(therm_name, sensor_temp)
|
fb.correct_offset(therm_name, sensor_temp)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
@ -81,31 +59,23 @@ async def init(ha: HomeAssistantAPI, fb: FritzBox):
|
|||||||
await ha.wait_for_close()
|
await ha.wait_for_close()
|
||||||
logging.info("Websocket closed, shutting down..")
|
logging.info("Websocket closed, shutting down..")
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
config_path = sys.argv[1]
|
config_path = sys.argv[1]
|
||||||
config = json.load(open(config_path))
|
config = json.load(open(config_path))
|
||||||
level = logging.INFO
|
level = logging.INFO
|
||||||
if "log_level" in config:
|
if "log_level" in config:
|
||||||
print(f"Setting log_level {config['log_level']}")
|
|
||||||
if config["log_level"] == "DEBUG":
|
if config["log_level"] == "DEBUG":
|
||||||
level = logging.DEBUG
|
level = logging.DEBUG
|
||||||
logging.basicConfig(
|
logging.basicConfig(level=level, format="[%(asctime)s] [%(levelname)s] %(message)s")
|
||||||
level=level, format="[%(asctime)s] [%(levelname)s] %(message)s"
|
|
||||||
)
|
|
||||||
logging.debug(config)
|
logging.debug(config)
|
||||||
|
|
||||||
global fb
|
global fb
|
||||||
fb = FritzBox(
|
fb = FritzBox(url=config["fritzbox"]["url"],
|
||||||
url=config["fritzbox"]["url"],
|
user=config["fritzbox"]["username"],
|
||||||
user=config["fritzbox"]["username"],
|
password=config["fritzbox"]["password"],
|
||||||
password=config["fritzbox"]["password"],
|
update_timeout=config["update_timeout"],
|
||||||
update_timeout=config["update_timeout"],
|
dry_run=False)
|
||||||
dry_run=False,
|
|
||||||
)
|
|
||||||
supervisor_url = "ws://supervisor/core/websocket"
|
supervisor_url = "ws://supervisor/core/websocket"
|
||||||
if "SUPERVISOR_URL" in os.environ:
|
|
||||||
supervisor_url = os.environ["SUPERVISOR_URL"]
|
|
||||||
supervisor_token = os.environ["SUPERVISOR_TOKEN"]
|
supervisor_token = os.environ["SUPERVISOR_TOKEN"]
|
||||||
global ha
|
global ha
|
||||||
ha = HomeAssistantAPI(supervisor_token, supervisor_url)
|
ha = HomeAssistantAPI(supervisor_token, supervisor_url)
|
||||||
@ -115,11 +85,10 @@ async def main():
|
|||||||
sensor_mappings[mapping["sensor"]] = []
|
sensor_mappings[mapping["sensor"]] = []
|
||||||
sensor_mappings[mapping["sensor"]].append(mapping["thermostate"])
|
sensor_mappings[mapping["sensor"]].append(mapping["thermostate"])
|
||||||
thermostate_mappings[mapping["thermostate"]] = mapping["sensor"]
|
thermostate_mappings[mapping["thermostate"]] = mapping["sensor"]
|
||||||
logging.debug(f"Mappings: {sensor_mappings} {thermostate_mappings}")
|
|
||||||
try:
|
try:
|
||||||
await init(ha, fb)
|
await init(ha, fb)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user