A lightweight, secure REST API daemon for remote GPIO control on Linux systems with GPIO support (Raspberry Pi, embedded Linux devices, etc.). Perfect for home automation, IoT projects, and remote device control.
- Modern GPIO Interface: Uses libgpiod (not deprecated sysfs)
- RESTful API: Clean HTTP endpoints for GPIO control
- Secure Authentication: SHA-256 hashed token-based authentication
- Friendly Pin Names: Map GPIO pins to meaningful names (e.g., "door_strike", "outdoor_light")
- Device Type System:
- Trigger devices: Momentary activation (door strikes, garage doors)
- Switch devices: Persistent on/off control (lights, relays)
- State Persistence: Switch devices remember their state across restarts
- Active-Low Support: Built-in support for active-low logic (relays, opto-isolators)
- Home Assistant Ready: Easy integration with Home Assistant
- Docker Deployment: Containerized with GPIO device pass-through
- Async Operations: Non-blocking trigger operations with concurrent request protection
- Linux system with GPIO support (Raspberry Pi, etc.)
- Docker and Docker Compose
- Access to GPIO device (
/dev/gpiochip0)
- Clone the repository:
git clone https://github.com/pmokbel/libgpiod-relay-rest-api.git
cd libgpiod-relay-rest-api- Copy and configure the example config:
cp config.example.json config.json- Generate an API token hash:
./generate-token-hash.sh "your-secret-token"-
Update
config.jsonwith your token hash and GPIO pin definitions -
Run with Docker Compose:
docker-compose up -dThe API will be available at http://localhost:8080
{
"api_token_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"gpio_chip": "/dev/gpiochip0",
"devices": {
"door_strike": {
"gpio": "GPIO26",
"type": "trigger",
"trigger_duration_ms": 200,
"description": "Door strike relay"
},
"outdoor_light": {
"gpio": "GPIO17",
"type": "switch",
"description": "Outdoor light control"
}
}
}-
trigger: Momentary activation devices (door strikes, garage openers)- Allowed operations:
read,trigger - Requires
trigger_duration_msfield
- Allowed operations:
-
switch: Persistent on/off devices (lights, relays)- Allowed operations:
read,on,off - State persists across restarts
- Allowed operations:
Many relays use active-low logic where LOW (0V) = active. Set "active_low": true to invert the logic:
- With
active_low: true: API "on" → 0V on pin → relay activates - With
active_low: false: API "on" → 3.3V on pin → normal behavior
All endpoints require Authorization header with your token.
GET /api/version
# Returns: {"version": "1.0.0", "api": "GPIO Relay API"}GET /api/devices
Authorization: your-secret-token
# Returns: {"devices": {...}}GET /api/devices/{device_id}
Authorization: your-secret-token
# Returns: {"id": "outdoor_light", "state": "on"}# Turn switch on/off
POST /api/devices/{device_id}
Authorization: your-secret-token
Content-Type: application/json
{"state": "on"} # or "off" or "trigger"
# Trigger device
POST /api/devices/{device_id}
Authorization: your-secret-token
Content-Type: application/json
{"state": "trigger"}POST /api/cmd
Authorization: your-secret-token
Content-Type: application/json
{"id": "door_strike", "state": "trigger"}# Switch operations
PUT /api/devices/{device_id}/on
PUT /api/devices/{device_id}/off
# Trigger operations
PUT /api/devices/{device_id}/trigger# configuration.yaml
switch:
- platform: rest
name: "Outdoor Light"
resource: "http://192.168.1.100:8080/api/devices/outdoor_light"
is_on_template: '{{ value_json.state == "on" }}'
headers:
Authorization: !secret gpio_api_token
body_on: '{"state": "on"}'
body_off: '{"state": "off"}'# configuration.yaml
rest_command:
unlock_front_door:
url: "http://192.168.1.100:8080/api/devices/door_strike/trigger"
method: PUT
headers:
Authorization: !secret gpio_api_token
# automations.yaml
automation:
- alias: "Front Door Unlock Button"
trigger:
- platform: state
entity_id: input_button.unlock_front_door
action:
- service: rest_command.unlock_front_doorStore your token in secrets.yaml:
gpio_api_token: "your-secret-token-here"# Install dependencies
pip install -r requirements.txt
# Run with custom config
python server.py --config /path/to/config.json
# Or use default config.json
python server.pydocker-compose build- Never commit
config.jsonwith production tokens - Use strong, random tokens for production
- The API token is sent as plaintext; use HTTPS in production
- Token hash uses SHA-256 for server-side validation
- Example token hash (
9f86d081...) is for token "test"
- Python 3.11+
- FastAPI
- libgpiod (Python bindings)
- Uvicorn
- Linux with GPIO support
- Framework: FastAPI (modern async Python web framework)
- GPIO Library: libgpiod (modern kernel interface)
- Server: Uvicorn (ASGI server)
- Container: Docker with device pass-through
- Security: Token-based authentication with SHA-256 hashing
- SETUP.md - Detailed setup and deployment guide
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Report issues on the GitHub issue tracker
- Check documentation for common questions