127 lines
5.4 KiB
Python
Executable File
127 lines
5.4 KiB
Python
Executable File
#!/usr/bin/python3
|
|
''' Weather acquirer for: https://github.com/miklhh/i3blocks-config '''
|
|
import os
|
|
import datetime
|
|
import xml.etree.ElementTree as ET
|
|
import requests
|
|
|
|
# Forecast URL.
|
|
#YR_URL = "https://www.yr.no/place/Sverige/%C3%96sterg%C3%B6tland/Link%C3%B6ping/forecast.xml"
|
|
#YR_URL = "https://www.yr.no/place/Spain/Valencia/Valencia/forecast.xml"
|
|
YR_URL = "https://www.yr.no/place/Spain/Valencia/X%C3%A0tiva/forecast.xml"
|
|
|
|
# Good to have data + funky emojicons.
|
|
FORECAST_CACHE_FILE = os.path.dirname(os.path.realpath(__file__)) + "/forecast.xml"
|
|
|
|
# Emojis associatted with weather # Day # Night
|
|
WEATHER_TYPES = { "Fair" : ["☀️", "🌙"], #pylint: disable=C0326
|
|
"Partly cloudy" : ["⛅", "☁️"], #pylint: disable=C0326
|
|
"Clear sky" : ["☀️", "🌙"], #pylint: disable=C0326
|
|
"Cloudy" : ["☁️", "☁️"], #pylint: disable=C0326
|
|
"Light rain" : ["🌧️", "🌧️"], #pylint: disable=C0326
|
|
"Rain" : ["🌧️", "🌧️"], #pylint: disable=C0326
|
|
"Heavy Rain" : ["🌧️", "🌧️"], #pylint: disable=C0326
|
|
"Light snow" : ["🌨️", "🌨️"], #pylint: disable=C0326
|
|
"Snow" : ["🌨️", "🌨️"], #pylint: disable=C0326
|
|
"Heavy snow" : ["🌨️", "🌨️"], #pylint: disable=C0326
|
|
"Foggy" : ["🌫️", "🌫️"], #pylint: disable=C0326
|
|
"Fog" : ["🌫️", "🌫️"], #pylint: disable=C0326
|
|
"Light snow showers" : ["🌨️", "🌨️"]} #pylint: disable=C0326
|
|
|
|
|
|
def get_xml_root():
|
|
""" Returns a weather XML root, cached from old data if necessary. """
|
|
yr_response = 0
|
|
try:
|
|
# Request data from YR.
|
|
yr_response = requests.get(YR_URL)
|
|
if yr_response.status_code != 200:
|
|
raise RuntimeError('Error: YR status code ' + str(yr_response.status_code))
|
|
|
|
# New response, store in cache file and return XML root.
|
|
with open(FORECAST_CACHE_FILE, "w") as file_handle:
|
|
file_handle.write(yr_response.text)
|
|
return ET.fromstring(yr_response.text)
|
|
|
|
except requests.ConnectionError:
|
|
# Probably just no internet. Use cached forecast.
|
|
if os.path.isfile(FORECAST_CACHE_FILE):
|
|
with open(FORECAST_CACHE_FILE) as file_handle:
|
|
yr_response = file_handle.read()
|
|
# Print recycle emoji and continue using cached forecast.
|
|
print("(♻️)", end=" ")
|
|
return ET.fromstring(yr_response)
|
|
|
|
# Dead end, no XML-root acquired.
|
|
raise RuntimeError('No forecast data available.')
|
|
|
|
|
|
def main():
|
|
""" Entry point for program. """
|
|
# Get the XML root.
|
|
try:
|
|
xml_root = get_xml_root()
|
|
except RuntimeError as exception:
|
|
print(exception)
|
|
|
|
# Parse the sun rise and set time. Appearntly, they are not always available and
|
|
# so we need to make sure they exist in the recieved data.
|
|
rise_fall_available = True
|
|
sun_rise_time = sun_set_time = ""
|
|
try:
|
|
sun_rise_time = xml_root.find("sun").attrib.get("rise")
|
|
sun_rise_time = sun_rise_time[sun_rise_time.find('T')+1 : len(sun_rise_time)-3]
|
|
sun_set_time = xml_root.find("sun").attrib.get("set")
|
|
sun_set_time = sun_set_time[sun_set_time.find('T')+1 : len(sun_set_time)-3]
|
|
except (ET.ParseError, AttributeError):
|
|
rise_fall_available = False
|
|
|
|
# Get the current weather information.
|
|
forecast = xml_root.find("forecast").find("tabular").find("time")
|
|
weather = forecast.find("symbol").attrib.get("name")
|
|
temperature = forecast.find("temperature").attrib.get("value")
|
|
wind_direction = forecast.find("windDirection").attrib.get("code")
|
|
wind_speed = forecast.find("windSpeed").attrib.get("mps")
|
|
precipitation = forecast.find("precipitation").attrib.get("value")
|
|
|
|
# Night time?
|
|
is_night = 0
|
|
now = datetime.datetime.now()
|
|
if rise_fall_available:
|
|
# Use sun rise and fall time to determine.
|
|
sun_rise = datetime.datetime.strptime(sun_rise_time, "%H:%M")
|
|
sun_set = datetime.datetime.strptime(sun_set_time, "%H:%M")
|
|
is_night = 1 if now.time() < sun_rise.time() or sun_set.time() < now.time() else 0
|
|
else:
|
|
# No rise/fall time available. Approximate daytime as [07:00 - 21:00].
|
|
sun_rise = datetime.datetime.strptime("07:00", "%H:%M")
|
|
sun_set = datetime.datetime.strptime("21:00", "%H:%M")
|
|
is_night = 1 if now.time() < sun_rise.time() or sun_set.time() < now.time() else 0
|
|
|
|
# Print the weather.
|
|
if weather in WEATHER_TYPES:
|
|
# Emoji is avaiable for usage.
|
|
print(weather + ": " + WEATHER_TYPES.get(weather)[is_night] + " ", end="")
|
|
else:
|
|
# No emoji available, use regular text.
|
|
print(weather + " ", end="")
|
|
|
|
# Print the temperature and sun times.
|
|
print(temperature, end="°C ")
|
|
|
|
# Print the sun rise and set time.
|
|
if rise_fall_available:
|
|
#print("[" + sun_rise_time + " 🌅 " + sun_set_time + "]", end=" ")
|
|
print("[""WE""]", end=" ")
|
|
|
|
# Print the precipitation (if there is any).
|
|
if precipitation != "0":
|
|
# Print with a wet umbrella
|
|
print("| ☔ " + precipitation + "mm", end=" ")
|
|
|
|
# Print wind data.
|
|
print("| 🍃 " + wind_speed + "m/s " + "(" + wind_direction + ")", end="")
|
|
|
|
# Go gadget, go!
|
|
main()
|