Skip to content

Commit

Permalink
Merge pull request #11 from amenekowo/master
Browse files Browse the repository at this point in the history
Update auth api, add config file, add rotation
  • Loading branch information
santoru authored Aug 13, 2023
2 parents 105a4b1 + b8e119c commit 7882a7a
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 24 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ Additionally, I do not use static IP so if this ever change, I have an easy way
- <a href="https://pi-hole.net/">Pi-Hole</a> (I have v5.2.4 at the moment)

## Configuration
The tool should run out of the box with standard installation of Pi-Hole. If you have a different setup probably the scripts should be adapted too.\
If your instance of Pi-Hole is running on a different port than 80, you should change it inside `pihole_dashboard/__init__.py`.\
The IP address is shown considering the `wlan0` interface, you can change this value from `pihole_dashboard/__init__.py`.
After set the webui api token, the tool should run out of the box with standard installation of Pi-Hole.\
You can find your API in Pi-Hole's webpage: Settings - API - Show API token - Yes, show API token. Then, RAW API Token is the token.\
If your instance of Pi-Hole is running on a different port than 80, you should change it inside `/etc/pihole-dashboard/config.toml`.\
The IP address is shown considering the `wlan0` interface, you can change this value in `/etc/pihole-dashboard/config.toml`.

### WaveShare e-Paper dependency
Making the E-Ink display work is not fully covered here, as it depends mostly on the display you use. As said before, I have the WaveShare's 2.13 inch E-Ink display, that has a nice detailed Wiki here: https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT.
Expand All @@ -37,11 +38,15 @@ git clone https://github.com/waveshare/e-Paper.git
cd e-Paper/RaspberryPi_JetsonNano/python/
sudo python3 setup.py install
```

You can check if the display is working by running the test example:
```bash
cd e-Paper/RaspberryPi_JetsonNano/python/
sudo python3 examples/epd_2in13_V2_test.py
```
Test script depends on your screen type. There should be a sticker which tells your screen type.
If yours is a newer V3, before run the test, your should change V2 to V3.

Remember that you need **root** access to control the display, so be sure to run the python example as root.\
You also need to [enable the SPI interface](https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md#software), otherwise the display connection will not work.

Expand All @@ -66,16 +71,18 @@ git clone https://github.com/santoru/pihole-dashboard
cd pihole-dashboard
sudo pip3 install .
```
Once installed, reboot the Raspberry Pi. The dashboard should appear few minutes after the reboot.
Once installed, **Add API key to your config file, change screen type if needed** (at `/etc/pihole-dashboard/config.toml`), then reboot the Raspberry Pi.
The dashboard should appear few minutes after the reboot.

## Uninstall
You can remove the tool anytime by running
```bash
sudo pip uninstall pihole-dashboard
```
You can also manually remove the cronjob by running
You can also manually remove the cronjob and config file by running
```bash
sudo rm /etc/cron.d/pihole-dashboard-cron
sudo rm -rf /etc/pihole-dashboard/
```

## How it works
Expand Down
24 changes: 24 additions & 0 deletions conf/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Configuration file for pihole-dashboard

# Interface to parse ip address. Default is wlan0
interface = "wlan0"

# Pi-hole lighttpd web admin port. Default is 80
pihole_port = 80

# Pi-hole IP. Useful when monitor remote pi-hole server. Default 127.0.0.1 (localhost)
pihole_ip = "127.0.0.1"

# Pi-hole api token.
# To get api token, go to web admin page, see Settings -> API -> Show API token
# Or run "grep WEBPASSWORD /etc/pihole/setupVars.conf" and get the string after "="
# https://github.com/pi-hole/AdminLTE/issues/2467
pihole_api_token = ""

# Rotate indicator, set 1 for 180 degrees rotation. Default is 0
is_rotated = 0

# Screen selection. Supported screens:
# 213v2 | Waveshare 2.13 BW V2
# 213v3 | Waveshare 2.13 BW V3
screen_type = "213v2"
50 changes: 40 additions & 10 deletions pihole_dashboard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# pihole-dashboard
# Copyright (C) 2021 santoru
# Copyright (C) 2023 ameneko
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -23,28 +24,54 @@
import json
import os
import sys
import toml
import hashlib
import netifaces as ni
from waveshare_epd import epd2in13_V2
from PIL import Image, ImageFont, ImageDraw

if os.geteuid() != 0:
sys.exit("You need root permissions to access E-Ink display, try running with sudo!")

INTERFACE = "wlan0"
PIHOLE_IP = "127.0.0.1"
PIHOLE_PORT = 80
PIHOLE_APITOKEN = ""
IS_ROTATED = 0
SCREEN_TYPE = "213v2"

OUTPUT_STRING = ""
FILENAME = "/tmp/.pihole-dashboard-output"
DISPHASH_FILENAME = "/tmp/.pihole-dashboard-output"
CONFIG_FILENAME = "/etc/pihole-dashboard/config.toml"

# Read config file
try:
CONFIG = toml.load(CONFIG_FILENAME, _dict=dict)
INTERFACE = CONFIG["interface"]
PIHOLE_IP = CONFIG["pihole_ip"]
PIHOLE_PORT = CONFIG["pihole_port"]
PIHOLE_APITOKEN = CONFIG["pihole_api_token"]
IS_ROTATED = CONFIG["is_rotated"]
SCREEN_TYPE = CONFIG["screen_type"]
except TomlDecodeError:
output_error = "Config can't be parsed! Please check config file."
sys.exit(output_error)

hostname = socket.gethostname()
font_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'font')
font_name = os.path.join(font_dir, "font.ttf")
font16 = ImageFont.truetype(font_name, 16)
font12 = ImageFont.truetype(font_name, 12)

epd = epd2in13_V2.EPD()
epd.init(epd.FULL_UPDATE)
# Determine display type and clear
if SCREEN_TYPE == "213v2":
from waveshare_epd import epd2in13_V2
epd = epd2in13_V2.EPD()
epd.init(epd.FULL_UPDATE)
elif SCREEN_TYPE == "213v3":
from waveshare_epd import epd2in13_V3
epd = epd2in13_V3.EPD()
epd.init()
epd.Clear(0xFF)


def valid_ip(address):
Expand All @@ -56,7 +83,7 @@ def valid_ip(address):


def draw_dashboard(out_string=None):

# Draw a white canvas
image = Image.new("1", (epd.height, epd.width), 255)
draw = ImageDraw.Draw(image)

Expand All @@ -70,22 +97,25 @@ def draw_dashboard(out_string=None):
output = process.stdout.read().decode().split('\n')
version = output[0].split("(")[0].strip()

# Draw frame & text
draw.rectangle([(0, 105), (250, 122)], fill=0)
if out_string is not None:
draw.text((0, 0), out_string, font=font16, fill=0)
draw.text((5, 106), version, font=font12, fill=1)
draw.text((150, 106), time_string, font=font12, fill=1)
if (IS_ROTATED == 1):
image = image.rotate(180)
epd.display(epd.getbuffer(image))


def update():
url = "http://127.0.0.1:{}/admin/api.php".format(PIHOLE_PORT)
url = "http://{}:{}/admin/api.php?summary&auth={}".format(PIHOLE_IP, PIHOLE_PORT, PIHOLE_APITOKEN)
r = json.load(urllib.request.urlopen(url))

try:
ip = ni.ifaddresses(INTERFACE)[ni.AF_INET][0]['addr']
except KeyError:
ip_str = "[×] Can't connect to Wi-Fi"
ip_str = "[×] Can't get IP address"
ip = ""

if "unique_clients" not in r:
Expand All @@ -110,11 +140,11 @@ def update():

hash_string = hashlib.sha1(OUTPUT_STRING.encode('utf-8')).hexdigest()
try:
hash_file = open(FILENAME, "r+")
hash_file = open(DISPHASH_FILENAME, "r+")

except FileNotFoundError:
os.mknod(FILENAME)
hash_file = open(FILENAME, "r+")
os.mknod(DISPHASH_FILENAME)
hash_file = open(DISPHASH_FILENAME, "r+")

file_string = hash_file.read()
if file_string != hash_string:
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
waveshare-epd
netifaces>=0.10.9
Pillow>=8.2.0
Pillow>=8.2.0
toml>=0.10.2
32 changes: 24 additions & 8 deletions scripts/pihole-dashboard-clean-screen
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# pihole-dashboard-clean-screen
# Copyright (C) 2021 santoru
# Copyright (C) 2023 ameneko
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -19,22 +20,37 @@
import time
import sys
import os
from waveshare_epd import epd2in13_V2
import toml
from PIL import Image, ImageFont, ImageDraw

FILENAME = "/tmp/.pihole-dashboard-output"

DISPHASH_FILENAME = "/tmp/.pihole-dashboard-output"
CONFIG_FILENAME = "/etc/pihole-dashboard/config.toml"

if __name__ == '__main__':
if os.geteuid() != 0:
sys.exit("You need root permissions to access E-Ink display, try running with sudo!")
try:
os.remove(FILENAME)
os.remove(DISPHASH_FILENAME)
except FileNotFoundError:
pass

os.mknod(FILENAME)
os.mknod(DISPHASH_FILENAME)

try:
CONFIG = toml.load(CONFIG_FILENAME, _dict=dict)
SCREEN_TYPE = CONFIG["screen_type"]
except TomlDecodeError:
output_error = "Config can't be parsed! Please check config file."
sys.exit(output_error)


if SCREEN_TYPE == "213v2":
from waveshare_epd import epd2in13_V2
epd = epd2in13_V2.EPD()
epd.init(epd.FULL_UPDATE)
elif SCREEN_TYPE == "213v3":
from waveshare_epd import epd2in13_V3
epd = epd2in13_V3.EPD()
epd.init()
epd.Clear(0xFF)

epd = epd2in13_V2.EPD()
epd.init(epd.FULL_UPDATE)
epd.Clear(0xFF)
8 changes: 8 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ def run(self):
cron_dir = os.path.join(self_dir, 'cron')
copyfile(os.path.join(cron_dir, "pihole-dashboard-cron"),
"/etc/cron.d/pihole-dashboard-cron")
print("Installing config file...")
self_dir = os.path.dirname(os.path.realpath(__file__))
conf_dir = os.path.join(self_dir, 'conf')
conf_sys_dir = "/etc/pihole-dashboard"
if not os.path.exists(conf_sys_dir):
os.makedirs(conf_sys_dir)
copyfile(os.path.join(conf_dir, "config.toml"),
"/etc/pihole-dashboard/config.toml")
print("Done.")


Expand Down

0 comments on commit 7882a7a

Please sign in to comment.