Skip to content

Instantly share code, notes, and snippets.

@gboone
Last active February 3, 2023 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gboone/40dc2a58c0f608a7b6bf2a4fe623ec0b to your computer and use it in GitHub Desktop.
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
#! /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