Add GitHub actions workflow
[EVA-2020-02-2.git] / examples / all-in-one.py
index 413b0999be3c6cdc59e70ffdabb3f875972c8c19..f7933a9e78b9f7603b642e2cad07b0d67e27f945 100755 (executable)
@@ -1,21 +1,32 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import time
 import colorsys
 
 import time
 import colorsys
-import os
 import sys
 import ST7735
 import sys
 import ST7735
-import ltr559
+try:
+    # Transitional fix for breaking change in LTR559
+    from ltr559 import LTR559
+    ltr559 = LTR559()
+except ImportError:
+    import ltr559
 
 from bme280 import BME280
 
 from bme280 import BME280
-from pms5003 import PMS5003
+from pms5003 import PMS5003, ReadTimeoutError as pmsReadTimeoutError
 from enviroplus import gas
 from subprocess import PIPE, Popen
 from PIL import Image
 from PIL import ImageDraw
 from PIL import ImageFont
 from enviroplus import gas
 from subprocess import PIPE, Popen
 from PIL import Image
 from PIL import ImageDraw
 from PIL import ImageFont
+from fonts.ttf import RobotoMedium as UserFont
+import logging
+
+logging.basicConfig(
+    format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
+    level=logging.INFO,
+    datefmt='%Y-%m-%d %H:%M:%S')
 
 
-print("""all-in-one.py - Displays readings from all of Enviro plus' sensors
+logging.info("""all-in-one.py - Displays readings from all of Enviro plus' sensors
 
 Press Ctrl+C to exit!
 
 
 Press Ctrl+C to exit!
 
@@ -46,8 +57,8 @@ HEIGHT = st7735.height
 # Set up canvas and font
 img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
 draw = ImageDraw.Draw(img)
 # Set up canvas and font
 img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
 draw = ImageDraw.Draw(img)
-path = os.path.dirname(os.path.realpath(__file__))
-font = ImageFont.truetype(path + "/fonts/Asap/Asap-Bold.ttf", 20)
+font_size = 20
+font = ImageFont.truetype(UserFont, font_size)
 
 message = ""
 
 
 message = ""
 
@@ -60,23 +71,22 @@ def display_text(variable, data, unit):
     # Maintain length of list
     values[variable] = values[variable][1:] + [data]
     # Scale the values for the variable between 0 and 1
     # Maintain length of list
     values[variable] = values[variable][1:] + [data]
     # Scale the values for the variable between 0 and 1
-    colours = [(v - min(values[variable]) + 1) / (max(values[variable])
-               - min(values[variable]) + 1) for v in values[variable]]
+    vmin = min(values[variable])
+    vmax = max(values[variable])
+    colours = [(v - vmin + 1) / (vmax - vmin + 1) for v in values[variable]]
     # Format the variable name and value
     message = "{}: {:.1f} {}".format(variable[:4], data, unit)
     # Format the variable name and value
     message = "{}: {:.1f} {}".format(variable[:4], data, unit)
-    print(message)
+    logging.info(message)
     draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
     for i in range(len(colours)):
         # Convert the values to colours from red to blue
         colour = (1.0 - colours[i]) * 0.6
     draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
     for i in range(len(colours)):
         # Convert the values to colours from red to blue
         colour = (1.0 - colours[i]) * 0.6
-        r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour,
-                   1.0, 1.0)]
+        r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour, 1.0, 1.0)]
         # Draw a 1-pixel wide rectangle of colour
         # Draw a 1-pixel wide rectangle of colour
-        draw.rectangle((i, top_pos, i+1, HEIGHT), (r, g, b))
+        draw.rectangle((i, top_pos, i + 1, HEIGHT), (r, g, b))
         # Draw a line graph in black
         # Draw a line graph in black
-        line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos)))\
-                 + top_pos
-        draw.rectangle((i, line_y, i+1, line_y+1), (0, 0, 0))
+        line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos))) + top_pos
+        draw.rectangle((i, line_y, i + 1, line_y + 1), (0, 0, 0))
     # Write the text at the top in black
     draw.text((0, 0), message, font=font, fill=(0, 0, 0))
     st7735.display(img)
     # Write the text at the top in black
     draw.text((0, 0), message, font=font, fill=(0, 0, 0))
     st7735.display(img)
@@ -84,19 +94,19 @@ def display_text(variable, data, unit):
 
 # Get the temperature of the CPU for compensation
 def get_cpu_temperature():
 
 # Get the temperature of the CPU for compensation
 def get_cpu_temperature():
-    process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE)
+    process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE, universal_newlines=True)
     output, _error = process.communicate()
     return float(output[output.index('=') + 1:output.rindex("'")])
 
 
 # Tuning factor for compensation. Decrease this number to adjust the
 # temperature down, and increase to adjust up
     output, _error = process.communicate()
     return float(output[output.index('=') + 1:output.rindex("'")])
 
 
 # Tuning factor for compensation. Decrease this number to adjust the
 # temperature down, and increase to adjust up
-factor = 0.8
+factor = 2.25
 
 
-cpu_temps = [0] * 5
+cpu_temps = [get_cpu_temperature()] * 5
 
 delay = 0.5  # Debounce the proximity tap
 
 delay = 0.5  # Debounce the proximity tap
-mode = 0  # The starting mode
+mode = 0     # The starting mode
 last_page = 0
 light = 1
 
 last_page = 0
 light = 1
 
@@ -130,7 +140,7 @@ try:
 
         # One mode for each variable
         if mode == 0:
 
         # One mode for each variable
         if mode == 0:
-            variable = "temperature"
+            variable = "temperature"
             unit = "C"
             cpu_temp = get_cpu_temperature()
             # Smooth out with some averaging to decrease jitter
             unit = "C"
             cpu_temp = get_cpu_temperature()
             # Smooth out with some averaging to decrease jitter
@@ -138,70 +148,82 @@ try:
             avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
             raw_temp = bme280.get_temperature()
             data = raw_temp - ((avg_cpu_temp - raw_temp) / factor)
             avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
             raw_temp = bme280.get_temperature()
             data = raw_temp - ((avg_cpu_temp - raw_temp) / factor)
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 1:
 
         if mode == 1:
-            variable = "pressure"
+            variable = "pressure"
             unit = "hPa"
             data = bme280.get_pressure()
             unit = "hPa"
             data = bme280.get_pressure()
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 2:
 
         if mode == 2:
-            variable = "humidity"
+            variable = "humidity"
             unit = "%"
             data = bme280.get_humidity()
             unit = "%"
             data = bme280.get_humidity()
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 3:
 
         if mode == 3:
-            variable = "light"
+            variable = "light"
             unit = "Lux"
             if proximity < 10:
                 data = ltr559.get_lux()
             else:
                 data = 1
             unit = "Lux"
             if proximity < 10:
                 data = ltr559.get_lux()
             else:
                 data = 1
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 4:
 
         if mode == 4:
-            variable = "oxidised"
+            variable = "oxidised"
             unit = "kO"
             data = gas.read_all()
             data = data.oxidising / 1000
             unit = "kO"
             data = gas.read_all()
             data = data.oxidising / 1000
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 5:
 
         if mode == 5:
-            variable = "reduced"
+            variable = "reduced"
             unit = "kO"
             data = gas.read_all()
             data = data.reducing / 1000
             unit = "kO"
             data = gas.read_all()
             data = data.reducing / 1000
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 6:
 
         if mode == 6:
-            variable = "nh3"
+            variable = "nh3"
             unit = "kO"
             data = gas.read_all()
             data = data.nh3 / 1000
             unit = "kO"
             data = gas.read_all()
             data = data.nh3 / 1000
-            display_text(variable, data, unit)
+            display_text(variables[mode], data, unit)
 
         if mode == 7:
 
         if mode == 7:
-            variable = "pm1"
+            variable = "pm1"
             unit = "ug/m3"
             unit = "ug/m3"
-            data = pms5003.read()
-            data = data.pm_ug_per_m3(1.0)
-            display_text(variable, data, unit)
+            try:
+                data = pms5003.read()
+            except pmsReadTimeoutError:
+                logging.warning("Failed to read PMS5003")
+            else:
+                data = float(data.pm_ug_per_m3(1.0))
+                display_text(variables[mode], data, unit)
 
         if mode == 8:
 
         if mode == 8:
-            variable = "pm25"
+            variable = "pm25"
             unit = "ug/m3"
             unit = "ug/m3"
-            data = pms5003.read()
-            data = data.pm_ug_per_m3(2.5)
-            display_text(variable, data, unit)
+            try:
+                data = pms5003.read()
+            except pmsReadTimeoutError:
+                logging.warning("Failed to read PMS5003")
+            else:
+                data = float(data.pm_ug_per_m3(2.5))
+                display_text(variables[mode], data, unit)
 
         if mode == 9:
 
         if mode == 9:
-            variable = "pm10"
-            unit = "g/m3"
-            data = pms5003.read()
-            data = data.pm_ug_per_m3(10)
-            display_text(variable, data, unit)
+            # variable = "pm10"
+            unit = "ug/m3"
+            try:
+                data = pms5003.read()
+            except pmsReadTimeoutError:
+                logging.warning("Failed to read PMS5003")
+            else:
+                data = float(data.pm_ug_per_m3(10))
+                display_text(variables[mode], data, unit)
 
 # Exit cleanly
 except KeyboardInterrupt:
 
 # Exit cleanly
 except KeyboardInterrupt: