From 67371322311ef1befc1c45cdeb4cd99a059c2f11 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Sun, 1 Nov 2020 13:56:28 +0100 Subject: [PATCH] Fixed #28 - weather icons: don't show sun at nighttime --- src/logic/Helpers.py | 21 ++++++++-- src/logic/tile/tiles/CurrentWeatherTile.html | 8 +++- src/logic/tile/tiles/CurrentWeatherTile.py | 15 +++++-- src/logic/tile/tiles/HourlyForecastTile.html | 8 +++- src/logic/tile/tiles/HourlyForecastTile.py | 14 ++++--- src/logic/tile/tiles/SevenDaysForecastTile.py | 2 +- test/__init__.py | 0 test/logic/HelpersTest.py | 39 +++++++++++++++++++ test/logic/__init__.py | 0 9 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/logic/HelpersTest.py create mode 100644 test/logic/__init__.py diff --git a/src/logic/Helpers.py b/src/logic/Helpers.py index a497f4b..2eee764 100644 --- a/src/logic/Helpers.py +++ b/src/logic/Helpers.py @@ -1,3 +1,5 @@ +from datetime import datetime + from logic import Constants @@ -29,7 +31,7 @@ def determine_color_for_wind(windSpeed: float) -> str: return Constants.RED.to_rgba() -def determine_color_for_weather_icon(iconId: int): +def determine_color_for_weather_icon(iconId: int, isDayTime: bool): if 200 <= iconId < 300: # thunderstorm return Constants.RED.to_rgba() elif 300 <= iconId < 400: # drizzle @@ -40,7 +42,20 @@ def determine_color_for_weather_icon(iconId: int): return Constants.WHITE.to_rgba() elif 700 <= iconId < 800: # fog return Constants.WHITE.to_rgba() - elif 800 <= iconId < 802: # clear of partly cloudy (up to 25%) - return Constants.ORANGE.to_rgba() + elif 800 <= iconId < 802: # clear or partly cloudy (up to 25%) + if isDayTime: + return Constants.ORANGE.to_rgba() + return Constants.WHITE.to_rgba() elif 802 <= iconId < 805: # clouds > 25% return Constants.WHITE.to_rgba() + + +def is_dayTime(sunrise: int, sunset: int, currentTimestamp: int = None) -> bool: + if not currentTimestamp: + currentTimestamp = int(datetime.now().timestamp()) + return sunrise < currentTimestamp < sunset + + +def timestamp_to_timezone(timestamp: int, timeZone: datetime.tzinfo): + timestamp = datetime.utcfromtimestamp(timestamp) + return timeZone.fromutc(timestamp) diff --git a/src/logic/tile/tiles/CurrentWeatherTile.html b/src/logic/tile/tiles/CurrentWeatherTile.html index 8363486..71adec4 100644 --- a/src/logic/tile/tiles/CurrentWeatherTile.html +++ b/src/logic/tile/tiles/CurrentWeatherTile.html @@ -63,7 +63,13 @@ <div class="currentTemperatureTile"> <div class="content"> - <i class="wi wi-owm-{{ data['icon'] }} icon" style="color: {{ data['iconColor'] }};"></i> + {% if data['isDayTime'] %} + {% set iconPrefix = 'wi-owm-day-' %} + {% else %} + {% set iconPrefix = 'wi-owm-night-' %} + {% endif %} + + <i class="wi {{ iconPrefix }}{{ data['icon'] }} icon" style="color: {{ data['iconColor'] }};"></i> <div class="entries"> <div class="temperatures"> <div class="temperature-entry"> diff --git a/src/logic/tile/tiles/CurrentWeatherTile.py b/src/logic/tile/tiles/CurrentWeatherTile.py index 237fde0..3fd7910 100644 --- a/src/logic/tile/tiles/CurrentWeatherTile.py +++ b/src/logic/tile/tiles/CurrentWeatherTile.py @@ -1,6 +1,8 @@ import os +from datetime import datetime from typing import Dict +import pytz from flask import Blueprint from logic import Helpers @@ -12,7 +14,8 @@ class CurrentWeatherTile(Tile): EXAMPLE_SETTINGS = { "lat": "51.012825", "lon": "13.666365", - "apiKey": "myApiKey" + "apiKey": "myApiKey", + "timeZone": "Europe/Berlin" } def __init__(self, uniqueName: str, settings: Dict, intervalInSeconds: int): @@ -23,6 +26,8 @@ class CurrentWeatherTile(Tile): fetchIntervalInSeconds = 60 * 10 # query api less often + timeZone = pytz.timezone(self._settings['timeZone']) + # cache key will be determined in service weatherData = weatherService.get_data('', fetchIntervalInSeconds, self._settings) currentWeather = weatherData['current'] @@ -30,6 +35,9 @@ class CurrentWeatherTile(Tile): feelsLike = currentWeather['feels_like'] windSpeed = currentWeather['wind_speed'] * 3.6 icon = currentWeather['weather'][0]['id'] + sunrise = Helpers.timestamp_to_timezone(currentWeather['sunrise'], timeZone).timestamp() + sunset = Helpers.timestamp_to_timezone(currentWeather['sunset'], timeZone).timestamp() + isDayTime = Helpers.is_dayTime(sunrise, sunset) return { 'temperature': Helpers.round_to_decimals(currentTemperature, 1), @@ -37,10 +45,11 @@ class CurrentWeatherTile(Tile): 'feelsLike': Helpers.round_to_decimals(feelsLike, 1), 'feelsLikeColor': Helpers.determine_color_for_temperature(feelsLike), 'icon': icon, - 'iconColor': Helpers.determine_color_for_weather_icon(icon), + 'iconColor': Helpers.determine_color_for_weather_icon(icon, isDayTime), 'windDegrees': currentWeather['wind_deg'], 'windSpeed': f'{Helpers.round_to_decimals(windSpeed, 1)} km/h', - 'windSpeedColor': Helpers.determine_color_for_wind(windSpeed) + 'windSpeedColor': Helpers.determine_color_for_wind(windSpeed), + 'isDayTime': isDayTime } def render(self, data: Dict) -> str: diff --git a/src/logic/tile/tiles/HourlyForecastTile.html b/src/logic/tile/tiles/HourlyForecastTile.html index 9fc2159..515bf1e 100644 --- a/src/logic/tile/tiles/HourlyForecastTile.html +++ b/src/logic/tile/tiles/HourlyForecastTile.html @@ -64,9 +64,15 @@ <div class="hourlyForecastTile"> <div class="content"> {% for item in data %} + {% if data['isDayTime'] %} + {% set iconPrefix = 'wi-owm-day-' %} + {% else %} + {% set iconPrefix = 'wi-owm-night-' %} + {% endif %} + <div class="entry"> <div class="hour">{{ item['hour'] }} Uhr</div> - <i class="wi wi-owm-{{ item['icon'] }} icon" style="color: {{ item['iconColor'] }};"></i> + <i class="wi {{ iconPrefix }}{{ item['icon'] }} icon" style="color: {{ item['iconColor'] }};"></i> <div class="temperature" style="color: {{ item['temperatureColor'] }}">{{ item['temperature'] }}°C</div> <div class="rain"> <i class="wi wi-raindrops"></i> diff --git a/src/logic/tile/tiles/HourlyForecastTile.py b/src/logic/tile/tiles/HourlyForecastTile.py index 8747ede..92caa78 100644 --- a/src/logic/tile/tiles/HourlyForecastTile.py +++ b/src/logic/tile/tiles/HourlyForecastTile.py @@ -31,27 +31,31 @@ class HourlyForecastTile(Tile): # cache key will be determined in service weatherData = weatherService.get_data('', fetchIntervalInSeconds, self._settings) + sunrise = Helpers.timestamp_to_timezone(weatherData['current']['sunrise'], timeZone).timestamp() + sunset = Helpers.timestamp_to_timezone(weatherData['current']['sunset'], timeZone).timestamp() + hourData = [] hourlyForecast = weatherData['hourly'] for entry in hourlyForecast[:12]: - timestamp = entry['dt'] - timestamp = datetime.utcfromtimestamp(timestamp) - timestamp = timeZone.fromutc(timestamp) + timestamp = Helpers.timestamp_to_timezone(entry['dt'], timeZone) temperature = entry['temp'] icon = entry['weather'][0]['id'] rainProbability = round(entry['pop'] * 100, -1) # -1 rounds to the next ten windSpeed = entry['wind_speed'] * 3.6 + isDayTime = Helpers.is_dayTime(sunrise, sunset, currentTimestamp=timestamp.timestamp()) + hourData.append({ 'hour': timestamp.strftime('%H'), 'temperature': Helpers.round_to_decimals(temperature, 0), 'temperatureColor': Helpers.determine_color_for_temperature(temperature), 'icon': icon, - 'iconColor': Helpers.determine_color_for_weather_icon(icon), + 'iconColor': Helpers.determine_color_for_weather_icon(icon, isDayTime), 'windSpeed': f'{Helpers.round_to_decimals(windSpeed, 0)} km/h', 'windSpeedColor': Helpers.determine_color_for_wind(windSpeed), - 'rainProbability': f'{Helpers.round_to_decimals(rainProbability, 0)} %' + 'rainProbability': f'{Helpers.round_to_decimals(rainProbability, 0)} %', + 'isDayTime': isDayTime }) return { diff --git a/src/logic/tile/tiles/SevenDaysForecastTile.py b/src/logic/tile/tiles/SevenDaysForecastTile.py index d518eaf..2557683 100644 --- a/src/logic/tile/tiles/SevenDaysForecastTile.py +++ b/src/logic/tile/tiles/SevenDaysForecastTile.py @@ -39,7 +39,7 @@ class SevenDaysForecastTile(Tile): date = datetime.fromtimestamp(date) date = datetime.strftime(date, self.DATE_FORMAT) icon = day['weather'][0]['id'] - iconColor = Helpers.determine_color_for_weather_icon(icon) + iconColor = Helpers.determine_color_for_weather_icon(icon, True) icons.append((icon, iconColor)) forecastData[date] = (int(day['temp']['min']), int(day['temp']['max'])) diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/logic/HelpersTest.py b/test/logic/HelpersTest.py new file mode 100644 index 0000000..7b76e78 --- /dev/null +++ b/test/logic/HelpersTest.py @@ -0,0 +1,39 @@ +import unittest +from datetime import datetime + +from logic import Helpers + + +class HelpersTest(unittest.TestCase): + def test_join_url_parts(self): + self.assertEqual('https://myWebsite/eimer/0815', Helpers.join_url_parts('https://myWebsite', 'eimer', '0815')) + + def test_round_to_decimals_one(self): + self.assertEqual('0.4', Helpers.round_to_decimals(0.428, 1)) + + def test_round_to_decimals_zero(self): + self.assertEqual('0', Helpers.round_to_decimals(0.428, 0)) + + def test_is_dayTime_true(self): + sunrise = datetime(year=2020, month=11, day=1, hour=8, minute=0, second=0).timestamp() + sunset = datetime(year=2020, month=11, day=1, hour=17, minute=0, second=0).timestamp() + + currentTimestamp = datetime(year=2020, month=11, day=1, hour=12, minute=0, second=0).timestamp() + + self.assertTrue(Helpers.is_dayTime(sunrise, sunset, currentTimestamp)) + + def test_is_dayTime_false_before(self): + sunrise = datetime(year=2020, month=11, day=1, hour=8, minute=0, second=0).timestamp() + sunset = datetime(year=2020, month=11, day=1, hour=17, minute=0, second=0).timestamp() + + currentTimestamp = datetime(year=2020, month=11, day=1, hour=4, minute=0, second=0).timestamp() + + self.assertFalse(Helpers.is_dayTime(sunrise, sunset, currentTimestamp)) + + def test_is_dayTime_false_after(self): + sunrise = datetime(year=2020, month=11, day=1, hour=8, minute=0, second=0).timestamp() + sunset = datetime(year=2020, month=11, day=1, hour=17, minute=0, second=0).timestamp() + + currentTimestamp = datetime(year=2020, month=11, day=1, hour=18, minute=0, second=0).timestamp() + + self.assertFalse(Helpers.is_dayTime(sunrise, sunset, currentTimestamp)) diff --git a/test/logic/__init__.py b/test/logic/__init__.py new file mode 100644 index 0000000..e69de29 -- GitLab