rjsears/genmaster

By rjsears

Updated 2 months ago

Generator Control System - Master Controller for Raspberry Pi

Image
0

7.2K

rjsears/genmaster repository overview

RPi Generator Control

RPi Generator Control

Documentation Latest Release Last Commit License: MIT Issues Pull Requests

Docker Build Lint Stars Forks

Python FastAPI Pydantic SQLAlchemy

Vue.js Pinia Tailwind CSS Vite Chart.js

PostgreSQL Redis Docker Nginx

Cloudflare Tailscale Let's Encrypt Apprise Raspberry Pi

View Full Documentation

A working (in production in my system), distributed generator control system designed for off-grid solar installations with Victron energy systems. Built on a master-slave architecture using Raspberry Pi devices, it provides automated generator management with manual override capabilities, scheduling, and real-time monitoring through a modern web interface.

While designed around Victron integration, the architecture is universal—any two-wire trigger source (home automation, PLC, manual switch, or relay output) can signal GenMaster, and GenSlave can control any device with a two-wire start input (generators, pumps, HVAC, irrigation, industrial equipment). With optional Tailscale VPN and Cloudflare Tunnel support, your trigger source and controlled device can operate anywhere in the world—same building or different continents, wherever there's internet access.


Watch the demo video


Table of Contents


Overview

The RPi Generator Control system automates generator management for off-grid solar installations. When your Victron Cerbo GX determines that battery levels are low and generator power is needed, it sends a signal to GenMaster, which coordinates with GenSlave to physically start the generator.

System Overview


Safety by Design

This is a system that starts and stops a real generator in a real location, sometimes unattended. Safety is treated as a first-class concern, not an afterthought — it shows up at every layer of the stack:

  • Hardware EPO at the generator that physically opens the start circuit with a Schneider XB4 mushroom E-stop. No software override exists or can exist — even if every Pi is offline and every line of code in this repo has a bug, the generator cannot start while the EPO is engaged.
  • HOA selector at the operator location for everyday Quiet / Auto / Run mode control without touching the web UI.
  • Independent failsafe on GenSlave that drops the relay if it stops hearing from GenMaster for 30 seconds — without any network, database, or web UI dependency.
  • Fail-safe boot policy that ships the relay disarmed on every GenMaster restart unless the operator explicitly opts into preserve-state behavior.
  • Two-layer notification system so a failure on the master side still pages you from the slave side.

How the EPO and HOA work together

The EPO and HOA are optional — the system runs fine without either — but together they give you the hardware-enforced safety and operator-side control you'd expect from a production-grade generator setup. See Hardware Switches for the full operator guide and the Security model for why the two-layer pattern is the actual safety guarantee.


Features

Automated Control
FeatureDescription
Victron IntegrationMonitors GPIO signal from Cerbo GX relay for automated start/stop
Scheduled RunsAPScheduler-based scheduling with cron expressions
Manual OverrideForce start/stop from web UI regardless of Victron signal
State MachineComprehensive state tracking (idle, starting, running, stopping, cooldown)
Reliability & Safety
FeatureDescription
Automation ArmingExplicit arm/disarm prevents accidental operations during startup or maintenance
Heartbeat SystemContinuous health monitoring between GenMaster and GenSlave
Independent FailsafeGenSlave automatically stops generator if communication lost for 30s
Hardware EPO (optional)Schneider XB4 mushroom E-stop at the generator. NC contact physically interrupts the start circuit AND signals software — hardware-enforced maintenance lockout
HOA Selector (optional)Schneider XB4 3-position rotary at the operator location. Quiet / Auto / Run modes for everyday operator control without touching the web UI
State PersistencePostgreSQL database survives reboots and power failures
Webhook NotificationsReal-time alerts to n8n, Home Assistant, or any webhook receiver
Modern Web Interface
FeatureDescription
Real-time DashboardLive status updates via WebSocket
Dark ModeFull dark/light theme support
Mobile ResponsiveWorks on any device
Container ManagementPortainer integration for Docker control
Generator Information & Fuel Tracking
FeatureDescription
Generator ProfileStore manufacturer, model number, and serial number
Fuel ConfigurationConfigure fuel type (LPG, Natural Gas, Diesel) and expected load
Consumption RatesSet fuel consumption rates at 50% and 100% load
Per-Run TrackingAutomatically track fuel usage for each generator run
Fuel HistoryView estimated fuel consumed in run history
Exercise Scheduling
FeatureDescription
Automated ExerciseSchedule regular generator runs for maintenance
Configurable FrequencySet exercise interval (weekly, bi-weekly, monthly, or custom)
Time SelectionChoose start time for exercise runs
Duration ControlSet how long each exercise run should last
Run NowManually trigger an exercise run on demand
Operational Excellence
FeatureDescription
Run HistoryComplete log of all generator runs with duration, trigger, and fuel usage
StatisticsDaily, monthly, and all-time runtime tracking
System HealthCPU, memory, disk, and temperature monitoring
Backup/RestoreDatabase backup with one-click restore

System and Network Architecture

System Architecture

Component Overview
ComponentTechnologyPurpose
GenMaster BackendFastAPI + Python 3.11REST API, state machine, scheduler
GenMaster FrontendVue.js 3 + Tailwind CSSReactive web interface
DatabasePostgreSQL 16State persistence, run history, configuration
CacheRedisSession storage, real-time data
Reverse ProxyNginxHTTPS termination, rate limiting, security headers
GenSlave BackendFastAPI (Docker)Relay control, heartbeat responder
HATPimoroni Automation Hat MiniPhysical relay + LCD status display

Hardware Requirements

GenMaster
ComponentSpecification
ComputerRaspberry Pi 5 (8GB RAM)
Storage128GB NVMe SSD via PCIe adapter
Power5V 5A USB-C supply (27W recommended)
GPIOPin 11 (GPIO17) for Victron input
NetworkWiFi or Ethernet
GenSlave
ComponentSpecification
ComputerRaspberry Pi Zero 2W
HATPimoroni Automation Hat Mini
StorageQuality SD card or USB SSD
Power5V 2.5A supply
RelayBuilt-in 24V @ 2A max (GPIO16)
DisplayBuilt-in 0.96" 160x80 LCD
Victron Connection
  • 2-wire normally-open contact from Cerbo GX MK2 Relay
  • Connected to GPIO17 (Pin 11) and Ground (Pin 9)
Optional Hardware Switches (EPO + HOA)

Both switches are optional — the system runs fine without either. Together they provide hardware safety at the generator and operator-side mode control. See Hardware Switches for the full operator guide.

SwitchSchneider P/NWires to
EPO actuator (mushroom E-stop at the generator)XB4-BS542The contact block below — mounts in any 22 mm panel cutout
EPO contact blockZB4-BZ104 (1 NC + 1 NO)NC in series with the GenSlave start-relay circuit; NO from Auto Hat Mini 5V → IN1
HOA actuator (3-position rotary at the operator)XB4-BD33The contact block below
HOA contact blockZB4-BZ103 (2 NO)Block A NO → GenMaster GPIO22 (Quiet); Block B NO → GPIO27 (Run); shared common → GND
HOA legend plate (optional)ZBY2-seriesPrinted QUIET / AUTO / RUN labels around the rotary knob

Total parts cost: ~$70–120 for both switches plus the optional legend plate. Order from AutomationDirect, Mouser, or Digikey — avoid no-name Amazon listings as Schneider counterfeits are common and defeat the point of paying for rated safety hardware.

  • Internal pull-up resistor enabled

Tested Deployment

This is what I've actually verified in my own off-grid setup — not just what the design supports on paper. Other hardware combinations (different Pi models, alternative relay HATs, other battery monitors) may work fine but have not been field-tested here.

AreaTested configuration
GenMasterRaspberry Pi 5, 8GB, Raspberry Pi OS 64-bit
GenSlaveRaspberry Pi Zero 2 W
Relay HATPimoroni Automation HAT Mini
Trigger sourceVictron Cerbo GX MK2 relay
NetworkLAN baseline (same-network operation works with no VPN). Tailscale optional — required for remote administration or when GenMaster and GenSlave are on different networks. Cloudflare Tunnel optional — used to expose the GenMaster web UI publicly.
Boot policies testedfail_safe and preserve_state (both verified across real reboots)
Failure tests runGenMaster reboot mid-operation, GenSlave reboot mid-operation, network loss between master and slave, heartbeat loss triggering GenSlave's independent failsafe, relay forced OFF on failsafe trigger

Known Limitations

A handful of architectural and operational realities to be aware of before deploying this in your own setup:

  • Fuel usage is estimated, not measured. The fuel-tracking number is calculated from runtime × your configured consumption-rate values (fuel_consumption_50 / fuel_consumption_100) — there is no actual fuel-flow sensor. Accuracy depends on how well your rate values match real-world performance.

  • Network and security configuration is non-trivial. This project has many moving parts (nginx reverse proxy, cloudflared tunnel, Tailscale, per-route auth, IP allowlists). Read docs/SECURITY.md end-to-end before exposing GenMaster beyond your LAN.

  • GenSlave needs privileged GPIO access. It runs as a privileged container with host networking so the Pimoroni Automation Hat Mini can drive GPIO. That's a deliberate trade-off — if you compromise the GenSlave container, you have effective root on the Pi Zero. See docs/SECURITY.md#container-privilege-model.

  • Tested with my specific hardware setup; other generators may need wiring/config changes. Generators differ in start-contact polarity, voltage tolerance, dry-vs-wet contacts, hold-time requirements, etc. The relay control logic itself is generator-agnostic, but the physical wiring between GenSlave's relay and your generator's start input is your responsibility to verify.


Quick Start

Prerequisites
  • Raspberry Pi 5 with Raspberry Pi OS (64-bit)
  • Docker and Docker Compose installed
  • Network connectivity between GenMaster and GenSlave
One-Command Install
curl -fsSL https://raw.githubusercontent.com/rjsears/pizero_generator_control/main/genmaster/install.sh | sudo bash
Manual Installation
# Clone repository
git clone https://github.com/rjsears/pizero_generator_control.git
cd pizero_generator_control/genmaster

# Run interactive setup
./setup.sh

The setup wizard will:

  1. Detect environment - Raspberry Pi, LXC container, or standard Linux
  2. LXC Warning - Show Proxmox configuration requirements if running in LXC
  3. Hardware detection - Enable mock GPIO mode if not on Raspberry Pi
  4. System checks - Verify memory, disk, ports, network connectivity
  5. Install Docker if needed (with platform-specific guidance for macOS/WSL)
  6. Domain validation - DNS resolution, IP matching, connectivity tests
  7. Configure GenSlave - IP address, API secret (prominently displayed for copying)
  8. Connection validation - Retries 3 times with 10-second delays if GenSlave is starting
  9. Configure timezone - Default America/Phoenix with host sync option
  10. Configure generator info - Optional manufacturer, model, fuel type, consumption rates
  11. Optional services - Tailscale VPN, Cloudflare Tunnel, Portainer
  12. Generate configs - .env, docker-compose.yml, nginx.conf
  13. Deploy stack - Start all containers
Setup Command Line Options
# Interactive setup
./setup.sh

# Show help
./setup.sh --help

# Use pre-configuration file
./setup.sh --config myconfig.conf

# Validate GenSlave connection (run after GenSlave is set up)
./setup.sh --genslave

# Update GenSlave IP/URL address
./setup.sh --genslaveip

# Show version
./setup.sh --version
Pre-configuring Generator Information

To pre-populate generator information during setup, create a gen_info.json file:

# Copy the template
cp genmaster/setup/gen_info.json.template genmaster/setup/gen_info.json

# Edit with your generator details
nano genmaster/setup/gen_info.json

Template contents:

{
  "manufacturer": "Generac",
  "model_number": "7043",
  "serial_number": "ABC123456",
  "fuel_type": "lpg",
  "load_expected": 50,
  "fuel_consumption_50": 1.6,
  "fuel_consumption_100": 2.8
}

The setup wizard will detect this file and offer to use these values. Fuel type options: lpg, natural_gas, diesel. Load options: 50 or 100.

Verify Installation
# Check container status
docker compose ps

# View logs
docker compose logs -f genmaster

# Access web interface
# https://your-domain.com or https://genmaster (via Tailscale)
GenSlave Installation (Pi Zero 2W)

GenSlave runs as a Docker container on the Pi Zero 2W:

# SSH into your Pi Zero
ssh [email protected]

# Download and run the setup script
curl -fsSL https://raw.githubusercontent.com/rjsears/pizero_generator_control/main/genslave/setup.sh -o setup.sh
chmod +x setup.sh
sudo ./setup.sh

The GenSlave setup will:

  1. Install Docker - From Debian repositories (optimized for Pi Zero)
  2. Install Docker Compose - For container orchestration
  3. Prompt for API secret - Must match GenMaster's SLAVE_API_SECRET
  4. Configure notifications - Optional Apprise URLs for failsafe alerts
  5. Pull Docker image - Pre-built ARM image from Docker Hub
  6. Create systemd service - Auto-start container on boot
  7. Configure Tailscale - Optional VPN for GenMaster connectivity
  8. Start container - Begin listening on port 8001
Verify GenSlave
# Check container status
cd /opt/genslave
docker-compose ps

# View logs
docker-compose logs -f

# Test API (requires API key)
curl -H "X-API-Key: your-api-secret" http://localhost:8001/api/health

Configuration

Environment Variables

Configuration is managed through .env file. Key settings:

# Domain Configuration
DOMAIN=genmaster.example.com

# Application
APP_ENV=production
APP_DEBUG=false
APP_SECRET_KEY=<generated-secret>

# Database
DATABASE_USER=genmaster
DATABASE_PASSWORD=<generated-password>
DATABASE_NAME=genmaster

# GenSlave Communication
SLAVE_API_URL=http://genslave.local:8001
SLAVE_API_SECRET=<shared-secret>

# Heartbeat
HEARTBEAT_INTERVAL_SECONDS=10
HEARTBEAT_FAILURE_THRESHOLD=3

# Webhooks (Optional)
WEBHOOK_BASE_URL=https://n8n.example.com/webhook/xxx
WEBHOOK_SECRET=<webhook-secret>

# Generator Information (Optional - can be configured via UI)
GEN_INFO_MANUFACTURER=Generac
GEN_INFO_MODEL_NUMBER=7043
GEN_INFO_SERIAL_NUMBER=ABC123456
GEN_INFO_FUEL_TYPE=lpg           # lpg, natural_gas, or diesel
GEN_INFO_LOAD_EXPECTED=50        # 50 or 100
GEN_INFO_FUEL_CONSUMPTION_50=1.6 # gal/hr at 50% load
GEN_INFO_FUEL_CONSUMPTION_100=2.8 # gal/hr at 100% load

# Cloudflare Tunnel
CLOUDFLARE_TUNNEL_TOKEN=<tunnel-token>

# Tailscale (Optional)
TAILSCALE_AUTHKEY=<auth-key>
TAILSCALE_HOSTNAME=genmaster
Docker Profiles

Enable optional services using profiles:

# Basic stack (GenMaster, PostgreSQL, Nginx)
docker compose up -d

# With Tailscale VPN
docker compose --profile tailscale up -d

# With Cloudflare Tunnel
docker compose --profile cloudflare up -d

# With Portainer
docker compose --profile portainer up -d

# All optional services
docker compose --profile tailscale --profile cloudflare --profile portainer up -d

Web Interface

Dashboard

The dashboard provides at-a-glance status of:

  • Generator State - Current status with color-coded indicator
  • GenSlave Status - Online/offline with last heartbeat time
  • Victron Signal - Active/inactive GPIO17 state
  • System Health - CPU, memory, disk usage
Quick Actions
  • Start Generator - Manual start (requires GenSlave online)
  • Stop Generator - Manual stop
  • View Schedule - Manage scheduled runs
  • View History - Browse run history with fuel consumption data
Generator Tab
  • Generator Information - View and edit manufacturer, model, serial number
  • Fuel Configuration - Set fuel type, expected load, and consumption rates
  • Exercise Schedule - Configure automated maintenance runs
    • Enable/disable exercise scheduling
    • Set frequency (weekly, bi-weekly, monthly, or custom days)
    • Configure start time and duration
    • Run exercise immediately with "Run Now" button
Settings
  • Webhook Configuration - URL, secret, event toggles
  • GenSlave Settings - API URL and secret
  • Backup/Restore - Database backup management
  • System - Timezone, logging level

API Reference

Generator Control
# Get current status
GET /api/status

# Start generator manually
POST /api/generator/start
Content-Type: application/json
{"trigger": "manual"}

# Stop generator
POST /api/generator/stop
Schedule Management
# List schedules
GET /api/schedule

# Create schedule
POST /api/schedule
Content-Type: application/json
{
  "name": "Morning Run",
  "cron_expression": "0 6 * * *",
  "duration_minutes": 60,
  "enabled": true
}

# Delete schedule
DELETE /api/schedule/{id}
Generator Information
# Get generator info
GET /api/generator-info

# Response
{
  "manufacturer": "Generac",
  "model_number": "7043",
  "serial_number": "ABC123456",
  "fuel_type": "lpg",
  "load_expected": 50,
  "fuel_consumption_50": 1.6,
  "fuel_consumption_100": 2.8
}

# Update generator info (partial update)
PATCH /api/generator-info
Content-Type: application/json
{
  "manufacturer": "Generac",
  "fuel_type": "lpg",
  "load_expected": 50
}
Exercise Schedule
# Get exercise schedule
GET /api/exercise

# Response
{
  "enabled": true,
  "frequency_days": 7,
  "start_time": "10:00",
  "duration_minutes": 15,
  "last_exerci

Tag summary

Content type

Image

Digest

sha256:dee4d64c5

Size

244.1 MB

Last updated

2 months ago

docker pull rjsears/genmaster:sha-42fe97b