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:
parent
bc0ada494e
commit
d4186e0e43
57
blocklists.py
Normal file
57
blocklists.py
Normal 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
2
config.ini
Normal file
@ -0,0 +1,2 @@
|
||||
[internal]
|
||||
cache_root=/run/starcontrol
|
8
config.py
Normal file
8
config.py
Normal 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
47
mainloop.py
Executable 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
58
pitft-screen-test.py
Executable 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
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
BIN
res/image/download.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 568 B |
BIN
res/image/hourglass.png
Normal file
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
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
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
BIN
res/image/wifi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
86
screen.py
Normal file
86
screen.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user