Haltezeit im Rahmen: "Auslösen erst nach X ununterbrochen"
Der Gegenspieler zur Sperre, direkt daneben: die bremst die Wiederholung, die Haltezeit den ersten Lauf. Damit lassen sich Dauerzustände abfragen, die in einem einzelnen Messwert nicht zu sehen sind - "der Wasserzähler läuft seit einer halben Stunde ohne Pause". Gespeichert wird in automations.hold_secs (haltezeit.sql im SolarManager), gezählt wird im Runner. Angeboten werden feste Stufen, wie bei der Sperre: eine weitere ist eine Zeile in haltezeitChoices(). 0 ist die Vorgabe und heißt "sofort" - vorhandene Automatiken ändern sich nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+47
-5
@@ -59,6 +59,7 @@ erDiagram
|
||||
tinyint force_once "am Fensterende notfalls doch"
|
||||
tinyint once_per_day "höchstens einmal am Tag"
|
||||
int lockout_secs "Sperrzeit nach einem Lauf"
|
||||
int hold_secs "Haltezeit vor dem Auslösen"
|
||||
tinyint cond_met "Laufzustand: war die Bedingung zuletzt wahr?"
|
||||
datetime last_run "Laufzustand: wann zuletzt ausgelöst"
|
||||
timestamp changed "Signal an den Runner"
|
||||
@@ -72,13 +73,13 @@ erDiagram
|
||||
}
|
||||
```
|
||||
|
||||
Drei Felder sind **nachgerüstet** und stehen deshalb nicht in der
|
||||
Vier Felder sind **nachgerüstet** und stehen deshalb nicht in der
|
||||
Schema-Datei, sondern in eigenen Skripten im SolarManager-Repo
|
||||
(`autoActions/`): `next_day` (`vorabend.sql`), `once_per_day` und die
|
||||
Dreiwertigkeit von `on_vacation`/`on_holiday` (`rahmen_erweitern.sql`),
|
||||
sowie der Datentyp `elapsed` samt gerechnetem Gerät „Automatiken“
|
||||
(`automatik_ausloeser.sql`). Wer die Datenbank neu aufsetzt, spielt sie nach
|
||||
`homeMesh_automations.sql` ein.
|
||||
`hold_secs` (`haltezeit.sql`), sowie der Datentyp `elapsed` samt gerechnetem
|
||||
Gerät „Automatiken“ (`automatik_ausloeser.sql`). Wer die Datenbank neu
|
||||
aufsetzt, spielt sie nach `homeMesh_automations.sql` ein.
|
||||
|
||||
Drei Spalten in `automations` sind **kein Regelwerk, sondern Laufzustand**:
|
||||
`cond_met`, `last_run` und `changed`. Sie werden vom Runner geschrieben.
|
||||
@@ -169,6 +170,7 @@ sonst steht in der Übersicht etwas anderes als im Editor.
|
||||
| `next_day` | Der Rahmen gilt für **morgen** (Vorabend-Form) | Uhrzeit und Fenster bleiben bei heute |
|
||||
| `window_from`/`window_to` | Zeitfenster; `von > bis` heißt über Mitternacht | |
|
||||
| `lockout_secs` | Sperrzeit nach einem Lauf (0 / 60 / 900) | |
|
||||
| `hold_secs` | Haltezeit: so lange muss die Bedingung **ununterbrochen** erfüllt sein (0 = sofort) | Zählt im Speicher des Runners — ein Neustart fängt die Zeit von vorn an |
|
||||
| `once_per_day` | höchstens ein Lauf je Kalendertag | |
|
||||
| `force_once` | am Ende des Fensters notfalls doch ausführen | greift nur, wenn im Fenster gar nichts lief |
|
||||
|
||||
@@ -282,7 +284,9 @@ flowchart TB
|
||||
C -- nein --> Z1["Fenster zu:<br/>force_once prüfen,<br/>Flanke zurücksetzen"]
|
||||
C -- ja --> D{"Bedingung erfüllt?<br/><small>any(all(gruppe))</small>"}
|
||||
D -- nein --> E["cond_met = 0"]
|
||||
D -- ja --> F{"cond_met schon 1?"}
|
||||
D -- ja --> HZ{"hold_secs erfüllt?<br/><small>lange genug am Stück</small>"}
|
||||
HZ -- nein --> G
|
||||
HZ -- ja --> F{"cond_met schon 1?"}
|
||||
F -- ja --> G["nichts tun<br/><small>keine neue Flanke</small>"]
|
||||
F -- nein --> H{"once_per_day<br/>und lief heute?"}
|
||||
H -- ja --> G
|
||||
@@ -297,6 +301,40 @@ flowchart TB
|
||||
`cond_met` hält fest, ob die Bedingung beim letzten Durchlauf schon erfüllt
|
||||
war. Ohne das würde „Temperatur über 22 °C“ in jedem Takt erneut feuern.
|
||||
|
||||
### Haltezeit: erst, wenn es dabei bleibt
|
||||
|
||||
Manches zeigt sich nicht in einem einzelnen Messwert, sondern erst in seiner
|
||||
Dauer. „Der Wasserzähler läuft“ ist jedes Händewaschen; „läuft seit einer
|
||||
halben Stunde ohne Pause“ ist ein offener Hahn. `hold_secs` schiebt deshalb
|
||||
die Flanke nach hinten: Erst wenn die Bedingung so viele Sekunden **am
|
||||
Stück** erfüllt war, gilt sie als erfüllt.
|
||||
|
||||
```
|
||||
Bedingung ──┐ ┌──────────────────────────────────┐
|
||||
└───┘ └────
|
||||
↑ ↑ ↑
|
||||
angefangen nach 30 min: Bedingung weg,
|
||||
(Zeit läuft) ausgelöst Zeit verfällt
|
||||
```
|
||||
|
||||
Entscheidend ist, dass `cond_met` bis dahin auf 0 bleibt: Die Flanke wird
|
||||
**aufgeschoben, nicht verbraucht**. Alles danach — Tagessperre, Sperrzeit,
|
||||
Protokoll — bleibt unverändert.
|
||||
|
||||
Was man dazu wissen sollte:
|
||||
|
||||
* **Ein Aussetzer setzt zurück.** Auch ein einzelner Takt genügt; genau das
|
||||
ist mit „ununterbrochen“ gemeint.
|
||||
* **Gezählt wird im Speicher** (`erfuellt_seit`), nicht in der Datenbank. Es
|
||||
ist Laufzustand wie `war_aktiv` — und nach einem Neustart weiß niemand, ob
|
||||
die Bedingung zwischendurch angelegen hat. Die Zeit beginnt dann von vorn.
|
||||
* **Die Messrate ist die Untergrenze der Genauigkeit.** Ein Zähler, der alle
|
||||
fünf Minuten meldet, macht die Haltezeit auf fünf Minuten genau. Mit einem
|
||||
punktgenauen Zeit-Auslöser („um 16:30“, nur im Nachholfenster wahr) ist sie
|
||||
gar nicht sinnvoll zu kombinieren — sie würde nie reif.
|
||||
* **Das Zeitfenster schneidet sie ab.** Geht das Fenster zu, verfällt eine
|
||||
angefangene Haltezeit: Sie soll innerhalb des Fensters voll gelaufen sein.
|
||||
|
||||
### Die drei Zeitformen
|
||||
|
||||
| Schreibweise | Operator | Bedeutung | Gedacht für |
|
||||
@@ -339,6 +377,7 @@ heute um 06:00 wahr, an einem Tag, an dem der Auslöser gar nicht lief.
|
||||
|
||||
| Mittel | Wogegen | Verhalten |
|
||||
|---|---|---|
|
||||
| `hold_secs` | Zustände, die erst durch ihre Dauer auffallen (Wasser läuft, Fenster steht offen) | Die Flanke wird **aufgeschoben**, bis die Bedingung lange genug am Stück steht. Der Gegenspieler zur Sperrzeit: die bremst die Wiederholung, diese den ersten Lauf |
|
||||
| `lockout_secs` | Messwerte, die um die Schwelle pendeln (22,1 / 21,9 / 22,1) | Die Flanke wird **verworfen**, nicht aufgehoben — ein Rollladen, der eine Viertelstunde später doch losfährt, wäre unangenehmer als einer, der gar nicht fährt |
|
||||
| `once_per_day` | Dinge, die man hinterher von Hand anders stellt | Nach dem ersten Lauf ist bis Mitternacht Ruhe. Die Sperrzeit taugt dafür nicht: sie zählt Sekunden und verfehlte am nächsten Morgen den Termin |
|
||||
| `force_once` | verpasste Fenster | Beim Zugehen des Fensters, aber nur, wenn darin nichts lief (zusätzlich gegen `last_run` geprüft, damit ein Neustart nicht doppelt auslöst) |
|
||||
@@ -392,6 +431,7 @@ räumt der Runner selbst weg.
|
||||
| Automatik läuft gar nicht, ohne Protokolleintrag | Rahmen: falscher Wochentag, Ferien/Feiertag auf „nie“, Fenster zu eng — oder die Bedingung war nie *neu* erfüllt (`cond_met` stand schon auf 1) |
|
||||
| Läuft einmal und dann nicht mehr am selben Tag | `once_per_day` |
|
||||
| Läuft kurz nacheinander nicht erneut | `lockout_secs` |
|
||||
| Läuft gar nicht, obwohl die Bedingung sichtbar zutrifft | `hold_secs`: sie war noch nicht lange genug am Stück erfüllt, oder ein Aussetzer hat die Zeit zurückgesetzt |
|
||||
| Kette bleibt stehen | Auslöser pausiert oder an dem Tag nicht dran |
|
||||
| Änderung im Editor wirkt nicht | Regelwerk-Signatur: erst beim nächsten `reload_seconds`-Fenster (30 s) |
|
||||
| `error` im Protokoll | Gerät nicht erreichbar, Kommando oder Transport gibt es nicht mehr |
|
||||
@@ -407,3 +447,5 @@ räumt der Runner selbst weg.
|
||||
| … eine neue Geräteart anschließen | eine Klasse in `SolarManager/autoActions/transports.py` (Lesen + Senden), Erkennung an der Aktor-URL |
|
||||
| … verstehen, warum etwas lief | `automation_log`, dann die Zeitleiste des Tages (→ [zeitleiste.md](zeitleiste.md)) |
|
||||
| … das Nachholfenster ändern | `catchup_minutes` in `config.ini` des Runners |
|
||||
| … eine weitere Stufe für Sperre oder Haltezeit | `lockoutChoices()` / `haltezeitChoices()` in `restricted/automations.php` — eine Zeile, der Rest zieht nach |
|
||||
| … auf Dauerzustände reagieren (Wasser läuft, Tür steht offen) | Haltezeit im Rahmen, dazu eine Aktion des Geräts „Benachrichtigungen“ (→ [benachrichtigungen.md](benachrichtigungen.md)) |
|
||||
|
||||
Reference in New Issue
Block a user