i3_cockpit/weather_applet/weather.py

124 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python3
""" queries openweathermap to get weather data """
import os
import sys
import configparser
import subprocess
from time import sleep
from datetime import datetime
import requests
iconlist = {
'01d': '',
'02d': '',
'03d': '',
'04d': '',
'09d': '',
'10d': '',
'11d': '',
'13d': '',
'50d': '🌫',
'01n': '',
'02n': '',
'03n': '',
'04n': '',
'09n': '',
'10n': '',
'11n': '',
'13n': '',
'50n': '🌫'
}
def get_config(config_path):
""" read out the .env file and return config values """
# parse
config_parser = configparser.ConfigParser()
config_parser.read(config_path)
# return false on error
if config_parser.options('api') == ['openweathermap_api_key', 'lat', 'lon', 'unit']:
api_key = config_parser.get('api', 'openweathermap_api_key')
lat = config_parser.get('api', 'lat')
lon = config_parser.get('api', 'lon')
unit = config_parser.get('api', 'unit')
else:
print('config parse error')
return False
return api_key, lat, lon, unit
def get_data(api_key, lat, lon, unit):
""" get celsius and icon_id based on lat and lon """
url = "https://api.openweathermap.org/data/2.5/weather?&units=" + unit \
+ "&appid=" + api_key + "&lat=" + lat + "&lon=" + lon
# try up to 3 times
for i in range(1, 4):
try:
response = requests.get(url, timeout=5)
except:
sleep(int(i) * 30)
else:
break
# parse response
json = response.json()
celsius = round(json['main']['temp'])
celsius_pretty = str(celsius) + "°"
icon_id = json['weather'][0]['icon']
icon = iconlist.get(icon_id)
# return
return celsius_pretty, icon
def get_forecast(api_key, lat, lon, unit):
""" get next three days forecast """
# get data
url = "https://api.openweathermap.org/data/2.5/onecall?lat=" + lat + "&lon=" + lon \
+ "&units=" + unit + "&exclude=current,minutely,hourly,alerts&appid=" + api_key
response = requests.get(url, timeout=5)
json = response.json()
notify_list = []
# loop three days
for i in json['daily'][1:4]:
timestamp = i['dt']
date_clean = datetime.fromtimestamp(timestamp).strftime("%a %Y-%m-%d")
min_temp = round(i['temp']['min'])
max_temp = round(i['temp']['max'])
weather = i['weather'][0]['main']
weather_desc = i['weather'][0]['description']
icon_id = i['weather'][0]['icon']
icon = iconlist.get(icon_id)
first_line = f'{date_clean} {icon} {weather}'
second_line = f'{min_temp}° - {max_temp}°, {weather_desc}\n'
notify_list.append(first_line)
notify_list.append(second_line)
# output with notify-send
message = "\n".join(notify_list)
subprocess.call(['notify-send', 'Three days forecast:', message])
def main():
""" main function to run """
# make the call
celsius_pretty, icon = get_data(api_key, lat, lon, unit)
# print three lines for i3blocks
print(icon, celsius_pretty)
print(icon, celsius_pretty)
print()
# start from here
if __name__ == '__main__':
# get config file path relative to script file
config_path = os.path.dirname(sys.argv[0]) + '/config'
api_key, lat, lon, unit = get_config(config_path)
# check for button clicked
env = os.environ.copy()
button = env.get('BLOCK_BUTTON', False)
if button == '1':
get_forecast(api_key, lat, lon, unit)
# regular
main()