175 lines
4.7 KiB
Python
Executable File
175 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import json
|
|
import locale
|
|
import argparse
|
|
import requests
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
from sty import fg
|
|
from meteo.config import Config
|
|
|
|
YR_NO_URL = "https://api.met.no/weatherapi/locationforecast/2.0/"
|
|
|
|
|
|
def load_args():
|
|
"""Charge l'action et les paramêtres communs a toutes les actions."""
|
|
parser = argparse.ArgumentParser(description="Affiche la météo")
|
|
parser.add_argument(
|
|
"-c",
|
|
"--config",
|
|
default=Path.home() / ".config" / "meteo.yaml",
|
|
help="Chemin vers le fichier de configuration",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--location",
|
|
default="home",
|
|
help="",
|
|
)
|
|
return vars(parser.parse_args())
|
|
|
|
|
|
def ask_api(latitude: float, longitude: float, altitude: int) -> dict:
|
|
""" interrege l'API de https://yr.no """
|
|
url = f"{YR_NO_URL}compact.json?lat={latitude}&lon={longitude}&altitude={altitude}"
|
|
headers = {"User-Agent": "DaikoMete/0.1 daiko@daiko.fr"}
|
|
response = requests.get(url, headers=headers)
|
|
|
|
if response.status_code != 200:
|
|
print("Error contacting API.")
|
|
os._exit(1)
|
|
|
|
return json.loads(response.text)
|
|
|
|
|
|
def display_full(data):
|
|
""" Affiche les informations météo complètes """
|
|
locale.setlocale(locale.LC_TIME, "fr_FR.utf8")
|
|
cur_date = datetime.fromisoformat("1970-01-01T00:00:00Z").date()
|
|
|
|
for infos in data["properties"]["timeseries"]:
|
|
new_date = datetime.fromisoformat(infos["time"])
|
|
|
|
if new_date.date() > cur_date:
|
|
print(new_date.strftime("%A, %d. %B %Y"))
|
|
cur_date = new_date.date()
|
|
|
|
time = new_date.strftime("%H:%M")
|
|
|
|
temperature = coloring_temperature(
|
|
infos["data"]["instant"]["details"]["air_temperature"]
|
|
)
|
|
|
|
wind_speed = infos["data"]["instant"]["details"]["wind_speed"]
|
|
|
|
wind_dir = display_wind_direction(
|
|
infos["data"]["instant"]["details"]["wind_from_direction"]
|
|
)
|
|
|
|
icon_str = ''
|
|
if "next_12_hours" in infos["data"]:
|
|
icon_str = infos["data"]["next_12_hours"]["summary"]["symbol_code"]
|
|
if "next_6_hours" in infos["data"]:
|
|
icon_str = infos["data"]["next_6_hours"]["summary"]["symbol_code"]
|
|
if "next_1_hours" in infos["data"]:
|
|
icon_str = infos["data"]["next_1_hours"]["summary"]["symbol_code"]
|
|
icon = display_icon(icon_str)
|
|
|
|
humidity = infos["data"]["instant"]["details"]["relative_humidity"]
|
|
print(f" {time} : {icon} {temperature}° / {humidity}% / {wind_dir} {wind_speed} m/s")
|
|
|
|
|
|
def display_wind_direction(degrees: float) -> str:
|
|
""" Retourne une fleche indicant la direction du vent"""
|
|
if 22.5 <= degrees < 67.5:
|
|
return '↙'
|
|
|
|
if 67.5 <= degrees < 112.5:
|
|
return '←'
|
|
|
|
if 112.5 <= degrees < 157.5:
|
|
return '↖'
|
|
|
|
if 157.5 <= degrees < 202.5:
|
|
return '↑'
|
|
|
|
if 202.5 <= degrees < 247.5:
|
|
return '↗'
|
|
|
|
if 247.5 <= degrees < 292.5:
|
|
return '→'
|
|
|
|
if 292.5 <= degrees < 337.5:
|
|
return '↘'
|
|
|
|
return '↓'
|
|
|
|
|
|
def display_icon(string: str) -> str:
|
|
""" """
|
|
# https://www.nerdfonts.com/cheat-sheet
|
|
t = {
|
|
'clearsky_day': fg.yellow + '' + fg.rs,
|
|
'clearsky_night': '',
|
|
'cloudy': '',
|
|
'fog': '',
|
|
'lightrain': '',
|
|
'heavyrain': '',
|
|
'partlycloudy_night': '',
|
|
'partlycloudy_day': '',
|
|
'rain': '',
|
|
'lightrainshowers_night': '',
|
|
'lightrainshowers_day':'',
|
|
'fair_day': fg.yellow + '' + fg.rs,
|
|
'fair_night': '',
|
|
}
|
|
|
|
if string in t:
|
|
return t[string]
|
|
|
|
return string
|
|
|
|
def coloring_temperature(temperature: float) -> str:
|
|
""" A partir de la température retourne une chaine de caractères colorisée """
|
|
|
|
temp_limit = [40, 30, 25, 20, 10, 0]
|
|
color = [fg.magenta, fg.red, fg(255, 150, 50), fg.yellow, '', fg.cyan]
|
|
|
|
for key, limit in enumerate(temp_limit):
|
|
if temperature >= limit:
|
|
return color[key] + str(temperature) + fg.rs
|
|
|
|
return fg.blue + str(temperature) + fg.rs
|
|
|
|
|
|
def main():
|
|
"""Fonction principale"""
|
|
|
|
args = load_args()
|
|
config_file = Path(args["config"])
|
|
|
|
if not config_file.is_file():
|
|
print(f"{config_file} n'est pas un fichier.")
|
|
os._exit(1)
|
|
|
|
conf = Config(args["config"])
|
|
try:
|
|
location = conf.get_location(args["location"])
|
|
except AttributeError:
|
|
print(f"{args['location']} n'est pas configuré.")
|
|
os._exit(1)
|
|
|
|
api_response = ask_api(
|
|
latitude=location["latitude"],
|
|
longitude=location["longitude"],
|
|
altitude=location["altitude"],
|
|
)
|
|
|
|
display_full(api_response)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|