# Normalisierte Datenbankstruktur für Somfy Tahoma ## Übersicht Die Datenbank wurde von einer denormalisierten Struktur (mit JSON in `parameters`) in eine vollständig normalisierte relationale Struktur überführt. ## Datenbankschema ### Haupttabellen #### `actors` Speichert alle Aktoren (Geräte mit Steuerungsfunktion) | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INT (PK, AUTO_INCREMENT) | Eindeutige ID | | type | VARCHAR(50) | Gerätetyp (z.B. RollerShutter) | | name | VARCHAR(70) | Name des Geräts | | parameters | TEXT (nullable) | Optionale Meta-Informationen | | url | VARCHAR(100) UNIQUE | Tahoma Device URL | #### `sensors` Speichert alle Sensoren (Geräte die Werte melden) | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INT (PK, AUTO_INCREMENT) | Eindeutige ID | | type | VARCHAR(50) | Sensortyp (z.B. TemperatureSensor) | | name | VARCHAR(70) | Name des Sensors | | parameters | TEXT (nullable) | Optionale Meta-Informationen | | url | VARCHAR(100) UNIQUE | Tahoma Device URL | ### Aktor-Detailtabellen #### `actor_commands` Speichert alle verfügbaren Commands für jeden Aktor | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INT (PK, AUTO_INCREMENT) | Eindeutige ID | | actor_id | INT (FK → actors.id) | Referenz zum Aktor | | command_name | VARCHAR(100) | Name des Commands (z.B. setPosition, open) | **Beispieldaten:** ``` actor_id | command_name ---------|------------- 1 | open 1 | close 1 | setPosition 2 | on 2 | off ``` #### `command_parameters` Speichert die Parameter für jeden Command | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INT (PK, AUTO_INCREMENT) | Eindeutige ID | | command_id | INT (FK → actor_commands.id) | Referenz zum Command | | parameter_name | VARCHAR(100) | Name des Parameters (z.B. position) | | parameter_type | VARCHAR(50) | Datentyp (z.B. integer, string) | | min_value | DECIMAL(10,2) | Minimaler Wert (nullable) | | max_value | DECIMAL(10,2) | Maximaler Wert (nullable) | | possible_values | TEXT | JSON Array mit möglichen Werten (nullable) | **Beispieldaten:** ``` command_id | parameter_name | parameter_type | min_value | max_value -----------|----------------|----------------|-----------|---------- 3 | position | integer | 0 | 100 ``` #### `actor_states` Speichert die aktuellen States von Aktoren | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INT (PK, AUTO_INCREMENT) | Eindeutige ID | | actor_id | INT (FK → actors.id) | Referenz zum Aktor | | state_name | VARCHAR(100) | Name des State (z.B. core:ClosureState) | | state_type | INT | State-Typ Code aus Tahoma API | | current_value | VARCHAR(255) | Aktueller Wert | | unit | VARCHAR(20) | Einheit (nullable) | | last_updated | TIMESTAMP | Zeitpunkt der letzten Aktualisierung | ### Sensor-Detailtabellen #### `sensor_states` Speichert alle verfügbaren States für jeden Sensor | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INT (PK, AUTO_INCREMENT) | Eindeutige ID | | sensor_id | INT (FK → sensors.id) | Referenz zum Sensor | | state_name | VARCHAR(100) | Name des State (z.B. core:TemperatureState) | | state_type | INT | State-Typ Code aus Tahoma API | | current_value | VARCHAR(255) | Aktueller Wert | | unit | VARCHAR(20) | Einheit (z.B. °C, %) (nullable) | | last_updated | TIMESTAMP | Zeitpunkt der letzten Aktualisierung | **Beispieldaten:** ``` sensor_id | state_name | state_type | current_value | unit ----------|-------------------------|------------|---------------|------ 1 | core:TemperatureState | 1 | 21.5 | °C 2 | core:LuminanceState | 1 | 350 | lux ``` ## Beziehungen (Foreign Keys) ``` actors (1) ──< (N) actor_commands └──< (N) command_parameters actors (1) ──< (N) actor_states sensors (1) ──< (N) sensor_states ``` Alle Foreign Keys mit `ON DELETE CASCADE` → Wenn ein Aktor/Sensor gelöscht wird, werden automatisch alle zugehörigen Commands, Parameter und States gelöscht. ## Hilfreiche Views ### `view_actors_with_commands` Zeigt alle Aktoren mit ihren Commands und Parametern in einer flachen Ansicht ```sql SELECT * FROM view_actors_with_commands WHERE actor_name = 'Wohnzimmer Rollo'; ``` ### `view_sensors_with_states` Zeigt alle Sensoren mit ihren aktuellen States ```sql SELECT * FROM view_sensors_with_states WHERE sensor_type = 'TemperatureSensor'; ``` ### `view_all_devices` Zeigt eine Übersicht aller Geräte (Aktoren und Sensoren) ```sql SELECT * FROM view_all_devices ORDER BY name; ``` ## Beispiel-Queries ### Alle Commands eines bestimmten Aktors anzeigen ```sql SELECT a.name as aktor_name, ac.command_name, cp.parameter_name, cp.min_value, cp.max_value FROM actors a JOIN actor_commands ac ON a.id = ac.actor_id LEFT JOIN command_parameters cp ON ac.id = cp.command_id WHERE a.name = 'Wohnzimmer Rollo'; ``` ### Alle Temperatursensoren mit aktuellem Wert ```sql SELECT s.name as sensor_name, ss.current_value as temperatur, ss.unit, ss.last_updated FROM sensors s JOIN sensor_states ss ON s.id = ss.sensor_id WHERE s.type = 'TemperatureSensor' AND ss.state_name LIKE '%Temperature%'; ``` ### Alle Aktoren eines bestimmten Typs ```sql SELECT name, type, COUNT(DISTINCT ac.id) as anzahl_commands FROM actors a LEFT JOIN actor_commands ac ON a.id = ac.actor_id WHERE a.type = 'RollerShutter' GROUP BY a.id, a.name, a.type; ``` ### Commands ohne Parameter finden ```sql SELECT a.name as aktor, ac.command_name FROM actors a JOIN actor_commands ac ON a.id = ac.actor_id LEFT JOIN command_parameters cp ON ac.id = cp.command_id WHERE cp.id IS NULL; ``` ## Vorteile der normalisierten Struktur 1. **Keine Datenduplizierung**: Jeder Command und Parameter wird nur einmal gespeichert 2. **Einfache Queries**: SQL-Joins statt JSON-Parsing 3. **Flexible Erweiterung**: Neue Spalten können einfach hinzugefügt werden 4. **Referentielle Integrität**: Foreign Keys garantieren Konsistenz 5. **Performance**: Indizes auf relevanten Spalten für schnelle Suchen 6. **Typsicherheit**: Min/Max als DECIMAL statt String ## Migration von alter zu neuer Struktur Falls Sie bereits Daten in der alten Struktur haben: ```sql -- Backup erstellen CREATE TABLE actors_old AS SELECT * FROM actors; CREATE TABLE sensors_old AS SELECT * FROM sensors; -- Alte Tabellen löschen DROP TABLE actors; DROP TABLE sensors; -- Neue Struktur erstellen (database_schema.sql ausführen) SOURCE database_schema.sql; -- Python-Script ausführen um Daten neu zu importieren ``` ## Wartung ### Regelmäßige Aktualisierung der States Das Script kann regelmäßig ausgeführt werden. Bei `CLEAR_TABLES = True` werden alle Daten neu importiert. Bei `CLEAR_TABLES = False` können Updates implementiert werden. ### Veraltete Geräte entfernen ```sql -- Geräte finden die nicht mehr in der Tahoma Box vorhanden sind -- (nach erneutem Import) ``` ### Index-Optimierung prüfen ```sql SHOW INDEX FROM actors; SHOW INDEX FROM actor_commands; ```