Update python versions for CI (#96)
[EVA-2020-02-2.git] / examples / weather-and-light.py
index fde1d9610ee31c031e1c294ec1043859bc797b53..cd8ae962c1e40f6571c4e7a7995eb9850a162d18 100755 (executable)
@@ -1,4 +1,7 @@
 #!/usr/bin/env python3
 #!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+f"Sorry! This program requires Python >= 3.6 ðŸ˜…"
 
 import os
 import time
 
 import os
 import time
@@ -12,6 +15,7 @@ from bme280 import BME280
 from ltr559 import LTR559
 
 import pytz
 from ltr559 import LTR559
 
 import pytz
+from pytz import timezone
 from astral.geocoder import database, lookup
 from astral.sun import sun
 from datetime import datetime, timedelta
 from astral.geocoder import database, lookup
 from astral.sun import sun
 from datetime import datetime, timedelta
@@ -79,19 +83,21 @@ def x_from_sun_moon_time(progress, period, x_range):
     return x
 
 
     return x
 
 
-def sun_moon_time(dt, city_name, time_zone):
+def sun_moon_time(city_name, time_zone):
     """Calculate the progress through the current sun/moon period (i.e day or
        night) from the last sunrise or sunset, given a datetime object 't'."""
 
     city = lookup(city_name, database())
 
     # Datetime objects for yesterday, today, tomorrow
     """Calculate the progress through the current sun/moon period (i.e day or
        night) from the last sunrise or sunset, given a datetime object 't'."""
 
     city = lookup(city_name, database())
 
     # Datetime objects for yesterday, today, tomorrow
-    today = dt.date()
-    dt = pytz.timezone(time_zone).localize(dt)
+    utc = pytz.utc
+    utc_dt = datetime.now(tz=utc)
+    local_dt = utc_dt.astimezone(pytz.timezone(time_zone))
+    today = local_dt.date()
     yesterday = today - timedelta(1)
     tomorrow = today + timedelta(1)
 
     yesterday = today - timedelta(1)
     tomorrow = today + timedelta(1)
 
-    # Sun objects for yesterfay, today, tomorrow
+    # Sun objects for yesterday, today, tomorrow
     sun_yesterday = sun(city.observer, date=yesterday)
     sun_today = sun(city.observer, date=today)
     sun_tomorrow = sun(city.observer, date=tomorrow)
     sun_yesterday = sun(city.observer, date=yesterday)
     sun_today = sun(city.observer, date=today)
     sun_tomorrow = sun(city.observer, date=tomorrow)
@@ -103,29 +109,29 @@ def sun_moon_time(dt, city_name, time_zone):
     sunrise_tomorrow = sun_tomorrow["sunrise"]
 
     # Work out lengths of day or night period and progress through period
     sunrise_tomorrow = sun_tomorrow["sunrise"]
 
     # Work out lengths of day or night period and progress through period
-    if sunrise_today < dt < sunset_today:
+    if sunrise_today < local_dt < sunset_today:
         day = True
         period = sunset_today - sunrise_today
         day = True
         period = sunset_today - sunrise_today
-        mid = sunrise_today + (period / 2)
-        progress = dt - sunrise_today
+        mid = sunrise_today + (period / 2)
+        progress = local_dt - sunrise_today
 
 
-    elif dt > sunset_today:
+    elif local_dt > sunset_today:
         day = False
         period = sunrise_tomorrow - sunset_today
         day = False
         period = sunrise_tomorrow - sunset_today
-        mid = sunset_today + (period / 2)
-        progress = dt - sunset_today
+        mid = sunset_today + (period / 2)
+        progress = local_dt - sunset_today
 
     else:
         day = False
         period = sunrise_today - sunset_yesterday
 
     else:
         day = False
         period = sunrise_today - sunset_yesterday
-        mid = sunset_yesterday + (period / 2)
-        progress = dt - sunset_yesterday
+        mid = sunset_yesterday + (period / 2)
+        progress = local_dt - sunset_yesterday
 
     # Convert time deltas to seconds
     progress = progress.total_seconds()
     period = period.total_seconds()
 
 
     # Convert time deltas to seconds
     progress = progress.total_seconds()
     period = period.total_seconds()
 
-    return (progress, period, day)
+    return (progress, period, day, local_dt)
 
 
 def draw_background(progress, period, day):
 
 
 def draw_background(progress, period, day):
@@ -139,7 +145,7 @@ def draw_background(progress, period, day):
     if day:
         x = WIDTH - x
 
     if day:
         x = WIDTH - x
 
-    # Calculate position on sun/moon's curve
+    # Calculate position on sun/moon's curve
     centre = WIDTH / 2
     y = calculate_y_pos(x, centre)
 
     centre = WIDTH / 2
     y = calculate_y_pos(x, centre)
 
@@ -148,7 +154,7 @@ def draw_background(progress, period, day):
 
     # New image for background colour
     img = Image.new('RGBA', (WIDTH, HEIGHT), color=background)
 
     # New image for background colour
     img = Image.new('RGBA', (WIDTH, HEIGHT), color=background)
-    draw = ImageDraw.Draw(img)
+    draw = ImageDraw.Draw(img)
 
     # New image for sun/moon overlay
     overlay = Image.new('RGBA', (WIDTH, HEIGHT), color=(0, 0, 0, 0))
 
     # New image for sun/moon overlay
     overlay = Image.new('RGBA', (WIDTH, HEIGHT), color=(0, 0, 0, 0))
@@ -213,12 +219,12 @@ def analyse_pressure(pressure, t):
         slope = line[0][0]
         intercept = line[0][1]
         variance = numpy.var(pressure_vals)
         slope = line[0][0]
         intercept = line[0][1]
         variance = numpy.var(pressure_vals)
-        residuals = numpy.var([(slope * x + intercept - y)  for x, y in zip(time_vals, pressure_vals)])
+        residuals = numpy.var([(slope * x + intercept - y) for x, y in zip(time_vals, pressure_vals)])
         r_squared = 1 - residuals / variance
 
         # Calculate change in pressure per hour
         change_per_hour = slope * 60 * 60
         r_squared = 1 - residuals / variance
 
         # Calculate change in pressure per hour
         change_per_hour = slope * 60 * 60
-        variance_per_hour = variance * 60 * 60
+        variance_per_hour = variance * 60 * 60
 
         mean_pressure = numpy.mean(pressure_vals)
 
 
         mean_pressure = numpy.mean(pressure_vals)
 
@@ -241,10 +247,10 @@ def analyse_pressure(pressure, t):
         change_per_hour = 0
         trend = "-"
 
         change_per_hour = 0
         trend = "-"
 
-#    time.sleep(interval)
-
+    # time.sleep(interval)
     return (mean_pressure, change_per_hour, trend)
 
     return (mean_pressure, change_per_hour, trend)
 
+
 def describe_pressure(pressure):
     """Convert pressure into barometer-type description."""
     if pressure < 970:
 def describe_pressure(pressure):
     """Convert pressure into barometer-type description."""
     if pressure < 970:
@@ -319,7 +325,6 @@ font_lg = ImageFont.truetype(UserFont, 14)
 # Margins
 margin = 3
 
 # Margins
 margin = 3
 
-dt = datetime.now()
 
 # Set up BME280 weather sensor
 bus = SMBus(1)
 
 # Set up BME280 weather sensor
 bus = SMBus(1)
@@ -346,14 +351,13 @@ start_time = time.time()
 
 while True:
     path = os.path.dirname(os.path.realpath(__file__))
 
 while True:
     path = os.path.dirname(os.path.realpath(__file__))
-    dt = datetime.now()
-    progress, period, day = sun_moon_time(dt, city_name, time_zone)
+    progress, period, day, local_dt = sun_moon_time(city_name, time_zone)
     background = draw_background(progress, period, day)
 
     # Time.
     time_elapsed = time.time() - start_time
     background = draw_background(progress, period, day)
 
     # Time.
     time_elapsed = time.time() - start_time
-    date_string = dt.strftime("%d %b %y").lstrip('0')
-    time_string = dt.strftime("%H:%M")
+    date_string = local_dt.strftime("%d %b %y").lstrip('0')
+    time_string = local_dt.strftime("%H:%M")
     img = overlay_text(background, (0 + margin, 0 + margin), time_string, font_lg)
     img = overlay_text(img, (WIDTH - margin, 0 + margin), date_string, font_lg, align_right=True)
 
     img = overlay_text(background, (0 + margin, 0 + margin), time_string, font_lg)
     img = overlay_text(img, (WIDTH - margin, 0 + margin), date_string, font_lg, align_right=True)
 
@@ -384,7 +388,7 @@ while True:
     else:
         range_string = "------"
     img = overlay_text(img, (68, 18 + spacing), range_string, font_sm, align_right=True, rectangle=True)
     else:
         range_string = "------"
     img = overlay_text(img, (68, 18 + spacing), range_string, font_sm, align_right=True, rectangle=True)
-    temp_icon = Image.open(path + "/icons/temperature.png")
+    temp_icon = Image.open(f"{path}/icons/temperature.png")
     img.paste(temp_icon, (margin, 18), mask=temp_icon)
 
     # Humidity
     img.paste(temp_icon, (margin, 18), mask=temp_icon)
 
     # Humidity
@@ -395,7 +399,7 @@ while True:
     spacing = font_lg.getsize(humidity_string)[1] + 1
     humidity_desc = describe_humidity(corr_humidity).upper()
     img = overlay_text(img, (68, 48 + spacing), humidity_desc, font_sm, align_right=True, rectangle=True)
     spacing = font_lg.getsize(humidity_string)[1] + 1
     humidity_desc = describe_humidity(corr_humidity).upper()
     img = overlay_text(img, (68, 48 + spacing), humidity_desc, font_sm, align_right=True, rectangle=True)
-    humidity_icon = Image.open(path + "/icons/humidity-" + humidity_desc.lower() + ".png")
+    humidity_icon = Image.open(f"{path}/icons/humidity-{humidity_desc.lower()}.png")
     img.paste(humidity_icon, (margin, 48), mask=humidity_icon)
 
     # Light
     img.paste(humidity_icon, (margin, 48), mask=humidity_icon)
 
     # Light
@@ -405,7 +409,7 @@ while True:
     spacing = font_lg.getsize(light_string.replace(",", ""))[1] + 1
     light_desc = describe_light(light).upper()
     img = overlay_text(img, (WIDTH - margin - 1, 18 + spacing), light_desc, font_sm, align_right=True, rectangle=True)
     spacing = font_lg.getsize(light_string.replace(",", ""))[1] + 1
     light_desc = describe_light(light).upper()
     img = overlay_text(img, (WIDTH - margin - 1, 18 + spacing), light_desc, font_sm, align_right=True, rectangle=True)
-    light_icon = Image.open(path + "/icons/bulb-" + light_desc.lower() +  ".png")
+    light_icon = Image.open(f"{path}/icons/bulb-{light_desc.lower()}.png")
     img.paste(humidity_icon, (80, 18), mask=light_icon)
 
     # Pressure
     img.paste(humidity_icon, (80, 18), mask=light_icon)
 
     # Pressure
@@ -417,7 +421,7 @@ while True:
     pressure_desc = describe_pressure(mean_pressure).upper()
     spacing = font_lg.getsize(pressure_string.replace(",", ""))[1] + 1
     img = overlay_text(img, (WIDTH - margin - 1, 48 + spacing), pressure_desc, font_sm, align_right=True, rectangle=True)
     pressure_desc = describe_pressure(mean_pressure).upper()
     spacing = font_lg.getsize(pressure_string.replace(",", ""))[1] + 1
     img = overlay_text(img, (WIDTH - margin - 1, 48 + spacing), pressure_desc, font_sm, align_right=True, rectangle=True)
-    pressure_icon = Image.open(path + "/icons/weather-" + pressure_desc.lower() +  ".png")
+    pressure_icon = Image.open(f"{path}/icons/weather-{pressure_desc.lower()}.png")
     img.paste(pressure_icon, (80, 48), mask=pressure_icon)
 
     # Display image
     img.paste(pressure_icon, (80, 48), mask=pressure_icon)
 
     # Display image