odoo_mqtt/iot_bridge/Dockerfile
matthias.lotz 19be0903d2 feat: Implement HTTP Config API for Bridge (Phase 3.1)
Implements PUSH architecture - Bridge receives config from Odoo via HTTP

NEW FEATURES:
- HTTP Config Server (FastAPI on port 8080)
  - POST /config: Receive device configuration from Odoo
  - GET /config: Query currently active configuration
  - GET /health: Health check endpoint with device statistics
  - Optional Bearer token authentication (BRIDGE_API_TOKEN)

- Config Validation (Pydantic models)
  - BridgeConfig, DeviceConfig, SessionConfig schemas
  - Validation: unique device_id, unique mqtt_topic
  - Threshold validation: working_threshold_w > standby_threshold_w

- Dynamic Device Management (DeviceManager)
  - Device diff detection (add/update/remove)
  - Automatic MQTT subscribe/unsubscribe for topic changes
  - SessionDetector lifecycle management
  - Active session closing on device removal

- Config Persistence
  - Saves received config to /data/config-active.yaml
  - Bridge startup: loads config-active.yaml as fallback
  - Docker volume iot-bridge-data:/data for persistence

NEW FILES:
- iot_bridge/config_server.py          - FastAPI HTTP server
- iot_bridge/device_manager.py         - Device lifecycle management
- iot_bridge/tests/test-config-push.sh - Integration test script
- iot_bridge/tests/test-config-push.json - Test configuration

MODIFIED FILES:
- iot_bridge/main.py                   - Integrated HTTP server in thread
- iot_bridge/mqtt_client.py            - Added subscribe()/unsubscribe()
- iot_bridge/requirements.txt          - Added fastapi, uvicorn, pydantic
- iot_bridge/Dockerfile                - EXPOSE 8080, HTTP healthcheck
- odoo/docker-compose.dev.yaml         - Port 8080, volume /data

TESTING:
Verified via iot_bridge/tests/test-config-push.sh:
 Config push via HTTP works (200 OK)
 Old devices removed, new devices added
 MQTT topics dynamically updated (subscribe/unsubscribe)
 Config persisted to /data/config-active.yaml
 Health endpoint shows last_config_update timestamp
 Bridge restarts load config-active.yaml automatically

NEXT STEP:
Phase 3.2 - Implement Odoo-side config push (Model hooks)
2026-02-12 20:05:49 +01:00

57 lines
1.7 KiB
Docker

# Multi-stage build for IoT MQTT Bridge
# Stage 1: Builder - Install dependencies
FROM python:3.11-slim AS builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc && \
rm -rf /var/lib/apt/lists/*
# Copy requirements and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
# Stage 2: Runtime - Minimal image
FROM python:3.11-slim
LABEL maintainer="Open Workshop MQTT IoT Bridge"
LABEL description="MQTT Bridge for Odoo IoT Device Integration with Session Detection"
LABEL version="1.0.0"
WORKDIR /app
# Copy installed packages from builder to site-packages (not user directory)
COPY --from=builder /root/.local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
# Copy application code
COPY *.py ./
COPY config.example.yaml ./
# Create non-root user for security
RUN useradd -m -u 1000 bridge && \
chown -R bridge:bridge /app && \
mkdir -p /app/logs /data && \
chown -R bridge:bridge /app/logs /data
# Switch to non-root user
USER bridge
# Environment variables (can be overridden at runtime)
ENV BRIDGE_CONFIG=/app/config.yaml \
PYTHONUNBUFFERED=1 \
LOG_LEVEL=INFO \
BRIDGE_PORT=8080
# Expose HTTP Config API port
EXPOSE 8080
# Health check via HTTP endpoint
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python3 -c "import requests; requests.get('http://localhost:8080/health', timeout=3).raise_for_status()" || exit 1
# CMD python -c "import socket; s=socket.socket(); s.connect(('localhost',8080)); s.close()" || exit 1
# Run bridge with unbuffered output
CMD ["python", "-u", "main.py"]