Skip to content

MagTag Weather fixes for open-meteo update #2914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified MagTag/MagTag_Weather/openmeteo/bmps/weather_bg.bmp
Binary file not shown.
84 changes: 37 additions & 47 deletions MagTag/MagTag_Weather/openmeteo/code.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
# SPDX-FileCopyrightText: 2024 Carter Nelson for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# pylint: disable=redefined-outer-name, eval-used, wrong-import-order
# pylint: disable=redefined-outer-name, eval-used, wrong-import-order, unsubscriptable-object

import time
import terminalio
import displayio
import adafruit_imageload
from adafruit_display_text import label
from adafruit_magtag.magtag import MagTag
# needed for NTP
import wifi
import socketpool
import adafruit_ntp

# --| USER CONFIG |--------------------------
LAT = 47.6 # latitude
LON = -122.3 # longitude
TMZ = "America/Los_Angeles" # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
METRIC = False # set to True for metric units
LAT = 47.6 # latitude
LON = -122.3 # longitude
TMZ = "America/Los_Angeles" # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
METRIC = False # set to True for metric units
CITY = None # optional
# -------------------------------------------

# ----------------------------
Expand Down Expand Up @@ -61,15 +58,15 @@

# Map the above WMO codes to index of icon in 3x3 spritesheet
WMO_CODE_TO_ICON = (
(0,), # 0 = sunny
(1,), # 1 = partly sunny/cloudy
(2,), # 2 = cloudy
(3,), # 3 = very cloudy
(61, 63, 65), # 4 = rain
(51, 53, 55, 80, 81, 82), # 5 = showers
(95, 96, 99), # 6 = storms
(56, 57, 66, 67, 71, 73, 75, 77, 85, 86), # 7 = snow
(45, 48), # 8 = fog and stuff
(0,), # 0 = sunny
(1,), # 1 = partly sunny/cloudy
(2,), # 2 = cloudy
(3,), # 3 = very cloudy
(61, 63, 65), # 4 = rain
(51, 53, 55, 80, 81, 82), # 5 = showers
(95, 96, 99), # 6 = storms
(56, 57, 66, 67, 71, 73, 75, 77, 85, 86), # 7 = snow
(45, 48), # 8 = fog and stuff
)

magtag = MagTag()
Expand All @@ -88,14 +85,15 @@
# /////////////////////////////////////////////////////////////////////////
# helper functions


def get_forecast():
URL = f"https://api.open-meteo.com/v1/forecast?latitude={LAT}&longitude={LON}&"
URL = f"https://api.open-meteo.com/v1/forecast?latitude={LAT}&longitude={LON}&"
URL += "daily=weather_code,temperature_2m_max,temperature_2m_min"
URL += ",sunrise,sunset,wind_speed_10m_max,wind_direction_10m_dominant"
URL += "&timeformat=unixtime"
URL += f"&timezone={TMZ}"
resp = magtag.network.fetch(URL)
return resp.json()
return resp


def make_banner(x=0, y=0):
Expand Down Expand Up @@ -168,10 +166,7 @@ def update_today(data):
s = data["daily"]["time"][0] + data["utc_offset_seconds"]
t = time.localtime(s)
today_date.text = "{} {} {}, {}".format(
DAYS[t.tm_wday].upper(),
MONTHS[t.tm_mon - 1].upper(),
t.tm_mday,
t.tm_year
DAYS[t.tm_wday].upper(), MONTHS[t.tm_mon - 1].upper(), t.tm_mday, t.tm_year
)
# weather icon
w = data["daily"]["weather_code"][0]
Expand All @@ -194,37 +189,24 @@ def update_future(data):
"""Update the future forecast info."""
for i, banner in enumerate(future_banners):
# day of week
s = data["daily"]["time"][i+1] + data["utc_offset_seconds"]
s = data["daily"]["time"][i + 1] + data["utc_offset_seconds"]
t = time.localtime(s)
banner[0].text = DAYS[t.tm_wday][:3].upper()
# weather icon
w = data["daily"]["weather_code"][i+1]
w = data["daily"]["weather_code"][i + 1]
banner[1][0] = next(x for x, t in enumerate(WMO_CODE_TO_ICON) if w in t)
# temperature
t = data["daily"]["temperature_2m_max"][i+1]
t = data["daily"]["temperature_2m_max"][i + 1]
banner[2].text = temperature_text(t)


def get_ntp_time(offset):
"""Use NTP to get current local time."""
pool = socketpool.SocketPool(wifi.radio)
ntp = adafruit_ntp.NTP(pool, tz_offset=offset)
if ntp:
return ntp.datetime
else:
return None


def go_to_sleep(current_time):
def go_to_sleep(current_time_secs):
"""Enter deep sleep for time needed."""
# compute current time offset in seconds
hour = current_time.tm_hour
minutes = current_time.tm_min
seconds = current_time.tm_sec
seconds_since_midnight = 60 * (hour * 60 + minutes) + seconds
# work in units of seconds
seconds_in_a_day = 24 * 60 * 60
three_fifteen = (3 * 60 + 15) * 60
# wake up 15 minutes after 3am
seconds_to_sleep = (24 * 60 * 60 - seconds_since_midnight) + three_fifteen
seconds_to_sleep = (seconds_in_a_day - current_time_secs) + three_fifteen
print(
"Sleeping for {} hours, {} minutes".format(
seconds_to_sleep // 3600, (seconds_to_sleep // 60) % 60
Expand All @@ -240,7 +222,12 @@ def go_to_sleep(current_time):
today_date.anchor_point = (0, 0)
today_date.anchored_position = (15, 14)

location_name = label.Label(terminalio.FONT, text=f"({LAT},{LON})", color=0x000000)
location_name = label.Label(terminalio.FONT, color=0x000000)
if CITY:
location_name.text = f"{CITY[:16]} ({LAT:.1f},{LON:.1f})"
else:
location_name.text = f"({LAT},{LON})"

location_name.anchor_point = (0, 0)
location_name.anchored_position = (15, 25)

Expand Down Expand Up @@ -301,7 +288,8 @@ def go_to_sleep(current_time):
# M A I N
# ===========
print("Fetching forecast...")
forecast_data = get_forecast()
resp_data = get_forecast()
forecast_data = resp_data.json()

print("Updating...")
update_today(forecast_data)
Expand All @@ -313,6 +301,8 @@ def go_to_sleep(current_time):
time.sleep(magtag.display.time_to_refresh + 1)

print("Sleeping...")
go_to_sleep(get_ntp_time(forecast_data["utc_offset_seconds"]/3600))
h, m, s = (int(t) for t in resp_data.headers["date"].split(" ")[4].split(":"))
current_time_secs = (h * 3600) + (m * 60) + (s) + forecast_data["utc_offset_seconds"]
go_to_sleep(current_time_secs)
# entire code will run again after deep sleep cycle
# similar to hitting the reset button