Web UI and LOGO!-style FBD logic editor for the PiFace Digital 2 I/O HAT on a Raspberry Pi. Bypasses the unmaintained pifacedigitalio library (broken on current Bookworm kernels) by talking to the MCP23S17 directly over /dev/spidev0.0.
Deutsche Version: README.de.md
- Manual tab — 8 output toggle buttons (outputs 0+1 also drive the on-board relays K0/K1), 8 live input indicators (50 ms WebSocket push), 8 virtual test switches, named light patterns with a built-in editor.
- Logic tab — Drag-and-drop function-block diagram (FBD) editor with 30+ block types: AND/OR/NAND/NOR/XOR/NOT, TON/TOF/TP timers, stairwell, blinker, counters, RS/D/JK flip-flops, 8-bit shift register, edge detectors, weekly time switch, comparator, debounce, hours counter, virtual test inputs, DS18B20 temperature, raw Pi-GPIO blocks, pattern-start trigger. Pan/zoom canvas, live wire highlighting during execution, undo/redo, copy/paste, save/load/export programs as JSON. 50 ms scan cycle with back-edge handling (PLC-typical).
- Stats tab — Per-output switching cycles and operating hours, input change counts, engine starts, live oscilloscope (30 s sliding window for all 16 channels).
- Settings tab — HTTP basic auth (admin/viewer roles), MQTT bridge with Home Assistant auto-discovery, webhook fan-out on input events, pattern auto-trigger by input bit patterns, ZIP backup/restore, optional git auto-push.
- REST API —
/api/state,/api/outputs[/<pin>],/api/inputs,/api/programs[/<name>][/run],/api/programs/stop,/api/stats,/api/scope,/api/backup,/api/import,/api/webhooks,/api/triggers,/api/settings,/api/block-defs. - WebSocket — same surface plus live input/output deltas, engine state, block-level value introspection.
- Optional HDMI kiosk mode — boots straight into Chromium full-screen pointing at
http://localhost:5000/.
| Component | Notes |
|---|---|
| Raspberry Pi | Pi 3 B / 3 B+ / 4 / 5 (developed on Pi 3 B v1.2) |
| PiFace Digital 2 HAT | MCP23S17 over SPI |
| Storage | 8 GB SD or larger |
| Network | Wired Ethernet recommended for the kiosk use case |
| Display (optional) | HDMI 1920×1080 for the kiosk-mode auto-launch |
| 1-Wire temperature sensor (optional) | DS18B20 on GPIO4 if you enable the temperature block |
Multiple PiFace boards can be stacked — pass hw_addr=1..3 when instantiating PiFace. HAEN is enabled automatically when hw_addr != 0.
On a freshly imaged Raspberry Pi OS Lite (64-bit, Bookworm):
# Enable SPI (one-time)
sudo raspi-config nonint do_spi 0
# Add yourself to the SPI / GPIO / I2C groups
sudo usermod -aG gpio,i2c,spi "$USER"
# Reboot so the group membership and SPI take effect
sudo rebootAfter the reboot:
sudo apt update
sudo apt install -y git python3-venv python3-pip
git clone https://github.com/Bazilus/piface-web-control.git ~/piface-app
cd ~/piface-app
python3 -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -r requirements.txt
# Try it
.venv/bin/python app.pyOpen http://<pi-ip>:5000/ (or http://<hostname>.local:5000/) in your browser. The first input press should light up the corresponding indicator; clicking an output should toggle the matching on-board LED (and relay for outputs 0/1).
The included unit file assumes user dirk and /home/dirk/piface-app. If your username or path differs, edit piface-app.service before installing:
sudo cp piface-app.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now piface-app.service
sudo systemctl status piface-app.serviceLogs: journalctl -u piface-app.service -f.
Boots the Pi straight into Chromium full-screen on http://localhost:5000/. Requires a desktop-class environment with X — the script installs the bits you need but assumes Pi OS Lite:
sudo apt install -y --no-install-recommends \
xserver-xorg xinit openbox chromium-browser unclutter curl
cd ~/piface-app/kiosk
chmod +x install.sh xinitrc
./install.sh
sudo rebootThe kiosk scripts are hardcoded to user dirk. Adjust install.sh, bash_profile_kiosk, getty-autologin.conf and xinitrc if your username differs.
The Flask dev server speaks HTTP. To put HTTPS in front with a self-signed cert (good enough for a LAN device):
sudo apt install -y caddy
sudo mkdir -p /etc/caddy/certs
sudo openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout /etc/caddy/certs/piface.key \
-out /etc/caddy/certs/piface.crt \
-subj "/CN=piface.local"Add to /etc/caddy/Caddyfile:
{
auto_https off
}
:80, :443 {
tls /etc/caddy/certs/piface.crt /etc/caddy/certs/piface.key
reverse_proxy localhost:5000
}
Then sudo systemctl restart caddy. Your browser will warn about the self-signed cert on first visit — accept once, or import piface.crt into your trust store for a permanent fix.
In the Settings tab, enable MQTT and fill in host, port, optional credentials, and a topic prefix (default piface). Home Assistant auto-discovery is published under homeassistant/... so all 8 inputs and 8 outputs appear as binary sensors / switches automatically.
piface-app/
app.py Flask + Flask-SocketIO entry point. Owns the I/O poll thread,
MQTT bridge, REST routes, websocket handlers, settings, backups.
piface.py Direct MCP23S17 driver (spidev). Multi-board stacking via hw_addr.
logic.py Block catalogue + evaluation engine + topo sort with back-edge handling.
hardware.py Optional GPIO (gpiozero) and DS18B20 (1-wire) providers.
templates/ Jinja2 templates (single page).
static/ Frontend JS/CSS (vanilla, no build step).
kiosk/ Optional X / Chromium / agetty config for the HDMI kiosk launch.
piface-app.service systemd unit.
programs.json Four demo programs (stairwell, latching relay, blinker, click counter).
Why the custom MCP23S17 driver? The legacy pifacedigitalio library throws OSError [Errno 22] on the SPI driver shipped with current Pi OS kernels. The driver in piface.py is ~100 lines, talks SPI directly, and supports board stacking.
Why async_mode="threading" for Flask-SocketIO? Eventlet is unmaintained and breaks on Python ≥3.11; gevent has its own deployment hassles. The threading mode with Werkzeug's dev server is enough for a handful of concurrent clients on a LAN. socketio.run(..., allow_unsafe_werkzeug=True) is required to start the dev server with SocketIO.
| File | Contents |
|---|---|
patterns.json |
Saved light patterns (default set seeded if missing) |
settings.json |
Auth, MQTT bridge, webhook list, pattern triggers, git config |
triggers.json |
Pattern auto-trigger rules |
webhooks.json |
Webhook target URLs |
stats.json |
Switching cycles, operating hours, input change counts |
events.log |
Append-only input/output event log |
Delete any of these to reset that subsystem; the app re-creates them with safe defaults on the next start.
- The Flask dev server is bound to all interfaces. Do not expose port 5000 to the public internet. Use the optional Caddy front-end and basic-auth for any network beyond your LAN.
- The default Flask
SECRET_KEYis"piface-local-only". SetPIFACE_SECRET_KEYin the environment if the app is reachable beyond trusted networks. - The MQTT bridge sends credentials in plaintext unless you configure a TLS broker — pass
port: 8883and use a broker that requires TLS. - The webhook fan-out uses
urllibwithout certificate pinning. Trusted endpoints only.
Apache License 2.0. See LICENSE.
