From 7a910ab962a1b8611c866264bf88a3833c7b49cf Mon Sep 17 00:00:00 2001 From: Mikey Sklar Date: Mon, 2 Jun 2025 12:43:59 -0700 Subject: [PATCH] pi-hole / bookworm / st7789 changes A lot has changed since this guide was release. The Pi Hole 6.x release in early 2025 dramatically changed the API. Bookworm changes how some of the pins are used. Even the ST7789 MiniPiTFT chip has some different options. This code was tested and work with a MiniPiTFt on a Pi 4. I'd like to update the guide to support accommidate the software updates. --- Pi_Hole_Ad_Blocker/mini_pitft_stats.py | 105 ++++++++++++------------- 1 file changed, 50 insertions(+), 55 deletions(-) diff --git a/Pi_Hole_Ad_Blocker/mini_pitft_stats.py b/Pi_Hole_Ad_Blocker/mini_pitft_stats.py index 3d1349458..b631d3e3f 100755 --- a/Pi_Hole_Ad_Blocker/mini_pitft_stats.py +++ b/Pi_Hole_Ad_Blocker/mini_pitft_stats.py @@ -19,11 +19,10 @@ import board from PIL import Image, ImageDraw, ImageFont import adafruit_rgb_display.st7789 as st7789 -API_TOKEN = "YOUR_API_TOKEN_HERE" -api_url = "http://localhost/admin/api.php?summaryRaw&auth="+API_TOKEN +API_URL = "http://pi.hole/api/stats/summary" # Configuration for CS and DC pins (these are FeatherWing defaults on M0/M4): -cs_pin = digitalio.DigitalInOut(board.CE0) +cs_pin = digitalio.DigitalInOut(board.D17) dc_pin = digitalio.DigitalInOut(board.D25) reset_pin = None @@ -34,54 +33,42 @@ BAUDRATE = 64000000 spi = board.SPI() # Create the ST7789 display: -disp = st7789.ST7789(spi, cs=cs_pin, dc=dc_pin, rst=reset_pin, baudrate=BAUDRATE, - width=135, height=240, x_offset=53, y_offset=40) +disp = st7789.ST7789( + spi, + dc_pin, + cs_pin, + reset_pin, + 135, + 240, + baudrate=BAUDRATE, + x_offset=53, + y_offset=40, + rotation=90 +) # Create blank image for drawing. # Make sure to create image with mode 'RGB' for full color. -height = disp.width # we swap height/width to rotate it to landscape! -width = disp.height -image = Image.new('RGB', (width, height)) -rotation = 90 - -# Get drawing object to draw on image. +CANVAS_WIDTH = disp.height +CANVAS_HEIGHT = disp.width +image = Image.new('RGB', (CANVAS_WIDTH, CANVAS_HEIGHT)) draw = ImageDraw.Draw(image) -# Draw a black filled box to clear the image. -draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0)) -disp.image(image, rotation) -# Draw some shapes. -# First define some constants to allow easy resizing of shapes. -padding = -2 -top = padding -bottom = height-padding -# Move left to right keeping track of the current x position for drawing shapes. -x = 0 +# Load default font (or replace with a TTF if desired) +FONT_PATH = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" +font = ImageFont.truetype(FONT_PATH, 20) - -# Alternatively load a TTF font. Make sure the .ttf font file is in the -# same directory as the python script! -# Some other nice fonts to try: http://www.dafont.com/bitmap.php -font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 24) - -# Turn on the backlight -backlight = digitalio.DigitalInOut(board.D22) -backlight.switch_to_output() -backlight.value = True - -# Add buttons as inputs buttonA = digitalio.DigitalInOut(board.D23) buttonA.switch_to_input() while True: # Draw a black filled box to clear the image. - draw.rectangle((0, 0, width, height), outline=0, fill=0) + draw.rectangle((0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), outline=0, fill=(0, 0, 0)) # Shell scripts for system monitoring from here: # https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load - cmd = "hostname -I | cut -d\' \' -f1" - IP = "IP: "+subprocess.check_output(cmd, shell=True).decode("utf-8") - cmd = "hostname | tr -d \'\\n\'" + cmd = "hostname -I | cut -d' ' -f1" + IP = "IP: " + subprocess.check_output(cmd, shell=True).decode("utf-8").strip() + cmd = "hostname | tr -d '\\n'" HOST = subprocess.check_output(cmd, shell=True).decode("utf-8") cmd = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'" CPU = subprocess.check_output(cmd, shell=True).decode("utf-8") @@ -89,22 +76,24 @@ while True: MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8") cmd = "df -h | awk '$NF==\"/\"{printf \"Disk: %d/%d GB %s\", $3,$2,$5}'" Disk = subprocess.check_output(cmd, shell=True).decode("utf-8") - cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk \'{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}\'" # pylint: disable=line-too-long + cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk '{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}'" Temp = subprocess.check_output(cmd, shell=True).decode("utf-8") - # Pi Hole data! try: - r = requests.get(api_url) - data = json.loads(r.text) - DNSQUERIES = data['dns_queries_today'] - ADSBLOCKED = data['ads_blocked_today'] - CLIENTS = data['unique_clients'] - except KeyError: - time.sleep(1) - continue + r = requests.get(API_URL, timeout=5) + r.raise_for_status() + data = r.json() + DNSQUERIES = data["queries"]["total"] + ADSBLOCKED = data["queries"]["blocked"] + CLIENTS = data["clients"]["total"] + except (KeyError, requests.RequestException, json.JSONDecodeError): + DNSQUERIES = None + ADSBLOCKED = None + CLIENTS = None - y = top + y = top = 5 + x = 5 if not buttonA.value: # just button A pressed draw.text((x, y), IP, font=font, fill="#FFFF00") y += font.getbbox(IP)[3] @@ -121,13 +110,19 @@ while True: y += font.getbbox(IP)[3] draw.text((x, y), HOST, font=font, fill="#FFFF00") y += font.getbbox(HOST)[3] - draw.text((x, y), "Ads Blocked: {}".format(str(ADSBLOCKED)), font=font, fill="#00FF00") - y += font.getbbox(str(ADSBLOCKED))[3] - draw.text((x, y), "Clients: {}".format(str(CLIENTS)), font=font, fill="#0000FF") - y += font.getbbox(str(CLIENTS))[3] - draw.text((x, y), "DNS Queries: {}".format(str(DNSQUERIES)), font=font, fill="#FF00FF") - y += font.getbbox(str(DNSQUERIES))[3] + if ADSBLOCKED is not None: + txt = f"Ads Blocked: {ADSBLOCKED}" + draw.text((x, y), txt, font=font, fill="#00FF00") + y += font.getbbox(txt)[3] + if CLIENTS is not None: + txt = f"Clients: {CLIENTS}" + draw.text((x, y), txt, font=font, fill="#0000FF") + y += font.getbbox(txt)[3] + if DNSQUERIES is not None: + txt = f"DNS Queries: {DNSQUERIES}" + draw.text((x, y), txt, font=font, fill="#FF00FF") + y += font.getbbox(txt)[3] # Display image. - disp.image(image, rotation) + disp.image(image) time.sleep(.1)