Testosterone and sensitivity.
[kiosk.git] / ratago_renderer.py
1 #!/usr/bin/env python3
2
3 import datetime
4 import logging
5 import json
6 from dateutil.parser import parse
7 from typing import Any, Dict, Optional
8
9 import requests
10 from pyutils.datetimes import datetime_utils
11
12 import file_writer
13 import globals
14 import kiosk_constants
15 import kiosk_secrets as secrets
16 import renderer
17
18
19 logger = logging.getLogger(__name__)
20
21
22 class ratago_renderer(renderer.abstaining_renderer):
23     def __init__(self, name_to_timeout_dict: Dict[str, int]) -> None:
24         super().__init__(name_to_timeout_dict)
25         self.last_update: Optional[datetime.datetime] = None
26         self.doors: Dict[str, Dict[str, Any]] = {
27             "cover.ratgdo_middle_door_door": {"state": "unknown"},
28             "cover.ratgdo_near_house_door": {"state": "unknown"},
29             "cover.ratgdo_shop_door": {"state": "unknown"},
30         }
31
32     def debug_prefix(self) -> str:
33         return "ratago"
34
35     def periodic_render(self, key: str) -> bool:
36         if key == "Poll Home Assistant":
37             return self.poll_home_assistant()
38         elif key == "Update Page":
39             return self.update_page()
40         else:
41             raise Exception("Unknown operaiton")
42
43     def poll_home_assistant(self) -> bool:
44         key = secrets.homeassistant_api_key
45         headers = {
46             "Authorization": f"Bearer {key}",
47             "Content-Type": "application/json",
48         }
49         for door in self.doors.keys():
50             try:
51                 r = requests.get(
52                     f"https://home.acknak.org/api/states/{door}",
53                     headers=headers,
54                     timeout=3.0,
55                 )
56                 if r.ok:
57                     j = json.loads(r.content.decode())
58                     self.doors[door] = j
59                 else:
60                     logger.warning("Unable to get state of garage door {door}, using 'unknown'")
61             except Exception:
62                 logger.exception("Unable to get state of garage door {door}, using 'unknown'")
63         self.last_update = datetime_utils.now_pacific()
64         return True
65
66     def update_page(self) -> bool:
67         with file_writer.file_writer(kiosk_constants.ratago_pagename) as f:
68             f.write(
69                 f"""
70 <H1>Garage Door Status</H1>
71 <!-- Last updated at {self.last_update} -->
72 <HR>
73 <TABLE BORDER=0 WIDTH=99%>
74     <TR>
75 """
76             )
77             html = self.do_door('cover.ratgdo_near_house_door')
78             if html is None:
79                 return False
80             f.write(html)
81
82             html = self.do_door('cover.ratgdo_middle_door_door')
83             if html is None:
84                 return False
85             f.write(html)
86
87             html = self.do_door('cover.ratgdo_shop_door')
88             if html is None:
89                 return False
90             f.write(html)
91             f.write(
92                 """
93     </TR>
94 </TABLE>"""
95             )
96         return True
97
98     def get_state_icon(self, state: str) -> str:
99         if state == "open":
100             return "/kiosk/images/garage_open.png"
101         elif state == "closed":
102             return "/kiosk/images/garage_closed.png"
103         elif state == "opening":
104             return "/kiosk/images/garage_opening.png"
105         elif state == "closing":
106             return "/kiosk/images/garage_closing.png"
107         else:
108             return str(state) + ", an unknown state for the door."
109
110     def do_door(self, name: str) -> Optional[str]:
111         friendly_door_names = {
112             "cover.ratgdo_middle_door_door": "Middle Door",
113             "cover.ratgdo_near_house_door": "Near House Door",
114             "cover.ratgdo_shop_door": "Workshop Door",
115         }
116         friendly_name = friendly_door_names.get(name, "unknown")
117         attributes = self.doors[name] #.get(name) #, {"state": "unknown"})
118         state = attributes.get("state", "unknown").lower()
119         since = attributes.get("last_changed", "unknown").lower()
120
121         # "last_update": "2020-07-04T18:11:34.2981419Z"
122         if since != "unknown":
123             ts = parse(since)
124             tz_info = ts.tzinfo
125             now = datetime.datetime.now(tz_info)
126             delta = (now - ts).total_seconds()
127             duration = datetime_utils.describe_duration_briefly(int(delta))
128         else:
129             duration = "unknown"
130
131         now = datetime.datetime.now()
132         is_night = now.hour <= 7 or now.hour >= 21
133         width = 0
134         if is_night and state == "open":
135             color = "border-color: #ff0000;"
136             width = 15
137             globals.put("ratago_triggered", True)
138         else:
139             color = ""
140             width = 0
141             globals.put("ratago_triggered", False)
142         return f"""
143 <TD WIDTH=32%>
144   <CENTER>
145   <FONT STYLE="font-size:26pt">{friendly_name}<BR>
146   <IMG SRC="{self.get_state_icon(state)}"
147        HEIGHT=250
148        STYLE="border-style: solid; border-width: {width}px; {color}">
149   <BR>
150   <B>{state}</B></FONT><BR>
151   for {duration}
152   </CENTER>
153 </TD>"""
154
155
156 # Test
157 #x = ratago_renderer({"Test": 1})
158 #x.periodic_render("Poll Home Assistant")
159 #x.periodic_render("Update Page")