| name | gpio-controller |
| description | Web UI for controlling Raspberry Pi GPIO pins in real time. Use when you need to read or write a GPIO pin state, set PWM duty cycle or frequency, apply a saved configuration, create or schedule pin configurations, query pin history, or access the REST API from another device. Triggers include "set pin", "gpio high", "gpio low", "PWM", "pin state", "raspberry pi gpio", or any task involving GPIO pin control. |
gpio-controller
Control Raspberry Pi GPIO pins via a web UI or REST API. Real-time state via WebSocket.
When to use
- Reading or writing a GPIO pin state (HIGH/LOW)
- Setting PWM duty cycle and frequency on a PWM-capable pin
- Applying a saved named configuration to set multiple pins at once
- Creating, editing, or scheduling configurations
- Querying pin change history
- Using the REST API from another script or device
- Managing pin groups
Base URL
The server runs on the Raspberry Pi itself:
http://localhost:4800 (on the Pi)
http://pi.local:4800 (from LAN via mDNS)
http://192.168.x.x:4800 (from LAN via IP)
Configure with PORT env var if different.
Quick Reference
Set a pin HIGH
curl -X POST http://pi.local:4800/api/pins/18/write \
-H "Content-Type: application/json" \
-d '{"value": 1}'
Set a pin LOW
curl -X POST http://pi.local:4800/api/pins/18/write \
-H "Content-Type: application/json" \
-d '{"value": 0}'
Read all pin states
curl http://pi.local:4800/api/pins
Set PWM duty cycle (duty_cycle: 0-255, 191 = ~75%)
curl -X POST http://pi.local:4800/api/pins/18/pwm \
-H "Content-Type: application/json" \
-d '{"duty_cycle": 191, "frequency": 1000}'
Change pin mode
curl -X POST http://pi.local:4800/api/pins/18/mode \
-H "Content-Type: application/json" \
-d '{"mode": "output"}'
Get pin change history
curl "http://pi.local:4800/api/history?pin=18&limit=50"
Installation on Raspberry Pi
See skills/raspberry-pi-setup/SKILL.md for full setup instructions.
Quick start:
git clone <repo> gpio-controller
cd gpio-controller
pnpm install
MOCK_GPIO=0 pnpm start
Running in mock mode (no Pi hardware)
MOCK_GPIO=1 pnpm start
All GPIO operations are simulated in memory. Useful for development and testing on non-Pi hardware.
API Reference
Pins
| Method | Path | Description |
|---|
| GET | /api/pins | All pin states and config |
| POST | /api/pins/:bcm/write | Write HIGH (1) or LOW (0) to output pin |
| POST | /api/pins/:bcm/pwm | Set PWM duty_cycle (0-255) and frequency (Hz) |
| POST | /api/pins/:bcm/mode | Set mode: input, output, or pwm |
History
| Method | Path | Description |
|---|
| GET | /api/history | Pin change history (query: pin, limit, offset) |
| DELETE | /api/history | Clear all history |
WebSocket
Connect to ws://pi.local:4800 to receive real-time pin state updates.
Message types received from server:
{ "type": "snapshot", "pins": { "17": 1, "18": 0 } }
{ "type": "pin_change", "pin": 17, "value": 1, "timestamp": 1711111111111 }
Pin naming
Assign friendly names to pins via the web UI (Dashboard > click pin > Rename) or via the database:
INSERT OR REPLACE INTO pin_config (pin, mode, label) VALUES (17, 'output', 'LED 1');
Creating configurations
- Navigate to Configurations in the web UI
- Click "New configuration"
- Give it a name and description
- Add pins and their target states (HIGH / LOW / PWM %)
- Click "Save"
- Apply at any time with the "Apply" button
Scheduling configurations
- Navigate to Schedule
- Click "Add schedule"
- Select a configuration
- Enter a cron expression (e.g.
0 8 * * 1-5 for 8 AM weekdays)
- Enable the toggle
Cron expressions use standard 5-field format: minute hour day month weekday
Environment variables
| Variable | Default | Description |
|---|
| PORT | 4800 | HTTP and WebSocket server port |
| DATA_DIR | ./data | SQLite database directory |
| MOCK_GPIO | 0 | Set to 1 to use mock GPIO driver |
| HISTORY_MAX_ROWS | 10000 | Max rows in pin_history table |
Boolean env vars use 0 or 1 (not true/false).
PWM pins on Raspberry Pi
Hardware PWM is available on GPIO pins 12, 13, 18, and 19.
Software PWM (via pigpio) is available on all GPIO pins.
Hardware PWM requires the pigpiod daemon to be running:
sudo pigpiod
Pin numbering
gpio-controller uses BCM (Broadcom GPIO) numbering throughout. Physical pin numbers are shown in the web UI for reference only.
Example: GPIO 17 = Physical pin 11 = BCM 17.
Troubleshooting
Cannot access the web UI
- Check the server is running:
pnpm start
- Check the port is not blocked by firewall:
sudo ufw allow 4800
- Check the Pi's IP address:
hostname -I
GPIO permission denied
- Add your user to the gpio group:
sudo usermod -aG gpio $USER
- Then log out and back in, or run
newgrp gpio
pigpio cannot initialize
- Start the pigpiod daemon:
sudo pigpiod
- Check daemon is running:
pgrep pigpiod
- Ensure pigpio is installed:
sudo apt install pigpio