weather: update to use met.no

This commit is contained in:
Vincent Bernat 2024-05-12 16:22:08 +02:00
parent dd885314b1
commit c1e81df684
3 changed files with 58 additions and 60 deletions

View file

@ -30,17 +30,17 @@ def get_location():
return ((data["location"]["latitude"], data["location"]["longitude"]), location) return ((data["location"]["latitude"], data["location"]["longitude"]), location)
def get_weather(apikey, latitude, longitude): def get_weather(latitude, longitude):
"""Return data from openweathermap.""" """Return data from met.no."""
logger.debug("query openweathermap for %s, %s", latitude, longitude) logger.debug("query met.no for %s, %s", latitude, longitude)
r = requests.get( r = requests.get(
f"https://api.openweathermap.org/data/2.5/onecall", "https://api.met.no/weatherapi/locationforecast/2.0/complete.json",
params={ params={
"appid": apikey, "lat": f"{latitude:.4f}",
"lat": latitude, "lon": f"{longitude:.4f}",
"lon": longitude, },
"units": "metric", headers={
"exclude": "minutely,hourly", "user-agent": "WeatherWidget https://github.com/vincentbernat/i3wm-configuration"
}, },
timeout=10, timeout=10,
) )
@ -50,37 +50,43 @@ def get_weather(apikey, latitude, longitude):
return data return data
def format_weather(data, show_temperature=True): def format_icon(symbol_code):
"""Translate OWM icon to WeatherIcons.""" """Translate met.no icon to Font Awesome."""
# https://erikflowers.github.io/weather-icons/ # See https://github.com/metno/weathericons/blob/main/weather/legend.csv
icon = data["weather"][0]["icon"] symbol_code = symbol_code.removeprefix("light")
temperature = data["temp"] if show_temperature else 0 symbol_code = symbol_code.removeprefix("heavy")
if icon == "01d" and temperature > 32: if symbol_code.startswith("ss"):
icon = "" symbol_code = symbol_code[1:]
else:
icon = { icon = {
"01d": "", # Clear sky - day "clearsky_day": "\uf00d",
"01n": "⏾", # Clear sky - night "clearsky_night": "\uf02e",
"02d": "🌤", # Few clouds (11-25%) - day "cloudy": "\uf013",
"02n": "", # Few clouds (11-25%) - night "fair_day": "\uf002",
"03d": "⛅", # Scattered clouds (25-50%) - day/night "fair_night": "\uf086",
"03n": "", # Scattered clouds (25-50%) - day/night "fog": "\uf014",
"04d": "", # Broken / Overcast clouds (51-84% / 85-100%) - day/night "partlycloudy_day": "\uf002",
"04n": "", # Broken / Overcast clouds (51-84% / 85-100%) - day/night "partlycloudy_night": "\uf086",
"09d": "🌦", # Shower rain - day "rain": "\uf019",
"09n": "", # Shower rain - night "rainandthunder": "\uf01e",
"10d": "", # Moderate / heavy rain - day "rainshowers_day": "\uf009",
"10n": "", # Moderate / heavy rain - night "rainshowers_night": "\uf037",
"11d": "", # Thunderstorm - day "rainshowersandthunder_day": "\uf010",
"11n": "", # Thunderstorm - night "rainshowersandthunder_night": "\uf03b",
"13d": "", # Snow - day "sleet": "\uf0b5",
"13n": "❄", # Snow - night "sleetandthunder": "\uf01d",
"50d": "", # Fog - day "sleetshowers_day": "\uf0b2",
"50n": "🌫", # Fog - night "sleetshowers_night": "\uf0b3",
}.get(icon, "") "sleetshowersandthunder_day": "\uf068",
"sleetshowersandthunder_night": "\uf069",
"snow": "\uf01b",
"snowandthunder": "\uf06b",
"snowshowers_day": "\uf009",
"snowshowers_night": "\uf038",
"snowshowersandthunder_day": "\uf06b",
"snowshowersandthunder_night": "\uf06c",
}.get(symbol_code, "?")
logger.debug("symbol %s translated to %s (\\u%04x)", symbol_code, icon, ord(icon))
output = ["%{Tx}", icon, "%{T-}"] output = ["%{Tx}", icon, "%{T-}"]
if show_temperature:
output += [" ", str(int(round(temperature))), "°C"]
return "".join(output) return "".join(output)
@ -106,12 +112,7 @@ if __name__ == "__main__":
help="enable debugging", help="enable debugging",
) )
parser.add_argument( parser.add_argument(
"--owm-api-key", "--font-index", default=4, type=int, help="Polybar font 1-index"
default=os.environ.get("OWM_API_KEY"),
help="OpenWeatherMap API key",
)
parser.add_argument(
"--font-index", default=3, type=int, help="Font Awesome 1-index"
) )
parser.add_argument( parser.add_argument(
"--output", "--output",
@ -156,25 +157,21 @@ if __name__ == "__main__":
sys.exit(1) sys.exit(1)
# Grab current weather and daily forecast # Grab current weather and daily forecast
weather = get_weather(options.owm_api_key, *location) weather = get_weather(*location)
daily_weather_ts = time.strftime( weather = weather["properties"]["timeseries"][0]["data"]
"%Y-%m-%d %H:%M %Z", time.gmtime(weather["daily"][0]["dt"])
)
description = weather["current"]["weather"][0]["description"]
logger.info(f"current weather at {city}: {description}")
logger.info(f"daily forecast: {daily_weather_ts}")
# Format output # Format output
conditions = [format_weather(weather["current"])] conditions = [
conditions += [ format_icon(weather["next_1_hours"]["summary"]["symbol_code"]),
format_weather(weather["daily"][0], False), "{}°C".format(round(weather["instant"]["details"]["air_temperature"])),
format_icon(weather["next_6_hours"]["summary"]["symbol_code"]),
"{}—{}°C".format( "{}—{}°C".format(
round(weather["daily"][0]["temp"]["min"]), round(weather["next_6_hours"]["details"]["air_temperature_min"]),
round(weather["daily"][0]["temp"]["max"]), round(weather["next_6_hours"]["details"]["air_temperature_max"]),
), ),
] ]
city = city.replace("%", "%%") city = city.replace("%", "%%")
conditions.insert(0, f"%{{F#888}}%{{Tx}}%{{T-}} {city}%{{F-}}") conditions.insert(0, f"%{{F#888}}{city}%{{F-}}")
output = " ".join(conditions).replace("%{Tx}", "%%{T%d}" % options.font_index) output = " ".join(conditions).replace("%{Tx}", "%%{T%d}" % options.font_index)
logger.debug("output: %s", output) logger.debug("output: %s", output)

View file

@ -108,7 +108,7 @@ def on_overlay_draw(widget, cctx, ctx):
# Weather # Weather
# We can have polybar markups in it. We assume %{Tx} means to use # We can have polybar markups in it. We assume %{Tx} means to use
# Font Awesome 6 and we ignore font color change. The parsing is # Weather Icons and we ignore font color change. The parsing is
# quite basic. # quite basic.
if ctx.weather: if ctx.weather:
data = re.sub(r"%{F[#\d+-]+?}", "", ctx.weather) data = re.sub(r"%{F[#\d+-]+?}", "", ctx.weather)
@ -120,7 +120,7 @@ def on_overlay_draw(widget, cctx, ctx):
font = ctx.font_family font = ctx.font_family
continue continue
elif chunk.startswith("%{T"): elif chunk.startswith("%{T"):
font = "Font Awesome 6 Pro" font = "Weather Icons"
continue continue
elif not chunk: elif not chunk:
continue continue

View file

@ -29,6 +29,7 @@ foreground = ${colors.foreground}
font-0 = Iosevka Term SS18:style=Regular:size=10;4 font-0 = Iosevka Term SS18:style=Regular:size=10;4
font-1 = Font Awesome 6 Pro:style=Solid:size=10;4 font-1 = Font Awesome 6 Pro:style=Solid:size=10;4
font-2 = Font Awesome 6 Brands:style=Regular:size=10;4 font-2 = Font Awesome 6 Brands:style=Regular:size=10;4
font-3 = Weather Icons:style=Regular:size=10;4
modules-left = i3 modules-left = i3
modules-center = date weather modules-center = date weather