diff --git a/inkycal/modules/inkycal_weather.py b/inkycal/modules/inkycal_weather.py index a14abc3..990f710 100644 --- a/inkycal/modules/inkycal_weather.py +++ b/inkycal/modules/inkycal_weather.py @@ -9,7 +9,7 @@ import math import arrow from inkycal.custom import * -from inkycal.custom import OpenWeatherMap +from inkycal.custom.openweathermap_wrapper import OpenWeatherMap from inkycal.modules.template import inkycal_module logger = logging.getLogger(__name__) @@ -88,54 +88,46 @@ class Weather(inkycal_module): self.round_temperature = config['round_temperature'] self.round_windspeed = config['round_windspeed'] self.forecast_interval = config['forecast_interval'] - self.units = config['units'] self.hour_format = int(config['hour_format']) - self.use_beaufort = config['use_beaufort'] - - # additional configuration - self.owm = OpenWeatherMap(api_key=self.api_key, city_id=self.location, units=config['units']) - self.timezone = get_system_tz() + if config['units'] == "imperial": + self.temp_unit = "fahrenheit" + else: + self.temp_unit = "celsius" + + if config['use_beaufort'] == True: + self.wind_unit = "beaufort" + elif config['units'] == "imperial": + self.wind_unit = "miles_hour" + else: + self.wind_unit = "meters_sec" self.locale = config['language'] + # additional configuration + + self.owm = OpenWeatherMap(api_key=self.api_key, city_id=self.location, wind_unit=self.wind_unit, temp_unit=self.temp_unit,language=self.locale) + self.timezone = get_system_tz() + self.weatherfont = ImageFont.truetype( fonts['weathericons-regular-webfont'], size=self.fontsize) + + if self.wind_unit == "beaufort": + self.windDispUnit = "bft" + elif self.wind_unit == "knots": + self.windDispUnit = "kn" + elif self.wind_unit == "km_hour": + self.windDispUnit = "km/h" + elif self.wind_unit == "miles_hour": + self.windDispUnit = "mph" + else: + self.windDispUnit = "m/s" + if self.temp_unit == "fahrenheit": + self.tempDispUnit = "F" + elif self.temp_unit == "celsius": + self.tempDispUnit = "°" # give an OK message print(f"{__name__} loaded") - @staticmethod - def mps_to_beaufort(meters_per_second: float) -> int: - """Map meters per second to the beaufort scale. - - Args: - meters_per_second: - float representing meters per seconds - - Returns: - an integer of the beaufort scale mapping the input - """ - thresholds = [0.3, 1.6, 3.4, 5.5, 8.0, 10.8, 13.9, 17.2, 20.7, 24.5, 28.4] - return next((i for i, threshold in enumerate(thresholds) if meters_per_second < threshold), 11) - - @staticmethod - def mps_to_mph(meters_per_second: float) -> float: - """Map meters per second to miles per hour, rounded to one decimal place. - - Args: - meters_per_second: - float representing meters per seconds. - - Returns: - float representing the input value in miles per hour. - """ - # 1 m/s is approximately equal to 2.23694 mph - miles_per_hour = meters_per_second * 2.23694 - return round(miles_per_hour, 1) - - @staticmethod - def celsius_to_fahrenheit(celsius: int or float): - """Converts the given temperate from degrees Celsius to Fahrenheit.""" - fahrenheit = (celsius * 9 / 5) + 32 - return fahrenheit + def generate_image(self): """Generate image for this module""" @@ -181,13 +173,13 @@ class Weather(inkycal_module): }[int(index) & 7] def is_negative(temp): - """Check if temp is below freezing point of water (0°C/30°F) + """Check if temp is below freezing point of water (0°C/32°F) returns True if temp below freezing point, else False""" answer = False - if temp_unit == 'celsius' and round(float(temp.split('°')[0])) <= 0: + if self.temp_unit == 'celsius' and round(float(temp.split('°')[0])) <= 0: answer = True - elif temp_unit == 'fahrenheit' and round(float(temp.split('°')[0])) <= 0: + elif self.temp_unit == 'fahrenheit' and round(float(temp.split('°')[0])) <= 32: answer = True return answer @@ -389,20 +381,14 @@ class Weather(inkycal_module): # Create current-weather and weather-forecast objects logging.debug('looking up location by ID') - weather = self.owm.get_current_weather() - forecast = self.owm.get_weather_forecast() + current_weather = self.owm.get_current_weather() + weather_forecasts = self.owm.get_weather_forecast() # Set decimals - dec_temp = None if self.round_temperature == True else 1 - dec_wind = None if self.round_windspeed == True else 1 + dec_temp = 0 if self.round_temperature == True else 1 + dec_wind = 0 if self.round_windspeed == True else 1 - # Set correct temperature units - if self.units == 'metric': - temp_unit = 'celsius' - elif self.units == 'imperial': - temp_unit = 'fahrenheit' - - logging.debug(f'temperature unit: {self.units}') + logging.debug(f'temperature unit: {self.temp_unit}') logging.debug(f'decimals temperature: {dec_temp} | decimals wind: {dec_wind}') # Get current time @@ -426,21 +412,18 @@ class Weather(inkycal_module): for _ in range(0, 12, 3)] # Create forecast objects for given timings - forecasts = [_ for _ in forecast if arrow.get(_["dt"]) in forecast_timings] + hourly_forecasts = [_ for _ in weather_forecasts if arrow.get(_["datetime"]) in forecast_timings] # Add forecast-data to fc_data dictionary fc_data = {} - for forecast in forecasts: - if self.units == "metric": - temp = f"{round(weather['main']['temp'], ndigits=dec_temp)}°C" - else: - temp = f"{round(self.celsius_to_fahrenheit(weather['weather']['main']['temp']), ndigits=dec_temp)}°F" + for index, forecast in enumerate(hourly_forecasts): + temp = f"{forecast['temp']:.{dec_temp}f}{self.tempDispUnit}" - icon = forecast["weather"][0]["icon"] - fc_data['fc' + str(forecasts.index(forecast) + 1)] = { + icon = forecast["icon"] + fc_data['fc' + str(index + 1)] = { 'temp': temp, 'icon': icon, - 'stamp': forecast_timings[forecasts.index(forecast)].to( + 'stamp': forecast_timings[index].to( get_system_tz()).format('H.00' if self.hour_format == 24 else 'h a') } @@ -461,25 +444,25 @@ class Weather(inkycal_module): ))[::3] # Get forecasts for each time-object - forecasts = [_ for _ in forecast if arrow.get(_["dt"]) in time_range] + my_forecasts = [_ for _ in weather_forecasts if arrow.get(_["datetime"]) in time_range] # Get all temperatures for this day - daily_temp = [round(_["main"]["temp"]) for _ in forecasts] + daily_temp = [round(_["temp"]) for _ in my_forecasts] # Calculate min. and max. temp for this day temp_range = f'{min(daily_temp)}°/{max(daily_temp)}°' # Get all weather icon codes for this day - daily_icons = [_["weather"][0]["icon"] for _ in forecasts] + daily_icons = [_["icon"] for _ in my_forecasts] # Find most common element from all weather icon codes status = max(set(daily_icons), key=daily_icons.count) weekday = now.shift(days=days_from_today).format('ddd', locale=self.locale) return {'temp': temp_range, 'icon': status, 'stamp': weekday} - forecasts = [calculate_forecast(days) for days in range(1, 5)] + daily_forecasts = [calculate_forecast(days) for days in range(1, 5)] - for forecast in forecasts: - fc_data['fc' + str(forecasts.index(forecast) + 1)] = { + for index, forecast in enumerate(daily_forecasts): + fc_data['fc' + str(index +1)] = { 'temp': forecast['temp'], 'icon': forecast['icon'], 'stamp': forecast['stamp'] @@ -490,14 +473,14 @@ class Weather(inkycal_module): # Get some current weather details if dec_temp != 0: - temperature = f"{round(weather['main']['temp'])}°" + temperature = f"{round(current_weather['temp'])}°" else: - temperature = f"{round(weather['main']['temp'], ndigits=dec_temp)}°" + temperature = f"{round(current_weather['temp'], ndigits=dec_temp)}°" - weather_icon = weather["weather"][0]["icon"] - humidity = str(weather["main"]["humidity"]) - sunrise_raw = arrow.get(weather["sys"]["sunrise"]).to(self.timezone) - sunset_raw = arrow.get(weather["sys"]["sunset"]).to(self.timezone) + weather_icon = current_weather["weather_icon_name"] + humidity = str(current_weather["humidity"]) + sunrise_raw = arrow.get(current_weather["sunrise"]).to(self.timezone) + sunset_raw = arrow.get(current_weather["sunset"]).to(self.timezone) logger.debug(f'weather_icon: {weather_icon}') @@ -512,16 +495,8 @@ class Weather(inkycal_module): sunset = sunset_raw.format('H:mm') # Format the wind-speed to user preference - if self.use_beaufort: - logger.debug("using beaufort for wind") - wind = str(self.mps_to_beaufort(weather["wind"]["speed"])) - else: - if self.units == 'metric': - logging.debug('getting wind speed in meters per second') - wind = f"{weather['wind']['speed']} m/s" - else: - logging.debug('getting wind speed in imperial unit') - wind = f"{self.mps_to_mph(weather['wind']['speed'])} miles/h" + logging.debug(f'getting wind speed in {self.windDispUnit}') + wind = f"{current_weather['wind']:.{dec_wind}f} {self.windDispUnit}" moon_phase = get_moon_phase()