135 lines
5.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
hier die verbindungen zu HA aufbauen etc
außerdem das vergleichen der werte und dass anstoßen der updates
"""
import asyncio
import os
from typing import Dict
from fritzbox import FritzBox
from homeassistant import HomeAssistantAPI
import logging
import json
sensor_mappings = {}
thermostate_mappings = {}
async def handle_event(idx: int):
logging.debug(f"Wait for events for {idx}")
while event := await ha.events[idx].get():
entity_id = event["data"]["entity_id"]
if entity_id in sensor_mappings.keys() or entity_id in thermostate_mappings.keys():
state = await ha.get_device_state(entity_id)
new_state = event["data"]["new_state"]
logging.info(f"received changed state from {entity_id}")
if entity_id in thermostate_mappings.keys() and state["state"] != "unavailable":
therm_temp = new_state["attributes"]["current_temperature"]
therm_name = new_state["attributes"]["friendly_name"]
sensor = thermostate_mappings[entity_id]
sensor_state = await ha.get_device_state(sensor)
sensor_temp = round(float(sensor_state["attributes"]["temperature"]) * 2) / 2
if therm_temp != sensor_temp:
logging.info(f"{therm_name}: {therm_temp}")
logging.info(f"{sensor}: {sensor_state['attributes']['temperature']} ({sensor_temp})")
fb.correct_offset(therm_name, sensor_temp)
elif entity_id in sensor_mappings.keys():
sensor_temp = round(float(new_state["attributes"]["temperature"]) * 2) / 2
"""
fb.login()
logged = False
"""
for thermostate in sensor_mappings[entity_id]:
therm_state = await ha.get_device_state(thermostate)
if therm_state["state"] == "unavailable":
continue
therm_temp = float(therm_state["attributes"]["current_temperature"])
therm_name = therm_state["attributes"]["friendly_name"]
if therm_temp != sensor_temp:
logging.info(f"{therm_name}: {therm_temp}")
logging.info(f"{entity_id}: {new_state['attributes']['temperature']} ({sensor_temp})")
fb.correct_offset(therm_name, sensor_temp)
"""
current_temp, current_offset, id, name = fb.get_device_data(name=thermostate)
if not logged:
logging.info(
f"Current measurement from {entity_id}: {new_state['attributes']['temperature']} ({rounded})")
logged = True
logging.info(f"Current measurement from {thermostate}: {current_temp}")
new_offset = current_offset + rounded - current_temp
if new_offset != current_offset:
old_offset = current_offset
logging.debug(f"Set offset for {thermostate} from {current_offset} to {new_offset}")
fb.set_offset(current_temp, new_offset, id, name)
current_temp, current_offset, id, name = fb.get_device_data(name=thermostate)
logging.debug(f"Target: {new_offset} ; Set: {current_offset}")
if new_offset == current_offset:
logging.info(f"Adjustet offset from {old_offset} to {new_offset}")
else:
logging.warning(f"Failed to adjust offset from {old_offset} to {new_offset}")
fb.logout()
"""
async def init(ha: HomeAssistantAPI):
await ha.connect()
logging.debug("Subscribe")
state_changed_id = await ha.subscribe_event("state_changed")
logging.debug(state_changed_id)
asyncio.create_task(handle_event(state_changed_id))
fb.login()
await ha.wait_for_close()
logging.info("Websocket closed, shutting down..")
asyncio.get_running_loop().stop()
async def migrate_config(config_path: str, ha: HomeAssistantAPI):
config = json.load(open(config_path))
therm_ids = {}
for state in await ha.get_states():
if state["entity_id"].startswith("climate.") and "friendly_name" in state["attributes"].keys():
therm_ids[state["attributes"]["friendly_name"]] = state["entity_id"]
mappings = []
for mapping in config["mappings"]:
if not mapping["thermostate"].startswith("climate."):
mapping["thermostate"] = therm_ids[mapping["thermostate"]]
mappings.append(mapping)
config["mappings"] = mappings
json.dump(open(config_path), config)
return config
logging.basicConfig(level=logging.INFO, format="[%(asctime)s] [%(levelname)s] %(message)s")
config_path = "/data/options.json"
config_path = "options.json"
config = json.load(open(config_path))
logging.debug(config)
loop = asyncio.get_event_loop()
fb = FritzBox(config["fritzbox"]["url"], config["fritzbox"]["password"])
supervisor_url = "ws://supervisor/core/websocket"
supervisor_url = "ws://192.168.124.187:8123/api/websocket"
ha = HomeAssistantAPI(os.environ["SUPERVISOR_TOKEN"], supervisor_url)
if '"thermostate": "climate.' not in open(config_path).read():
config = loop.run_until_complete(migrate_config(config_path, ha))
logging.info(config)
exit()
for mapping in config["mappings"]:
if mapping["sensor"] not in sensor_mappings.keys():
sensor_mappings[mapping["sensor"]] = []
sensor_mappings[mapping["sensor"]].append(mapping["thermostate"])
thermostate_mappings[mapping["thermostate"]] = mapping["sensor"]
loop.create_task(init(ha))
try:
loop.run_forever()
except KeyboardInterrupt:
pass