Alarm erst ab 5 Bewegungen pro Minute auslösen - Wie?

Begonnen von chunter1, 18 Januar 2016, 15:07:39

Vorheriges Thema - Nächstes Thema

chunter1


Kann mir wer helfen folgendes für meine Alarmanlage umzusetzen?

Ich möchte erst Alarm auslösen wenn sich innerhalb z.B. einer Minute mindestens 5 Bewegungen ereignet haben.
Dabei soll das Zeitfenster "fließend" sein und nicht starr jede Minute z.B. ein Zähler ausgewertet und resetet werden.

Habs mit DOIF probiert aber irgendwie weiß ich nicht so recht wie.

Edi77

Master FHEM 6 als VM auf ESX Ubuntu 20.04 LTS mit MAXCube/MAX!/FS20|TabletUI|Flightradar|Tasmota|TTN Lora|CCU3 HomematicIP|RPi mit GammaScout|MQTT EasyESP 8266|LuftdatenInfo|deCONZ HUEDev|probemon|Siemens Logo|P4D|3D PRINTER RAISE3D

chunter1

Mit dem Bewegungsmelder HM-Sen-MDIR-WM55.
Mir ist klar, dass der max. alle 15 Sekunden ein Motion Event triggern kann ;)

Habs mal für Testzwecke mit einem Dummy "s1" statt dem Bewegungsmelder probiert.
Allerdings scheint das "[s1:state:sec] < 20" irgendwie nicht zu funktionieren.
Sollte doch auch mit einem Dummy als Quelle funktionieren?

Kurz zu Code Beschreibung:
Solange "motion"-Events innerhalb von 20 Sekunden kommen, wird die Dummy Variable "s1_cnt" hochgezählt.
Wenn "s1_cnt" > 3 ist wird Alarm ausgelöst.
Wenn der Abstand zwischen zwei "motion"-Events größer 20 Sekunden ist, wird der Counter resetet.

Ist zwar nicht genau das was ich wollte, aber evtl. ein Anfang ;)


define alarmTest DOIF ([s1:state] =~ "motion" and [s1:state:sec] < 20)
({
my $n=ReadingsVal("s1_cnt","state","0");;
if ($n > 3)
{
  fhem("set alarm 1");;
  $n = 0;;
} else {
  $n++;;
}
fhem("set s1_cnt $n");;
}) DOELSE ({
fhem("set s1_cnt 0");;
})

Ellert

Zitat von: chunter1 am 18 Januar 2016, 15:07:39
Kann mir wer helfen folgendes für meine Alarmanlage umzusetzen?

Ich möchte erst Alarm auslösen wenn sich innerhalb z.B. einer Minute mindestens 5 Bewegungen ereignet haben.
Dabei soll das Zeitfenster "fließend" sein und nicht starr jede Minute z.B. ein Zähler ausgewertet und resetet werden.

Habs mit DOIF probiert aber irgendwie weiß ich nicht so recht wie.

Definiere einen Dummy mit 5 Readings.
Durch die Readings schiebst Du die Zeitstempel jeder Bewegungsmeldung.
Danach ziehst Du den ältesten Zeitstempel vom neusten Zeitstempel ab, Mit DOIF, notify oder stateFormat
Wenn die Zeitdifferenz <= 1 Minute ist, dann ist die von Dir gewünschte Bedingung erfüllt. Das kannst Du dann mit einem DOIF oder notify weiter verarbeiten.

Eine Alternative könnte das readingFnAttribute event-aggregator sein

Hilft Dir das weiter?

chunter1

Zitat von: Ellert am 18 Januar 2016, 18:39:37
Definiere einen Dummy mit 5 Readings.
Durch die Readings schiebst Du die Zeitstempel jeder Bewegungsmeldung.
Danach ziehst Du den ältesten Zeitstempel vom neusten Zeitstempel ab, Mit DOIF, notify oder stateFormat
Wenn die Zeitdifferenz <= 1 Minute ist, dann ist die von Dir gewünschte Bedingung erfüllt. Das kannst Du dann mit einem DOIF oder notify weiter verarbeiten.

Die Idee ist gut ein klassisches FIFO zu implementieren :)
Allerdings hab ich grad Probleme mit dem "Durchschieben" der Zeitstempel.
Habs mit Triggern auf userReadings probiert - der Trigger scheint aber auf userReadings nicht anzusprechen?

Hier mal der Eintrag ins attr userReadings:

old6:old5 { ReadingsVal("s1_history","old5",0);},
old5:old4 { ReadingsVal("s1_history","old4",0);},
old4:old3 { ReadingsVal("s1_history","old3",0);},
old3:old2 { ReadingsVal("s1_history","old2",0);},
old2:old1 { ReadingsVal("s1_history","old1",0);},
old1:old0 { ReadingsVal("s1_history","old0",0);},
old0:state { ReadingsVal("s1_history","state",0);}

Ellert

Mich interessiert die Lösung auch, daher hab ich es auch mal versucht. Es funktioniert so:

([PIR24] and [mpm] eq "initialized") (
   setreading mpm t1 {(time)},
   setreading mpm t2 {(time - 61)},
   setreading mpm t3 {(time - 61)},
   setreading mpm t4 {(time - 61)},
   setreading mpm t5 {(time - 61)})
DOELSEIF ([PIR24]) (
   setreading mpm t5 [mpm:t4],
   setreading mpm t4 [mpm:t3],
   setreading mpm t3 [mpm:t2],
   setreading mpm t2 [mpm:t1],
   setreading mpm t1 {(time)},
   IF ([mpm:t1]-[mpm:t5] < 60 ) (set Test Nacht))


mpm ist der DOIF Name
PIR24 ist mein Bewegungmelder
Test ein Dummy

chunter1

Ist der Umweg über den Dummy bei dir notwendig oder könnte man die readings gleich ins DOIF integrieren?

Ellert


chunter1

#8
Noch eine Frage.
Kann man statt jedesmal den Name "mpm" reinzuschreiben auch eine Platzhalter für den Namen des aktuellen DOIFs verwenden?
Also so zu sagen einen "THIS pointer" ;)

UPDATE:
Grade gefunden im thread "Antw:DOIF neue Features: Generalisierung, $DEVICE, $EVENT, Attribut notexist".
$DEVICE ist die Wahl - allerdings noch nicht verfügbar.

Ellert

#9
Du kannst die Zeilen mit Kopieren & Einfügen erzeugen und dann nur die Ziffern ändern, oder Du nimmst [mpm:&NAME] ;)

Suchen & Ersetzen geht natürlich auch (Ctrl+Shift F)