String für Push-Message in DOIF erzeugen (Liste von Geräten)?

Begonnen von MichaelO, 15 November 2015, 13:25:34

Vorheriges Thema - Nächstes Thema

MichaelO

Moin,

ich bekomme beim Verlassen der Wohnung eine Warnung, wenn noch Fenster offen sind. Kann mir wer einen Hinweis geben, wie ich meine Meldung derart ergänze, dass die Geräte bennant werden, die die Meldung auslösten (quasi Liste der offenen Fenster)?

## Wenn beim Verlassen des Hauses nicht alle
## (kontrollierten) Fenster/Türen zu sind
( ([Mittelstr:residentsTotalOwnersPresent] == 0) and
  ([?WZ_FK_Fenster_links] eq "open" or [?GZ_FK_Fenster_rechts] eq "open") )

     ## Nachricht schicken.
     (set pushmsg msg 'Hinweis!' 'Es sind noch Fenster offen.'  '' 2 '' 30 3600)

## ansonsten Modul umschalten
DOELSE


Meine Sensoren enthalten alle im Namen _FK_Fenster_ , aber ich bekomme es nicht hin, einen String für die Meldung ereignisgesteuert zusammenzubauen.

Danke
Michael

kumue

ich übergebe bei meinem Tür-Alarm-DOIF das Device-Reading
meinst Du sowas ?


(set Pushover msg 'TÜR-ALARM' '[DO_TK_Alarm:Device] ist offen' '' 1 'siren')

MichaelO

Zitat von: kumue am 15 November 2015, 13:56:33
ich übergebe bei meinem Tür-Alarm-DOIF das Device-Reading
meinst Du sowas ?


(set Pushover msg 'TÜR-ALARM' '[DO_TK_Alarm:Device] ist offen' '' 1 'siren')

Ja, prima... im Prinzip schon. War mir nicht klar, dass ich im set Pushover... das so benutzen kann. Nun vielleicht noch eine Frage. Es werden ja mehrere Sensoren in meinem DOIF abgefragt. Damit ich nun nicht für jeden Sensor eine eigene Meldung bekomme, wie würde der Syntax lauten, mit dem ich quasi einen String erstelle, der in einer letzten Anweisung im set Pushover... verwendet wird? Grob ins Unreine gesprochen quasi so etwas:

DOIF (Bedingung)
     (Nachricht = 'Es sind Fenster offen: ')
     (IF (Sensor1 ist offen) (Nachricht = Nachricht + '[Sensorname1] '))
     (IF (Sensor2 ist offen) (Nachricht = Nachricht + '[Sensorname2] '))
     (...)
     (set Pushover msg 'Hinweis' Nachricht 1 'siren')

kumue

Beim Schreiben meiner Antwort wusste ich schon, daß die Frage aufkommen wird...   :D
Ich weiß es aber selber (noch) nicht, wie das umgesetzt werden kann....

Laffer72

Hallo,

ich habe das ganze als sub in den 99_myUtils.pm wie folgt gelöst:

sub
FensterKontrolle()
{
my $Fensteroffen="";
if ( ReadingsVal("sensor_fenster_bad","state","") ne "closed" ) {$Fensteroffen=$Fensteroffen." Badezimmer"};
if ( ReadingsVal("sensor_fenster_ankleide","state","") ne "closed") {$Fensteroffen=$Fensteroffen." Ankleide"};
if ( ReadingsVal("sensor_fenster_sz","state","") ne "closed" ) {$Fensteroffen=$Fensteroffen." Schlafzimmer"};
if ( ReadingsVal("sensor_fenster_wz_rechts","state","") ne "closed" || ReadingsVal("sensor_fenster_wz_links","state","") ne "closed") {$Fensteroffen=$Fensteroffen." Wohnzimmer"};
if ( ReadingsVal("sensor_fenster_ki_links","state","") ne "closed" || ReadingsVal("sensor_fenster_ki_mitte","state","") ne "closed" ||  ReadingsVal("sensor_fenster_ki_rechts","state","") ne "closed") {$Fensteroffen=$Fensteroffen." Kinderzimmer"};

fhem("set Sonos_Wohnzimmer Speak 20 de Fenster offen in $Fensteroffen");
fhem("set PushNotifyReinhard message \"$Fensteroffen\" \"Fenster-Alarm\" \"\" \"\" \"\" True False");
}


aufgerufen wird das ganze einfach durch {FensterKontrolle()}.

Hoffe es hilft Die etwas weiter.

Viele Grüße

Reinhard
Raspberry Pi Rev.B, FB7390 (FHEM2FHEM), Sonos, Smarter Coffee
Osram Lightify:2m LED-Streifen, 5m-LED-Streifen, Gartenspot, Surface 28W, Classic E14,E27, Classic RGBW E27, PAR16 GU10, Plug
CUL868:FS20-ST, FS20-DI, FS20-FMS, FS20-ES1
HMUSB:HM-Sec-RHS,HM-Sec-MDIR2
Jeelink868:TX-29-IT, TFA30.315

MichaelO

Klasse, das sollte funktionieren, werde es die Tage testen. Ich hatte gehofft, es auch direkt im DOIF lösen zu können, aber wenn es so klappt, ist es auch gut!

Nochmals danke
Gruß
Michael

Laffer72

#6
Du kannst natürlich den Meldungsteil (Sonos,Push) auch auf die DOIF-Ebene heben, indem Du den Wert $Fensteroffen beim return wieder mit zurückgibst.

return $Fensteroffen;

als letzte Zeile, vor der geschweiften Klammer.

Raspberry Pi Rev.B, FB7390 (FHEM2FHEM), Sonos, Smarter Coffee
Osram Lightify:2m LED-Streifen, 5m-LED-Streifen, Gartenspot, Surface 28W, Classic E14,E27, Classic RGBW E27, PAR16 GU10, Plug
CUL868:FS20-ST, FS20-DI, FS20-FMS, FS20-ES1
HMUSB:HM-Sec-RHS,HM-Sec-MDIR2
Jeelink868:TX-29-IT, TFA30.315

viegener

Hi,
nur zur Ergänzung, ich habe mir Routinen gebaut, die die Überprüfung anhand des typs oder wenn das nicht passt eine Gruppe (es ist natürlich auch möglich andere Auswahlkriterien machen). Ziel ist es die Routinen nicht immer anpassen zu müssen, wenn ein Gerät dazukommt oder umbenannt wird. Das ist mir wichtig, da ich plane auch weiterhin Sensoren nachzurüsten und schon jetzt verschiedene Sensoren im Einsatz habe.

Durch Übergabe des parameters "msg" wird eine komplette nachricht (mit Timestamp) zusammengebaut, die auch gepushed werden kann


##############################################
# Check state of Windows and return list (undef if nothing open) or message (cmd = msg / might be empty string)
sub checkWindowOpen($) {

my ($cmd) = @_;


  my $wOpen = "";
  my @list;
  my $sdev;
 
  # Log 1, "checkWindowOpen called :$cmd:";

  # PT_2262
  @list = devspec2array("group=IT_F_SENSOR");

    foreach $sdev (@list) {
    if($defs{$sdev}) {
      $wOpen = $wOpen."$sdev " if (ReadingsVal($sdev,"state","unknown") !~ "off");
    }
  }
 
  # HM threestate
  @list = devspec2array("subType=threeStateSensor:FILTER=TYPE=CUL_HM");

  foreach $sdev (@list) {
    if($defs{$sdev}) {
      $wOpen = $wOpen."$sdev " if (ReadingsVal($sdev,"state","unknown") !~ "closed");
    }
  }

  #Log 1, "checkWindowOpen returned :$wOpen:";

  if ( ! defined( $cmd ) || ( $cmd eq "" ) ) {
    $wOpen = undef if ( $wOpen eq "" );
  } elsif ( $cmd eq "msg" ) {
    my ($seconds, $microseconds) = gettimeofday();
    my @t = localtime($seconds);
    my $tim = sprintf("%02d.%02d %02d:%02d:%02d",
            $t[3],$t[4]+1, $t[2],$t[1],$t[0]);

    $wOpen = "Es sind nicht alle Fenster geschlossen ($wOpen) - [$tim]" if ( $wOpen ne "" );
    Log 1, "checkWindowOpen result :$wOpen:";
  } else {
    $wOpen = "unknwown cmd :$cmd: in checkWindowOpen";
  }
 
  return $wOpen;

}


Ich bin dabei mehrere solche Routinen (Batteriewarnung, Tempsensor meldet sich länger nicht, etc) zubauen und an mein Benachrichtigungssystem anzuschliessen, je nach Wichtigkeit.

Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

devil77

Hallo,

versuche gerade die Routine zu verstehen aber begreife noch nicht ganz wie ich das ganze zu einer Meldung bewegen kann?
Grob gesagt möchte ich gerne das ganze verwenden um zu einer festgelegten Uhrzeit alle Fensterkontakte abzufragen und die offenen zu melden.

viegener

Generell muss die Methode in einem notify oder DOIF oder at eingebaut werden zum Beispiel so:



define alarm_test DOIF ([dummy_test:?on]) ( set telegrambot message {(checkWindowOpen("msg"))} )


In diesem Fall wird auf die Änderung eines Dummies reagiert, aber das lässt sich natürlich analog in einem at einbauen.

Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

automatisierer

So hab ich mir den Code von Viegener umgebaut:

# Check state of Windows and return list (undef if nothing open) or message (cmd = msg / might be empty string)
sub checkWindowOpen($) {

my ($cmd) = @_;


  my $wOpen = "";
  my @list;
  my $sdev;

  # Log 1, "checkWindowOpen called :$cmd:";

  # PT_2262
  #@list = devspec2array("group=IT_F_SENSOR");

  #  foreach $sdev (@list) {
  #  if($defs{$sdev}) {
  #    $wOpen = $wOpen."$sdev " if (ReadingsVal($sdev,"state","unknown") !~ "off");
  #  }
  #}

  # HM threestate
  @list = devspec2array("subType=threeStateSensor:FILTER=winOpenMsg=1");

  foreach $sdev (@list) {
    if($defs{$sdev}) {
      $wOpen = $wOpen."$sdev " if (ReadingsVal($sdev,"state","unknown") !~ "closed");
    }
  }

  #Log 1, "checkWindowOpen returned :$wOpen:";

  if ( ! defined( $cmd ) || ( $cmd eq "" ) ) {
    $wOpen = undef if ( $wOpen eq "" );
  } elsif ( $cmd eq "msg" ) {
    my ($seconds, $microseconds) = gettimeofday();
    my @t = localtime($seconds);
    my $tim = sprintf("%02d.%02d %02d:%02d:%02d",
            $t[3],$t[4]+1, $t[2],$t[1],$t[0]);

    $wOpen = "Es sind nicht alle Fenster geschlossen ($wOpen) - [$tim]" if ( $wOpen ne "" );
    Log 1, "checkWindowOpen result :$wOpen:";
  } else {
    $wOpen = "unknwown cmd :$cmd: in checkWindowOpen";
  }

  return $wOpen;

}

und bei mir werden die Geräte nur mit einbezogen, wenn ich denen ein 'attr <dev> winOpenMsg 1' gebe.

Da ich die Meldung nochmal nach einbruchgefährdeten und nicht einbruchgefährdeten Fenstern teile, also einmal Pushover mit bestätigung und einmal ohne...

Was ich noch gerne hätte, aber mangels Perlkenntnis noch nicht umgesetzt habe, ist das nicht die Device-Namen, sondern der alias Name oder sonst ein Wunschname übergeben wird.

viegener

Probiers doch mal mit dieser Veränderung, auch wenn das jetzt nur ein Schnellschuss ist:


# Check state of Windows and return list (undef if nothing open) or message (cmd = msg / might be empty string)
sub checkWindowOpen($) {

my ($cmd) = @_;


  my $wOpen = "";
  my @list;
  my $sdev;

  # Log 1, "checkWindowOpen called :$cmd:";

  # PT_2262
  #@list = devspec2array("group=IT_F_SENSOR");

  #  foreach $sdev (@list) {
  #  if($defs{$sdev}) {
  #    $wOpen = $wOpen."$sdev " if (ReadingsVal($sdev,"state","unknown") !~ "off");
  #  }
  #}

  # HM threestate
  @list = devspec2array("subType=threeStateSensor:FILTER=winOpenMsg=1");

  my @openList = ();
  foreach $sdev (@list) {
    if($defs{$sdev}) {
      push (@openList,$sdev) if (ReadingsVal($sdev,"state","unknown") !~ "closed");
      $wOpen = $wOpen."$sdev " if (ReadingsVal($sdev,"state","unknown") !~ "closed");
      }
  }

  #Log 1, "checkWindowOpen returned :$wOpen:";

  if ( ! defined( $cmd ) || ( $cmd eq "" ) ) {
    $wOpen = undef if ( $wOpen eq "" );
  } elsif ( $cmd eq "msg" ) {
    my ($seconds, $microseconds) = gettimeofday();
    my @t = localtime($seconds);
    my $tim = sprintf("%02d.%02d %02d:%02d:%02d",
            $t[3],$t[4]+1, $t[2],$t[1],$t[0]);

    if ( scalar(@openList) > 0 ) {
      $wOpen = "";
      foreach $sdev (@openList) {
        $wOpen .= ", " if ( length($wOpen) > 0 );
        $wOpen .= $sdev;
      }
      $wOpen = "Es sind nicht alle Fenster geschlossen ($wOpen) - [$tim]";
    }
    Log 1, "checkWindowOpen result :$wOpen:";
  } else {
    $wOpen = "unknwown cmd :$cmd: in checkWindowOpen";
  }

  return $wOpen;

}
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

automatisierer

das hat nicht geklappt (Gott sei Dank), ich wollte das ja mal selber hin fuckeln... quasi als Lernprojekt.

# Check state of Windows and return list (undef if nothing open) or message (cmd = msg / might be empty string)
sub checkWindowOpen($) {

my ($cmd) = @_;


  my $wOpen = "";
  my @list;
  my $sdev;

  #Log 1, "checkWindowOpen called :$cmd:";

    # HM threestate
  @list = devspec2array("subType=threeStateSensor:FILTER=winOpenMsg=1");
  #Log 1, "Zeile 15 at list: @list";
  foreach $sdev (@list)
    {
    if($defs{$sdev})
        {
        $wOpen = $wOpen.(AttrVal($sdev,"winOpenName",$sdev)) if (ReadingsVal($sdev,"state","unknown") !~ "closed");
        }
    }

# Log 1, "Zeile 24 checkWindowOpen returned :$wOpen:";

  if ( ! defined( $cmd ) || ( $cmd eq "" ) ) {
    $wOpen = undef if ( $wOpen eq "" );
  } elsif ( $cmd eq "msg" ) {
    my ($seconds, $microseconds) = gettimeofday();
    my @t = localtime($seconds);
    my $tim = sprintf("%02d.%02d %02d:%02d:%02d",
            $t[3],$t[4]+1, $t[2],$t[1],$t[0]);

    $wOpen = "Es sind nicht alle Fenster geschlossen ($wOpen) - [$tim]" if ( $wOpen ne "" );
    Log 1, "checkWindowOpen result :$wOpen:";
  } else {
    $wOpen = "unknwown cmd :$cmd: in checkWindowOpen";
  }

  return $wOpen;


}


so hats geklappt, was allerdings noch fehlt ist ein Leerzeichen oder ein ',' zwischen den Devices. Da muss ich mal noch ein wenig studieren, wie das geht...

Mit dem 'attr winOpenMsg 1' wird das Device nun hinzugefügt und mit dem 'attr winOpenName Wunschname' kann man einen Namen bestimmen, ohne das wird der Device-Name genommen.

automatisierer

nochmal aufgehübscht...

# Check state of Windows and return list (undef if nothing open) or message (cmd = msg / might be empty string)
sub checkWindowOpen($)
{

my ($cmd) = @_;

my $wOpen = "";
my @list;
my $sdev;
   
# HM threestate
@list = devspec2array("subType=threeStateSensor:FILTER=winOpenMsg=1");
foreach $sdev (@list)
        {
        if($defs{$sdev})
            {
            my $devname=AttrVal($sdev,'winOpenName',AttrVal($sdev,'alias',$sdev));
            $wOpen = $wOpen."$devname\n" if (ReadingsVal($sdev,"state","unknown") !~ "closed");
            }
        }

if ( ! defined( $cmd ) || ( $cmd eq "" ) )
{
    $wOpen = undef if ( $wOpen eq "" );
    } elsif ( $cmd eq "msg" )
{
        my ($seconds, $microseconds) = gettimeofday();
        my @t = localtime($seconds);
        my $tim = sprintf("%02d.%02d %02d:%02d:%02d",
                $t[3],$t[4]+1, $t[2],$t[1],$t[0]);
        $wOpen = "Fenster nicht geschlossen:\n$wOpen [$tim]" if ( $wOpen ne "" );
    } else
{
    $wOpen = "unknwown cmd :$cmd: in checkWindowOpen";
    }
   
return $wOpen;

}



Jetzt wird erst der Wunschname wenn vorhanden, dann der Alias und sonst der Dev-Name genommen. Dann noch mit Zeilenumbruch statt dem Leerzeichen zwischen einzelnen Namen - macht es besser lesbar.