Sperrzeit je Automatik in drei Stufen
Die steigende Flanke allein schuetzt nicht gegen einen Messwert, der um die Schwelle pendelt: "Temperatur > 22" bei 22,1 / 21,9 / 22,1 Grad ist jedes Mal eine echte Flanke, und ueber MQTT koennen die Werte im Sekundentakt hereinkommen. Gemessen: fuenf Kommandos in einer halben Minute. automations.lockout_secs sagt jetzt, wie lange nach einer Ausloesung nicht wieder geschaltet wird. Der Editor bietet drei Stufen an - ohne, eine Minute, eine Viertelstunde -, weil die passende Wahl am Geraet haengt und nicht an einer Zahl: ein Rollladen soll nicht alle zwanzig Sekunden losfahren, eine Lichtfarbe darf das. Gespeichert werden Sekunden, damit eine vierte Stufe eine Zeile in lockoutChoices() ist und keine Wanderung durch die Datenbank. Vorbelegt ist eine Minute. Eine Flanke in der Sperrzeit wird verworfen, nicht aufgehoben. Ein Rollladen, der eine Viertelstunde spaeter doch noch losfaehrt, weil vor langer Zeit einmal eine Schwelle gestreift wurde, waere unangenehmer als einer, der gar nicht faehrt - und der naechste echte Anlass nach Ablauf der Sperre kommt ohnehin durch. Verworfene Flanken stehen auf DEBUG und nicht in automation_log, sonst waere die Tabelle bei einem zappelnden Sensor voll davon. force_once bleibt unberuehrt: es greift nur, wenn im Fenster gar nichts gelaufen ist - dann ist auch keine Sperre aktiv. Nachgemessen am pendelnden Sensor: mit 60 s Sperre ein Kommando, ohne Sperre fuenf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,35 @@ und `vor` verschiebt sich der wahre Bereich entsprechend mit.
|
||||
`force_once` („am Ende des Zeitraums auf jeden Fall ausführen") greift, wenn
|
||||
das Fenster zugeht und in diesem Fenster noch nichts passiert ist.
|
||||
|
||||
## Sperrzeit
|
||||
|
||||
Die Flanke allein schützt nicht gegen einen Messwert, der um die Schwelle
|
||||
**pendelt**: „Temperatur > 22" bei 22,1 / 21,9 / 22,1 °C ist jedes Mal eine
|
||||
echte steigende Flanke, und über MQTT können die Werte im Sekundentakt
|
||||
hereinkommen. `automations.lockout_secs` sagt, wie lange nach einer Auslösung
|
||||
nicht wieder geschaltet wird. Der Editor bietet drei Stufen an:
|
||||
|
||||
| | | gedacht für |
|
||||
|---|---|---|
|
||||
| Ohne | 0 s | volle Geschwindigkeit, jede Flanke schaltet |
|
||||
| Kurz | 60 s | Licht, Farbe, Dimmwert |
|
||||
| Lang | 900 s | Rollläden, Ventile, alles mit Motor |
|
||||
|
||||
Gespeichert werden Sekunden, angeboten werden nur die drei Stufen — eine
|
||||
vierte ist damit eine Zeile in `lockoutChoices()` und keine Wanderung durch
|
||||
die Datenbank.
|
||||
|
||||
Eine Flanke innerhalb der Sperrzeit wird **verworfen, nicht aufgehoben**. Ein
|
||||
Rollladen, der eine Viertelstunde später doch noch losfährt, weil vor langer
|
||||
Zeit einmal eine Schwelle gestreift wurde, wäre unangenehmer als einer, der
|
||||
gar nicht fährt — und der nächste echte Anlass nach Ablauf der Sperre kommt
|
||||
ohnehin durch. Verworfene Flanken stehen im Log auf `DEBUG`, nicht in
|
||||
`automation_log`; bei einem zappelnden Sensor wäre die Tabelle sonst voll
|
||||
davon.
|
||||
|
||||
`force_once` ist von der Sperre nicht betroffen: es greift nur, wenn im
|
||||
Fenster gar nichts gelaufen ist — dann ist auch keine Sperre aktiv.
|
||||
|
||||
## Transporte
|
||||
|
||||
Welcher Weg zum Gerät führt, entscheidet die URL des Aktors in `actors`:
|
||||
|
||||
@@ -575,7 +575,11 @@ class Runner:
|
||||
self.lief_im_fenster[automatik["id"]] = False
|
||||
erfuellt = gruppen_erfuellt(automatik, self.regelwerk, self.werte, jetzt)
|
||||
if erfuellt and not automatik["cond_met"]:
|
||||
self.ausloesen(automatik, "fired")
|
||||
if self.gesperrt(automatik, jetzt):
|
||||
logger.debug("%s: Flanke faellt in die Sperrzeit, uebersprungen",
|
||||
automatik["name"])
|
||||
else:
|
||||
self.ausloesen(automatik, "fired")
|
||||
self.flanke_merken(automatik, erfuellt)
|
||||
else:
|
||||
# Das Fenster ist gerade zugegangen. Wer "auf jeden Fall"
|
||||
@@ -595,6 +599,30 @@ class Runner:
|
||||
|
||||
self.war_aktiv[automatik["id"]] = aktiv
|
||||
|
||||
@staticmethod
|
||||
def gesperrt(automatik, jetzt):
|
||||
"""
|
||||
Liegt die letzte Ausloesung noch innerhalb der Sperrzeit?
|
||||
|
||||
Gegen Messwerte, die um die Schwelle pendeln: "Temperatur > 22" bei
|
||||
22,1 / 21,9 / 22,1 Grad ist jedes Mal eine echte steigende Flanke, und
|
||||
ueber MQTT koennen die Werte im Sekundentakt hereinkommen.
|
||||
|
||||
Die Flanke wird dabei verworfen und nicht aufgehoben. Ein Rollladen,
|
||||
der eine Viertelstunde spaeter doch noch losfaehrt, weil vor langer
|
||||
Zeit einmal eine Schwelle gestreift wurde, waere unangenehmer als
|
||||
einer, der gar nicht faehrt. Der naechste echte Anlass nach Ablauf
|
||||
der Sperre kommt ohnehin durch.
|
||||
|
||||
force_once ist davon nicht betroffen: es greift nur, wenn im Fenster
|
||||
gar nichts gelaufen ist - dann ist auch keine Sperre aktiv.
|
||||
"""
|
||||
sperre = int(automatik.get("lockout_secs") or 0)
|
||||
letzter = automatik.get("last_run")
|
||||
if not sperre or not letzter:
|
||||
return False
|
||||
return (jetzt - letzter).total_seconds() < sperre
|
||||
|
||||
@staticmethod
|
||||
def lief_heute(automatik, jetzt):
|
||||
letzter = automatik.get("last_run")
|
||||
|
||||
Reference in New Issue
Block a user