Update inkycal_weather.py

This commit is contained in:
Ace 2019-11-05 15:45:56 +01:00 committed by GitHub
parent e3a4997fdb
commit 8a53438191
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,8 +3,10 @@
"""
Weather module for Inky-Calendar software. In development...
To-do:
- make locations of icons and text dynamic
The lunar phase calculation algorithm was taken from Michael Bishop
from Github after being granted permission. Thanks, Michael Bishop for your
awesome code!
Copyright by aceisace
"""
from __future__ import print_function
@ -13,6 +15,8 @@ from settings import *
from configuration import *
from PIL import Image, ImageDraw, ImageFont
import arrow
import math, decimal
dec = decimal.Decimal
print('Initialising weather...', end=' ')
owm = pyowm.OWM(api_key, language=language)
@ -29,132 +33,260 @@ weathericons = {
}
"""Split top_section into to 2 rows"""
section_height = top_section_height // 2
section_width = (top_section_width - top_section_height) // 3
"""Add a border to increase readability"""
border_top = int(top_section_height * 0.05)
border_left = int(top_section_width * 0.02)
"""Allocate icon sizes"""
icon_small = section_height
icon_large = top_section_height
"""Calculate size for each weather sub-section"""
row_height = (top_section_height-(border_top*2)) // 3
coloumn_width = (top_section_width-(border_left*2)) // 7
"""Split top section into 4 coloums"""
section1 = 0
section2 = icon_large + (top_section_width - icon_large) // 3 * 0
section3 = icon_large + (top_section_width - icon_large) // 3 * 1
section4 = icon_large + (top_section_width - icon_large) // 3 * 2
"""Calculate paddings"""
x_padding = int( (top_section_width % coloumn_width) / 2 )
y_padding = int( (top_section_height % row_height) / 2 )
"""Allocate positions for icons"""
weather_icon_pos = (section1, 0)
wind_icon_pos = (section2, 0)
sun_icon_pos = (section3, 0)
temperature_icon_pos = (section4, 0)
weather_description_pos = (section2, section_height)
humidity_icon_pos = (section4, section_height)
"""Allocate sizes for weather icons"""
icon_small = row_height
icon_medium = row_height * 2
"""Allocate positions for text"""
next_to = lambda x: (x[0]+ icon_small, x[1])
icon_offset = section_width - icon_small
"""Calculate the x-axis position of each coloumn"""
coloumn1 = x_padding
coloumn2 = coloumn1 + coloumn_width
coloumn3 = coloumn2 + coloumn_width
coloumn4 = coloumn3 + coloumn_width
coloumn5 = coloumn4 + coloumn_width
coloumn6 = coloumn5 + coloumn_width
coloumn7 = coloumn6 + coloumn_width
wind_pos = next_to(wind_icon_pos)
temperature_pos = next_to(temperature_icon_pos)
sun_pos = next_to(sun_icon_pos)
humidity_pos = next_to(humidity_icon_pos)
weather_pos = (section2, section_height)
"""Calculate the y-axis position of each row"""
row1 = y_padding
row2 = row1 + row_height
row3 = row2 + row_height
"""Allocate positions for current weather details"""
text_now_pos = (coloumn1, row1)
weather_icon_now_pos = (coloumn1, row2)
temperature_icon_now_pos = (coloumn2, row1)
temperature_now_pos = (coloumn2+icon_small, row1)
humidity_icon_now_pos = (coloumn2, row2)
humidity_now_pos = (coloumn2+icon_small, row2)
windspeed_icon_now_pos = (coloumn2, row3)
windspeed_now_pos = (coloumn2+icon_small, row3)
moon_phase_now_pos = (coloumn3, row1)
sunrise_icon_now_pos = (coloumn3, row2)
sunrise_time_now_pos = (coloumn3+icon_small, row2)
sunset_icon_now_pos = (coloumn3, row3)
sunset_time_now_pos = (coloumn3+ icon_small, row3)
"""Allocate positions for weather forecast after 3 hours"""
text_3h_pos = (coloumn4, row1)
icon_3h_pos = (coloumn4, row2)
temperature_3h_pos = (coloumn4, row3)
"""Allocate positions for weather forecast after 6 hours"""
text_6h_pos = (coloumn5, row1)
icon_6h_pos = (coloumn5, row2)
temperature_6h_pos = (coloumn5, row3)
"""Allocate positions for weather forecast after 9 hours"""
text_9h_pos = (coloumn6, row1)
icon_9h_pos = (coloumn6, row2)
temperature_9h_pos = (coloumn6, row3)
"""Allocate positions for weather forecast after 12 hours"""
text_12h_pos = (coloumn7, row1)
icon_12h_pos = (coloumn7, row2)
temperature_12h_pos = (coloumn7, row3)
"""Windspeed (m/s) to beaufort (index of list) conversion"""
windspeed_to_beaufort = [0.02, 1.5, 3.3, 5.4, 7.9, 10.7, 13.8, 17.1, 20.7,
24.4, 28.4, 32.6, 100]
"""Function to convert tempertures from kelvin to celcius or fahrenheit"""
def to_units(kelvin):
if units == 'metric':
conversion = str(int(kelvin - 273.15)) + '°C'
else:
conversion = str(int((kelvin - 273.15) * 9/5 + 32)) + 'F'
return conversion
"""Function to convert time objects to specified format 12/24 hours"""
"""Simple means just the hour and if 12 hours, am/pm as well"""
def to_hours(datetime_object, simple = False):
if hours == '24':
if simple == True:
converted_time = datetime_object.format('H')
else:
converted_time = datetime_object.format('HH:mm')
else:
if simple == True:
converted_time = datetime_object.format('H a')
else:
converted_time = datetime_object.format('hh:mm')
return str(converted_time)
#def main():
try:
"""Connect to Openweathermap API and fetch weather data"""
if top_section == "Weather" and api_key != "" and owm.is_API_online() is True:
#try:
print("Fetching weather data from openweathermap API...",end = ' ')
current_weather_setup = owm.weather_at_place(location)
weather = current_weather_setup.get_weather()
"""Connect to Openweathermap API and fetch weather data"""
if top_section == "Weather" and api_key != "" and owm.is_API_online() is True:
try:
print("Fetching weather data from openweathermap...",end = ' ')
observation = owm.weather_at_place(location)
"""Set-up and get weather forecast data"""
forecast = owm.three_hours_forecast(location)
print("Done")
weather = observation.get_weather()
weathericon = weather.get_weather_icon_name()
Humidity = str(weather.get_humidity())
cloudstatus = str(weather.get_clouds())
weather_description = (str(weather.get_detailed_status()))
"""Add the icons at the correct positions"""
print('Adding weather info and icons to the image...', end = ' ')
write_text(icon_small, icon_small, '\uf055', temperature_icon_pos,
font = w_font, adapt_fontsize = True) # Temperature icon
write_text(icon_large, icon_large, weathericons[weathericon],
weather_icon_pos, font = w_font, adapt_fontsize = True) # Weather icon
write_text(icon_small, icon_small, '\uf07a', humidity_icon_pos, font = w_font,
adapt_fontsize = True) #Humidity icon
write_text(icon_small,icon_small, '\uf050', wind_icon_pos, font = w_font,
adapt_fontsize = True) #Wind icon
"""Format and write the temperature and windspeed"""
if units == "metric":
Temperature = str(int(weather.get_temperature(unit='celsius')['temp']))
windspeed = str(int(weather.get_wind()['speed']))
write_text(icon_offset, section_height, Temperature+'°C', temperature_pos)
write_text(icon_offset,section_height, windspeed+" km/h", wind_pos)
else:
Temperature = str(int(weather.get_temperature('fahrenheit')['temp']))
windspeed = str(int(weather.get_wind()['speed']*0.621))
write_text(icon_offset, section_height, Temperature+' F', temperature_pos)
write_text(icon_offset,section_height, windspeed+" mph", wind_pos)
"""write the humidity at the given position"""
write_text(icon_offset, section_height, Humidity+'%', humidity_pos)
"""Round the hour to the nearest multiple of 3"""
now = arrow.now(tz=get_tz())
sunrise = arrow.get(weather.get_sunrise_time()).to(get_tz())
sunset = arrow.get(weather.get_sunset_time()).to(get_tz())
hour_gap = (now.hour % 3)
"""Add the sunrise/sunset icon and display the time"""
if (now <= sunrise and now <= sunset) or (now >= sunrise and now >= sunset):
write_text(icon_small, icon_small, '\uf051', sun_icon_pos, font = w_font,
adapt_fontsize = True)
if hours == "24":
write_text(icon_offset, section_height, sunrise.format('H:mm'), sun_pos)
else:
write_text(icon_offset, section_height, sunrise.format('h:mm'), sun_pos)
else:
write_text(icon_small, '\uf052', sun_icon_pos, font = w_font,
adapt_fontsize = True)
if hours == "24":
write_text(icon_offset, section_height, sunset.format('H:mm'), sun_pos)
else:
write_text(icon_offset, section_height, sunset.format('h:mm'), sun_pos)
"""Prepare timings for forecasts"""
in_3h = now.replace(hours = + hour_gap + 3)
in_6h = now.replace(hours = + hour_gap + 6)
in_9h = now.replace(hours = + hour_gap + 9)
in_12h = now.replace(hours = + hour_gap + 12)
"""Prepare forecast objects for the specified timings"""
forecast_3h = forecast.get_weather_at(in_3h.datetime)
forecast_6h = forecast.get_weather_at(in_6h.datetime)
forecast_9h = forecast.get_weather_at(in_9h.datetime)
forecast_12h = forecast.get_weather_at(in_12h.datetime)
"""Get the current temperature and forcasts temperatures"""
temperature_now = to_units(weather.get_temperature()['temp'])
temperature_3h = to_units(forecast_3h.get_temperature()['temp'])
temperature_6h = to_units(forecast_6h.get_temperature()['temp'])
temperature_9h = to_units(forecast_9h.get_temperature()['temp'])
temperature_12h = to_units(forecast_12h.get_temperature()['temp'])
"""Get current and forecast weather icon names"""
weather_icon_now = weather.get_weather_icon_name()
weather_icon_3h = forecast_3h.get_weather_icon_name()
weather_icon_6h = forecast_6h.get_weather_icon_name()
weather_icon_9h = forecast_9h.get_weather_icon_name()
weather_icon_12h = forecast_12h.get_weather_icon_name()
"""Parse current weather details"""
sunrise_time_now = arrow.get(weather.get_sunrise_time()).to(get_tz())
sunset_time_now = arrow.get(weather.get_sunset_time()).to(get_tz())
humidity_now = str(weather.get_humidity())
cloudstatus_now = str(weather.get_clouds())
weather_description_now = str(weather.get_detailed_status())
windspeed_now = weather.get_wind(unit='meters_sec')['speed']
beaufort = str([windspeed_to_beaufort.index(_) for _ in windspeed_to_beaufort
if windspeed_now < _][0])
"""Add a short weather description"""
write_text(section2+section3-icon_offset, section_height,
weather_description, weather_pos)
"""Calculate the moon phase"""
def get_moon_phase():
diff = now - arrow.get(2001, 1, 1)
days = dec(diff.days) + (dec(diff.seconds) / dec(86400))
lunations = dec("0.20439731") + (days * dec("0.03386319269"))
position = lunations % dec(1)
index = math.floor((position * dec(8)) + dec("0.5"))
return {0: '\uf095',1: '\uf099',2: '\uf09c',3: '\uf0a0',
4: '\uf0a3',5: '\uf0a7',6: '\uf0aa',7: '\uf0ae' }[int(index) & 7]
moonphase = get_moon_phase()
print('Adding weather details on the image...', end = ' ')
"""Add weather details in column 1"""
write_text(coloumn_width, row_height, 'now', text_now_pos)
write_text(icon_medium, icon_medium, weathericons[weather_icon_now],
weather_icon_now_pos, font = w_font, adapt_fontsize = True)
"""Add weather details in column 2"""
write_text(icon_small, icon_small, '\uf053', temperature_icon_now_pos,
font = w_font, adapt_fontsize = True)
write_text(icon_small, icon_small, '\uf07a', humidity_icon_now_pos,
font = w_font, adapt_fontsize = True)
write_text(icon_small, icon_small, '\uf050', windspeed_icon_now_pos,
font = w_font, adapt_fontsize = True)
write_text(coloumn_width-icon_small, row_height,
temperature_now, temperature_now_pos)
write_text(coloumn_width-icon_small, row_height, humidity_now+'%',
humidity_now_pos)
write_text(coloumn_width-icon_small, row_height, beaufort,
windspeed_now_pos)
"""Add weather details in column 3"""
write_text(coloumn_width, row_height, moonphase , moon_phase_now_pos,
font = w_font, adapt_fontsize = True)
write_text(icon_small, icon_small, '\uf051', sunrise_icon_now_pos,
font = w_font, adapt_fontsize = True)
write_text(icon_small, icon_small, '\uf052', sunset_icon_now_pos,
font = w_font, adapt_fontsize = True)
write_text(coloumn_width-icon_small, row_height, to_hours(sunrise_time_now),
sunrise_time_now_pos)
write_text(coloumn_width-icon_small, row_height, to_hours(sunset_time_now),
sunset_time_now_pos)
"""Add weather details in column 4"""
write_text(coloumn_width, row_height, to_hours(in_3h, simple=True),
text_3h_pos)
write_text(coloumn_width, row_height, weathericons[weather_icon_3h],
icon_3h_pos, font = w_font, adapt_fontsize = True)
write_text(coloumn_width, row_height, temperature_3h,
temperature_3h_pos)
"""Add weather details in column 5"""
write_text(coloumn_width, row_height, to_hours(in_6h, simple=True),
text_6h_pos)
write_text(coloumn_width, row_height, weathericons[weather_icon_6h],
icon_6h_pos, font = w_font, adapt_fontsize = True)
write_text(coloumn_width, row_height, temperature_6h,
temperature_6h_pos)
"""Add weather details in column 6"""
write_text(coloumn_width, row_height, to_hours(in_9h, simple=True),
text_9h_pos)
write_text(coloumn_width, row_height, weathericons[weather_icon_9h],
icon_9h_pos, font = w_font, adapt_fontsize = True)
write_text(coloumn_width, row_height, temperature_9h,
temperature_9h_pos)
"""Add weather details in column 7"""
write_text(coloumn_width, row_height, to_hours(in_12h, simple=True),
text_12h_pos)
write_text(coloumn_width, row_height, weathericons[weather_icon_12h],
icon_12h_pos, font = w_font, adapt_fontsize = True)
write_text(coloumn_width, row_height, temperature_12h,
temperature_12h_pos)
"""Add seperators between section4 and section7"""
draw = ImageDraw.Draw(image)
line_start_y = int(top_section_height*0.1)
line_end_y = int(top_section_height*0.9)
draw.line((coloumn4, line_start_y, coloumn4, line_end_y), fill='black')
draw.line((coloumn5, line_start_y, coloumn5, line_end_y), fill='black')
draw.line((coloumn6, line_start_y, coloumn6, line_end_y), fill='black')
draw.line((coloumn7, line_start_y, coloumn7, line_end_y), fill='black')
draw.line((0, top_section_height-border_top, top_section_width-border_left,
top_section_height-border_top), fill='red', width=3)
print('Done'+'\n')
"""Show the fetched weather data"""
print("Today's weather report: The current Temperature is {0}°C. The "
"relative humidity is {1} %. The current windspeed is {2} km/h. "
"The sunrise today was at {3}. The sunset is at {4}. The weather can "
"be described with: {5}".format(Temperature, Humidity, windspeed,
sunrise.format('H:mm'), sunset.format('H:mm'), weather_description))
image.crop((0,0, top_section_width, top_section_height)).save('weather.png')
except Exception as e:
"""If no response was received from the openweathermap
api server, add the cloud with question mark"""
print('__________OWM-ERROR!__________')
print('Reason: ',e)
write_text(icon_large, icon_large, '\uf07b', weather_icon_pos,
font = w_font, adapt_fontsize = True)
pass
except Exception as e:
"""If no response was received from the openweathermap
api server, add the cloud with question mark"""
print('__________OWM-ERROR!__________')
print('Reason: ',e)
write_text(icon_medium, icon_medium, '\uf07b', weather_icon_now_pos,
font = w_font, adapt_fontsize = True)
message = 'No internet connectivity or API timeout'
write_text(coloumn_width*6, row_height, message, humidity_icon_now_pos)
pass
#if __name__ == '__main__':