Industrial icemaker control system with async FSM, physics-based simulation, and React dashboard.
- Async State Machine: Event-driven FSM controlling the ice-making cycle (CHILL → ICE → HEAT → repeat)
- Hardware Abstraction: Supports real Raspberry Pi GPIO/sensors or mock implementations for development
- Physics-Based Simulator: Realistic thermal model for testing without hardware
- REST + WebSocket API: Real-time state updates and control via FastAPI
- React Dashboard: Live temperature charts, relay status, and cycle control
┌─────────────────────────────────────────────────────────────┐
│ React Frontend │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ State │ │ Temp │ │ Relay │ │ Controls │ │
│ │ Display │ │ Chart │ │ Status │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────┬───────────────────────────────────┘
│ WebSocket + REST
┌─────────────────────────┴───────────────────────────────────┐
│ FastAPI Backend │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Controller │ │
│ │ ┌─────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
│ │ │ FSM │ │ HAL │ │ Thermal Model │ │ │
│ │ │ States │ │ GPIO/Sensors│ │ (Simulator) │ │ │
│ │ └─────────┘ └─────────────┘ └─────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- Python 3.9+
- Node.js 18+ (for frontend development)
- uv (recommended) or pip
The easiest way to get started is using the setup script:
# Clone the repository
git clone <repo-url>
cd icemaker
# Run setup (auto-detects platform)
./setup.shThe setup script will:
- Detect if running on Raspberry Pi or development machine
- Install uv if not present (or fall back to pip)
- Install appropriate dependencies (including RPi.GPIO on Pi)
- Create
.envwith correct environment settings
# With uv (recommended)
uv run python -m icemaker
# Or with virtual environment
source .venv/bin/activate
python -m icemaker# Terminal 1: Start backend with simulator
uv run python -m icemaker --simulator
# Terminal 2: Start frontend dev server
cd frontend && npm run devOpen http://localhost:5173 to view the dashboard.
git clone <repo-url> icemaker
cd icemaker
./setup.sh --serviceThis installs dependencies and sets up a systemd service that starts on boot.
sudo systemctl start icemaker # Start the service
sudo systemctl stop icemaker # Stop the service
sudo systemctl status icemaker # Check status
journalctl -u icemaker -f # View logsBy default, the water priming sequence is skipped on startup (assumes the system is already primed). To run the priming sequence on first boot:
# One-time priming
ICEMAKER_PRIMING_ENABLED=true uv run python -m icemaker
# Or set in config/production.yaml:
# startup:
# priming_enabled: true# Upgrade pip and install
pip install --upgrade pip
pip install ".[rpi]"
# Set environment
export ICEMAKER_ENV=production
# Run
python -m icemakericemaker/
├── setup.sh # Automated setup script
├── config/ # YAML configuration files
│ ├── default.yaml # Default settings
│ ├── development.yaml # Dev environment (simulator enabled)
│ └── production.yaml # Production settings (real hardware)
├── src/icemaker/
│ ├── core/ # FSM, states, events, controller
│ ├── hal/ # Hardware abstraction layer
│ ├── simulator/ # Physics-based thermal model
│ └── api/ # FastAPI routes and WebSocket
├── tests/
│ ├── unit/ # Unit tests
│ └── integration/ # Integration tests
└── frontend/ # React + TypeScript dashboard
The system follows this state flow:
- OFF - System powered off (initial state)
- POWER_ON - Water priming sequence (optional, skipped by default)
- STANDBY - Ready, waiting for manual start
- CHILL (prechill) - Cool plate to 32°F
- ICE - Make ice at -2°F with water recirculation
- HEAT - Harvest ice by heating plate to 38°F
- CHILL (rechill) - Cool to 35°F before next cycle
- Check bin:
- If full → IDLE (auto-restarts when bin empties)
- If not full → repeat from step 4
Configuration is loaded from YAML files with environment variable overrides:
| Environment Variable | Description | Default |
|---|---|---|
ICEMAKER_ENV |
Config environment (development/production) | development |
ICEMAKER_USE_SIMULATOR |
Enable thermal simulator | false |
ICEMAKER_SKIP_PRIMING |
Skip water priming on startup | true |
ICEMAKER_PRECHILL_TEMP |
Prechill target temperature (°F) | 32.0 |
ICEMAKER_ICE_TEMP |
Ice-making target temperature (°F) | -2.0 |
ICEMAKER_HARVEST_TEMP |
Harvest threshold temperature (°F) | 38.0 |
ICEMAKER_RECHILL_TEMP |
Rechill target temperature (°F) | 35.0 |
ICEMAKER_BIN_THRESHOLD |
Bin full detection threshold (°F) | 35.0 |
config/default.yaml- Base defaultsconfig/development.yaml- Development settings (simulator enabled)config/production.yaml- Production settings (matches hardware values)
| Endpoint | Method | Description |
|---|---|---|
/api/state/ |
GET | Current icemaker state |
/api/state/cycle |
POST | Start/stop/emergency stop |
/api/state/ws |
WebSocket | Real-time updates |
/api/relays/ |
GET/POST | Relay states |
/api/sensors/ |
GET | Temperature readings |
/api/config/ |
GET/PUT | Configuration |
/health |
GET | Health check |
# Run all tests
uv run pytest tests -v
# Run unit tests only
uv run pytest tests/unit -v
# Run integration tests only
uv run pytest tests/integration -v
# Run with coverage
uv run pytest tests --cov=icemaker| Relay | GPIO Pin |
|---|---|
| Water Valve | 12 |
| Hot Gas Solenoid | 5 |
| Recirculating Pump | 6 |
| Compressor 1 | 24 |
| Compressor 2 | 25 |
| Condenser Fan | 23 |
| LED | 22 |
| Ice Cutter | 27 |
| Sensor | ID |
|---|---|
| Plate | 092101487373 |
| Ice Bin | 3c01f0956abd |
MIT