Last active
February 3, 2023 16:35
-
-
Save gboone/40dc2a58c0f608a7b6bf2a4fe623ec0b to your computer and use it in GitHub Desktop.
Script to display some basic info from a pihole on an adafruit 1.14" tft display. Buttons control pihole and display a qr code for the wifi network
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python3 | |
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries | |
# SPDX-License-Identifier: MIT | |
# -*- coding: utf-8 -*- | |
# to test, edit /etc/rc.local then reboot | |
import time | |
import subprocess | |
import digitalio | |
import board | |
import socket | |
from PIL import Image, ImageDraw, ImageFont | |
from adafruit_rgb_display import st7789 | |
# Configuration for CS and DC pins (these are FeatherWing defaults on M0/M4): | |
cs_pin = digitalio.DigitalInOut(board.CE0) | |
dc_pin = digitalio.DigitalInOut(board.D25) | |
reset_pin = None | |
# Config for display baudrate (default max is 24mhz): | |
BAUDRATE = 64000000 | |
# Setup SPI bus using hardware SPI: | |
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, | |
) | |
# 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("RGBA", (width, height)) | |
rotation = 270 | |
BLACK = (0,0,0) | |
WHITE = (255,255,255) | |
# Get drawing object to draw on image. | |
draw = ImageDraw.Draw(image) | |
# Draw a black filled box to clear the image. | |
draw.rectangle((0, 0, width, height), outline=0, fill=BLACK) | |
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 | |
y = top | |
# 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/piboto/Piboto-Regular.ttf", 20) | |
# Turn on the backlight | |
backlight = digitalio.DigitalInOut(board.D22) | |
backlight.switch_to_output() | |
backlight.value = True | |
# Watch them buttons | |
buttonA = digitalio.DigitalInOut(board.D23) | |
buttonB = digitalio.DigitalInOut(board.D24) | |
buttonA.switch_to_input() | |
buttonB.switch_to_input() | |
# check an internet connection | |
def is_connected(): | |
try: | |
socket.create_connection(("1.1.1.1", 53)) | |
return True | |
except OSError: | |
pass | |
return False | |
# get the current CPU load | |
def getCPU(): | |
getCPU = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'" | |
return subprocess.check_output(getCPU, shell=True).decode("utf-8") | |
# get the current IP address | |
def getIP(): | |
getIP = "hostname -I | cut -d' ' -f1" | |
return "IP: " + subprocess.check_output(getIP, shell=True).decode("utf-8") | |
# get the current disk usage | |
def getDF(): | |
getDF = 'df -h | awk \'$NF=="/"{printf "Disk: %d/%d GB %s full", $3,$2,$5}\'' | |
return subprocess.check_output(getDF, shell=True).decode("utf-8") | |
# get the pihole's status | |
def getPiHoleStatus(): | |
getPiholeStatus = "pihole status | tail -n1 | awk 'NF>1{print $NF}'" | |
piholeStatus = subprocess.check_output(getPiholeStatus, shell=True).decode("utf-8").strip() | |
return "Blocking: {}".format(piholeStatus) | |
def getConnection(): | |
return "Connected" if is_connected() else "Disconnected" | |
def piHoleToggleState(): | |
status = getPiHoleStatus() | |
toggleAction = "disable" if status.split()[-1] == "enabled" else "enable" | |
toggleText = "Top button to {}".format(toggleAction) | |
return (toggleAction, toggleText) | |
def togglePiHole(action): | |
return subprocess.run("pihole {}".format(action), shell=True) | |
def clearfix(y): | |
height = y + 22 | |
draw.rectangle((-1, y, width, height), outline=0, fill=BLACK) | |
def exitClear(): | |
draw.rectangle((-1, 0, width, height), outline=0, fill=BLACK) | |
backlight.value = False | |
# draw image placeholders for each line | |
ip = getIP() | |
cpu = getCPU() | |
disk = getDF() | |
piHoleStatus = getPiHoleStatus() | |
connected = getConnection() | |
toggleAction = piHoleToggleState()[1] | |
#set appropriate spacing for six lines | |
ONE = 0 | |
TWO = 22 | |
THREE = 44 | |
FOUR = 66 | |
FIVE = 88 | |
SIX = 110 | |
# draw initial text lines | |
draw.text((x, ONE), ip, font=font, fill=WHITE) | |
draw.text((x, TWO), cpu, font=font, fill=WHITE) | |
draw.text((x, THREE), disk, font=font, fill=WHITE) | |
draw.text((x, FOUR), piHoleStatus, font=font, fill=WHITE) | |
draw.text((x, FIVE), toggleAction, font=font, fill=WHITE) | |
draw.text((x, SIX), connected, font=font, fill=WHITE) | |
while True: | |
x = 0 | |
#backlight.value = False | |
#backlight.value = True | |
# Draw a black filled box to clear the image. | |
#draw.rectangle((x, y, width, height), outline=0, fill=BLACK) | |
# Shell scripts for system monitoring from here: | |
# https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load | |
#getIP = "hostname -I | cut -d' ' -f1" | |
#IP = "IP: " + subprocess.check_output(getIP, shell=True).decode("utf-8") | |
# import pdb; pdb.set_trace() | |
currIP = getIP() | |
currCPU = getCPU() | |
currDisk = getDF() | |
currPiHoleStatus = getPiHoleStatus() | |
# button status | |
toggleState = piHoleToggleState() | |
nextPiHoleAction = toggleState[0] | |
newToggleAction = toggleState[1] | |
# internet connection status | |
currConnection = getConnection() | |
# Write lines of text. | |
#draw.text((x,y), "Hi", font=font, fill="#FFFFFF") | |
# Current IP address | |
if currIP != ip: | |
clearfix(ONE) | |
draw.text((x, ONE), currIP, font=font, fill=WHITE) | |
# Current CPU usage | |
if currCPU != cpu: | |
clearfix(TWO) | |
draw.text((x, TWO), currCPU, font=font, fill=WHITE) | |
# Disk usage | |
if currDisk != disk: | |
clearfix(THREE) | |
draw.text((x, THREE), currDisk, font=font, fill=WHITE) | |
# Print internet status | |
#draw.text((x,y), connected, font=font, fill=WHITE) | |
# Check the buttons | |
# Because our screen is flipped 180º the B button is the top button. | |
if not buttonB.value: | |
clearfix(FOUR) | |
draw.text((x, FOUR), "updating Pi-hole", font=font, fill=WHITE) | |
togglePiHole(nextPiHoleAction) | |
clearfix(FOUR) | |
elif currPiHoleStatus != piHoleStatus: | |
clearfix(FOUR) | |
draw.text((x, FOUR), currPiHoleStatus, font=font, fill=WHITE) | |
clearfix(FIVE) | |
draw.text((x, FIVE), newToggleAction, font=font, fill=WHITE) | |
if currConnection != connected: | |
clearfix(SIX) | |
draw.text((x, SIX), currConnection, font=font, fill=WHITE) | |
# Display image. | |
disp.image(image, rotation) | |
time.sleep(2) | |
#draw.rectangle((0,0, width, height), outline=0, fill="#FFFFFF") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment