README
Zigbee Monitor
A full-stack web application for monitoring and controlling Zigbee devices via Zigbee2MQTT, with face recognition and sensor data charting.
Features
Monitor
- Real-time event log from Zigbee devices with toast notifications
- Device inventory with vendor/model information
- Light controls (power, color, brightness) for RGB/LED devices
- Per-device flash alerts — flash an LED strip when a specific device sends events
- Per-device sound notifications — play configurable sounds (ting, chime, buzz, doorbell, blip) through the server's speakers on device events
- Pairing mode control (permit join with countdown timer)
- Device renaming (click any device name to edit)
- Bridge status monitoring (online/offline, version, coordinator info)
- System health dashboard — CPU, RAM, temperature, load average, Go runtime stats
- WebSocket subscriptions for live updates
Charts
- Time-series plotting of sensor data (temperature, humidity, illuminance, etc.)
- Device and field selection with checkboxes
- Time range selector: 1h, 6h, 24h, 7d, 30d
- Battery level summary with color-coded bars
- Auto-detection of numeric fields from device payloads
Face Recognition
- Enroll faces via browser camera (HTTPS) or file upload (HTTP)
- Face detection using OpenCV DNN with YuNet ONNX model
- Face recognition using SFace ONNX model with cosine similarity matching
- Profile management — view enrolled faces, delete profiles
- Detection history with confidence scores and thumbnails
- Works on ARM64 (KickPi K2B) — ~230ms per image for detection
Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Zigbee │────>│ Zigbee2MQTT │────>│ MQTT │────>│ Backend │──── sound out
│ Devices │ │ (Docker) │ │ Broker │ │ (Go/GQL) │ (aplay)
└─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
│
HTTP/WS + HTTPS/WSS
│
┌──────v──────┐
│ Frontend │
│ (React) │
└─────────────┘
┌─────────────┐
│ Python │◄──── HTTP ────┐
│ Face Sidecar│ │
│ (OpenCV) │ ┌─────┴─────┐
└─────────────┘ │ Backend │
port 8089 │ (Go) │
└───────────┘
Tech Stack
| Component | Technology |
|---|---|
| Backend | Go, GraphQL (gqlgen), SQLite |
| Frontend | React 18, Vite, Apollo Client, Chart.js |
| Real-time | WebSocket (graphql-ws) |
| Messaging | MQTT (Paho) |
| Face Recognition | Python, OpenCV DNN, YuNet + SFace ONNX models |
| Audio | WAV generation + aplay (ALSA) |
| TLS | Self-signed ECDSA P256 certificates (auto-generated) |
Prerequisites
- Go 1.23+
- Node.js 18+
- Python 3.10+ (for face recognition)
- Docker
- MQTT broker (e.g., Mosquitto)
- Zigbee2MQTT running and connected to your Zigbee adapter
aplay(ALSA utils) for server-side sound notifications
Quick Start
./dev-all.shThis checks prerequisites, sets up the Python virtual environment, builds the backend, starts Zigbee2MQTT (Docker), launches all services, and shows stats:
- Bridge status and version
- Device count
- Service URLs (HTTP + HTTPS)
Ctrl+C to stop all services.Manual Start
Python Face Service:
cd backend/python
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python face_service.pyThe face service starts on http://localhost:8089. ONNX models (~37MB) are downloaded automatically on first run.
Backend:
cd backend
go build -o server ./cmd/server
./serverThe backend starts on http://localhost:8080 (HTTP) and https://localhost:8443 (HTTPS with self-signed cert).
| Variable | Default | Description |
|---|---|---|
PORT | 8080 | HTTP server port |
TLS_PORT | 8443 | HTTPS server port |
DB_PATH | ./zigbee.db | SQLite database path |
MQTT_BROKER | tcp://localhost:1883 | MQTT broker address |
FACE_SERVICE_URL | http://localhost:8089 | Python face sidecar URL |
FRONTEND_DIR | ../frontend/dist | Path to built frontend assets |
cd frontend
npm install
npm run dev
The frontend starts on http://localhost:5173 and proxies /query and /api to the backend.
Production Install (KickPi / any Linux)
Clone and run the install script:
git clone https://github.com/jonathanleahy/zigbee.git /home/kickpi/zigbee
cd /home/kickpi/zigbee
sudo bash install.shThe install script:
zigbee-faces — Python face recognition sidecar (port 8089)
- zigbee-monitor — Go backend serving HTTP (8080) + HTTPS (8443)
Managing services:
sudo systemctl status zigbee-monitor # Check status
sudo systemctl status zigbee-faces
sudo journalctl -u zigbee-monitor -f # View logs
sudo journalctl -u zigbee-faces -f
sudo systemctl restart zigbee-monitor # Restart
sudo systemctl restart zigbee-facesAccess via https://\<host\>:8443 for camera support (getUserMedia requires HTTPS).
HTTPS / Camera Access
The backend auto-generates a self-signed TLS certificate on startup, including all local IP addresses as SANs. This enables:
- Browser camera access via
getUserMedia(requires secure context) - WebSocket connections over
wss://
Project Structure
zigbee/
├── backend/
│ ├── cmd/server/
│ │ ├── main.go # Entry point, HTTP/HTTPS servers, routing
│ │ └── health.go # System health endpoint (/health)
│ ├── graph/
│ │ ├── schema.graphqls # GraphQL schema
│ │ ├── schema.resolvers.go # Resolver implementations
│ │ └── resolver.go # Dependency injection
│ ├── internal/
│ │ ├── db/sqlite.go # SQLite database layer (events, devices, faces)
│ │ ├── faces/
│ │ │ ├── handlers.go # REST API handlers for face operations
│ │ │ └── python.go # HTTP client for Python face sidecar
│ │ ├── mqtt/client.go # MQTT client + event broadcasting
│ │ └── sound/sound.go # WAV tone generation + playback
│ └── python/
│ ├── face_service.py # Python face detection/recognition server
│ └── requirements.txt # Python dependencies
├── frontend/
│ ├── src/
│ │ ├── main.jsx # React entry + Apollo setup (auto WS/WSS)
│ │ ├── App.jsx # Tab navigation + bridge status
│ │ ├── App.css # All styles (dark theme)
│ │ ├── components/
│ │ │ ├── DeviceList.jsx # Device grid, light controls, flash/sound settings
│ │ │ ├── EventLog.jsx # Event table with filtering + pagination
│ │ │ ├── Toast.jsx # Toast notifications + LED flash triggers
│ │ │ ├── Charts.jsx # Sensor data time-series charts
│ │ │ ├── FaceRecognition.jsx # Face enroll/identify with camera
│ │ │ └── SystemHealth.jsx # CPU, RAM, temperature dashboard
│ │ └── graphql/queries.js # GraphQL queries, mutations, subscriptions
│ └── vite.config.js # Vite + proxy config
├── zigbee2mqtt-data/ # Zigbee2MQTT config volume
├── install.sh # Production install (systemd services)
└── dev-all.sh # Dev environment launcher
API
GraphQL (POST /query)
Queries:
events(limit, offset, deviceName)— paginated event log with optional device filterdevices— list all paired devicesbridgeStatus— bridge connection status, version, coordinatorsoundSettings— per-device sound notification settings
permitJoin(enable, duration)— enable/disable pairing moderenameDevice(ieeeAddress, newName)— rename a devicesetDeviceState(deviceId, payload)— send commands to devices (power, color, brightness)setSoundSetting(deviceName, sound)— set notification sound for a device
eventAdded— real-time event stream via WebSocket
REST — Face Recognition
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/faces/enroll | Enroll a face (JSON: {name, image_b64}) |
| POST | /api/faces/identify | Identify faces in an image (JSON: {image_b64}) |
| GET | /api/faces/profiles | List enrolled profiles with thumbnails |
| DELETE | /api/faces/profiles/{id} | Delete a profile |
| GET | /api/faces/profiles/{id}/thumbnail | Serve profile thumbnail JPEG |
| GET | /api/faces/detections | List detection history |
| GET | /api/faces/detections/{id}/thumbnail | Serve detection thumbnail JPEG |
REST — System Health
| Method | Endpoint | Description |
|---|---|---|
| GET | /health | System stats: CPU, RAM, temperature, uptime, Go runtime |
Database
SQLite database is created automatically on first run with tables:
events— event log (topic, device_name, payload, timestamp)devices— device inventory (ieee_address, friendly_name, vendor, model)sound_settings— per-device notification sound preferencesface_profiles— enrolled faces (name, encoding blob, thumbnail blob)face_detections— detection history (profile_name, confidence, thumbnail blob)
Development
Regenerate GraphQL Code
After modifying schema.graphqls:
cd backend
go generate ./...
Target Hardware
Tested on KickPi K2B (Allwinner H618, ARM64, 4 cores, 4GB RAM) running Ubuntu. Face detection runs at ~230ms per image on this hardware.
License
MIT