open_workshop/open_workshop_mqtt/TODO.md
matthias.lotz f1b0c50fbf fix: MQTT topic matching + UI button fixes
- Fix MQTT topic pattern matching (_mqtt_topic_matches):
  * Implement proper # wildcard (multi-level)
  * Implement proper + wildcard (single-level)
  * Fix bug where first device got ALL messages
  * Now shaperorigin/# only matches shaperorigin/* topics

- Fix Stop Connection button (Odoo-style):
  * Remove manual commit() - let Odoo handle it
  * Use write() to update state
  * Handle case where service doesn't have connection

- Fix Test Connection hanging:
  * Add proper cleanup with sleep after disconnect
  * Catch cleanup exceptions

- Add @unittest.skip to real MQTT tests:
  * TransactionCase incompatible with paho-mqtt threads
  * See TODO.md M8 for details

- Fix run-tests.sh:
  * Remove -i flag (was hanging)
  * Simplify to direct output redirect

- Add TODO.md documentation
- Update .gitignore for test logs
2026-01-28 22:08:59 +01:00

12 KiB

TODO - Open Workshop MQTT (Stand: 28. 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: Odoo Integration (IN ARBEIT - 70% fertig)

Architektur: Odoo macht ALLES direkt (kein REST API, keine externe Bridge)

Shelly PM → MQTT Broker → Odoo (MQTT Client) → Session Detection → Sessions

M6: Odoo Modul Grundgerüst (FERTIG - 100%)

  • Modul open_workshop_mqtt erstellt
  • Models implementiert:
    • mqtt.connection - MQTT Broker Verbindungen
    • mqtt.device - IoT Device Management
    • mqtt.session - Runtime Sessions
    • mqtt.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 (TEILWEISE FERTIG - 20%) [war M9]

Was funktioniert:

  • mqtt.session Model existiert
  • Basic Session CRUD
  • Session Views (Pivot, Graph, Analytics)
  • Device-Session Verknüpfung
  • VEREINFACHTE Session Detection in iot_bridge_service.py:543-594:
    • Power > 0 → Session start
    • Power == 0 → Session end
    • Duration Tracking (total_duration_s)

Was FEHLT (kritisch):

  • RICHTIGE Session Detection Logic (aus Python Prototype übernehmen):
    Aktuell: power > 0 → start, power == 0 → end (ZU SIMPEL!)
    Benötigt: Dual-Threshold State Machine aus session_detector.py
    
    ⚠️ WICHTIG: strategy_config EXISTIERT in UI + Model + Validation,
               wird aber in _process_session() IGNORIERT!
    
    • Dual-Threshold Detection:
      • Standby Threshold (z.B. 20W) - Maschine an, Spindel aus
      • Working Threshold (z.B. 100W) - Spindel läuft
      • UI Field existiert (mqtt_device_views.xml:106 - JSON Editor)
      • Validation existiert (mqtt_device.py:195)
      • Wird NICHT verwendet in _process_session()!
    • Debounce Timer:
      • Start Debounce (3s) - Power muss 3s über Threshold bleiben
      • Stop Debounce (15s) - Power muss 15s unter Threshold bleiben
      • In strategy_config definiert
      • Wird NICHT verwendet!
    • State Machine (5 States):
      IDLE → STARTING (debounce) → STANDBY/WORKING → STOPPING (debounce) → IDLE
      
    • Timeout Detection (20s keine Messages → Session end)
      • message_timeout_s in strategy_config
      • Wird NICHT geprüft!
    • Duration Tracking:
      • standby_duration_s (Zeit in Standby)
      • working_duration_s (Zeit in Working - das ist die eigentliche Laufzeit!)
    • State Recovery nach Odoo Restart
    • end_reason Logic (normal/timeout/power_drop)

Aktueller Code-Location:

  • Vereinfacht: services/iot_bridge_service.py:543 (_process_session())
  • UI + Validation: models/mqtt_device.py + views/mqtt_device_views.xml:106
  • Helper: device.get_strategy_config_dict() existiert
  • FEHLT: State Machine + strategy_config wird NICHT verwendet!

Implementation:

  1. Session Detector Service portieren

    • File: services/session_detector.py
    • Class SessionDetector (aus Python Prototype)
    • States: IDLE, STARTING, STANDBY, WORKING, STOPPING
    • Config aus mqtt.device.strategy_config lesen
  2. Integration in iot_bridge_service.py

    • _process_session() ersetzen durch SessionDetector
    • Timeout Check Worker (jede Sekunde)
    • State Recovery nach Restart
  3. Session Model erweitern

    • Fields: standby_duration_s, working_duration_s
    • Field: state (idle/starting/standby/working/stopping)
    • Computed: actual_working_time (= working_duration_s)

Tests (parallel entwickeln):

  • test_session_detector.py:
    • test_idle_to_starting_transition()
    • test_start_debounce_timer()
    • test_standby_to_working_transition()
    • test_stop_debounce_timer()
    • test_timeout_detection()
    • test_state_recovery_after_restart()
    • test_duration_tracking()
  • test_session_integration.py:
    • test_full_session_cycle() (MQTT → Session mit Debounce)
    • test_session_timeout_scenario()

Code zu portieren:

  • python_prototype/session_detector.py (515 Zeilen) → services/session_detector.py

Datei-Struktur:

/services/session_detector.py       # Portiert aus Python
/services/iot_bridge_service.py     # _process_session() erweitern
/models/mqtt_session.py              # Fields erweitern
/tests/test_session_detector.py     # Tests!
/tests/test_session_integration.py  # Tests!

Feature Request Referenz: Section 6 (Verarbeitungslogik), Anhang C (Shelly Examples)


🚧 M8: Test-Infrastruktur reparieren (BLOCKIERT - 0.5 Tag) [war M10]

Problem:

  • Alte Tests mit echtem MQTT Broker hängen in TransactionCase
  • test_mqtt_mocked.py erstellt, aber nicht aktiv

TODO:

  1. Alte hängende Tests deaktivieren

    cd tests/
    mv test_mqtt_connection.py DISABLED_test_mqtt_connection.py
    mv test_device_status.py DISABLED_test_device_status.py
    mv test_session_detection.py DISABLED_test_session_detection.py
    mv test_start_stop.py DISABLED_test_start_stop.py
    
  2. Mock-Tests aktivieren und testen

    • test_mqtt_mocked.py aktiv lassen
    • run-tests.sh durchlaufen lassen
    • Verifizieren: Tests laufen durch ohne Hanging
  3. Test-Coverage erweitern (parallel zu M7-M9)

    • Tests werden bei jedem Milestone erstellt (siehe oben)
    • Nicht am Ende, sondern während der Entwicklung!

Dokumentation (am Ende):

  • README.md erstellt
  • Feature Request aktuell
  • TODO.md (dieses Dokument)
  • API Dokumentation (/docs/API.md)
    • Endpoint Schema (Event v1)
    • Authentication
    • Error Codes
  • Deployment Guide (/docs/DEPLOYMENT.md)
    • Production Setup
    • Docker Compose Example
    • Systemd Service
  • Troubleshooting Guide (/docs/TROUBLESHOOTING.md)

Zusammenfassung: Was ist implementiert vs. was fehlt?

FUNKTIONIERT (Odoo Integration)

  1. MQTT Connection - Broker Verbindung mit TLS, Auto-Reconnect
  2. Device Management - Devices anlegen, konfigurieren
  3. Message Parsing - Shelly PM Mini G3 Payloads parsen
  4. VEREINFACHTE Session Detection - Power > 0 → Session (ABER ZU SIMPEL!)
  5. Views & UI - Forms, Lists, Pivot Tables, Graphs

FEHLT (Nur noch 2 Dinge!)

  1. RICHTIGE Session Detection - Dual-Threshold State Machine fehlt
    • Aktuell: power > 0 = start, power == 0 = end (ZU SIMPEL!)
    • Benötigt: Standby/Working Thresholds, Debounce, Timeout
  2. Odoo Tests - Tests hängen, Mocks nicht aktiv

NICHT MEHR NÖTIG

  • REST API Endpoint - Odoo macht MQTT direkt
  • Event Storage Model - mqtt.message reicht für Debug
  • Python Bridge - Odoo ist die Bridge

Prioritäten (Nächste Schritte)

🔥 HIGH PRIORITY (Phase 2 abschließen - NUR NOCH 2-3 Tage!)

Reihenfolge (mit Tests!):

  1. M8: Test-Infrastruktur reparieren (0.5 Tag - ZUERST!)

    • Alte hängende Tests deaktivieren
    • run-tests.sh zum Laufen bringen
    • Dann können wir TDD machen!
  2. M7: Session-Engine portieren + Tests (1-2 Tage)

    • State Machine Tests → State Machine Code
    • Debounce Tests → Debounce Logic Code
    • Timeout Tests → Timeout Detection Code
    • Portierung aus Python Prototype (Tests existieren bereits!)
    • Das ist der einzige große Brocken!
  3. Dokumentation (0.5 Tag - parallel)

    • Setup Guide
    • Troubleshooting

M7+M8 (REST/Bridge) GESTRICHEN = 2 Tage gespart! 🎉

🟡 MEDIUM PRIORITY (Optional M11)

  1. POS Integration (später)

    • Realtime Display
    • WebSocket Feed
    • Live Power Consumption
  2. Maintenance Integration

    • Link zu maintenance.equipment
    • Usage Tracking
    • Separate Module open_workshop_mqtt_maintenance

🟢 LOW PRIORITY (Nice-to-have)

  1. Performance & Scale

    • Last-Tests (20 Devices, 1h)
    • Queue Optimization
    • Database Indexes
  2. Security Hardening

    • IP Allowlist
    • Rate Limiting (Reverse Proxy)
    • Token Rotation

Bekannte Probleme

🐛 BUGS

  1. 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
  2. Manual Session Start/Stop TODO

    • Location: models/mqtt_device.py:327, 349
    • Methods: action_start_session(), action_stop_session()
    • Status: Placeholder, nicht implementiert
  3. Topic Matching ohne Wildcards

    • Location: services/iot_bridge_service.py:498
    • TODO Comment: Implement proper topic matching (+, #)
    • Status: Funktioniert nur mit exakten Topics

⚠️ TECHNICAL DEBT

  1. Session Detection zu simpel
    • Problem: power > 0 = start ist zu vereinfacht
    • Impact: Flackernde Sessions bei Power-Spikes
    • Solution: Session-Engine aus Python portieren (M7) ← DAS IST ALLES
  • M7: REST Endpoint /ows/iot/event funktioniert
    • Auth Tests: Alle Tests grün
    • Manual Test: curl -H "Authorization: Bearer xxx" -X POST ... → 200 OK
  • M7: Events werden in mqtt.event persistiert
    • 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.sh lä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.event persistiert
  • 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-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!