From 020e87981006d66910a5acb116e6fae5f560be09 Mon Sep 17 00:00:00 2001 From: Paco Hope Date: Thu, 30 Nov 2023 22:05:29 -0500 Subject: [PATCH] moved variables to global config --- CONFIG.py | 21 ++++++ WIFI_CONFIG.py | 8 ++ inky-lovelace.py | 187 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 CONFIG.py create mode 100644 WIFI_CONFIG.py create mode 100644 inky-lovelace.py diff --git a/CONFIG.py b/CONFIG.py new file mode 100644 index 0000000..de4c2de --- /dev/null +++ b/CONFIG.py @@ -0,0 +1,21 @@ +# this is just python syntax. +# Edit this file and enter the network name for your Wifi in SSID +# Enter the password for your Wifi network in the PSK +# Set the COUNTRY to the country code of your local country (yes, this matters!) + +SSID = "Example_Network" +PSK = "Example_Password" +COUNTRY = "US" # Change to your local two-letter ISO 3166-1 country code + +# URL that has the image +IMG_URL = "http://home.example.com:8123/local/image.png" + +# Length of time between updates in minutes. +# Frequent updates will reduce battery life! +UPDATE_INTERVAL = 60 + +# Filename on the SD card for the image. Probably doesn't need changing. +FILENAME = "/sd/frame.png" + +# tz_offset is hours from GMT. E.g., US PST is -7 (UTC-07:00) and CEST (Paris) is 1 (UTC+01:00) +TZ_OFFSET = -5 \ No newline at end of file diff --git a/WIFI_CONFIG.py b/WIFI_CONFIG.py new file mode 100644 index 0000000..d02987a --- /dev/null +++ b/WIFI_CONFIG.py @@ -0,0 +1,8 @@ +# this is just python syntax. +# Edit this file and enter the network name for your Wifi in SSID +# Enter the password for your Wifi network in the PSK +# Set the COUNTRY to the country code of your local country (yes, this matters!) + +SSID = "Example_Network" +PSK = "Example_Password" +COUNTRY = "US" # Change to your local two-letter ISO 3166-1 country code diff --git a/inky-lovelace.py b/inky-lovelace.py new file mode 100644 index 0000000..6522c5c --- /dev/null +++ b/inky-lovelace.py @@ -0,0 +1,187 @@ +# inky-lovelace.py: Fetch a lovelace dashboard and display it on an inky-frame. +# Copyright (C) 2023 Paco Hope +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# See LICENSE.md for details. + +""" +Copy a PNG into the root of the pico from a known URL + +Display it. + +Sleep +""" + +from picographics import PicoGraphics, DISPLAY_INKY_FRAME as DISPLAY # 5.7" +from urllib import urequest +from machine import Pin, SPI +from network_manager import NetworkManager +import time +import inky_frame +import pngdec +import gc +import sdcard +import os +import CONFIG +import inky_frame +import uasyncio +global graphics + +def display_image(j, CONFIG.FILENAME): + # Open the PNG file + j.open_file(CONFIG.FILENAME) + # Decode the PNG + j.decode() + + # write the date/time at the top + year, month, day, hour, minute, second, dow, _ = time.localtime(time.time()) + graphics.set_pen(0) + graphics.set_font('sans') + # display.text(text, x, y, wordwrap, scale, angle, spacing) + graphics.text(f"{hour:02}:{minute:02} {year}-{month}-{day}", 230, 10, scale=0.5) + gc.collect() + +def show_error(text,y): + WIDTH = 600 + HEIGHT = 0 + 20 * y + + graphics.set_pen(4) + graphics.rectangle(0, HEIGHT, WIDTH, 35) + graphics.set_pen(1) + graphics.text(text, 5, 16 + HEIGHT, 400, 2) + gc.collect() + +def fetch(url): + """ Fetch the image, store it onboard. + Returns False at first error. + Returns True only if everything succeeds. + """ + + inky_frame.button_b.led_on() + network_manager = NetworkManager(CONFIG.COUNTRY, status_handler=status_handler, client_timeout=60) + try: + uasyncio.get_event_loop().run_until_complete(network_manager.client(CONFIG.SSID, CONFIG.PSK)) + except RuntimeError: + pass + except Exception as e: + print("join network failed") + print(e) + inky_frame.button_b.led_off() + return False + inky_frame.button_b.led_off() + + year, month, day, hour, minute, second, dow, _ = time.localtime(time.time()) + print(f"{hour:02}:{minute:02} {year}-{month}-{day}") + + if year < 2023: + # blink b when we are setting the time + inky_frame.button_b.led_on() + inky_frame.set_time() # set time from network + inky_frame.button_b.led_off() + + tz_seconds = (CONFIG.TZ_OFFSET * 3600) + year, month, day, hour, minute, second, dow, _ = time.localtime(time.time() + tz_seconds) + + # don't bother updating before 06:00 or after 23:00 + if hour < 5 or hour > 22: + print("no need to fetch") + return False + del year, month, day, hour, minute, second, tz_seconds + print( "fetching " + url ) + inky_frame.button_c.led_on() + + try: + # Grab the image + socket = urequest.urlopen(url) + gc.collect() + except OSError as e: + print("Unable open URL. OSErr: ") + print(e) + except Exception as e: + print("other exception") + print(e) + return False + os.remove(CONFIG.FILENAME) + inky_frame.button_c.led_off() + inky_frame.button_d.led_on() + try: + data = bytearray(1024) + with open(CONFIG.FILENAME, "wb+") as f: + while True: + if socket.readinto(data) == 0: + break + else: + print(".", end="" ) + f.write(data) + socket.close() + del data + except Exception as e: + print("Unable to write file") + print(e) + return False + del socket + inky_frame.button_d.led_off() + gc.collect() + return True + +def status_handler(mode, status, ip): + print(mode, status, ip) + +def mount_sd(): + # set up the SD card + try: + sd_spi = SPI(0, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT), miso=Pin(16, Pin.OUT)) + sd = sdcard.SDCard(sd_spi, Pin(22)) + os.mount(sd, "/sd") + except Exception as e: + print("mounting SD card") + print(e) + + files = os.listdir("/sd") + if len(files) == 0: + show_error("SD didn't mount?", 5) + del files + +while True: + graphics = None + gc.collect() + inky_frame.led_busy.off() + inky_frame.button_a.led_off() + inky_frame.button_b.led_off() + inky_frame.button_c.led_off() + inky_frame.button_d.led_off() + inky_frame.button_e.led_off() + inky_frame.led_busy.on() + + inky_frame.button_a.led_on() + mount_sd() + gc.collect() + inky_frame.button_a.led_off() + if fetch(CONFIG.IMG_URL): + gc.collect() + inky_frame.button_e.led_on() + + # set up the display + graphics = PicoGraphics(DISPLAY) + + # Create a new PNG decoder for our PicoGraphics + j = pngdec.PNG(graphics) + + display_image(j, CONFIG.FILENAME) + # Display the result + graphics.update() + + inky_frame.button_e.led_off() + inky_frame.led_busy.off() + # Go to sleep if on battery power + inky_frame.button_a.led_off() + inky_frame.button_b.led_off() + inky_frame.button_c.led_off() + inky_frame.button_d.led_off() + inky_frame.button_e.led_off() + inky_frame.sleep_for(CONFIG.UPDATE_INTERVAL) +