Automatic Pool Cover Controller for Raspberry Pi
PyPoolPi is an extensible, event-driven pool cover controller built for the Raspberry Pi (or other Linux single-board computers). Designed around a modular finite state machine, it provides automated opening and closing operations, sensor-based end detection, safety timeouts, custom dive sequences, real-time cover state persistence, an interactive web dashboard + API and MQTT integration for smart home automation.
- Extensible State Machine Controller: Thread-safe finite state machine managing pool cover states (
OPENING,CLOSING,STOPPED,OPENED,CLOSED, etc.) with pluggable extension modules. - Custom Dive Sequence: Configurable multi-stage closing sequence (hanging, diving, surfacing) to prevent cover folding issues during closing operations.
- Sensor-Based End Detection: Automatic stop trigger using sensors with overrun delay for precise full-open and full-close positioning.
- Safety Timeout Protection: Automatically halts motor movement if configurable max opening or closing durations are exceeded to protect hardware.
- Hardware Abstraction Layer: Clean abstraction for different motor and sensor models and hardware/GPIO libraries.
- Dynamic Hot-Reloading Configuration: Configuration system with zero-downtime runtime updates and a TOML config file with hot-reload support on changes.
- Interactive Web UI & REST API: Built-in web server serving a control dashboard, API endpoints (
/command,/status,/config,/log), and Server-Sent Events. - MQTT Smart Home Integration: Full MQTT broker integration for remote command execution, status streaming, and live log broadcasting.
- State Persistence: Remembers and restores cover state across service restarts using configurable storage targets.
- Production-Ready Deployment: Systemd unit configuration with automated installation and version upgrade scripts for Raspberry Pi OS.
-
Clone the repository:
git clone https://github.com/Rhynaz/PyPoolPi.git cd PyPoolPi -
Create and activate a Python 3.13 virtual environment:
python3.13 -m venv .venv source .venv/bin/activate -
Install dependencies:
python3.13 -m pip install -r requirements.txt
-
Run PyPoolPi:
python3.13 main.py
-
Clone the repository into a versioned folder (e.g.,
~/pypoolpi-v1):git clone https://github.com/Rhynaz/PyPoolPi.git ~/pypoolpi-v1 -
Run the installation script with
sudo:sudo ~/pypoolpi-v1/pypoolpi_install.sh
The script installs system APT packages (python3-gpiozero, python3-flask, python3-paho-mqtt, etc.), sets network binding capabilities (CAP_NET_BIND_SERVICE), creates a symlink at ~/pypoolpi, and enables the pypoolpi.service systemd unit.
To deploy a new release without breaking service state:
-
Clone the new version:
git clone https://github.com/Rhynaz/PyPoolPi.git ~/pypoolpi-v2 -
Execute the version switch script:
sudo ~/pypoolpi-v2/pypoolpi_switch.sh
This gracefully stops the running service, updates the symlink to the new directory, and restarts pypoolpi.service.
PyPoolPi hosts an HTTP web server (default port 5000) serving a control dashboard and API endpoints:
| Endpoint | Method | Description |
|---|---|---|
/ |
GET |
Interactive web dashboard |
/command/open |
POST |
Trigger cover to open |
/command/close |
POST |
Trigger cover to close |
/command/stop |
POST |
Trigger cover to stop |
/status |
GET |
Returns current cover state (JSON) |
/config |
GET / PUT |
Read or update configuration schema dynamically |
/log |
GET |
View recent in-memory system log output |
/events |
GET |
Server-Sent Events (SSE) stream for real-time updates |
When enabled, PyPoolPi connects to an MQTT broker to integrate seamlessly with smart home platforms:
- Command Topic (default:
pypoolpi/command): Listens foropen,close, orstopmessages and executes the corresponding command. - State Topic (default:
pypoolpi/state): Publishes updated state names (OPENED,CLOSED,OPENING,CLOSING,STOPPED, etc.). - Log Topic (default:
pypoolpi/log): Publishes log records in real time.
- Python: 3.13+
- Operating System: Linux (Raspberry Pi OS, Debian or equivalent)
- Hardware: Raspberry Pi (or similar SBC with GPIO pins) or any PC (when using mock hardware).
| Package | Purpose |
|---|---|
gpiozero |
GPIO pin abstraction for motor control & sensor inputs |
Flask |
Lightweight web application framework for dashboard & API |
waitress |
Production WSGI HTTP server |
paho-mqtt |
Client library for MQTT communication |
mashumaro |
Serialization & deserialization for configuration |
tomli_w |
TOML encoder for Python |
watchdog |
Filesystem event monitoring for hot-reloading configuration |
| Path | Description |
|---|---|
config |
Dynamic and thread-safe runtime configuration management system |
config/parts |
Config schema implemented as dataclasses |
controller |
Main cover controller logic connecting hardware, state machine and persistence |
controller/extensions |
Modular state machine plugins for advanced behaviors (dive sequence, end detection, safety timeout) |
controller/state_machine |
Extensible state machine engine, state and extension interface contracts |
core |
Interfaces defining controller, hardware and persistence contracts |
hardware |
Hardware access implementation and factory for instatiating hardware drivers |
hardware/motor |
Motor driver implementations supporting different motors and hardware libraries |
hardware/sensor |
Driver implementations interacting with different end detection proximity switches |
persistence |
Persistence implementations handling all load / store operations. |
persistence/targets |
Storage backends, supporting file-based persistence and mock targets |
persistence/config.py |
Hot-reloading TOML configuration loader and filesystem event monitor |
presentation/http |
Web interface including an interactive dashboard and HTTP API for controlling the pool cover |
presentation/mqtt |
MQTT interface for triggering commands, getting the cover state and logs |
utils |
Shared utility modules including thread-safe value holders, caller introspection, and background timers |
utils/log |
Custom configuration based logging setup with exclusion filters and in-memory log buffers |
main.py |
Main application entry point, handles command-line arguments, dependency wiring, and graceful shutdown |
pypoolpi.service |
Systemd service unit for running PyPoolPi automatically as a background daemon |
pypoolpi_install.sh |
System installer script for installing dependencies, network capabilities, symlinks, and service |
pypoolpi_run.sh |
Wrapper script executed by systemd to run PyPoolPi unprivileged in the correct working directory |
pypoolpi_switch.sh |
Version switcher script that updates symlinks and restarts pypoolpi.service |
The system supports configurable GPIO pin assignments. Below is the pin mapping for our custom controller board:
| Pin Number | Function |
|---|---|
| 17 | Sensor Data |
| 27 | Motor Relay |
| 22 | Motor Relay |
| 5 | Sensor Power |
| 6 | Backup Relay |
PyPoolPi - Automatic pool cover controller running on a Raspberry Pi
Copyright (C) 2026 Elias*
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.