ECM_Control/CLAUDE.md

5.4 KiB

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:

# 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:

uv run python run.py web --log-level DEBUG --port 8000

GPIO Control Service:

# 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:

# 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:

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:

git add .
git commit -m "Description of changes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>"

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):

sudo usermod -a -G gpio $USER
# Then log out and back in

GPIO pin conflicts:

# 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.