Hallo,
ich bekomme von meinen Kameras eine Mail wenn eine Bewegung erkannt wird. Postfix führt dann ein Script aus und setzt ein Reading in einem Dummy.
Bei schlechtem Wetter oder Spinnweben vor der Kamera kommt es leider zu vielen Fehlalarmen. Diese würde ich gerne erkennen.
Dazu habe ich folgenden code, den ich irgendwo in den Untiefen des Forums gefunden habe, etwas modifiziert, sodass er bei bei Fehlalarmen eine Pushnachricht senden soll:
{
if ([camAlarm:192.168.178.12] eq "alarm" or [camAlarm:192.168.178.13] eq "alarm" and !get_Exec("counter")) { # wenn Ereignis (hier "camAlarm") eintritt und kein Timer läuft
$_count=1; # setze count-Variable auf 1
set_Exec("counter",300,'Log (3,"count: $_count action") if ($_count > 5)' FHEMControlPush_Send({'alert' => "Schlechtwetter" })); # setze Timer auf 5min zum Protokollieren der Anzahl der Ereignisse, wenn sie über 5 ist
} else {
$_count++; # wenn Timer bereits läuft zähle Ereignis
}
}
Leider funktioniert das nicht, im Log erscheint folgender Fehler:
2020.01.21 09:01:19 1: PERL WARNING: Bareword found where operator expected at (eval 355308) line 4, near "'Log (3,"count: $hash->{var}{count} action") if ($hash->{var}{count} > 5)' FHEMControlPush_Send"
2020.01.21 09:01:19 3: eval: cam_count: warning in condition c01
Syntax:
Zitat von: CommandRefset_Exec(<timerName>, <seconds>, <perlCode>, <parameter>)
timerName => "counter" => OK
seconds => 300 => OK
perlCode => 'Log (3,"count: $_count action") if ($_count > 5)' FHEMControlPush_Send({'alert' => "Schlechtwetter" }) => KO
Was willst Du genau machen?
Log Nachricht wenn count > 5, OK. Aber dann? Mit dem single quote hast Du schon perlCode geschlossen.
Vielen Dank für die Antwort!
In anderen DOIFs verwende ich diese Funktion um eine Push Nachricht zu versenden:
([20:00] and [rpi2rel3:state] eq "Offen") ({FHEMControlPush_Send({'alert' => "Garagentor ist noch offen!" })})
Das wollte ich hier nur zum testen nehmen.
Wenn ich es wie folgt ändere:
{
if ([camAlarm:192.168.178.12] eq "alarm" or [camAlarm:192.168.178.13] eq "alarm" and !get_Exec("counter")) { # wenn Ereignis (hier "camAlarm") eintritt und kein Timer läuft
$_count=1; # setze count-Variable auf 1
set_Exec("counter",300,'Log (3,"count: $_count action") if ($_count > 5) ({FHEMControlPush_Send({'alert' => "Test" })}) # setze Timer auf 5min zum Protokollieren der Anzahl der Ereignisse, wenn sie über 5 ist
} else {
$_count++; # wenn Timer bereits läuft zähle Ereignis
}
}
bekomme ich:
condition c01: Bad name after alert', line 4.
Du willst vermutlich deinen Send absetzen, wenn der Counter bei fünf angekommen ist.
Dann eher so:
set_Exec("counter",300,'FHEMControlPush_Send({"alert" => "Test" }) if ($_count > 5)');
Zitat von: Damian am 22 Januar 2020, 08:15:52
Du willst vermutlich deinen Send absetzen, wenn der Counter bei fünf angekommen ist.
Dann eher so:
set_Exec("counter",300,'FHEMControlPush_Send({"alert" => "Test" }) if ($_count > 5)');
Richtig. Jetzt kommen auch keine Meldungen mehr wegen falscher Syntax.
Allerdings kommt keine Pushnachricht an, wenn das DOIF mehr als 5x in 300sek. angetriggert wird.
Ein manuelles versenden der Push funktioniert:
{FHEMControlPush_Send({"alert" => "Test" })}
Hier nochmal das gesamte DOIF:
{
if ([camAlarm:192.168.178.12] eq "alarm" or [camAlarm:192.168.178.13] eq "alarm" and !get_Exec("counter")) {
$_count=1;
set_Exec("counter",300,'FHEMControlPush_Send({"alert" => "Test" }) if ($_count > 5)');
} else {
$_count++;
}
}
OK. FHEMControlPush_Send befindet sich wohl im main-package, daher muss man das so angeben, weil im Perl-Modus DOIF im eigenen package gekapselt ist:
set_Exec("counter",300,'::FHEMControlPush_Send({"alert" => "Test" }) if ($_count > 5)');
Zitat von: Damian am 22 Januar 2020, 08:15:52
Du willst vermutlich deinen Send absetzen, wenn der Counter bei fünf angekommen ist.
Dann eher so:
set_Exec("counter",300,'FHEMControlPush_Send({"alert" => "Test" }) if ($_count > 5)');
Funktioniert leider auch nicht, Logs gibts auch keine. Liegt es vielleicht am Trigger? Im Device camAlarm wird das Reading 192.168.178.12 für eine Sekunde auf Alarm gesetzt, anschließend wieder auf NoAlarm.
Hier auch mal ein list:
Internals:
DEF {
if ([camAlarm:192.168.178.12] eq "alarm" or [camAlarm:192.168.178.13] eq "alarm" and !get_Exec("counter")) {
$_count=1;
set_Exec("counter",300,'::FHEMControlPush_Send({"alert" => "Test" }) if ($_count > 5)');
} else {
$_count++;
}
}
FUUID 5e221f09-f33f-cd6f-5def-5bd4a8c94eb3f5c9
MODEL Perl
NAME cam_count
NOTIFYDEV global,camAlarm
NR 319
NTFY_ORDER 50-cam_count
STATE ???
TYPE DOIF
VERSION 20929 2020-01-10 09:44:35
READINGS:
2020-01-22 08:55:06 Device camAlarm
2020-01-22 08:55:06 block_01 executed
2020-01-22 08:55:06 e_camAlarm_192.168.178.12 NoAlarm
2020-01-22 08:48:43 mode enabled
2020-01-22 08:55:05 timer_counter 22.01.2020 09:00:05
Regex:
accu:
cond:
camAlarm:
0:
192.168.178.12 ^camAlarm$:^192.168.178.12:
192.168.178.13 ^camAlarm$:^192.168.178.13:
condition:
0
if (::ReadingValDoIf($hash,'camAlarm','192.168.178.12') eq "alarm" or ::ReadingValDoIf($hash,'camAlarm','192.168.178.13') eq "alarm" and !get_Exec("counter")) {
$hash->{var}{count}=1;
set_Exec("counter",300,'::FHEMControlPush_Send({"alert" => "Test" }) if ($hash->{var}{count} > 5)');
} else {
$hash->{var}{count}++;
}
helper:
DEVFILTER ^global$|^camAlarm$
NOTIFYDEV global|camAlarm
event 192.168.178.12: NoAlarm
globalinit 1
last_timer 0
sleeptimer -1
triggerDev camAlarm
triggerEvents:
192.168.178.12: NoAlarm
triggerEventsState:
192.168.178.12: NoAlarm
internals:
perlblock:
0
ptimer:
counter:
name counter
subname ::FHEMControlPush_Send({"alert" => "Test" }) if ($hash->{var}{count} > 5)
time 1579680005.94926
hash:
readings:
all camAlarm:192.168.178.12 camAlarm:192.168.178.13
trigger:
uiState:
uiTable:
var:
count 2
Attributes:
room Rules
Klar, wenn der Zustand sich ändert, dann wird das Modul getriggert - die Bedingung ist nicht mehr wahr, der Counter wird zurückgesetzt.
Du kannst reine Eventtrigger nehmen, allerdings musst du dann definieren, wann der Counter wieder zurück gesetzt werden soll.
["^camAlarm:192.168.178.12: alarm"] or ["^camAlarm:192.168.178.13: alarm"]
Zitat von: Damian am 22 Januar 2020, 09:13:13
Du kannst reine Eventtrigger nehmen, allerdings musst du dann definieren, wann der Counter wieder zurück gesetzt werden soll.
Das ist eine Herausforderung für mich. Am Ende soll einfach bei mehr als 5 Triggern in 300 Sekunden z.B. ein reading im Dummy gesetzt werden (zum Testen stattdessen die Push Nachricht). Den wollte ich dann z.B. bei nächsten Sonnenaufgang (dafür habe ich ein Device) zurücksetzen.
Verstehe ich es richtig, dass in diesem Fall die Lösung wäre, den Timer bei Sonnenaufgang zurückzusetzen, quasi so?:
{
if (["^camAlarm:192.168.178.12: alarm"] or ["^camAlarm:192.168.178.13: alarm"] and !get_Exec("counter")) {
$_count=1;
Log 1, $_count;
set_Exec("counter",300,'{fhem "setreading test state on"}) if ($_count > 5)');
} else {
Log 2, $_count;
$_count++;
my $InfrarotState = ReadingsVal("camgarage2_status","infraLedState","9");
if (Value($InfrarotState) eq "1") {del_Exec("counter");}
}
}
Der Einfachheit halber bin ich von der Push Message nun auf einen Dummy gewechselt.
Leider wird der nicht auf "on" geschaltet, obwohl das reading infraLedState vom Device camgarage2_status auf 1 steht.
Es gibt Probleme in der condition. Das Leerzeichen vor dem reading Wert ist nicht gut.
Weiters fehlen Klammern ohne die nur Kamera2 hochzählt.
Bei set_Exec hat der fhem Aufruf nicht gepasst.
Probier mal so:
{
if ((["^camAlarm:192.168.178.12:alarm"] or ["^camAlarm:192.168.178.13:alarm"]) and !get_Exec("counter")) {
$_count=1;
Log 1, $_count;
set_Exec("counter",300,'fhem("setreading test state on")) if ($_count > 5)');
} else {
Log 2, $_count;
$_count++;
my $InfrarotState = ReadingsVal("camgarage2_status","infraLedState","9");
if (Value($InfrarotState) eq "1") {del_Exec("counter");}
}
}
Du brauchst noch einen Trigger für deinen Sonnenaufgang:
{
if ((["^camAlarm:192.168.178.12:alarm"] or ["^camAlarm:192.168.178.13:alarm"]) and !get_Exec("counter")) {
$_count=1;
Log 1, $_count;
set_Exec("counter",300,'fhem("setreading test state on")) if ($_count > 5)');
} else {
Log 2, $_count;
$_count++;
}
}
{ if ([camgarage2_status:infraLedState,9] == 1) {$_count=0}}
Als nächstes stellt sich die Frage, ob man am Tage überhaupt zählen will und ob die Meldung nachts wiederholt kommen soll.
Irgendwie reagiert jetzt die Condition überhaupt nicht mehr :( Mit den Leerzeichen hatte es noch funktioniert.
Zitat von: hackepeter am 23 Januar 2020, 14:53:48
Irgendwie reagiert jetzt die Condition überhaupt nicht mehr :( Mit den Leerzeichen hatte es noch funktioniert.
ja, da gehört wohl auch ein Leerzeichen hin, wie im ersten Vorschlag von mir.
Mit Leerzeichen funktioniert die Condition wieder. Jetzt zählt er auch $_count hochgezählt, allerdings setzt er den testdummy nicht auf on, sollte er aber, wenn das Reading innerhalb der 300Sekunden öfter als 5 mal kommt, oder?
{ if ([camgarage2_status:infraLedState] == 1) {$_count=0}}
Müsste stattdessen nicht der Counter ala {del_Exec("counter");} zurück gesetzt werden?
Zitat von: hackepeter am 23 Januar 2020, 15:56:48
Mit Leerzeichen funktioniert die Condition wieder. Jetzt zählt er auch $_count hochgezählt, allerdings setzt er den testdummy nicht auf on, sollte er aber, wenn das Reading innerhalb der 300Sekunden öfter als 5 mal kommt, oder?
{ if ([camgarage2_status:infraLedState] == 1) {$_count=0}}
Müsste stattdessen nicht der Counter ala {del_Exec("counter");} zurück gesetzt werden?
kannst du noch dran setzen, falls gerade einer in den letzten fünf Minuten vor Sonnenaufgang angelaufen ist:
{ if ([camgarage2_status:infraLedState] == 1) {$_count=0;del_Exec("counter")}}
und hier ist noch eine Klammer zu viel:
set_Exec("counter",300,'fhem("setreading test state on")) if ($_count > 5)');
Funktioniert nun alles wie es soll, vielen Dank für die Hilfe!
Hier nochmal für andere die Definition:
{
if ((["^camAlarm:192.168.178.12: alarm"] or ["^camAlarm:192.168.178.13: alarm"]) and !get_Exec("counter")) {
$_count=1;
Log 1, $_count;
set_Exec("counter",120,'fhem("setreading Schlechtwetter state on") if ($_count > 3)');
} else {
Log 2, $_count;
$_count++;
}
}
{ if ([camgarage2_status:infraLedState] eq 0) {$_count=0;del_Exec("counter");fhem("setreading Schlechtwetter state off")}}