From c7932b2a71054af85a42e08a722daf88316a7723 Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Wed, 8 May 2024 22:10:52 +0200 Subject: [PATCH] Implemented network api for devices away mode --- requirements.txt | 5 ++- src/endpoints/handlers/fritz.py | 73 +++++++++++++++++++++++++++++++++ src/main.py | 3 +- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/endpoints/handlers/fritz.py diff --git a/requirements.txt b/requirements.txt index 3fd5bc7..22b4fca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,9 @@ -# For Philips Hue Counter +# For Philips Hue phue +# For Fritz.Box API +fritzconnection + # API fastapi uvicorn[standard] \ No newline at end of file diff --git a/src/endpoints/handlers/fritz.py b/src/endpoints/handlers/fritz.py new file mode 100644 index 0000000..2c7e091 --- /dev/null +++ b/src/endpoints/handlers/fritz.py @@ -0,0 +1,73 @@ +import asyncio +import logging +from fritzconnection import FritzConnection +from datetime import datetime +from ..hue import hue + + +refresh_every_seconds: int = 30 # Every x seconds devices are polled again +trigger_away_after_seconds: int = ( + 2 * 60 +) # After all away-devices are gone for x seconds, light is turned off +away_devices = ["B2:06:77:EE:A9:0F"] # Max' iPhone +macaddresses_to_track = ["B2:06:77:EE:A9:0F"] # Max' iPhone + +fritz_api = FritzConnection(address="192.168.178.1") + +# Referenced documentation: https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/hostsSCPD.pdf + + +devices_last_online = {} + + +def get_all_devices() -> list: + numberOfDevices = fritz_api.call_action("Hosts", "GetHostNumberOfEntries")[ + "NewHostNumberOfEntries" + ] + devices = [] + for i in range(numberOfDevices): + devices.append( + fritz_api.call_action("Hosts", "GetGenericHostEntry", NewIndex=i) + ) + return devices + + +def get_specific_device(mac_adress: str) -> dict: + return fritz_api.call_action( + "Hosts", "GetSpecificHostEntry", NewMACAddress=mac_adress + ) + + +def check_for_change(): + # Check if devices are away for away-mode + all_away = True + for device in away_devices: + last_online = devices_last_online[device] + if (datetime.now() - last_online).total_seconds() < trigger_away_after_seconds: + all_away = False + break + + # Execute away mode + if all_away: + hue.in_room_deactivate_lights("Max Zimmer") + + +async def track_network_devices(): + global devices_last_online + + # Initial values to avoid None + for macaddress in macaddresses_to_track: + devices_last_online[macaddress] = datetime(1970, 1, 1, 0, 0, 0) + + while True: + try: + for macaddress in macaddresses_to_track: + is_online = get_specific_device(macaddress)["NewActive"] + if is_online: + devices_last_online[macaddress] = datetime.now() + + check_for_change() + except Exception as ex: + logging.exception(ex) + finally: + await asyncio.sleep(refresh_every_seconds) diff --git a/src/main.py b/src/main.py index b4cf79a..8765c9f 100644 --- a/src/main.py +++ b/src/main.py @@ -2,7 +2,7 @@ import asyncio from fastapi import FastAPI from endpoints.hue import router as hue_router from endpoints.bettwaage import router as bettwaage_router -from endpoints.handlers.bett import log_bed_weights +from endpoints.handlers.fritz import track_network_devices app = FastAPI() @@ -10,4 +10,5 @@ app.include_router(hue_router, prefix="/hue", tags=["hue"]) app.include_router(bettwaage_router, prefix="/bettwaage", tags=["bett"]) if __name__ == "__main__": + asyncio.create_task(track_network_devices()) app.run()