Files
Smart-Dashboard/homeMesh_automations.sql
T
adminandClaude Opus 5 62a8af3fc6 Raeume ueber ihre feste Nummer: actors.room_id, Raum-Modal, Thermostat-Zweig
Geraete hingen ueber den Text "Etage/Raum" an ihrem Raum, das Raum-Modal
zerlegte "EG_Bad" am Unterstrich, und das Thermostat-Topic wurde aus Etage
und Name zusammengesetzt. Ein umbenannter Raum haette still alle Geraete,
seinen Temperaturregler und sein Heizsymbol verloren.

- actors.room (Text) -> actors.room_id, Fremdschluessel auf rooms, beim
  Loeschen eines Raums SET NULL. Alle 59 Zuordnungen uebernommen.
- automations.floor: ENUM(UG,EG,OG,AG) -> Verweis auf floors.
  Eine neue Etage kann damit auch Automatiken tragen.
- room.php nimmt ?room=<Nummer>; Solltemperatur geht an
  rooms.thermostat + /changeSetTemp.
- homeMQTT.js: Heizsymbol, Regler und Ist-Werte ueber mqttZweig(thermostat)
  statt mqttData.Raumtemp[Etage][Name].
- Raumvorschlaege in den Einstellungen: Messwerte unter dem Thermostat-
  Zweig eines Raums statt fest Raumtemp/<Etage>/<Name>.
- Schluessel in raumListe(), Katalog und Maske ist die Raumnummer als Text.

Geprueft gegen den Stand davor: Startseite gleich bis auf das Klickziel,
jede der 25 Kacheln oeffnet ihren eigenen Raum; Geraeteliste, Vorschlaege,
Editor-Katalog und die eigenen Geraete je Kachel gleich.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 10:58:30 +02:00

136 lines
9.3 KiB
SQL

-- ---------------------------------------------------------------------------
-- Automatiken (AutoActions) fuer die Datenbank `homeMesh`
-- ---------------------------------------------------------------------------
-- Bewusst hier und nicht in `solarLog`: der Editor liest Geraete, Messwerte
-- und Kommandos ohnehin aus homeMesh, und nur innerhalb einer Datenbank
-- koennen Fremdschluessel greifen. Die alten Tabellen autoActions,
-- autoactionsSensors und autoactionsActors in solarLog zeigten auf
-- solarLog.actors bzw. solarLog.sensors, waehrend das Formular homeMesh-IDs
-- lieferte - jedes INSERT lief gegen den Fremdschluessel, deshalb sind die
-- beiden Kindtabellen dort leer geblieben.
--
-- Ein Geraetebegriff: device_discovery.py legt auch reine Sensoren in
-- `actors`/`actor_states` ab (siehe insert_sensor()), die Tabellen
-- `sensors`/`sensor_states` sind unbenutzt. `actor_states` ist damit alles
-- Lesbare, `actor_commands` alles Schaltbare.
--
-- Voraussetzung: in restricted/deviceDiscovery/config.ini muss
-- clear_tables = false stehen. Discovery schreibt mit ON DUPLICATE KEY UPDATE
-- auf den URLs, das Leeren ist unnoetig - ein TRUNCATE wuerde dagegen die
-- Geraete-IDs neu vergeben und alle Regeln auf falsche Geraete zeigen lassen.
-- ---------------------------------------------------------------------------
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET NAMES utf8mb4;
-- ---------------------------------------------------------------------------
-- Die Automatik selbst: der Rahmen, in dem sie ueberhaupt greifen darf.
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `automations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL COMMENT 'Anzeigename, z.B. Kinder zu',
`floor` varchar(4) NOT NULL COMMENT 'Reiter in der Uebersicht (floors.code, Fremdschluessel legt homeMesh_grundriss.sql an). Ohne Etage waere die Automatik in keinem Reiter zu sehen, deshalb kein leerer Wert',
`enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Aktiv oder pausiert',
`window_from` time NOT NULL DEFAULT '00:00:00' COMMENT 'Aktiver Zeitraum, Beginn',
`window_to` time NOT NULL DEFAULT '23:59:00' COMMENT 'Aktiver Zeitraum, Ende. Kleiner als window_from = ueber Mitternacht',
`weekdays` tinyint(3) unsigned NOT NULL DEFAULT 127 COMMENT 'Bitmaske: Bit 0 = Montag ... Bit 6 = Sonntag',
`on_vacation` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Auch in den Ferien ausfuehren',
`on_holiday` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Auch an Feiertagen ausfuehren',
`next_day` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Wochentage, Ferien und Feiertage gelten fuer morgen (Vorabend). Nachgeruestet mit vorabend.sql im SolarManager',
`force_once` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Am Ende des Zeitraums auf jeden Fall ausfuehren',
`lockout_secs` int(11) NOT NULL DEFAULT 60 COMMENT 'Sperrzeit: so lange nach einer Ausloesung wird nicht erneut geschaltet. Gegen Messwerte, die um die Schwelle pendeln - jedes Ueberschreiten waere sonst eine echte Flanke. Der Editor bietet 0, 60 und 900 an',
`cond_met` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'War die Bedingung beim letzten Durchlauf erfuellt? Nur die steigende Flanke loest aus, sonst wuerde Temperatur groesser 22 im Sekundentakt feuern',
`last_run` datetime DEFAULT NULL COMMENT 'Zuletzt ausgeloest, NULL = noch nie',
`changed` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() COMMENT 'Signal an den Runner, das Regelwerk neu zu laden',
PRIMARY KEY (`id`),
KEY `idx_automations_floor` (`floor`),
KEY `idx_automations_changed` (`changed`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ---------------------------------------------------------------------------
-- Ausloeser. Eine Zeile ist ein Vergleich auf genau einen Messwert.
--
-- `state_id` zeigt direkt auf actor_states und traegt damit Geraet, Messwert,
-- Datentyp, Einheit und MQTT-Topic in einem Feld - frueher war das auf
-- sensorID, eine state-URL und ein unklares valID verteilt.
--
-- Verknuepft wird ueber `group_no`: gleiche Nummer = UND, verschiedene
-- Nummern = ODER. Ausgewertet wird also any(all(gruppe)). Im Editor ist eine
-- Gruppe ein gerahmter Block und zwischen den Bloecken steht ein ODER - die
-- Klammerung ist damit gezeichnet und nicht bloss vereinbart. Innerhalb einer
-- Gruppe wie zwischen den Gruppen ist die Reihenfolge fuer das Ergebnis egal,
-- `position` ist reine Lesehilfe.
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `automation_conditions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`automation_id` int(11) NOT NULL,
`group_no` int(11) NOT NULL DEFAULT 0 COMMENT 'UND-Block. Gleiche Nummer = UND, verschiedene Nummern = ODER',
`position` int(11) NOT NULL DEFAULT 0 COMMENT 'Reihenfolge innerhalb des Blocks, nur Darstellung',
`state_id` int(11) NOT NULL COMMENT 'Referenz auf actor_states: Geraet und Messwert in einem',
`operator` enum('=','!=','>','<','>=','<=','+','-','>=+','>=-','<+','<-') NOT NULL DEFAULT '=' COMMENT 'Immer ASCII, die Beschriftung macht erst die Anzeige daraus. Bei Zeit und Datum: = um, >= ab, < vor. Beim Sonnenstand traegt der Operator zusaetzlich das Vorzeichen des Versatzes: + genau danach, >=- ab davor, <+ bis danach',
`value` varchar(255) NOT NULL DEFAULT '' COMMENT 'Schwelle als Text, der Datentyp steckt im Messwert',
PRIMARY KEY (`id`),
KEY `idx_cond_automation` (`automation_id`,`group_no`,`position`),
KEY `idx_cond_state` (`state_id`),
CONSTRAINT `fk_cond_automation` FOREIGN KEY (`automation_id`) REFERENCES `automations` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_cond_state` FOREIGN KEY (`state_id`) REFERENCES `actor_states` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ---------------------------------------------------------------------------
-- Aktionen: ein Kommando eines Aktors, das bei Ausloesung geschickt wird.
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `automation_actions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`automation_id` int(11) NOT NULL,
`position` int(11) NOT NULL DEFAULT 0 COMMENT 'Ausfuehrungsreihenfolge',
`command_id` int(11) NOT NULL COMMENT 'Referenz auf actor_commands: Geraet und Kommando in einem',
PRIMARY KEY (`id`),
KEY `idx_action_automation` (`automation_id`,`position`),
KEY `idx_action_command` (`command_id`),
CONSTRAINT `fk_action_automation` FOREIGN KEY (`automation_id`) REFERENCES `automations` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_action_command` FOREIGN KEY (`command_id`) REFERENCES `actor_commands` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ---------------------------------------------------------------------------
-- Werte fuer die Parameter eines Kommandos. Eine Zeile je Parameter statt
-- fester Spalten Wert 1 bis Wert 4: wie viele es sind, sagt
-- command_parameters, nicht die Tabellenbreite.
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `automation_action_params` (
`action_id` int(11) NOT NULL,
`parameter_id` int(11) NOT NULL COMMENT 'Referenz auf command_parameters',
`value` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`action_id`,`parameter_id`),
KEY `idx_actionparam_parameter` (`parameter_id`),
CONSTRAINT `fk_actionparam_action` FOREIGN KEY (`action_id`) REFERENCES `automation_actions` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_actionparam_parameter` FOREIGN KEY (`parameter_id`) REFERENCES `command_parameters` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ---------------------------------------------------------------------------
-- Lauf-Protokoll. Speist die Spalte "zuletzt ausgeloest" in der Uebersicht
-- und macht Fehlschlaege sichtbar, die sonst still blieben. Der Runner
-- raeumt Eintraege aelter als 30 Tage selbst weg.
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `automation_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`automation_id` int(11) NOT NULL,
`ts` datetime NOT NULL DEFAULT current_timestamp(),
`result` enum('fired','forced','error') NOT NULL DEFAULT 'fired',
`detail` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `idx_log_automation` (`automation_id`,`ts`),
CONSTRAINT `fk_log_automation` FOREIGN KEY (`automation_id`) REFERENCES `automations` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ---------------------------------------------------------------------------
-- Ferien und Feiertage. Nur besondere Tage stehen drin, ein fehlendes Datum
-- ist ein gewoehnlicher Tag. Gefuellt von
-- SolarManager/autoActions/fetch_calendar.py, einmal jaehrlich per Cron.
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `calendar_days` (
`date` date NOT NULL,
`holiday` varchar(80) DEFAULT NULL COMMENT 'Name des Feiertags, NULL = keiner',
`vacation` varchar(80) DEFAULT NULL COMMENT 'Name der Ferien, NULL = keine',
PRIMARY KEY (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;