Removed deprecated in-process MQTT service in favor of standalone IoT Bridge container: Deleted: - services/ directory (iot_bridge_service, mqtt_client, session_detector, parsers) - Old tests (test_mqtt_connection, test_mqtt_mocked, test_session_detector, test_topic_matching, test_no_duplicate_messages) Modified: - mqtt_connection.py: action_start/stop now show deprecation message - mqtt_connection.py: Auto-start on Odoo restart disabled - mqtt_device.py: Auto-subscribe on device changes disabled - tests/__init__.py: Removed old test imports - tests/common.py: Replaced with stub (legacy support only) Reason: - Old integration ran MQTT client in Odoo process (tight coupling) - New architecture: Standalone IoT Bridge container + REST API - Better separation of concerns, scalability, and maintainability - All functionality moved to iot_bridge/ (Phase 1) + REST API (Phase 2) All old code is preserved in git history if needed. Models (mqtt.device, mqtt.session, mqtt.connection, ows.iot.event) remain unchanged.
12 KiB
TODO - Open Workshop MQTT (Stand: 30. Januar 2026)
Status-Übersicht
✅ Phase 1: Python Prototyp (ABGESCHLOSSEN)
- M0: Projekt Setup & MQTT Verbindung
- M1: Shelly PM Mini G3 Integration
- M2: Event-Normalisierung & Unified Schema
- M3: Session Detection Engine
- M4: Multi-Device Support & Config
- M5: Monitoring & Robustheit
- Unit Tests (pytest)
- Integration Tests (mit echtem MQTT Broker)
Ergebnis: python_prototype/ ist vollständig implementiert und getestet
🔄 Phase 2: ARCHITEKTUR-REDESIGN (IN ARBEIT)
ALTE Architektur (VERALTET):
Shelly PM → MQTT Broker → Odoo (MQTT Client) → Session Detection → Sessions
❌ Problem: MQTT Client in Odoo = zu eng gekoppelt, Container-Restart-Issues
NEUE Architektur (Sidecar-Pattern):
Shelly PM → MQTT Broker ← Bridge Container → REST API → Odoo (Business Logic)
✅ Vorteile:
- Klare Prozess-Trennung (Odoo = HTTP+Business, Bridge = MQTT+Retry)
- Bridge restart unabhängig von Odoo
- Docker Best Practice (ein Prozess pro Container)
- Einfache Orchestrierung via
docker compose up -d
✅ M6: Odoo Modul Grundgerüst (FERTIG - 100%)
- Modul
open_workshop_mqtterstellt - Models implementiert:
mqtt.connection- MQTT Broker Verbindungenmqtt.device- IoT Device Managementmqtt.session- Runtime Sessionsmqtt.message- Message Log (Debug)
- Views erstellt (List, Form, Kanban, Pivot, Graph)
- Security Rules (
ir.model.access.csv) - Services:
mqtt_client.py- MQTT Client (mit TLS, Auto-Reconnect)iot_bridge_service.py- Singleton Service für Connection Management- MQTT Client in Odoo - Subscribed DIREKT auf MQTT Topics ✅
- Parsers:
shelly_parser.py- Shelly PM Mini G3- Generic Parser Support
Code-Location: /models/, /services/, /views/
Flow: Shelly → MQTT → Odoo (kein REST API nötig!)
❌ M7: REST Endpoint & Authentication (GESTRICHEN!)
Begründung: Odoo hat bereits MQTT Client → REST API überflüssig!
NICHT NÖTIG weil:
- Odoo subscribed DIREKT auf MQTT Topics (via
mqtt_client.py) - Keine externe Bridge erforderlich
python_prototype/bleibt als Standalone-Tool für Tests/Entwicklung
❌ M8: Python-Bridge Integration (GESTRICHEN!)
Begründung: Python Prototype bleibt Standalone für Tests. Odoo macht Production!
❌ M7: Session-Engine in Odoo (GESTRICHEN - wird zu Bridge!)
Alte Architektur (in Odoo implementiert):
- ✅ SessionDetector State Machine in
services/session_detector.py - ✅ 5-State Machine: IDLE → STARTING → STANDBY/WORKING → STOPPING → IDLE
- ✅ Dual-Threshold Detection + Debounce
- ✅ Alle 7 Unit Tests grün
NEUE Architektur:
- 🔄 SessionDetector wird in Bridge Container portiert
- 🔄 Odoo bekommt nur noch fertige Events (run_start/run_stop)
- 🔄 Sessions werden in Odoo via REST API erstellt
Code wird wiederverwendet:
services/session_detector.py→iot_bridge/session_detector.py(leicht angepasst)- State Machine Logic bleibt identisch
- Nur Odoo-Abhängigkeiten (env, cursor) werden entfernt
🔧 M7: IoT Bridge Docker Container (IN ARBEIT - 0%)
Ziel: Separater Container für MQTT Bridge
Location: iot_bridge/ Unterverzeichnis
Tasks:
- Projekt-Struktur erstellen:
iot_bridge/ main.py # Bridge Hauptprogramm mqtt_client.py # MQTT Client (aus services/ portiert) session_detector.py # State Machine (aus services/ portiert) odoo_client.py # REST API Client für Odoo config.py # Config Management parsers/ shelly_parser.py tasmota_parser.py requirements.txt Dockerfile README.md - Docker Image:
iot_mqtt_bridge_for_odoo - ENV-Variablen:
ODOO_URL(z.B.http://odoo:8069)ODOO_TOKEN(API Token)MQTT_URL(z.B.mqtt://mosquitto:1883)
- Code-Portierung aus Odoo:
- SessionDetector State Machine
- MQTT Client (ohne Odoo-Abhängigkeiten)
- Shelly Parser
- Retry-Queue bei Odoo-Ausfall (lokal, in-memory oder SQLite)
- Config-Refresh alle 5 Min via
GET /ows/iot/config
Test:
docker build -t iot_mqtt_bridge_for_odoo iot_bridge/docker run -e ODOO_URL=... -e ODOO_TOKEN=... iot_mqtt_bridge_for_odoo
🔧 M8: Odoo REST API Endpoints (IN ARBEIT - 0%)
Ziel: Odoo bietet REST API für Bridge-Kommunikation
Tasks:
- Controller:
controllers/iot_api.pyGET /ows/iot/config- Device-Config für BridgePOST /ows/iot/event- Event-Empfang von Bridge
- Authentifizierung:
- Token in
ir.config_parameter:ows_iot.bridge_token - Bearer Token Validation in Controller
- Token in
- Event-Validation:
- Schema v1 prüfen
- Unique-Constraint auf
event_uid - 409 Conflict bei Duplikaten
- Session-Mapping:
- Events → Session-Updates
- run_start/run_stop Events
Test:
# Config abrufen
curl -H "Authorization: Bearer <token>" http://localhost:8069/ows/iot/config
# Event senden
curl -X POST -H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"schema_version":"v1","event_uid":"...","device_id":"..."}' \
http://localhost:8069/ows/iot/event
🔧 M9: Docker Compose Integration (TODO - 0%)
Tasks:
docker-compose.yamlUpdate:services: iot_bridge: image: iot_mqtt_bridge_for_odoo build: context: ./extra-addons/open_workshop/open_workshop_mqtt/iot_bridge environment: ODOO_URL: http://odoo:8069 ODOO_TOKEN: ${IOT_BRIDGE_TOKEN} MQTT_URL: mqtt://mosquitto:1883 depends_on: - odoo - mosquitto restart: unless-stopped.envTemplate mitIOT_BRIDGE_TOKENDEPLOYMENT.md- Setup-Anleitung
Test:
docker compose up -dstartet Odoo + Bridge- Bridge logs zeigen MQTT connection
- Events erscheinen in Odoo UI
- Standby/Working Thresholds ✅
- Debounce (Start: 3s, Stop: 15s) ✅
- 5-State Machine (IDLE → STARTING → STANDBY/WORKING → STOPPING → IDLE) ✅
- Timeout Detection (20s) ✅
- Duration Tracking (standby_duration_s, working_duration_s) ✅
- State Recovery nach Restart ✅
- Views & UI - Forms, Lists, Pivot Tables, Graphs ✅
- ENV-Passing Architecture - Keine Cursor-Fehler mehr! ✅
❌ TESTS BROKEN (Code IST NICHT FERTIG!)
-
8 Unit Tests schlagen fehl - Tests verwenden alte Signaturen
- Änderung nötig:
SessionDetector(device)→SessionDetector(device.id, device.name) - Änderung nötig:
detector.process_power_event(power, ts)→detector.process_power_event(env, power, ts) - Alle Assertions müssen mit
envarbeiten - Aufwand: ~1-2 Stunden (nicht 30 Min - Tests müssen auch laufen!)
- Änderung nötig:
-
**Keine grünen Tests = NICHT FERTIG!ctor(device)
→SessionDetector(device.id, device.name)`- Änderung:
detector.process_power_event(power, ts)→detector.process_power_event(env, power, ts) - Aufwand: ~30 Minuten
- Änderung:
NICHT MEHR NÖTIG
REST API Endpoint- Odoo macht MQTT direkt ✅Event Storage Model-mqtt.messagereicht für Debug ✅Python Bridge- Odoo ist die Bridge ✅
Phase 3: Optional Features (Noch nicht gestartet)
🟡 MEDIUM PRIORITY (Optional M9)
-
POS Integration (später)
- Realtime Display
- WebSocket Feed
- Live Power Consumption
-
Maintenance Integration
- Link zu
maintenance.equipment - Usage Tracking
- Separate Module
open_workshop_mqtt_maintenance
- Link zu
🟢 LOW PRIORITY (Nice-to-have)
-
Performance & Scale
- Last-Tests (20 Devices, 1h)
- Queue Optimization
- Database Indexes
-
Security Hardening
- IP Allowlist
- Rate Limiting (Reverse Proxy)
- Token Rotation
Bekannte Probleme
🐛 BUGS
-
Tests hängen mit echtem MQTT Broker
- Location:
tests/test_mqtt_connection.py, etc. - Reason: TransactionCase + Background Threads inkompatibel
- Solution: Mock-basierte Tests (erstellt, aber nicht aktiv)
- Status: WORKAROUND erstellt, muss aktiviert werden
- Location:
-
Manual Session Start/Stop TODO
- Location:
models/mqtt_device.py:327, 349 - Methods:
action_start_session(),action_stop_session() - Status: Placeholder, nicht implementiert
- Location:
-
Topic Matching ohne Wildcards
- Location:
services/iot_bridge_service.py:498 - TODO Comment: Implement proper topic matching (+, #)
- Status: Funktioniert nur mit exakten Topics
- Location:
⚠️ TECHNICAL DEBT
- Session Detection zu simpel
- Problem:
power > 0 = startist zu vereinfacht - Impact: Flackernde Sessions bei Power-Spikes
- Solution: Session-Engine aus Python portieren (M7) ← DAS IST ALLES
- Problem:
- M7: REST Endpoint
/ows/iot/eventfunktioniert- Auth Tests: ✅ Alle Tests grün
- Manual Test:
curl -H "Authorization: Bearer xxx" -X POST ...→ 200 OK
- M7: Events werden in
mqtt.eventpersistiert- Test: Event in DB sichtbar nach POST
- M8: Python Bridge sendet Events an Odoo
- Integration Test: ✅ Event kommt in Odoo an
- Manual Test: Bridge läuft, Events in Odoo UI sichtbar
- M9: Session-Detection läuft in Odoo (Dual-Threshold!)
- Unit Tests: ✅ State Machine korrekt
- Integration Test: ✅ Shelly → Session mit Debounce
- Manual Test: Maschine an/aus → Session startet/stoppt korrekt
- End-to-End: Shelly → MQTT → Bridge → Odoo → Session sichtbar
- Test: Kompletter Flow funktioniert
- Dokumentation: API, Setup, Troubleshooting komplett
Test-Driven Development:
- Jeder Milestone hat Tests BEVOR Code geschrieben wird
- Keine manuelle UI-Klickerei zum Testen
run-tests.shläuft jederzeit durch
Geschätzter Aufwand: 4-6 Tage (bei fokussierter TDD-rt
- Python Bridge sendet Events an Odoo (statt nur File)
- Events werden in
mqtt.eventpersistiert - Session-Detection läuft in Odoo (nicht nur Python)
- Sessions werden automatisch bei Events aktualisiert
- Tests laufen durch (Mock-basiert)
- End-to-End Test: Shelly → MQTT → Bridge → Odoo → Session sichtbar
- Dokumentation komplett (API, Setup, Troubleshooting)
Geschätzter Aufwand: 4-6 Tage (bei fokussierter Arbeit)
Changelog
2026-01-30 16:40 Uhr (Phase 2 FERTIG!):
- Phase 1: ✅ Komplett (Python Prototype)
- Phase 2: ✅ 100% FERTIG! - Code + Tests komplett!
- SessionDetector vollständig portiert + env-passing refactoring
- Live-Tests erfolgreich: State Machine funktioniert mit echten MQTT Messages!
- Alle 26 Unit Tests grün! (0 failed, 0 errors)
- Test-Fixes:
- test_session_detector.py: Alle 7 Tests an env-passing angepasst
- test_mqtt_mocked.py: Alle 4 Service-Tests repariert
- run-tests.sh: Verbesserte Ausgabe mit klarer Zusammenfassung
- SessionDetector ist produktionsreif!
2026-01-29 (Env-Passing Refactoring): Odoo Cursor Management gelöst
- Komplettes Refactoring: SessionDetector speichert nur IDs
- 20+ Method Signatures geändert (env-passing)
- Keine "Cursor already closed" Fehler mehr
- Live getestet mit echten MQTT Messages
2026-01-28 (Update 2): Architektur vereinfacht - Odoo macht ALLES direkt
- Phase 1: ✅ Komplett (Python Prototype)
- Phase 2: 🚧 70% (Odoo Integration)
- M7+M8 (REST/Bridge) GESTRICHEN → 2 Tage gespart!
- Nur noch: M7 (Session-Engine portieren) + M8 (Tests reparieren)
- Geschätzt: 2-3 Tage statt 4-6!