X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=weather_renderer.py;h=8da01ab73bae05e880c3e3e9e3ac32191608e899;hb=c377a67d1c1babf15404917e3b2e40005fae1613;hp=c72a8620cc3f1f9b5ef7f22be8adc0f89a0ea11c;hpb=55bcd1ba1b9d481e0d0dc604932bcc0f7f4fa127;p=kiosk.git diff --git a/weather_renderer.py b/weather_renderer.py index c72a862..8da01ab 100644 --- a/weather_renderer.py +++ b/weather_renderer.py @@ -1,16 +1,20 @@ #!/usr/bin/env python3 -from datetime import datetime +import logging import json -from typing import Dict, List import urllib.request import urllib.error import urllib.parse +from datetime import datetime +from collections import defaultdict +from typing import Dict, List import file_writer import renderer import kiosk_secrets as secrets +logger = logging.getLogger(__name__) + class weather_renderer(renderer.abstaining_renderer): """A renderer to fetch forecast from wunderground.""" @@ -19,12 +23,8 @@ class weather_renderer(renderer.abstaining_renderer): super().__init__(name_to_timeout_dict) self.file_prefix = file_prefix - def periodic_render(self, key: str) -> bool: - return self.fetch_weather() - - def pick_icon( - self, conditions: List[str], rain: List[float], snow: List[float] - ) -> str: + @staticmethod + def pick_icon(conditions: List[str], rain: List[float], snow: List[float]) -> str: # rain snow clouds sun # fog.gif # hazy.gif @@ -80,24 +80,30 @@ class weather_renderer(renderer.abstaining_renderer): return "partlysunny.gif" return "clear.gif" + def periodic_render(self, key: str) -> bool: + return self.fetch_weather() + def fetch_weather(self) -> bool: if self.file_prefix == "stevens": text_location = "Stevens Pass, WA" - param = "lat=47.74&lon=-121.08" + param = "lat=47.7322&lon=-121.1025" elif self.file_prefix == "telma": text_location = "Telma, WA" param = "lat=47.84&lon=-120.81" else: text_location = "Bellevue, WA" param = "id=5786882" - - www = urllib.request.urlopen( - "http://api.openweathermap.org/data/2.5/forecast?%s&APPID=%s&units=imperial" - % (param, secrets.openweather_key) - ) + secret = secrets.openweather_key + url = f"http://api.openweathermap.org/data/2.5/forecast?{param}&APPID={secret}&units=imperial" + logger.info(f"GETting {url}") + www = urllib.request.urlopen(url) response = www.read() www.close() + if www.getcode() != 200: + logger.error("Bad response: {response}") + raise Exception(response) parsed_json = json.loads(response) + logger.info("URL read ok") # https://openweathermap.org/forecast5 # {"cod":"200", @@ -118,11 +124,14 @@ class weather_renderer(renderer.abstaining_renderer): # {"dt":1485810000,.... with file_writer.file_writer(f"weather-{self.file_prefix}_3_10800.html") as f: - f.write(f""" + f.write( + f"""

Upcoming weather at {text_location}:


-""") - f.write(""" +""" + ) + f.write( + """
-""") +""" + ) count = parsed_json["cnt"] ts = {} highs = {} lows = {} - wind: Dict[str, List[float]] = {} - conditions: Dict[str, List[str]] = {} - rain: Dict[str, List[float]] = {} - snow: Dict[str, List[float]] = {} - precip: Dict[str, List[float]] = {} - - for x in range(0, count): - data = parsed_json["list"][x] - dt = data["dt_txt"] # 2019-10-07 18:00:00 - (date, time) = dt.split(' ') - wind[date] = [] - conditions[date] = [] - highs[date] = None - lows[date] = None - rain[date] = [] - snow[date] = [] - precip[date] = [] - ts[date] = 0 + wind: Dict[str, List[float]] = defaultdict(list) + conditions: Dict[str, List[str]] = defaultdict(list) + rain: Dict[str, List[float]] = defaultdict(list) + snow: Dict[str, List[float]] = defaultdict(list) + precip: Dict[str, List[float]] = defaultdict(list) for x in range(0, count): data = parsed_json["list"][x] dt = data["dt_txt"] # 2019-10-07 18:00:00 - (date, time) = dt.split(' ') + (date, time) = dt.split(" ") _ = data["dt"] - if _ > ts[date]: + if _ not in ts or _ > ts[date]: ts[date] = _ temp = data["main"]["temp"] - if highs[date] is None or highs[date] < temp: + + # High and low temp + if date not in highs or highs[date] < temp: highs[date] = temp - if lows[date] is None or temp < lows[date]: + if date not in lows or lows[date] > temp: lows[date] = temp + + # Windspeed and conditions wind[date].append(data["wind"]["speed"]) conditions[date].append(data["weather"][0]["main"]) + + # 3h precipitation (rain / snow) if "rain" in data and "3h" in data["rain"]: rain[date].append(data["rain"]["3h"]) else: @@ -257,18 +260,24 @@ function makePrecipChart(name, xValues, yValues) { if remaining >= 3: width = "33%" else: - width = f'{100/remaining}%' + width = f"{100/remaining}%" - precip[date] = [] - aggregate_precip = 0.0 + aggregate_daily_precip = 0.0 for r, s in zip(rain[date], snow[date]): - aggregate = r + s - aggregate_precip += aggregate - precip[date].append(aggregate) + hourly_aggregate = r + s + + # The weather report is always way wrong about Stevens. + if self.file_prefix == "stevens": + hourly_aggregate *= 3.5 + aggregate_daily_precip += hourly_aggregate + precip[date].append(hourly_aggregate) + logger.debug( + f"Aggregate precip on {date} was {aggregate_daily_precip} mm" + ) if first_day: while len(precip[date]) < 8: precip[date].insert(0, 0) - first_day = False + first_day = False day = datetime.fromtimestamp(ts[date]) formatted_date = day.strftime("%a %e %b") @@ -280,51 +289,61 @@ function makePrecipChart(name, xValues, yValues) { ) # Date - f.write(f''' + f.write( + f"""
{formatted_date}
-''') +""" + ) # Conditions icon - icon = self.pick_icon(conditions[date], rain[date], snow[date]) - f.write(f''' + icon = weather_renderer.pick_icon( + conditions[date], rain[date], snow[date] + ) + f.write( + f"""
-''') +""" + ) # Low temp -- left color = "#000099" if lows[date] <= 32.5: color = "#009999" - f.write(f''' + f.write( + f""" {int(lows[date])}°F   -''') +""" + ) - # Total aggregate_precip in inches - aggregate_precip *= 0.0393701 - if aggregate_precip > 0.025: - f.write(f''' + # Total aggregate_precip in inches (from mm) + aggregate_daily_precip /= 25.4 + if aggregate_daily_precip > 0.001: + f.write( + f"""
- {aggregate_precip:3.1f}” + {aggregate_daily_precip:3.1f}”
-''') +""" + ) else: f.write("  \n") @@ -332,34 +351,40 @@ function makePrecipChart(name, xValues, yValues) { color = "#800000" if highs[date] >= 80: color = "#AA0000" - f.write(f''' + f.write( + f"""   {int(highs[date])}°F -''') +""" + ) # Precip graph - f.write(f''' + f.write( + f""" -''') +""" + ) f.write("
") return True -x = weather_renderer({"Stevens": 1000}, "stevens") -x.periodic_render("Stevens") +# x = weather_renderer({"Stevens": 1000}, "stevens") +# x.periodic_render("Stevens")