1336 lines
36 KiB
Markdown
1336 lines
36 KiB
Markdown
# IoT Bridge - Optimization Plan
|
|
|
|
**Projekt:** IoT MQTT Bridge Code-Qualität & Wartbarkeit
|
|
**Version:** 1.0
|
|
**Datum:** 18. Februar 2026
|
|
**Status:** 🚧 In Umsetzung (Phase 0-1 abgeschlossen, Phase 2 weitgehend umgesetzt)
|
|
|
|
---
|
|
|
|
## 🎯 Projektziele
|
|
|
|
1. **Code-Qualität verbessern** ohne Funktionalitätsverlust
|
|
2. **Wartbarkeit erhöhen** durch bessere Struktur
|
|
3. **Testabdeckung erweitern** für kritische Komponenten
|
|
4. **Kompatibilität** mit Odoo-Modul vollständig erhalten
|
|
5. **Performance** durch gezielte Optimierungen steigern
|
|
|
|
---
|
|
|
|
## 📋 Grundprinzipien
|
|
|
|
- ✅ **Backward-Kompatibilität:** Keine Breaking Changes für Odoo-Integration
|
|
- ✅ **Inkrementell:** Kleine, testbare Änderungen
|
|
- ✅ **Test-First:** Jede Änderung wird durch Tests abgesichert
|
|
- ✅ **Dokumentation:** Code-Änderungen werden dokumentiert
|
|
- ✅ **Review-Ready:** Commits sind atomar und nachvollziehbar
|
|
|
|
---
|
|
|
|
## 🗓️ Projektphasen
|
|
|
|
### **Phase 0: Verzeichnisstruktur** ⏱️ ~2-3 Stunden
|
|
*Ziel: Klare, logische Verzeichnisstruktur für besseren Überblick*
|
|
|
|
### **Phase 1: Foundation & Quality Tools** ⏱️ ~4-6 Stunden
|
|
*Ziel: Test-Infrastruktur und Code-Quality-Tools etablieren*
|
|
|
|
### **Phase 2: Code Organization** ⏱️ ~6-8 Stunden
|
|
*Ziel: Code-Struktur verbessern, Verantwortlichkeiten klären*
|
|
|
|
### **Phase 3: Type Safety & Error Handling** ⏱️ ~4-5 Stunden
|
|
*Ziel: Type Hints vervollständigen, robuste Fehlerbehandlung*
|
|
|
|
### **Phase 4: Testing & Documentation** ⏱️ ~6-8 Stunden
|
|
*Ziel: Test-Coverage erhöhen, Dokumentation verbessern*
|
|
|
|
### **Phase 5: Performance & Observability** ⏱️ ~4-6 Stunden
|
|
*Ziel: Performance optimieren, Monitoring verbessern*
|
|
|
|
---
|
|
|
|
## 📦 Phase 0: Verzeichnisstruktur
|
|
|
|
**Status:** ✅ **ABGESCHLOSSEN**
|
|
**Aufwand:** ~2 Stunden (erwartet: 2-3h)
|
|
**Priorität:** 🔴 Hoch (Fundament für alle anderen Phasen)
|
|
**Abhängigkeiten:** Keine
|
|
**Git-Commit:** `a5929ed`
|
|
|
|
### Motivation
|
|
|
|
Eine klare Verzeichnisstruktur:
|
|
- ✅ Verbessert die Übersichtlichkeit
|
|
- ✅ Erleichtert Navigation im Code
|
|
- ✅ Trennt Verantwortlichkeiten (Separation of Concerns)
|
|
- ✅ Macht Abhängigkeiten explizit
|
|
- ✅ Vorbereitung für zukünftige Erweiterungen (z.B. weitere Parser)
|
|
|
|
### Ziel-Struktur
|
|
|
|
```
|
|
iot_bridge/
|
|
├── main.py # Entry Point (bleibt im Root)
|
|
├── requirements.txt
|
|
├── Dockerfile
|
|
├── config.yaml
|
|
├── config.example.yaml
|
|
│
|
|
├── core/ # ✨ NEU - Kern-Logik
|
|
│ ├── __init__.py
|
|
│ ├── session_detector.py # State Machine
|
|
│ ├── event_queue.py # Event Queue mit Retry
|
|
│ └── device_manager.py # Device Lifecycle Management
|
|
│
|
|
├── clients/ # ✨ NEU - External Integrations
|
|
│ ├── __init__.py
|
|
│ ├── mqtt_client.py # MQTT Broker Client
|
|
│ └── odoo_client.py # Odoo REST API Client
|
|
│
|
|
├── parsers/ # ✨ NEU - Message Parser
|
|
│ ├── __init__.py
|
|
│ ├── base.py # ✨ NEU - Parser Protocol/Base Class
|
|
│ ├── shelly_parser.py # Shelly PM Parser
|
|
│ └── tasmota_parser.py # ✨ Placeholder für zukünftige Parser
|
|
│
|
|
├── api/ # ✨ NEU - HTTP API
|
|
│ ├── __init__.py
|
|
│ ├── server.py # FastAPI App (von config_server.py)
|
|
│ └── models.py # ✨ NEU - Pydantic Models separiert
|
|
│
|
|
├── config/ # ✨ NEU - Configuration
|
|
│ ├── __init__.py
|
|
│ ├── schema.py # Config Schema (von config.py)
|
|
│ └── loader.py # Config Loader (von config.py)
|
|
│
|
|
├── utils/ # ✨ NEU - Utilities
|
|
│ ├── __init__.py
|
|
│ ├── logging.py # Logger Setup (von logger_setup.py)
|
|
│ └── status_monitor.py # Device Status Monitor
|
|
│
|
|
├── tests/ # Tests (bestehend, erweitert)
|
|
│ ├── conftest.py
|
|
│ ├── fixtures/
|
|
│ ├── unit/
|
|
│ ├── integration/
|
|
│ └── tools/
|
|
│
|
|
└── logs/ # Log files
|
|
```
|
|
|
|
### Aufgaben
|
|
|
|
#### 0.1 Verzeichnisse erstellen
|
|
**Aufwand:** 5 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `mkdir -p core clients parsers api config utils`
|
|
- [x] `touch core/__init__.py clients/__init__.py parsers/__init__.py api/__init__.py config/__init__.py utils/__init__.py`
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Alle Verzeichnisse existieren
|
|
- ✅ `__init__.py` in jedem Verzeichnis
|
|
|
|
---
|
|
|
|
#### 0.2 Core-Module verschieben
|
|
**Aufwand:** 30 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `session_detector.py` → `core/session_detector.py`
|
|
- [x] `event_queue.py` → `core/event_queue.py`
|
|
- [ ] `device_manager.py` → `core/device_manager.py`
|
|
- [ ] Imports in allen Dateien anpassen:
|
|
- `from session_detector import` → `from core.session_detector import`
|
|
- `from event_queue import` → `from core.event_queue import`
|
|
- `from device_manager import` → `from core.device_manager import`
|
|
|
|
**Betroffene Dateien:**
|
|
- `main.py`
|
|
- `tests/unit/test_*.py`
|
|
- `tests/integration/test_*.py`
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ `python main.py --config config.yaml` startet ohne ImportError
|
|
- ✅ `pytest tests/` läuft durch
|
|
|
|
---
|
|
|
|
#### 0.3 Client-Module verschieben
|
|
**Aufwand:** 20 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `mqtt_client.py` → `clients/mqtt_client.py`
|
|
- [x] `odoo_client.py` → `clients/odoo_client.py`
|
|
- [ ] Imports anpassen:
|
|
- `from mqtt_client import` → `from clients.mqtt_client import`
|
|
- `from odoo_client import` → `from clients.odoo_client import`
|
|
|
|
**Betroffene Dateien:**
|
|
- `main.py`
|
|
- `core/device_manager.py`
|
|
- Tests
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Bridge startet ohne Fehler
|
|
- ✅ MQTT-Connection funktioniert
|
|
- ✅ Tests laufen durch
|
|
|
|
---
|
|
|
|
#### 0.4 Parser-Module verschieben & erweitern
|
|
**Aufwand:** 40 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `parsers/base.py` erstellen mit Parser-Protocol/Base-Class
|
|
- [x] `shelly_parser.py` → `parsers/shelly_parser.py`
|
|
- [x] `shelly_parser.py` von `base.py` ableiten
|
|
- [ ] `parsers/tasmota_parser.py` als Placeholder erstellen (skip - nicht benötigt)
|
|
- [ ] Imports anpassen:
|
|
- `from shelly_parser import` → `from parsers.shelly_parser import`
|
|
|
|
**parsers/base.py:**
|
|
```python
|
|
"""Base parser interface for MQTT message parsers."""
|
|
from typing import Protocol, Dict, Optional
|
|
from abc import ABC, abstractmethod
|
|
|
|
class MessageParser(Protocol):
|
|
"""Protocol for message parsers."""
|
|
|
|
def parse_message(self, topic: str, payload: dict) -> Optional[Dict]:
|
|
"""Parse MQTT message to standardized format."""
|
|
...
|
|
|
|
class BaseParser(ABC):
|
|
"""Base class for message parsers with common utilities."""
|
|
|
|
@abstractmethod
|
|
def parse_message(self, topic: str, payload: dict) -> Optional[Dict]:
|
|
"""Parse MQTT message. Must be implemented by subclasses."""
|
|
pass
|
|
|
|
def _extract_device_id(self, topic: str) -> str:
|
|
"""Extract device ID from topic (override if needed)."""
|
|
parts = topic.split('/')
|
|
return parts[0] if parts else "unknown"
|
|
```
|
|
|
|
**Betroffene Dateien:**
|
|
- `core/device_manager.py`
|
|
- Tests
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Shelly-Parser funktioniert wie vorher
|
|
- ✅ Base-Class ist für neue Parser wiederverwendbar
|
|
|
|
---
|
|
|
|
#### 0.5 API-Module verschieben & aufteilen
|
|
**Aufwand:** 30 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `config_server.py` → `api/server.py` (FastAPI-App)
|
|
- [x] Pydantic-Models in `api/models.py` extrahieren
|
|
- [ ] Imports anpassen:
|
|
- `from config_server import` → `from api.server import`
|
|
- `from config_server import BridgeConfig` → `from api.models import BridgeConfig`
|
|
|
|
**api/models.py (NEU):**
|
|
```python
|
|
"""Pydantic models for API validation."""
|
|
from pydantic import BaseModel, Field, validator
|
|
from typing import List, Optional
|
|
|
|
class MqttConfig(BaseModel):
|
|
"""MQTT Broker configuration."""
|
|
broker: str = Field("localhost")
|
|
port: int = Field(1883)
|
|
# ... rest der Models von config_server.py
|
|
```
|
|
|
|
**Betroffene Dateien:**
|
|
- `main.py`
|
|
- Tests
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ HTTP-API funktioniert (`/health`, `/config`)
|
|
- ✅ Config-Push von Odoo funktioniert
|
|
- ✅ Pydantic-Validation unverändert
|
|
|
|
---
|
|
|
|
#### 0.6 Config-Module verschieben & aufteilen
|
|
**Aufwand:** 30 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `config.py` aufteilen:
|
|
- Dataclasses → `config/schema.py`
|
|
- Loader-Functions → `config/loader.py`
|
|
- [ ] Imports anpassen:
|
|
- `from config import load_config` → `from config.loader import load_config`
|
|
- `from config import BridgeConfig` → `from config.schema import BridgeConfig`
|
|
|
|
**config/__init__.py:**
|
|
```python
|
|
"""Configuration package."""
|
|
from config.schema import (
|
|
MQTTConfig,
|
|
OdooConfig,
|
|
LoggingConfig,
|
|
SessionConfig,
|
|
DeviceConfig,
|
|
BridgeConfig,
|
|
)
|
|
from config.loader import load_config, load_devices_from_config
|
|
|
|
__all__ = [
|
|
"MQTTConfig",
|
|
"OdooConfig",
|
|
"LoggingConfig",
|
|
"SessionConfig",
|
|
"DeviceConfig",
|
|
"BridgeConfig",
|
|
"load_config",
|
|
"load_devices_from_config",
|
|
]
|
|
```
|
|
|
|
**Betroffene Dateien:**
|
|
- `main.py`
|
|
- `api/server.py`
|
|
- Tests
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Config-Loading funktioniert
|
|
- ✅ YAML-Parsing unverändert
|
|
- ✅ Backward-Kompatibilität zu bestehenden config.yaml
|
|
|
|
---
|
|
|
|
#### 0.7 Utils-Module verschieben
|
|
**Aufwand:** 15 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] `logger_setup.py` → `utils/logging.py`
|
|
- [x] `device_status_monitor.py` → `utils/status_monitor.py`
|
|
- [ ] Imports anpassen:
|
|
- `from logger_setup import` → `from utils.logging import`
|
|
- `from device_status_monitor import` → `from utils.status_monitor import`
|
|
|
|
**Betroffene Dateien:**
|
|
- `main.py`
|
|
- `core/device_manager.py`
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Logging funktioniert
|
|
- ✅ Status-Monitor funktioniert
|
|
|
|
---
|
|
|
|
#### 0.8 Import-Cleanup & __init__.py befüllen
|
|
**Aufwand:** 20 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] Alle `__init__.py` befüllen mit Public API
|
|
- [x] Relative Imports innerhalb Packages nutzen
|
|
- [x] Absolute Imports von außen
|
|
|
|
**Beispiel core/__init__.py:**
|
|
```python
|
|
"""Core business logic for IoT Bridge."""
|
|
from core.session_detector import SessionDetector
|
|
from core.event_queue import EventQueue, QueuedEvent
|
|
from core.device_manager import DeviceManager
|
|
|
|
__all__ = [
|
|
"SessionDetector",
|
|
"EventQueue",
|
|
"QueuedEvent",
|
|
"DeviceManager",
|
|
]
|
|
```
|
|
|
|
**main.py imports werden:**
|
|
```python
|
|
# Vorher:
|
|
from config import load_config
|
|
from logger_setup import setup_logging
|
|
from odoo_client import MockOdooClient, OdooClient
|
|
from mqtt_client import MQTTClient
|
|
from session_detector import SessionDetector
|
|
from event_queue import EventQueue
|
|
from config_server import ConfigServer, BridgeConfig
|
|
from device_manager import DeviceManager
|
|
from device_status_monitor import DeviceStatusMonitor
|
|
|
|
# Nachher:
|
|
from config import load_config
|
|
from config.schema import BridgeConfig
|
|
from utils.logging import setup_logging
|
|
from clients.odoo_client import MockOdooClient, OdooClient
|
|
from clients.mqtt_client import MQTTClient
|
|
from core import SessionDetector, EventQueue, DeviceManager
|
|
from api.server import ConfigServer
|
|
from api.models import BridgeConfig as ApiBridgeConfig
|
|
from utils.status_monitor import DeviceStatusMonitor
|
|
```
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Imports sind konsistent
|
|
- ✅ Keine zirkulären Imports
|
|
- ✅ IDE/Editor zeigt korrekte Auto-Completion
|
|
|
|
---
|
|
|
|
#### 0.9 Tests aktualisieren
|
|
**Aufwand:** 20 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] Alle Test-Imports anpassen
|
|
- [x] Test-Fixtures auf neue Struktur anpassen
|
|
- [x] `pytest tests/` durchlaufen lassen (Syntax validiert, pytest nicht installiert)
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Alle Tests laufen durch
|
|
- ✅ Keine ImportErrors
|
|
- ✅ Test-Coverage unverändert
|
|
|
|
---
|
|
|
|
#### 0.10 Dokumentation aktualisieren
|
|
**Aufwand:** 10 Minuten
|
|
|
|
**Aufgaben:**
|
|
- [x] README.md "Project Structure" Sektion aktualisieren
|
|
- [x] Import-Beispiele im Code aktualisieren
|
|
- [x] `git mv` Commits mit aussagekräftigen Messages
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ README.md zeigt neue Struktur
|
|
- ✅ Git-History ist nachvollziehbar
|
|
|
|
---
|
|
|
|
### Migrations-Strategie
|
|
|
|
**Git-Workflow:**
|
|
```bash
|
|
# 1. Feature-Branch
|
|
git checkout -b refactor/phase0-directory-structure
|
|
|
|
# 2. Verzeichnisse erstellen
|
|
mkdir -p core clients parsers api config utils
|
|
# __init__.py files...
|
|
|
|
# 3. Git mv (erhält History!)
|
|
git mv session_detector.py core/
|
|
git mv event_queue.py core/
|
|
git mv device_manager.py core/
|
|
git commit -m "refactor: Move core modules to core/ directory"
|
|
|
|
git mv mqtt_client.py clients/
|
|
git mv odoo_client.py clients/
|
|
git commit -m "refactor: Move client modules to clients/ directory"
|
|
|
|
# ... usw. für jeden Schritt
|
|
|
|
# 4. Imports anpassen
|
|
# ... Code-Änderungen ...
|
|
git commit -m "refactor: Update imports for new directory structure"
|
|
|
|
# 5. Tests anpassen
|
|
# ... Test-Änderungen ...
|
|
git commit -m "test: Update test imports for new structure"
|
|
|
|
# 6. Final verification
|
|
pytest tests/
|
|
python main.py --help
|
|
```
|
|
|
|
**Rollback-Plan:**
|
|
```bash
|
|
# Falls etwas schiefgeht:
|
|
git reset --hard origin/main
|
|
```
|
|
|
|
---
|
|
|
|
### Erfolgskriterien Gesamt
|
|
|
|
- [ ] Alle Module in logischen Verzeichnissen
|
|
- [ ] `pytest tests/` - Alle Tests grün
|
|
- [ ] `python main.py --config config.yaml` - Bridge startet
|
|
- [ ] MQTT-Connection funktioniert
|
|
- [ ] Config-Push von Odoo funktioniert
|
|
- [ ] Health-Endpoint erreichbar (`curl localhost:8080/health`)
|
|
- [ ] Docker-Build erfolgreich: `docker build -t iot_bridge:test .`
|
|
- [ ] Git-History sauber (git mv verwendet)
|
|
|
|
---
|
|
|
|
### Kompatibilität
|
|
|
|
**✅ Keine Breaking Changes:**
|
|
- API-Endpoints unverändert (`/health`, `/config`)
|
|
- Config-File-Format (`config.yaml`) kompatibel
|
|
- ENV-Variablen funktionieren weiter
|
|
- Docker-Image-Build unverändert
|
|
- Odoo-Integration unberührt
|
|
|
|
**⚠️ Nur intern geändert:**
|
|
- Python-Import-Paths (nur relevant für Entwickler)
|
|
- Test-Imports (werden angepasst)
|
|
|
|
---
|
|
|
|
### Vorteile der neuen Struktur
|
|
|
|
1. **Klarere Verantwortlichkeiten:**
|
|
- `core/` = Business Logic
|
|
- `clients/` = External Systems
|
|
- `parsers/` = Message Parsing
|
|
- `api/` = HTTP Interface
|
|
- `config/` = Configuration
|
|
- `utils/` = Shared Utilities
|
|
|
|
2. **Bessere Skalierbarkeit:**
|
|
- Neue Parser in `parsers/` hinzufügen
|
|
- Neue Clients (z.B. InfluxDB) in `clients/`
|
|
- Weitere APIs in `api/`
|
|
|
|
3. **Einfacheres Testing:**
|
|
- Abhängigkeiten sind klar
|
|
- Mocking ist einfacher
|
|
- Unit Tests pro Package
|
|
|
|
4. **IDE-Support:**
|
|
- Bessere Auto-Completion
|
|
- Klarere Fehler-Meldungen
|
|
- Navigate to Definition funktioniert besser
|
|
|
|
---
|
|
|
|
## 📦 Phase 1: Foundation & Quality Tools
|
|
|
|
**Status:** ✅ **ABGESCHLOSSEN**
|
|
**Aufwand:** ~4 Stunden (erwartet: 4-6h)
|
|
**Priorität:** 🔴 Hoch (Blocker für andere Phasen)
|
|
**Abhängigkeiten:** Phase 0 abgeschlossen
|
|
**Git-Commit:** `fdddba7`
|
|
|
|
### Aufgaben
|
|
|
|
#### 1.1 Code-Quality-Tools einrichten
|
|
**Dateien:** `pyproject.toml`, `.pre-commit-config.yaml`
|
|
|
|
**Aufgaben:**
|
|
- [x] `pyproject.toml` erstellen mit Tool-Konfigurationen
|
|
- Black (Code-Formatter)
|
|
- isort (Import-Sortierer)
|
|
- mypy (Type-Checker)
|
|
- pytest (Test-Runner mit Coverage)
|
|
- flake8 (Linter)
|
|
- [x] `.pre-commit-config.yaml` für Git-Hooks erstellen
|
|
- [x] Pre-commit hooks lokal testen: `pre-commit run --all-files`
|
|
- [x] README.md mit Development-Setup aktualisieren
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ `black .` läuft ohne Fehler
|
|
- ✅ `isort .` läuft ohne Fehler
|
|
- ✅ `flake8 .` zeigt max. 5 Warnings
|
|
- ✅ Pre-commit hooks funktionieren
|
|
|
|
**Kompatibilität:** ✅ Keine Auswirkung auf Runtime
|
|
|
|
**Dateien zu erstellen:**
|
|
```
|
|
iot_bridge/
|
|
├── pyproject.toml # NEU
|
|
├── .pre-commit-config.yaml # NEU
|
|
└── .flake8 # NEU (optional)
|
|
```
|
|
|
|
---
|
|
|
|
#### 1.2 Test-Infrastruktur erweitern
|
|
**Dateien:** `tests/conftest.py`, `tests/fixtures.py`
|
|
|
|
**Aufgaben:**
|
|
- [x] Zentrale `conftest.py` mit Shared Fixtures erstellen
|
|
- [x] Mock-Factory für häufige Test-Objekte (MQTTClient, EventQueue, etc.)
|
|
- [x] Fixture für temporäre Config-Dateien
|
|
- [x] Fixture für MQTT-Broker-Simulation (in-memory)
|
|
- [x] Test-Utilities für Assert-Helpers
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ `pytest tests/` läuft ohne Setup-Fehler
|
|
- ✅ Fixtures sind wiederverwendbar
|
|
- ✅ Coverage-Report wird generiert
|
|
|
|
**Kompatibilität:** ✅ Keine Auswirkung auf Runtime
|
|
|
|
**Dateien zu erstellen:**
|
|
```
|
|
iot_bridge/tests/
|
|
├── conftest.py # NEU - Shared fixtures
|
|
├── fixtures/ # NEU - Test fixtures
|
|
│ ├── __init__.py
|
|
│ ├── mqtt_fixtures.py
|
|
│ ├── config_fixtures.py
|
|
│ └── device_fixtures.py
|
|
└── helpers.py # NEU - Test utilities
|
|
```
|
|
|
|
---
|
|
|
|
#### 1.3 CI/CD Pipeline (optional)
|
|
**Dateien:** `.github/workflows/test.yml`
|
|
|
|
**Aufgaben:**
|
|
- [x] GitHub Actions Workflow für Tests erstellen
|
|
- [x] Matrix-Testing: Python 3.10, 3.11, 3.12
|
|
- [x] Coverage-Report zu GitHub Actions hinzufügen
|
|
- [x] Docker-Build-Test in Pipeline
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Tests laufen automatisch bei Push/PR
|
|
- ✅ Docker-Image wird erfolgreich gebaut
|
|
|
|
**Kompatibilität:** ✅ Keine Auswirkung auf Runtime
|
|
|
|
---
|
|
|
|
## 📦 Phase 2: Code Organization
|
|
|
|
**Status:** ✅ Abgeschlossen (2.1-2.4 umgesetzt inkl. Resttests)
|
|
**Aufwand:** ~6-8 Stunden
|
|
**Priorität:** 🟡 Mittel
|
|
**Abhängigkeiten:** Phase 0-1 abgeschlossen
|
|
**Git-Commits:** `e744a1e`, `548f94a`, `eb3c49c`, `527b564`, `bad1d5d`
|
|
|
|
### Aufgaben
|
|
|
|
#### 2.1 Custom Exceptions erstellen
|
|
**Dateien:** `exceptions.py` (NEU), `mqtt_client.py`, `odoo_client.py`, etc.
|
|
|
|
**Aufgaben:**
|
|
- [x] `exceptions.py` mit Exception-Hierarchie erstellen
|
|
- `BridgeError` (Base)
|
|
- `ConfigurationError`
|
|
- `MQTTConnectionError`
|
|
- `OdooAPIError`
|
|
- `DeviceNotFoundError`
|
|
- `ParserError`
|
|
- [x] Bestehende `except Exception` durch spezifische Exceptions ersetzen
|
|
- [x] Error-Messages standardisieren
|
|
- [x] Tests für Exception-Handling schreiben
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Alle `except Exception` sind spezifisch (max. 3 Ausnahmen erlaubt)
|
|
- ✅ Error-Messages sind strukturiert
|
|
- ✅ Tests decken Exception-Pfade ab
|
|
|
|
**Kompatibilität:** ⚠️ **Zu prüfen:**
|
|
- Odoo-Modul darf nicht auf Exception-Namen angewiesen sein
|
|
- HTTP-API-Responses bleiben gleich (Status-Codes unverändert)
|
|
|
|
**Migration:**
|
|
```python
|
|
# Vorher:
|
|
try:
|
|
self.client.connect(...)
|
|
except Exception as e:
|
|
logger.error(f"error: {e}")
|
|
|
|
# Nachher:
|
|
try:
|
|
self.client.connect(...)
|
|
except MQTTConnectionError as e:
|
|
logger.error("mqtt_connection_failed", error=str(e))
|
|
raise # Re-raise für besseres Debugging
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.2 main.py refactoren
|
|
**Dateien:** `main.py`, `bootstrap.py` (NEU), `service_manager.py` (NEU)
|
|
|
|
**Aufgaben:**
|
|
- [x] `bootstrap.py` erstellen
|
|
- Config-Loading-Logik von main.py verschieben
|
|
- Logger-Setup-Logik verschieben
|
|
- Fallback-Strategie dokumentieren
|
|
- [x] `service_manager.py` erstellen
|
|
- Service-Lifecycle-Management (start/stop)
|
|
- Signal-Handler-Logik
|
|
- Graceful-Shutdown-Koordination
|
|
- [x] `main.py` auf ~50-80 Zeilen reduzieren (nur Orchestrierung)
|
|
- [x] Tests für Bootstrap-Logik schreiben
|
|
- [x] Tests für Service-Manager schreiben
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ `main.py` hat max. 100 Zeilen
|
|
- ✅ Keine globalen Variablen außer `__name__`
|
|
- ✅ Bootstrap ist isoliert testbar
|
|
- ✅ Service-Manager kann Services mocken
|
|
|
|
**Kompatibilität:** ✅ CLI-Interface bleibt gleich (`python main.py --config ...`)
|
|
|
|
**Dateien zu erstellen:**
|
|
```
|
|
iot_bridge/
|
|
├── main.py # REFACTOR - 50-80 Zeilen
|
|
├── bootstrap.py # NEU - Config & Logger Setup
|
|
└── service_manager.py # NEU - Service Lifecycle
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.3 Config-Management modernisieren
|
|
**Dateien:** `config.py`, `config_schema.py` (NEU)
|
|
|
|
**Aufgaben:**
|
|
- [x] Pydantic BaseSettings für ENV-Var-Support nutzen
|
|
- [x] Config-Validation mit Pydantic-Validatoren
|
|
- [x] Config-Hierarchie dokumentieren (ENV > YAML > Defaults)
|
|
- [x] `dataclass` zu Pydantic `BaseModel` migrieren
|
|
- [x] Config-Schema-Tests schreiben
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ ENV-Variablen überschreiben YAML-Werte
|
|
- ✅ Validation-Errors sind aussagekräftig
|
|
- ✅ Backward-Kompatibilität zu alten config.yaml
|
|
|
|
**Kompatibilität:** ✅ Bestehende `config.yaml` funktionieren weiter
|
|
|
|
**Migration:**
|
|
```python
|
|
# Vorher (dataclass):
|
|
@dataclass
|
|
class MQTTConfig:
|
|
broker: str
|
|
port: int
|
|
|
|
# Nachher (Pydantic):
|
|
class MQTTConfig(BaseSettings):
|
|
broker: str = Field("mosquitto", env="MQTT_BROKER")
|
|
port: int = Field(1883, env="MQTT_PORT")
|
|
|
|
class Config:
|
|
env_prefix = "MQTT_"
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.4 Dependency Injection Pattern
|
|
**Dateien:** `dependencies.py` (NEU), `main.py`
|
|
|
|
**Aufgaben:**
|
|
- [x] `dependencies.py` mit DI-Container erstellen
|
|
- [x] Factory-Methoden für Service-Initialisierung
|
|
- [x] Constructor-Injection statt globale Variablen
|
|
- [x] Tests mit Mock-Dependencies schreiben
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Services werden als Dependencies übergeben
|
|
- ✅ Tests können Dependencies einfach mocken
|
|
- ✅ Keine globalen Service-Instanzen in Modulen
|
|
|
|
**Kompatibilität:** ✅ Keine Auswirkung auf Odoo-Integration
|
|
|
|
---
|
|
|
|
## 📦 Phase 3: Type Safety & Error Handling
|
|
|
|
**Status:** 🟡 In Arbeit (3.1-3.2 abgeschlossen, 3.3 offen)
|
|
**Aufwand:** ~4-5 Stunden
|
|
**Priorität:** 🟢 Niedrig (kann parallel zu Phase 2)
|
|
**Abhängigkeiten:** Phase 0-1 abgeschlossen
|
|
|
|
### Aufgaben
|
|
|
|
#### 3.1 Type Hints vervollständigen
|
|
**Dateien:** Alle `.py` Dateien
|
|
|
|
**Aufgaben:**
|
|
- [x] Type Hints zu allen Funktions-Signaturen hinzufügen
|
|
- [x] `from __future__ import annotations` für Forward-References
|
|
- [x] `Protocol` für Callback-Interfaces (`bridge_types.py`)
|
|
- [x] Type-Aliases für komplexe Typen
|
|
- [x] MyPy im strict-mode ohne Fehler
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ `mypy --strict .` ohne Fehler
|
|
- ✅ Alle public-functions haben Type Hints
|
|
- ✅ Keine `# type: ignore` Kommentare
|
|
|
|
**Kompatibilität:** ✅ Runtime-Behavior unverändert
|
|
|
|
**Type-Alias-Beispiele:**
|
|
```python
|
|
# types.py
|
|
from typing import Protocol, Dict, Any
|
|
from datetime import datetime
|
|
|
|
PowerWatts = float
|
|
Timestamp = datetime
|
|
EventDict = Dict[str, Any]
|
|
DeviceID = str
|
|
|
|
class MessageParser(Protocol):
|
|
def parse_message(self, topic: str, payload: dict) -> dict | None: ...
|
|
|
|
class EventCallback(Protocol):
|
|
def __call__(self, event: EventDict) -> None: ...
|
|
```
|
|
|
|
---
|
|
|
|
#### 3.2 Logging vereinheitlichen
|
|
**Dateien:** Alle `.py` Dateien mit Logging
|
|
|
|
**Aufgaben:**
|
|
- [x] Nur `structlog` verwenden (stdlib `logging` entfernen)
|
|
- [x] Log-Events konsistent benennen (snake_case)
|
|
- [x] Strukturierte Log-Felder statt f-strings
|
|
- [x] Context-Variablen für Request-Correlation
|
|
- [x] Log-Level-Konsistenz prüfen
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Kein `import logging` in Code-Dateien
|
|
- ✅ Alle Logs haben Event-Name + Felder
|
|
- ✅ Request-IDs werden bei API-Calls geloggt
|
|
|
|
**Kompatibilität:** ✅ Log-Output-Format bleibt JSON
|
|
|
|
**Migration:**
|
|
```python
|
|
# Vorher:
|
|
logger.info(f"Device added: {device_id}")
|
|
|
|
# Nachher:
|
|
logger.info("device_added", device_id=device_id, topic=mqtt_topic)
|
|
```
|
|
|
|
---
|
|
|
|
#### 3.3 Robustere Error-Handling-Patterns
|
|
**Dateien:** `mqtt_client.py`, `odoo_client.py`, `event_queue.py`
|
|
|
|
**Aufgaben:**
|
|
- [x] Retry-Logic mit Exponential Backoff dokumentieren
|
|
- [x] Circuit-Breaker-Pattern für Odoo-API (optional)
|
|
- [x] Timeout-Handling vereinheitlichen
|
|
- [x] Error-Recovery-Tests schreiben
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Transient Errors werden automatisch recovered
|
|
- ✅ Fatal Errors stoppen Service mit klarer Message
|
|
- ✅ Tests decken Error-Recovery ab
|
|
|
|
**Kompatibilität:** ✅ Retry-Behavior bleibt gleich
|
|
|
|
---
|
|
|
|
## 📦 Phase 4: Testing & Documentation
|
|
|
|
**Status:** 🟡 In Arbeit (4.1-4.4 weitgehend umgesetzt)
|
|
**Aufwand:** ~6-8 Stunden
|
|
**Priorität:** 🟡 Mittel
|
|
**Abhängigkeiten:** Phase 0-2 abgeschlossen
|
|
|
|
### Aufgaben
|
|
|
|
#### 4.1 Unit Tests für kritische Module
|
|
**Dateien:** `tests/unit/test_*.py`
|
|
|
|
**Aufgaben:**
|
|
- [x] `tests/unit/test_config.py` - Config-Loading & Validation
|
|
- [x] `tests/unit/test_device_manager.py` - Device-Lifecycle
|
|
- [x] `tests/unit/test_bootstrap.py` - Config-Fallback-Strategie
|
|
- [x] `tests/unit/test_exceptions.py` - Exception-Handling
|
|
- [ ] Coverage-Ziel: 80% für Core-Module
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Test-Coverage: config.py >90%, device_manager.py >80%
|
|
- ✅ Alle Tests laufen in <10 Sekunden
|
|
- ✅ Tests sind isoliert (keine MQTT/Odoo-Connection nötig)
|
|
|
|
**Kompatibilität:** ✅ Keine Auswirkung auf Runtime
|
|
|
|
**Test-Beispiel:**
|
|
```python
|
|
# tests/unit/test_device_manager.py
|
|
def test_add_device_subscribes_to_mqtt(device_manager, mock_mqtt):
|
|
device = DeviceConfig(...)
|
|
config = BridgeConfig(devices=[device])
|
|
|
|
device_manager.apply_config(config)
|
|
|
|
mock_mqtt.subscribe.assert_called_once_with(device.mqtt_topic)
|
|
assert device.device_id in device_manager.session_detectors
|
|
```
|
|
|
|
---
|
|
|
|
#### 4.2 Integration Tests erweitern
|
|
**Dateien:** `tests/integration/test_*.py`
|
|
|
|
**Aufgaben:**
|
|
- [x] `test_mqtt_reconnect.py` - MQTT-Broker-Switch-Szenarien
|
|
- [x] `test_config_push_integration.py` - Vollständiger Config-Push-Flow
|
|
- [x] `test_event_delivery.py` - Event-Queue mit Retry
|
|
- [x] In-Memory MQTT-Broker für schnelle Tests
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ MQTT-Reconnect wird vollständig getestet
|
|
- ✅ Config-Push-Flow wird E2E getestet
|
|
- ✅ Tests laufen ohne externes Setup
|
|
|
|
**Kompatibilität:** ✅ Keine Auswirkung auf Runtime
|
|
|
|
---
|
|
|
|
#### 4.3 Dokumentation aktualisieren
|
|
**Dateien:** `README.md`, `ARCHITECTURE.md` (NEU), `DEVELOPMENT.md` (NEU)
|
|
|
|
**Aufgaben:**
|
|
- [x] `ARCHITECTURE.md` erstellen
|
|
- Komponenten-Diagramm
|
|
- Data-Flow dokumentieren
|
|
- Entscheidungs-Rationale (ADRs)
|
|
- [x] `DEVELOPMENT.md` erstellen
|
|
- Local-Setup-Guide
|
|
- Testing-Guide
|
|
- Debugging-Tipps
|
|
- [x] README.md aktualisieren
|
|
- Links zu neuen Docs
|
|
- Development-Sektion erweitern
|
|
- [ ] Code-Kommentare bei komplexer Logik
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Neue Entwickler können Setup in <30 Min durchführen
|
|
- ✅ Architektur-Entscheidungen sind nachvollziehbar
|
|
- ✅ README.md ist auf dem aktuellen Stand
|
|
|
|
**Kompatibilität:** ✅ Keine Code-Änderungen
|
|
|
|
---
|
|
|
|
#### 4.4 Docstrings vervollständigen
|
|
**Dateien:** Alle Module
|
|
|
|
**Aufgaben:**
|
|
- [x] Google-Style Docstrings für alle public functions
|
|
- [x] Module-Level Docstrings
|
|
- [ ] Class-Level Docstrings mit Beispielen
|
|
- [x] `Args` und `Returns` dokumentieren (`Raises` bei relevanten Fehlerpfaden)
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Alle public APIs haben Docstrings
|
|
- ✅ Sphinx-Dokumentation kann generiert werden (optional)
|
|
|
|
**Kompatibilität:** ✅ Runtime-Behavior unverändert
|
|
|
|
**Beispiel:**
|
|
```python
|
|
def process_power_measurement(self, power_w: PowerWatts, timestamp: Timestamp) -> None:
|
|
"""
|
|
Process a power measurement through the state machine.
|
|
|
|
Args:
|
|
power_w: Power consumption in watts
|
|
timestamp: Measurement timestamp (UTC)
|
|
|
|
Raises:
|
|
ValueError: If power_w is negative
|
|
|
|
Example:
|
|
>>> detector.process_power_measurement(125.5, datetime.utcnow())
|
|
"""
|
|
```
|
|
|
|
---
|
|
|
|
## 📦 Phase 5: Performance & Observability
|
|
|
|
**Status:** ⏳ Nicht gestartet
|
|
**Aufwand:** ~4-6 Stunden
|
|
**Priorität:** 🟢 Niedrig (Nice-to-have)
|
|
**Abhängigkeiten:** Phase 0 und (Phase 2 oder 4) abgeschlossen
|
|
|
|
### Aufgaben
|
|
|
|
#### 5.1 Event Batching (optional)
|
|
**Dateien:** `event_queue.py`, `odoo_client.py`
|
|
|
|
**Aufgaben:**
|
|
- [ ] Batch-Sending für Events implementieren
|
|
- Batch-Size: 10 Events (konfigurierbar)
|
|
- Batch-Timeout: 5 Sekunden
|
|
- [ ] Odoo-API Batch-Endpoint nutzen (wenn vorhanden)
|
|
- [ ] Fallback auf Single-Send bei Batch-Fehler
|
|
- [ ] Performance-Tests (Durchsatz messen)
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ HTTP-Requests reduziert bei hoher Last
|
|
- ✅ Latenz für einzelne Events bleibt <1s
|
|
- ✅ Tests mit >100 Events/Sekunde
|
|
|
|
**Kompatibilität:** ⚠️ **Zu prüfen:**
|
|
- Odoo-API muss Batch-Endpoint unterstützen
|
|
- Oder: Batching nur intern nutzen und sequenziell senden
|
|
|
|
**Feature-Flag:**
|
|
```yaml
|
|
# config.yaml
|
|
event_queue:
|
|
batching_enabled: false # Default: disabled für Kompatibilität
|
|
batch_size: 10
|
|
batch_timeout_s: 5.0
|
|
```
|
|
|
|
---
|
|
|
|
#### 5.2 Prometheus Metrics Endpoint
|
|
**Dateien:** `metrics.py` (NEU), `config_server.py`
|
|
|
|
**Aufgaben:**
|
|
- [ ] `prometheus_client` zu Dependencies hinzufügen
|
|
- [ ] Metrics definieren:
|
|
- `mqtt_messages_total` (Counter per device)
|
|
- `active_sessions` (Gauge per device)
|
|
- `event_processing_seconds` (Histogram)
|
|
- `event_queue_size` (Gauge)
|
|
- [ ] `/metrics` Endpoint in FastAPI
|
|
- [ ] Grafana-Dashboard-Template (optional)
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ `/metrics` Endpoint liefert Prometheus-Format
|
|
- ✅ Metrics sind aussagekräftig
|
|
- ✅ Performance-Overhead <1%
|
|
|
|
**Kompatibilität:** ✅ Neue Endpoint, bestehende bleiben gleich
|
|
|
|
---
|
|
|
|
#### 5.3 Connection Pooling für Odoo-API
|
|
**Dateien:** `odoo_client.py`
|
|
|
|
**Aufgaben:**
|
|
- [ ] `requests.Session` mit HTTPAdapter & Connection-Pooling
|
|
- [ ] Pool-Size konfigurierbar (default: 10 Connections)
|
|
- [ ] Keep-Alive aktivieren
|
|
- [ ] Timeout-Konfiguration
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Wiederverwendung von HTTP-Connections
|
|
- ✅ Latenz bei Multiple Events reduziert
|
|
|
|
**Kompatibilität:** ✅ API-Verhalten bleibt gleich
|
|
|
|
```python
|
|
# odoo_client.py
|
|
class OdooClient:
|
|
def __init__(self, ...):
|
|
self.session = requests.Session()
|
|
adapter = HTTPAdapter(
|
|
pool_connections=10,
|
|
pool_maxsize=20,
|
|
max_retries=3
|
|
)
|
|
self.session.mount('http://', adapter)
|
|
self.session.mount('https://', adapter)
|
|
```
|
|
|
|
---
|
|
|
|
#### 5.4 Health-Check Endpoint erweitern
|
|
**Dateien:** `config_server.py`
|
|
|
|
**Aufgaben:**
|
|
- [ ] MQTT-Connection-Status in Health-Response
|
|
- [ ] Last-Event-Timestamp
|
|
- [ ] Queue-Size und Retry-Stats
|
|
- [ ] Odoo-API-Erreichbarkeit (letzte 10 Requests)
|
|
|
|
**Erfolgskriterien:**
|
|
- ✅ Health-Check zeigt vollständigen Status
|
|
- ✅ Monitoring kann Probleme erkennen
|
|
|
|
**Kompatibilität:** ✅ Bestehende Felder bleiben, neue kommen hinzu
|
|
|
|
**Response-Beispiel:**
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"devices": 2,
|
|
"subscriptions": 2,
|
|
"last_config_update": "2026-02-12T19:40:18Z",
|
|
"mqtt": {
|
|
"connected": true,
|
|
"broker": "mosquitto:1883",
|
|
"last_message": "2026-02-12T19:41:00Z"
|
|
},
|
|
"queue": {
|
|
"pending": 3,
|
|
"retries_active": 1
|
|
},
|
|
"odoo": {
|
|
"last_success": "2026-02-12T19:40:55Z",
|
|
"success_rate_10min": 0.98
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Test-Strategie
|
|
|
|
### Test-Pyramide
|
|
|
|
```
|
|
/\
|
|
/ \ E2E Tests (5) - test_e2e_push_architecture.py
|
|
/____\
|
|
/ \ Integration (10) - MQTT, Config-Push, Retry-Logic
|
|
/________\
|
|
/ \ Unit Tests (30+) - Alle Module, >80% Coverage
|
|
/__________\
|
|
```
|
|
|
|
### Coverage-Ziele
|
|
|
|
| Modul | Aktuell | Ziel | Priorität |
|
|
|-------|---------|------|-----------|
|
|
| `config.py` | ~50% | >90% | 🔴 Hoch |
|
|
| `device_manager.py` | ~30% | >80% | 🔴 Hoch |
|
|
| `mqtt_client.py` | ~60% | >75% | 🟡 Mittel |
|
|
| `session_detector.py` | ~80% | >85% | 🟢 Niedrig |
|
|
| `event_queue.py` | ~70% | >80% | 🟡 Mittel |
|
|
| `odoo_client.py` | ~40% | >70% | 🟡 Mittel |
|
|
| **Gesamt** | **~55%** | **>80%** | 🔴 Hoch |
|
|
|
|
### Continuous Testing
|
|
|
|
```bash
|
|
# Watch-Mode für Development
|
|
pytest-watch tests/
|
|
|
|
# Coverage-Report
|
|
pytest --cov=. --cov-report=html --cov-report=term
|
|
|
|
# Type-Check
|
|
mypy --strict .
|
|
|
|
# Linting
|
|
flake8 .
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Erfolgsmetriken
|
|
|
|
### Code-Qualität
|
|
|
|
- [ ] Cyclomatic Complexity: <10 für alle Functions
|
|
- [ ] Code Duplication: <5%
|
|
- [ ] Test Coverage: >80%
|
|
- [ ] MyPy Strict: 0 Errors
|
|
- [ ] Flake8: <10 Warnings
|
|
|
|
### Performance
|
|
|
|
- [ ] Startup-Zeit: <5 Sekunden
|
|
- [ ] MQTT-Reconnect: <2 Sekunden
|
|
- [ ] Event-Processing: <100ms (P95)
|
|
- [ ] Memory-Usage: <100MB (Idle)
|
|
|
|
### Maintainability
|
|
|
|
- [ ] Onboarding neuer Entwickler: <30 Minuten Setup
|
|
- [ ] Documentation-Coverage: 100% Public APIs
|
|
- [ ] Kein Code-File >500 Zeilen (außer Tests)
|
|
|
|
---
|
|
|
|
## 🔄 Migrations-Checkliste
|
|
|
|
Für jede Code-Änderung:
|
|
|
|
1. **Funktionalität testen:**
|
|
- [ ] Alle existierenden Tests laufen durch
|
|
- [ ] Manuelle Tests mit Odoo-Integration
|
|
- [ ] Config-Push von Odoo funktioniert
|
|
|
|
2. **Kompatibilität prüfen:**
|
|
- [ ] API-Endpoints unverändert (oder backward-compatible)
|
|
- [ ] Config-File-Format kompatibel
|
|
- [ ] ENV-Variablen funktionieren weiter
|
|
|
|
3. **Dokumentation:**
|
|
- [ ] README.md aktualisiert (wenn nötig)
|
|
- [ ] CHANGELOG.md-Eintrag
|
|
- [ ] Code-Kommentare bei nicht-trivialen Änderungen
|
|
|
|
4. **Testing:**
|
|
- [ ] Unit Tests für neue Funktionen
|
|
- [ ] Integration Tests bei API-Änderungen
|
|
- [ ] Coverage nicht gesunken
|
|
|
|
---
|
|
|
|
## 🚀 Rollout-Strategie
|
|
|
|
### Development
|
|
|
|
```bash
|
|
# 1. Feature-Branch erstellen
|
|
git checkout -b feature/phase1-quality-tools
|
|
|
|
# 2. Änderungen implementieren
|
|
# ... Code-Änderungen ...
|
|
|
|
# 3. Tests laufen lassen
|
|
pytest tests/
|
|
mypy --strict .
|
|
black --check .
|
|
|
|
# 4. Commit & Push
|
|
git commit -m "feat: Add code quality tools (Phase 1.1)"
|
|
git push origin feature/phase1-quality-tools
|
|
```
|
|
|
|
### Testing
|
|
|
|
```bash
|
|
# 1. Docker-Image bauen
|
|
docker build -t iot_bridge:test ./iot_bridge
|
|
|
|
# 2. Lokaler Test mit docker-compose
|
|
docker-compose -f odoo/docker-compose.dev.yaml up -d iot-bridge
|
|
|
|
# 3. Smoke-Tests
|
|
curl http://localhost:8080/health
|
|
# Odoo: Device erstellen → Config-Push testen
|
|
```
|
|
|
|
### Production
|
|
|
|
1. **Staging-Deployment:**
|
|
- Parallel-Betrieb: Alter + Neuer Bridge
|
|
- Monitoring: Fehlerrate, Performance
|
|
- Rollback-Plan bereithalten
|
|
|
|
2. **Canary-Deployment:**
|
|
- 10% Traffic auf neue Version
|
|
- Metriken beobachten (24h)
|
|
- Graduelles Hochskalieren
|
|
|
|
3. **Full-Deployment:**
|
|
- Alte Version stilllegen
|
|
- Dokumentation aktualisieren
|
|
|
|
---
|
|
|
|
## 📝 Changelog-Template
|
|
|
|
```markdown
|
|
## [Unreleased]
|
|
|
|
### Added
|
|
- Code quality tools: Black, isort, mypy, flake8
|
|
- Custom exception hierarchy for better error handling
|
|
- Dependency injection pattern for testability
|
|
|
|
### Changed
|
|
- Refactored main.py into bootstrap.py and service_manager.py
|
|
- Migrated config from dataclasses to Pydantic BaseSettings
|
|
- Unified logging to structlog (removed stdlib logging)
|
|
|
|
### Fixed
|
|
- Type hints added to all public functions
|
|
- Error handling improved with specific exceptions
|
|
|
|
### Performance
|
|
- Connection pooling for Odoo API requests
|
|
- Event batching (optional, disabled by default)
|
|
|
|
### Deprecated
|
|
- None
|
|
|
|
### Removed
|
|
- None
|
|
|
|
### Breaking Changes
|
|
- None (backward-compatible)
|
|
```
|
|
|
|
---
|
|
|
|
## 🛡️ Risiken & Mitigationen
|
|
|
|
| Risiko | Wahrscheinlichkeit | Impact | Mitigation |
|
|
|--------|-------------------|--------|------------|
|
|
| Breaking Changes durch Refactoring | Mittel | Hoch | Umfassende Tests, Kompatibilitätsprüfung vor jedem Merge |
|
|
| Performance-Regression | Niedrig | Mittel | Performance-Tests, Baseline-Messung vor Änderungen |
|
|
| Config-Format-Inkompatibilität | Niedrig | Hoch | Backward-Kompatibilität zwingend, Migration-Guide |
|
|
| Odoo-API-Änderungen nicht bedacht | Mittel | Hoch | Integration Tests mit echtem Odoo-Setup |
|
|
| Zeit-Überschreitung | Hoch | Niedrig | Phasen sind optional, können einzeln ausgelassen werden |
|
|
|
|
---
|
|
|
|
## 📅 Zeitplan (Optional)
|
|
|
|
| Phase | Dauer | Start | Ende | Status |
|
|
|-------|-------|-------|------|--------|
|
|
| Phase 0 | 3h | - | - | ✅ Abgeschlossen |
|
|
| Phase 1 | 6h | - | - | ✅ Abgeschlossen |
|
|
| Phase 2 | 8h | - | - | 🟡 Teilweise abgeschlossen |
|
|
| Phase 3 | 5h | - | - | ⏳ Geplant |
|
|
| Phase 4 | 8h | - | - | ⏳ Geplant |
|
|
| Phase 5 | 6h | - | - | ⏳ Geplant |
|
|
| **Gesamt** | **~36h** | - | - | - |
|
|
|
|
---
|
|
|
|
## ✅ Definition of Done
|
|
|
|
Eine Phase ist abgeschlossen, wenn:
|
|
|
|
- [ ] Alle Aufgaben der Phase erledigt
|
|
- [ ] Alle Tests laufen durch (`pytest tests/`)
|
|
- [ ] Code-Quality-Checks bestanden (`black`, `mypy`, `flake8`)
|
|
- [ ] Coverage-Ziel erreicht
|
|
- [ ] Kompatibilitäts-Tests mit Odoo erfolgreich
|
|
- [ ] Dokumentation aktualisiert
|
|
- [ ] Code-Review durchgeführt (wenn Team-Arbeit)
|
|
- [ ] Deployment-Test erfolgreich
|
|
|
|
---
|
|
|
|
## 📚 Referenzen
|
|
|
|
- [Python Type Hints PEP 484](https://peps.python.org/pep-0484/)
|
|
- [Structlog Documentation](https://www.structlog.org/)
|
|
- [Pydantic BaseSettings](https://docs.pydantic.dev/latest/usage/settings/)
|
|
- [pytest Best Practices](https://docs.pytest.org/en/stable/goodpractices.html)
|
|
- [Clean Code Principles](https://github.com/zedr/clean-code-python)
|
|
|
|
---
|
|
|
|
## 🤝 Beiträge & Feedback
|
|
|
|
Dieses Optimierungsprojekt ist iterativ:
|
|
|
|
- **Feedback willkommen:** Jede Phase kann angepasst werden
|
|
- **Prioritäten flexibel:** Phasen können in anderer Reihenfolge bearbeitet werden
|
|
- **Optional:** Phase 5 kann übersprungen werden, wenn nicht benötigt
|
|
- **Inkrementell:** Commits sollten klein und testbar sein
|
|
|
|
---
|
|
|
|
**Letztes Update:** 18. Februar 2026
|
|
**Nächste Review:** Nach Abschluss Phase 1
|