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:
2026-08-31 13:26:18 +02:00
co-authored by Claude Opus 5
parent 25d3c47bd3
commit 27e5c0d331
6 changed files with 115 additions and 8 deletions
+29 -1
View File
@@ -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")