state sync: contains

* adafruit screen test script
* mainloop with threads
* a mostly finished screen thread
* a partly finished blocklist update thread
This commit is contained in:
Nicole O'Connor 2024-11-04 19:25:23 -08:00
parent bc0ada494e
commit d4186e0e43
12 changed files with 258 additions and 0 deletions

57
blocklists.py Normal file
View File

@ -0,0 +1,57 @@
import atexit
import logging
import os
import pathlib
import time
import requests
import config
import screen
log = logging.getLogger("blocklists")
running = True
blocklist_data_src = "https://github.com/hagezi/dns-blocklists/archive/refs/heads/main.zip"
blocklist_data_src_path = "dnsmasq"
blocklist_lib_path = "/var/lib/starcontrol"
log.debug("preparing cache directories")
pth_cache_root = pathlib.Path(config.cparse["internal"]["cache_root"])
pth_cache_root.mkdir(exist_ok=True, parents=True)
pth_blocklist_lib = pathlib.Path(blocklist_lib_path)
pth_blocklist_lib.mkdir(exist_ok=True, parents=True)
def blocklist_check():
log.debug("checking blocklist mtimes and updating if needed")
try:
ts_payload = os.path.getmtime(pth_blocklist_lib / "dns-blocklists-main.zip")
ts_now = time.time()
if (ts_now - ts_payload) >= 604800:
update_blocklists()
except OSError:
update_blocklists()
def update_blocklists():
log.info("blocklist update in progress")
screen.download_state = 1
fd_listpayload = open(pth_blocklist_lib / "dns-blocklists-main.zip", "wb")
hnd_download = requests.get(blocklist_data_src, stream=True)
for chunk in hnd_download.iter_content(chunk_size=256):
fd_listpayload.write(chunk)
hnd_download.close()
fd_listpayload.close()
screen.download_state = 0
def blocklist_thread():
while running:
blocklist_check()
time.sleep(3600) # 1 hour
@atexit.register
def stop_blocklist():
global running
running = False

2
config.ini Normal file
View File

@ -0,0 +1,2 @@
[internal]
cache_root=/run/starcontrol

8
config.py Normal file
View File

@ -0,0 +1,8 @@
import configparser
import logging
log = logging.getLogger("main")
log.debug("reading configuration file")
cparse = configparser.ConfigParser()
cparse.read("config.ini")

47
mainloop.py Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
import logging
import os
import math
import pathlib
import time
import threading
from PIL import Image, ImageDraw
import blocklists
import screen
log = logging.getLogger("main")
if __name__ == "__main__":
screen.screen_init()
screen.scr_light.value = True
img_canvas = Image.new("RGB", (135, 240))
hnd_canvas = ImageDraw.Draw(img_canvas)
hnd_canvas.rectangle((0,0,135,240), (0,0,0))
img_canvas.paste(Image.open("res/image/hourglass.png"),(math.floor(135/2) - math.ceil(49/2),math.floor(240/2) - math.ceil(90/2)))
screen.scr.image(img_canvas)
thr_blocklists = threading.Thread(target=blocklists.blocklist_thread)
thr_screen = threading.Thread(target=screen.screen_thread)
thr_blocklists.start()
thr_screen.start()
ok = True
while ok:
try:
thr_blocklists.join(5.0)
thr_screen.join(5.0)
ok = thr_blocklists.is_alive() and thr_screen.is_alive()
except KeyboardInterrupt:
ok = False
print("KEYBOARD INTERRUPT")
except:
ok = False
screen.running = False
blocklists.running = False
thr_screen.join()
thr_blocklists.join()

58
pitft-screen-test.py Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
import digitalio
import board
from adafruit_rgb_display.rgb import color565
from adafruit_rgb_display import st7789
# Configuration for CS and DC pins for Raspberry Pi
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = None
BAUDRATE = 64000000 # The pi can be very fast!
# Create the ST7789 display:
display = st7789.ST7789(
board.SPI(),
cs=cs_pin,
dc=dc_pin,
rst=reset_pin,
baudrate=BAUDRATE,
width=135,
height=240,
x_offset=53,
y_offset=40,
)
backlight = digitalio.DigitalInOut(board.D22)
backlight.switch_to_output()
backlight.value = True
buttonA = digitalio.DigitalInOut(board.D23)
buttonB = digitalio.DigitalInOut(board.D24)
buttonA.switch_to_input()
buttonB.switch_to_input()
buttonAToggle = False
buttonBToggle = False
# Main loop:
while True:
if buttonA.value and buttonB.value:
backlight.value = False # turn off backlight
else:
backlight.value = True # turn on backlight
if buttonB.value and not buttonA.value: # just button A pressed
display.fill(color565(255, 0, 0)) # red
if buttonA.value and not buttonB.value: # just button B pressed
display.fill(color565(0, 0, 255)) # blue
if not buttonA.value and not buttonB.value: # none pressed
display.fill(color565(0, 255, 0)) # green
if buttonA.value != buttonAToggle:
print("buttonA toggle state")
buttonAToggle = buttonA.value
if buttonB.value != buttonBToggle:
print("buttonB toggle state")
buttonBToggle = buttonB.value

BIN
res/image/dns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
res/image/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

BIN
res/image/hourglass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
res/image/okay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
res/image/problem.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
res/image/wifi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

86
screen.py Normal file
View File

@ -0,0 +1,86 @@
import atexit
import math
import time
import board
import digitalio
from adafruit_rgb_display import rgb, st7789
from PIL import Image, ImageDraw, ImageOps
running = True
scr = None
scr_light = None
btn_upper = None
btn_lower = None
def screen_init():
global scr
global scr_light
global btn_upper
global btn_lower
scr_light = digitalio.DigitalInOut(board.D22)
scr_light.switch_to_output()
scr_light.value = True
# Configuration for CS and DC pins for Raspberry Pi
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = None
BAUDRATE = 64000000 # The pi can be very fast!
# Create the ST7789 display:
scr = st7789.ST7789(
board.SPI(),
cs=cs_pin,
dc=dc_pin,
rst=reset_pin,
baudrate=BAUDRATE,
width=135,
height=240,
x_offset=53,
y_offset=40,
)
scr.fill(rgb.color565(0,0,0))
btn_upper = digitalio.DigitalInOut(board.D23)
btn_lower = digitalio.DigitalInOut(board.D24)
btn_upper.switch_to_input()
btn_lower.switch_to_input()
@atexit.register
def screen_deinit():
global running
running = False # stops update thread
scr.fill(rgb.color565(0,0,0))
scr_light.value = False
current_icon = None
wifi_state = 0 # -1 error, 0 disconnected, 1 connected
dns_state = 0 # -1 error, 0 off, 1 running
download_state = 0 # yes/no
screen_on = True
def screen_update():
global current_icon
if wifi_state < 1 or dns_state < 1:
current_icon = Image.open("res/image/problem.png") # ⚠️
else:
current_icon = Image.open("res/image/okay.png") # ✅
#scr.fill(rgb.color565(0,0,0)) # blank
img_canvas = Image.new("RGB", (135, 240))
hnd_canvas = ImageDraw.Draw(img_canvas)
hnd_canvas.rectangle([(0,0), (135,240)], fill=(0,0,0))
hnd_canvas.text((math.floor(135/2), 0), time.strftime("%H:%M"), # top center of screen, "16:20"
fill=(50,200,255), anchor="mt", # cyan, middle-top
font_size=16)
img_canvas.paste(current_icon, (math.floor(135/2) - 32, math.floor(240/2) - 32))
scr.image(img_canvas)
def screen_thread():
while running:
screen_update()
time.sleep(1)