- Fix form parameter handling for recipe_id (empty string vs None) - Remove interfering hx-on attributes from HTMX forms - Add explicit hx-swap="innerHTML" for proper content replacement - Implement global exception handler with detailed DEBUG logging - Add request middleware for comprehensive request/response logging - Enhanced modal closing logic with fallbacks - Add debug logging to recipe/button creation endpoints - Create error template for better error display - Update CLI to support --log-level per subcommand - Add CLAUDE.md with development guidelines and conventions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
ECM Control
A comprehensive system for controlling espresso coffee machines with GPIO relays, scale integration, and web-based recipe management.
Features
- Web Interface: Modern HTMX-based web application for recipe management
- GPIO Control: Hardware integration for controlling espresso machines via relays
- Scale Integration: Support for Acaia scales via Bluetooth (with mock implementation for development)
- Recipe Management: Create and manage extraction recipes with target weight and timeout
- Button Mapping: Map physical buttons to specific recipes
- Shot Logging: Comprehensive logging of all extraction attempts with detailed metrics
- Real-time Monitoring: Live monitoring of extractions with automatic stopping
- Systemd Integration: Production-ready service configuration
System Requirements
Hardware
- Raspberry Pi (or compatible GPIO-enabled device)
- Relay module connected to GPIO (default: GPIO 2)
- Physical buttons connected to GPIO pins
- Acaia scale (optional, mock implementation available)
Software
- Python 3.10+
- UV package manager
- SQLite 3
Installation
1. Clone and Setup
git clone <repository-url>
cd ecm-control
2. Install Dependencies
# Install UV if not already installed
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install project dependencies
uv sync
3. Initialize Database
uv run python run.py db init
Usage
Web Application
Start the web server:
uv run python run.py web --host 0.0.0.0 --port 8000
Access the web interface at http://localhost:8000
Web Interface Features:
- Dashboard: Overview of system status and recent shots
- Recipes: Create, edit, and delete extraction recipes
- Buttons: Configure physical button to recipe mappings
- Shot History: View detailed history of all extractions
- Settings: Configure scale address, thresholds, and logging levels
GPIO Control Service
Start the GPIO control service:
# For Raspberry Pi with actual GPIO
uv run python run.py gpio
# For development/testing with mock GPIO
uv run python run.py gpio --mock
Database Management
# Initialize database
uv run python run.py db init
# Reset database (WARNING: deletes all data)
uv run python run.py db reset
Configuration
Scale Configuration
- Access the web interface
- Go to Settings
- Set the
scale_addressto your Acaia scale's Bluetooth MAC address - Configure other parameters as needed:
shot_completion_threshold: Weight change rate (g/s) to detect completionweight_stabilize_time: Seconds to wait for weight stabilizationlog_level: Logging verbosity (DEBUG, INFO, WARNING, ERROR)
Button Configuration
- Access the web interface
- Go to Buttons
- Add buttons with their GPIO pin assignments
- Map buttons to recipes
Recipe Creation
- Access the web interface
- Go to Recipes
- Create recipes with:
- Name
- Target grams out
- Timeout in seconds
Hardware Setup
Relay Connection
Connect a relay module to GPIO 2 (configurable). The relay should be wired to simulate the coffee machine's brew button press.
Wiring:
- GPIO 2 <20> Relay Signal
- 5V <20> Relay VCC
- GND <20> Relay GND
- Relay NO/COM <20> Coffee machine button circuit
Button Connections
Connect momentary buttons between GPIO pins and ground. Use internal pull-up resistors.
Example for 4 buttons:
- Button 1: GPIO 17 <20> GND
- Button 2: GPIO 18 <20> GND
- Button 3: GPIO 19 <20> GND
- Button 4: GPIO 20 <20> GND
Production Deployment
Systemd Service
- Copy the service file:
sudo cp ecm-control.service /etc/systemd/system/
-
Update the paths in the service file to match your installation
-
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable ecm-control
sudo systemctl start ecm-control
- Check service status:
sudo systemctl status ecm-control
Web Server (Optional)
For production web deployment, consider using a reverse proxy like nginx:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Development
Mock Mode
For development on non-Raspberry Pi systems, use mock mode:
# Start GPIO service with mock hardware
uv run python -m ecm_control gpio --mock
# This enables:
# - Mock GPIO buttons (can be triggered via web interface)
# - Mock relay (logs actions instead of controlling hardware)
# - Mock scale (simulates weight readings)
Debug Logging
Enable debug logging for detailed troubleshooting:
uv run python -m ecm_control gpio --log-level DEBUG
This creates detailed logs in logs/debug.log with:
- GPIO event timing
- Scale reading details
- Shot phase progression
- System state changes
Project Structure
ecm-control/
src/ecm_control/
__init__.py # Package initialization
__main__.py # CLI entry point
database/ # Database schema and management
models/ # Pydantic data models
web/ # FastAPI web application
gpio/ # GPIO control and hardware interface
utils/ # Utilities (logging, scale management)
templates/ # HTML templates
static/ # CSS/JS assets
logs/ # Log files
ecm-control.service # Systemd service file
pyproject.toml # Project configuration
README.md # This file
API Reference
The web application provides REST API endpoints:
Recipes
GET /recipes- List all recipesPOST /recipes- Create new recipeDELETE /recipes/{id}- Delete recipe
Buttons
GET /buttons- List all buttonsPOST /buttons- Create new buttonPUT /buttons/{id}- Update button recipe mapping
Shots
GET /shots- List shot history
Settings
GET /settings- List all settingsPUT /settings/{id}- Update setting value
Troubleshooting
GPIO Permissions
If you get GPIO permission errors:
sudo usermod -a -G gpio $USER
# Log out and back in
Scale Connection Issues
- Verify Bluetooth is enabled and scale is discoverable
- Check scale MAC address in settings
- Ensure scale is not connected to other devices
- Check logs for connection errors
Service Not Starting
# Check service logs
sudo journalctl -u ecm-control -f
# Check for Python path issues
sudo systemctl edit ecm-control
# Add:
# [Service]
# Environment=PYTHONPATH=/path/to/ecm-control/src
Database Issues
# Reset database if corrupted
uv run python -m ecm_control db reset
# Check database permissions
ls -la ecm_control.db
Contributing
- Fork the repository
- Create a feature branch
- Make changes with tests
- Update documentation
- Submit pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Uses pyacaia for scale integration
- Built with FastAPI and HTMX for the web interface
- GPIO control via gpiozero library