|
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