FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: hackepeter am 21 Januar 2020, 11:52:12

Titel: Zählen von Ereignissen
Beitrag von: hackepeter am 21 Januar 2020, 11:52:12
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

Titel: Antw:Zählen von Ereignissen
Beitrag von: amenomade am 21 Januar 2020, 23:57:29
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.
Titel: Antw:Zählen von Ereignissen
Beitrag von: hackepeter am 22 Januar 2020, 07:35:23
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.
Titel: Antw:Zählen von Ereignissen
Beitrag 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)');
Titel: Antw:Zählen von Ereignissen
Beitrag von: hackepeter am 22 Januar 2020, 08:25:21
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++;
  }
}
Titel: Antw:Zählen von Ereignissen
Beitrag von: Damian am 22 Januar 2020, 08:47:40
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)');
Titel: Antw:Zählen von Ereignissen
Beitrag von: hackepeter am 22 Januar 2020, 09:01:24
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
Titel: Antw:Zählen von Ereignissen
Beitrag von: Damian am 22 Januar 2020, 09:13:13
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"]
Titel: Antw:Zählen von Ereignissen
Beitrag von: hackepeter am 22 Januar 2020, 20:51:52
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.
Titel: Antw:Zählen von Ereignissen
Beitrag von: kroman am 23 Januar 2020, 13:05:29
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");}
  }
}
Titel: Antw:Zählen von Ereignissen
Beitrag von: Damian am 23 Januar 2020, 13:19:08
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.

Titel: Antw:Zählen von Ereignissen
Beitrag von: hackepeter am 23 Januar 2020, 14:53:48
Irgendwie reagiert jetzt die Condition überhaupt nicht mehr :( Mit den Leerzeichen hatte es noch funktioniert.
Titel: Antw:Zählen von Ereignissen
Beitrag von: Damian am 23 Januar 2020, 15:42:50
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.
Titel: Antw:Zählen von Ereignissen
Beitrag 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?
Titel: Antw:Zählen von Ereignissen
Beitrag von: Damian am 23 Januar 2020, 16:04:33
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)');
Titel: Antw:Zählen von Ereignissen
Beitrag von: hackepeter am 23 Januar 2020, 17:01:19
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")}}