X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=weather_renderer.py;h=5d8df1e1129ffcb237ebd9f4234e370a4e9fa4a0;hb=addd4980077f6e3857c5c035b49784dc3ceca49a;hp=4a5663cfb612469b3890a2cb0a5be68b6a639a1d;hpb=da3a11e9fcea80a7700eb54605512d331a9ec612;p=kiosk.git diff --git a/weather_renderer.py b/weather_renderer.py index 4a5663c..5d8df1e 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(__file__) + 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: @@ -246,6 +249,7 @@ function makePrecipChart(name, xValues, yValues) { days_seen.add(formatted_date) total = len(days_seen) + first_day = True days_seen = set() for n, date in enumerate(sorted(highs.keys())): if n % 3 == 0: @@ -256,14 +260,20 @@ 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 + aggregate_daily_precip += hourly_aggregate + precip[date].append(hourly_aggregate) + logger.debug( + f"Aggregate precip on {date} was {aggregate_daily_precip} cm" + ) + if first_day: + while len(precip[date]) < 8: + precip[date].insert(0, 0) + first_day = False day = datetime.fromtimestamp(ts[date]) formatted_date = day.strftime("%a %e %b") @@ -276,42 +286,60 @@ function makePrecipChart(name, xValues, yValues) { # Date f.write( - "
" - + formatted_date - + "
\n" + f""" + + +
+ {formatted_date} +
+ +""" ) # Conditions icon + icon = weather_renderer.pick_icon( + conditions[date], rain[date], snow[date] + ) f.write( - '
\n' - % self.pick_icon(conditions[date], rain[date], snow[date]) + f""" + + +
+ +
+ +""" ) - # Low temp + # 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''' + aggregate_daily_precip /= 2.54 + if aggregate_daily_precip > 0.025: + f.write( + f"""
- - {aggregate_precip:3.1f}" + + {aggregate_daily_precip:3.1f}”
-''') +""" + ) else: f.write("  \n") @@ -319,31 +347,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("
") return True -#x = weather_renderer({"Stevens": 1000}, "stevens") -#x.periodic_render("Stevens") +# x = weather_renderer({"Stevens": 1000}, "stevens") +# x.periodic_render("Stevens")