#!/usr/bin/env python3 from aiohttp import ClientSession import asyncio import datetime from dateutil.parser import parse import pymyq # type: ignore from typing import Dict, Optional from pyutils.datetimes import datetime_utils import kiosk_constants import file_writer import renderer import kiosk_secrets as secrets class garage_door_renderer(renderer.abstaining_renderer): def __init__(self, name_to_timeout_dict: Dict[str, int]) -> None: super().__init__(name_to_timeout_dict) self.doors: Optional[Dict] = None self.last_update: Optional[datetime.datetime] = None def debug_prefix(self) -> str: return "myq" def periodic_render(self, key: str) -> bool: if key == "Poll MyQ": self.last_update = datetime.datetime.now() return asyncio.run(self.poll_myq()) elif key == "Update Page": return self.update_page() else: raise Exception("Unknown operaiton") async def poll_myq(self) -> bool: async with ClientSession() as websession: myq = await pymyq.login( secrets.myq_username, secrets.myq_password, websession ) self.doors = myq.devices assert(self.doors is not None) return len(self.doors) > 0 def update_page(self) -> bool: with file_writer.file_writer(kiosk_constants.myq_pagename) as f: f.write( f"""

Garage Door Status


""" ) html = self.do_door("Near House") if html is None: return False f.write(html) html = self.do_door("Middle Door") if html is None: return False f.write(html) f.write( """
""" ) return True def get_state_icon(self, state: str) -> str: if state == "open": return "/kiosk/images/garage_open.png" elif state == "closed": return "/kiosk/images/garage_closed.png" elif state == "opening": return "/kiosk/images/garage_opening.png" elif state == "closing": return "/kiosk/images/garage_closing.png" else: return str(state) + ", an unknown state for the door." def do_door(self, name: str) -> Optional[str]: if self.doors is None: return None for key in self.doors: door = self.doors[key] if door.name == name: j = self.doors[key].device_json state = j["state"]["door_state"] # "last_update": "2020-07-04T18:11:34.2981419Z" raw = j["state"]["last_update"] ts = parse(raw) tz_info = ts.tzinfo now = datetime.datetime.now(tz_info) delta = (now - ts).total_seconds() now = datetime.datetime.now() is_night = now.hour <= 7 or now.hour >= 21 duration = datetime_utils.describe_duration_briefly(int(delta)) width = 0 if is_night and door.state == "open": color = "border-color: #ff0000;" width = 15 else: color = "" width = 0 return f"""
{name}

{state}

for {duration}
""" return None # Test #x = garage_door_renderer({"Test": 1}) #x.periodic_render("Poll MyQ") #x.periodic_render("Update Page")