# Claude Development Guide for ECM Control This file contains important information for Claude Code when working on the ECM Control project. ## Project Overview ECM Control is an Espresso Coffee Machine Control System built with: - **Backend**: Python, FastAPI, SQLite - **Frontend**: HTMX, Bootstrap, Vanilla JavaScript - **Hardware**: Raspberry Pi GPIO, relay control, Acaia scale integration - **Package Manager**: UV (not pip/poetry) - **Database**: SQLite with schema in `src/ecm_control/database/schema.sql` ## Package Management - IMPORTANT **Always use UV, never use pip or poetry:** ```bash # Install dependencies uv add package-name # Remove dependencies uv remove package-name # Run commands in virtual environment uv run python script.py # Sync dependencies uv sync ``` ## Running the Application **Web Application:** ```bash uv run python run.py web --log-level DEBUG --port 8000 ``` **GPIO Control Service:** ```bash # With actual hardware uv run python run.py gpio # With mock hardware (for development) uv run python run.py gpio --mock --log-level DEBUG ``` **Database Management:** ```bash # Initialize database uv run python run.py db init # Reset database (deletes all data) uv run python run.py db reset ``` ## Development Commands **Testing endpoints:** - Web interface: http://localhost:8000 - Debug with console logging enabled in browser - Server logs show detailed request/response info at DEBUG level **Database queries for debugging:** ```bash uv run python -c " import sys; sys.path.insert(0, 'src') from ecm_control.database import DatabaseManager db = DatabaseManager() recipes = db.execute_query('SELECT * FROM recipes') print(recipes) " ``` ## Code Style and Conventions **File Structure:** - `src/ecm_control/` - Main package - `templates/` - Jinja2 HTML templates - `static/` - CSS/JS assets - `run.py` - Main entry point (use this instead of module execution) **Logging:** - Use `from ecm_control.utils.logging_config import get_logger` - Logger name: `logger = get_logger('module_name')` - DEBUG level shows detailed request/exception info **Database:** - Use `DatabaseManager` class for all DB operations - Schema in `src/ecm_control/database/schema.sql` - Models in `src/ecm_control/models/__init__.py` ## Git Workflow **When making changes:** ```bash git add . git commit -m "Description of changes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude " ``` **Commit message format:** - Use conventional commits (feat:, fix:, docs:, etc.) - Include the Claude Code footer - Be descriptive about what changed and why ## Testing and Deployment **Before committing:** 1. Test web interface functionality 2. Test GPIO service in mock mode 3. Verify database operations work 4. Check logs for errors/warnings **Hardware Testing:** - Use `--mock` flag for development without GPIO hardware - Real hardware requires Raspberry Pi with GPIO pins - Scale integration uses mock implementation (pyacaia had build issues) **Production Deployment:** - Copy `ecm-control.service` to `/etc/systemd/system/` - Update paths in service file for your installation - Use `systemctl` to manage the service ## Common Issues and Solutions **"No module named ecm_control":** - Use `uv run python run.py` instead of `uv run python -m ecm_control` **HTMX not updating UI:** - Check browser console for JavaScript errors - Verify `hx-target` selectors match element IDs - Ensure `hx-swap="innerHTML"` is specified for content replacement **Database errors:** - Reset database: `uv run python run.py db reset` - Check file permissions on `ecm_control.db` **GPIO permissions (on Raspberry Pi):** ```bash sudo usermod -a -G gpio $USER # Then log out and back in ``` **GPIO pin conflicts:** ```bash # Show safe GPIO pins and current configuration uv run python run.py gpio-info # Show pins during GPIO service startup uv run python run.py gpio --show-pins ``` **Safe GPIO pins for buttons:** 4, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 **Avoid these pins:** 5, 6, 7, 9 (SPI), 14, 15 (UART), 2, 3 (I2C) **Form validation errors (422):** - Check FastAPI endpoint parameter types - Handle empty strings vs None for optional fields - Use `str = Form("")` and convert to int/None in endpoint ## Architecture Notes **Web Application:** - FastAPI with dependency injection - HTMX for dynamic UI updates - Bootstrap for styling - Jinja2 templates with partials for HTMX responses **GPIO Control:** - Async event-driven architecture - Mock implementations for development - Real-time shot monitoring with scale feedback - Database logging of all shot attempts **Database Schema:** - `recipes` - extraction recipes (grams + timeout) - `buttons` - physical GPIO buttons mapped to recipes - `shots` - log of all extraction attempts - `settings` - configurable system parameters ## File Locations **Key configuration files:** - `pyproject.toml` - Project dependencies and metadata - `ecm-control.service` - Systemd service configuration - `src/ecm_control/database/schema.sql` - Database schema - `src/ecm_control/web/__init__.py` - FastAPI web application - `src/ecm_control/gpio/__init__.py` - GPIO control logic **Templates:** - `templates/base.html` - Base template with navigation - `templates/partials/` - HTMX response templates - `static/css/style.css` - Custom styles - `static/js/app.js` - Frontend JavaScript Remember: This is a hardware control system, so safety and reliability are important. Always test thoroughly and handle errors gracefully.