|
19 | 19 | from PIL import Image, ImageDraw, ImageFont
|
20 | 20 | import adafruit_rgb_display.st7789 as st7789
|
21 | 21 |
|
22 |
| -API_TOKEN = "YOUR_API_TOKEN_HERE" |
23 |
| -api_url = "http://localhost/admin/api.php?summaryRaw&auth="+API_TOKEN |
| 22 | +API_URL = "http://pi.hole/api/stats/summary" |
24 | 23 |
|
25 | 24 | # Configuration for CS and DC pins (these are FeatherWing defaults on M0/M4):
|
26 |
| -cs_pin = digitalio.DigitalInOut(board.CE0) |
| 25 | +cs_pin = digitalio.DigitalInOut(board.D17) |
27 | 26 | dc_pin = digitalio.DigitalInOut(board.D25)
|
28 | 27 | reset_pin = None
|
29 | 28 |
|
|
34 | 33 | spi = board.SPI()
|
35 | 34 |
|
36 | 35 | # Create the ST7789 display:
|
37 |
| -disp = st7789.ST7789(spi, cs=cs_pin, dc=dc_pin, rst=reset_pin, baudrate=BAUDRATE, |
38 |
| - width=135, height=240, x_offset=53, y_offset=40) |
| 36 | +disp = st7789.ST7789( |
| 37 | + spi, |
| 38 | + dc_pin, |
| 39 | + cs_pin, |
| 40 | + reset_pin, |
| 41 | + 135, |
| 42 | + 240, |
| 43 | + baudrate=BAUDRATE, |
| 44 | + x_offset=53, |
| 45 | + y_offset=40, |
| 46 | + rotation=90 |
| 47 | +) |
39 | 48 |
|
40 | 49 | # Create blank image for drawing.
|
41 | 50 | # Make sure to create image with mode 'RGB' for full color.
|
42 |
| -height = disp.width # we swap height/width to rotate it to landscape! |
43 |
| -width = disp.height |
44 |
| -image = Image.new('RGB', (width, height)) |
45 |
| -rotation = 90 |
46 |
| - |
47 |
| -# Get drawing object to draw on image. |
| 51 | +CANVAS_WIDTH = disp.height |
| 52 | +CANVAS_HEIGHT = disp.width |
| 53 | +image = Image.new('RGB', (CANVAS_WIDTH, CANVAS_HEIGHT)) |
48 | 54 | draw = ImageDraw.Draw(image)
|
49 | 55 |
|
50 |
| -# Draw a black filled box to clear the image. |
51 |
| -draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0)) |
52 |
| -disp.image(image, rotation) |
53 |
| -# Draw some shapes. |
54 |
| -# First define some constants to allow easy resizing of shapes. |
55 |
| -padding = -2 |
56 |
| -top = padding |
57 |
| -bottom = height-padding |
58 |
| -# Move left to right keeping track of the current x position for drawing shapes. |
59 |
| -x = 0 |
60 |
| - |
61 |
| - |
62 |
| -# Alternatively load a TTF font. Make sure the .ttf font file is in the |
63 |
| -# same directory as the python script! |
64 |
| -# Some other nice fonts to try: http://www.dafont.com/bitmap.php |
65 |
| -font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 24) |
66 |
| - |
67 |
| -# Turn on the backlight |
68 |
| -backlight = digitalio.DigitalInOut(board.D22) |
69 |
| -backlight.switch_to_output() |
70 |
| -backlight.value = True |
71 |
| - |
72 |
| -# Add buttons as inputs |
| 56 | +# Load default font (or replace with a TTF if desired) |
| 57 | +FONT_PATH = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" |
| 58 | +font = ImageFont.truetype(FONT_PATH, 20) |
| 59 | + |
73 | 60 | buttonA = digitalio.DigitalInOut(board.D23)
|
74 | 61 | buttonA.switch_to_input()
|
75 | 62 |
|
76 | 63 | while True:
|
77 | 64 | # Draw a black filled box to clear the image.
|
78 |
| - draw.rectangle((0, 0, width, height), outline=0, fill=0) |
| 65 | + draw.rectangle((0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), outline=0, fill=(0, 0, 0)) |
79 | 66 |
|
80 | 67 | # Shell scripts for system monitoring from here:
|
81 | 68 | # https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load
|
82 |
| - cmd = "hostname -I | cut -d\' \' -f1" |
83 |
| - IP = "IP: "+subprocess.check_output(cmd, shell=True).decode("utf-8") |
84 |
| - cmd = "hostname | tr -d \'\\n\'" |
| 69 | + cmd = "hostname -I | cut -d' ' -f1" |
| 70 | + IP = "IP: " + subprocess.check_output(cmd, shell=True).decode("utf-8").strip() |
| 71 | + cmd = "hostname | tr -d '\\n'" |
85 | 72 | HOST = subprocess.check_output(cmd, shell=True).decode("utf-8")
|
86 | 73 | cmd = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'"
|
87 | 74 | CPU = subprocess.check_output(cmd, shell=True).decode("utf-8")
|
88 | 75 | cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%s MB %.2f%%\", $3,$2,$3*100/$2 }'"
|
89 | 76 | MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8")
|
90 | 77 | cmd = "df -h | awk '$NF==\"/\"{printf \"Disk: %d/%d GB %s\", $3,$2,$5}'"
|
91 | 78 | Disk = subprocess.check_output(cmd, shell=True).decode("utf-8")
|
92 |
| - cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk \'{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}\'" # pylint: disable=line-too-long |
| 79 | + cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk '{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}'" |
93 | 80 | Temp = subprocess.check_output(cmd, shell=True).decode("utf-8")
|
94 | 81 |
|
95 |
| - |
96 | 82 | # Pi Hole data!
|
97 | 83 | try:
|
98 |
| - r = requests.get(api_url) |
99 |
| - data = json.loads(r.text) |
100 |
| - DNSQUERIES = data['dns_queries_today'] |
101 |
| - ADSBLOCKED = data['ads_blocked_today'] |
102 |
| - CLIENTS = data['unique_clients'] |
103 |
| - except KeyError: |
104 |
| - time.sleep(1) |
105 |
| - continue |
106 |
| - |
107 |
| - y = top |
| 84 | + r = requests.get(API_URL, timeout=5) |
| 85 | + r.raise_for_status() |
| 86 | + data = r.json() |
| 87 | + DNSQUERIES = data["queries"]["total"] |
| 88 | + ADSBLOCKED = data["queries"]["blocked"] |
| 89 | + CLIENTS = data["clients"]["total"] |
| 90 | + except (KeyError, requests.RequestException, json.JSONDecodeError): |
| 91 | + DNSQUERIES = None |
| 92 | + ADSBLOCKED = None |
| 93 | + CLIENTS = None |
| 94 | + |
| 95 | + y = top = 5 |
| 96 | + x = 5 |
108 | 97 | if not buttonA.value: # just button A pressed
|
109 | 98 | draw.text((x, y), IP, font=font, fill="#FFFF00")
|
110 | 99 | y += font.getbbox(IP)[3]
|
|
121 | 110 | y += font.getbbox(IP)[3]
|
122 | 111 | draw.text((x, y), HOST, font=font, fill="#FFFF00")
|
123 | 112 | y += font.getbbox(HOST)[3]
|
124 |
| - draw.text((x, y), "Ads Blocked: {}".format(str(ADSBLOCKED)), font=font, fill="#00FF00") |
125 |
| - y += font.getbbox(str(ADSBLOCKED))[3] |
126 |
| - draw.text((x, y), "Clients: {}".format(str(CLIENTS)), font=font, fill="#0000FF") |
127 |
| - y += font.getbbox(str(CLIENTS))[3] |
128 |
| - draw.text((x, y), "DNS Queries: {}".format(str(DNSQUERIES)), font=font, fill="#FF00FF") |
129 |
| - y += font.getbbox(str(DNSQUERIES))[3] |
| 113 | + if ADSBLOCKED is not None: |
| 114 | + txt = f"Ads Blocked: {ADSBLOCKED}" |
| 115 | + draw.text((x, y), txt, font=font, fill="#00FF00") |
| 116 | + y += font.getbbox(txt)[3] |
| 117 | + if CLIENTS is not None: |
| 118 | + txt = f"Clients: {CLIENTS}" |
| 119 | + draw.text((x, y), txt, font=font, fill="#0000FF") |
| 120 | + y += font.getbbox(txt)[3] |
| 121 | + if DNSQUERIES is not None: |
| 122 | + txt = f"DNS Queries: {DNSQUERIES}" |
| 123 | + draw.text((x, y), txt, font=font, fill="#FF00FF") |
| 124 | + y += font.getbbox(txt)[3] |
130 | 125 |
|
131 | 126 | # Display image.
|
132 |
| - disp.image(image, rotation) |
| 127 | + disp.image(image) |
133 | 128 | time.sleep(.1)
|
0 commit comments