Globale, flexible Fenster-/Tür-Offen-Meldungen

Begonnen von Benni, 20 April 2015, 20:19:31

Vorheriges Thema - Nächstes Thema

bastelfeak

Hallo Benni,
erstmal großen Dank an den tollen Code-Schnipsel.
Ich bin noch blutiger Anfänger und habe deine Fenstermeldung 1:1 kopiert und lasse mich mit PushOver benachrichtigen.
Ich habe allerdings ein kleines Problem, ein öffnen des Fensters bewirkt sofort, dass in die zweite Schleife des Timers gegangen wird. Ich bekomme also nicht 3 sondern nur 2 Nachrichten und die erste beinhaltet sofort "immer noch".

Das passiert sowohl beim "echten" HM Fensterkontakt als auch beim Testfenster.

Hat jemand eine Idee?

Benni

Zitat von: bastelfeak am 29 November 2016, 21:51:39
Hat jemand eine Idee?

Mit so wenig Information wirds schwierig!

Lass doch mal wenigstens ein list deines Fensters sehen.

Hollo

Zitat von: bastelfeak am 29 November 2016, 21:51:39
...Ich habe allerdings ein kleines Problem, ein öffnen des Fensters bewirkt sofort, dass in die zweite Schleife des Timers gegangen wird. Ich bekomme also nicht 3 sondern nur 2 Nachrichten und die erste beinhaltet sofort "immer noch"...
Beobachte das mal im Eventmonitor.
Kann es evtl. sein, dass Dein "Öffnen des Fensters" direkt 2x den Trigger auslöst?

Ich hatte einen ähnlichen Fall, da ich mir eine Ansage eingebaut hatte, die dann immer gleich 2x hintereinander erfolgte.
Durch Filtern bzw. event-on-change-reading liess sich das beheben.
FHEM 6.x auf RPi 3B Buster
Protokolle: Homematic, Z-Wave, MQTT, Modbus
Temp/Feuchte: JeeLink-Clone und LGW mit LaCrosse/IT
sonstiges: Linux-Server, Dreambox, "RSS-Tablet"

bastelfeak

Ich bin noch zweimal alles durchgegangen und habe den Fehler gefunden:

Ich habe die Zeile etwas zu frei verändert  ::)

    #Optional kann noch ein Zähler für das erneute Triggern übergeben werden,
    #dieser ist per default 0
    my $retrigger=shift(@_);
    $retrigger=0 if (!$retrigger);


Dort habe ich eine "1" eingetragen, was dazu führt, dass er von Anfang an sich im Zählstatus "1" befindet und nicht, dass er einmal wiederholt, wie ich anfangs dachte. Das macht ja später $maxtrigger 

Immerhin: Wieder was gelernt.

Benni


hartenthaler

#110
Zitat von: c2j2 am 27 November 2016, 20:10:56
a) bei mir haben Fenster einen Device-Namen "Fenster_"... (hier irrelevant, aber das macht Attribut-Setzen einfacher, z.B. für die Icons)
b) und einen comment mit dem "lesbaren" Namen.

...

In den myUtils:

sub Window_status {
my $resultstring='';
my @fhttks = devspec2array("DEF=ShutterContact .+");
my @wopen = ();
foreach(@fhttks) {
  my $fhttk_window = ReadingsVal($_, "state", "?");
  push (@wopen,AttrVal($_, "comment", "?")) if ($fhttk_window =~ m/open/ );
}
my $num_wopen = @wopen;
if ( $num_wopen gt 0 ) {
  $resultstring="folgende Fenster sind noch offen:\n\n";
  foreach(@wopen) {
   $resultstring.="- ".$_."\n";
   Log 4, "FHTTK_status: ". $_. "noch offen";
  }
} else {
  $resultstring.="alle Fenster sind geschlossen.";
}
return $resultstring;
}


Da bei mir die Balkontüren und die Fenster neben closed/open noch tilted sein können und ich den sprechenden Namen im alias und nicht im comment hinterlegt habe, habe ich dieses schöne script (Danke @c2j2) für mich angepasst:

################################################################
###      Status der Türen und Fenster für Sprachausgabe      ###
################################################################

sub win_Status {
  my $resultstring = '';
  my @fenster_tuer = devspec2array("Fenster.*|Tuer.*|Balkontuer.Wohnzimmer|Balkontuer.Schlafzimmer|Garagentorsensor");
  Log 4, "Überwachte Fenster und Türen: @fenster_tuer";
  my @wopen = ();
  foreach(@fenster_tuer) {
    my $status = ReadingsVal($_, "state", "?");
    push (@wopen,AttrVal($_, "alias", "?")) if (! ($status =~ m/closed/ ));
  }
  my $num_wopen = @wopen; # Anzahl der offenen Fenter und Türen
  if ( $num_wopen > 0 ) {
    $resultstring = latin1ToUtf8("Folgende Fenster und Türen sind nicht geschlossen: ");
my $i;
    for ($i=1;$i<=$num_wopen;$i++) {
      $resultstring .= $wopen[$i-1];
  if ($i==$num_wopen-1) {$resultstring .= " und ";}
      elsif ($i==$num_wopen) {$resultstring .= ".";}
      else {$resultstring .= ", ";}
    }
  } else {
    $resultstring = latin1ToUtf8("Alle Fenster und Türen sind geschlossen.");
  }
  return $resultstring;
}


Edit: Da bei meiner Ausgabe auf Sonos die Zeilenumbrüche \n Probleme gemacht haben, habe ich das ganze noch einmal etwas überarbeitet und so für die Sprachausgabe noch besser angepasst.
fhem 5.8 auf RaspberryPi 3 mit HMLAN und CCU2, ZWave, JeeLink, FHZ1000 für FS20, HMS, Fritz!Box, Fritz!DECT200, Harmony, Sonos, hue, netatmo, SSCam, Wetter- und Verkehrsmodule, Chat-Bot mit RiveScript/Telegram, IFTTT, pushover, ...

Benni

Sowohl der tilted-Status, als auch der sprechende Name aus alias werden auch in meiner ursprünglichen Lösung korrekt berücksichtigt. ???

hartenthaler

Zitat von: Benni am 30 November 2016, 22:25:49
Sowohl der tilted-Status, als auch der sprechende Name aus alias werden auch in meiner ursprünglichen Lösung korrekt berücksichtigt. ???
Das ist richtig! Es war aber in dieser Ergänzung von c2j2, die eine Sprachausgabe erlaubt, bislang nicht der Fall. Nun passt die Ergänzung aus meiner Sicht besser dazu.
fhem 5.8 auf RaspberryPi 3 mit HMLAN und CCU2, ZWave, JeeLink, FHZ1000 für FS20, HMS, Fritz!Box, Fritz!DECT200, Harmony, Sonos, hue, netatmo, SSCam, Wetter- und Verkehrsmodule, Chat-Bot mit RiveScript/Telegram, IFTTT, pushover, ...

marty29ak

#113
Hallo erst mal vielen Dank für das tolle Modul.
Ich habe das genau so umgesetzt wie hier beschrieben. Lediglich lasse ich mir keine Pushmeldung, schicken sondern die Meldung per MyTTS ausgeben.

Ein Problem habe ich allerdings: Wenn ich ein Fenster öffne kommt sofort danach die erste Meldung das ein Fenster noch offen ist und danach dann im richtigen Zeitintervall die weiteren Meldungen.
Das ist natürlich nicht so schön wenn jedes mal wenn Jemand kurz eine Türe öffnet um raus zu gehen eine Durchsage kommt.
Bin mir jetzt nicht sicher ob es so gewollt ist das direkt beim öffnen schon eine Meldung kommt, aber kann man das ändern?

Hier mal den Code welchen ich benutze:
##################################################
########### Fenster Überwachung     ##############
##################################################
sub winOpenStart($;$) {
    #Als Parameter muss der device-Name übergeben werden
    my $dev=shift(@_);
   
    #Optional kann noch ein Zähler für das erneute Triggern übergeben werden,
    #dieser ist per default 0
    my $retrigger=shift(@_);
    $retrigger=0 if (!$retrigger);
   

    #Erst mal prüfen, ob das übergebene device überhaupt existiert
    if ($defs{$dev}) {
   
        #Aus dem device, sofern vorhanden das Attribut winOpenMaxTrigger auslesen, das
        #angibt, wie oft eine Meldung ausgegeben werden soll.
        #Fehlt dieses Attribut oder ist 0, dann wird für das device gar keine Offen-Meldung ausgegeben
        my $maxtrigger=AttrVal($dev,'winOpenMaxTrigger',0);
   
        if($maxtrigger) {
   
      #Festlegen des Namens für den Timer, der angelegt wird um die Meldung nach gewünschter
          #Zeit auszugeben.
          my $devtimer=$dev.'_OpenTimer';

          #Sollte dieser Timer bereits existieren, so wird er zunächst gelöscht.
          fhem("delete $devtimer") if ($defs{$devtimer});

 
          #Holen von weiteren Attributen, sofern vorhanden:
         
          #Zeit, nach der die Meldung ausgegeben werden soll
          #Default sind 10 Minuten, falls nicht angegeben
          my $waittime=AttrVal($dev,'winOpenTimer','00:10:00');

          #Zeit für die Folge-Meldungen, sofern abweichend angegeben
          #Default ist die normale Zeit, die oben schon ermittelt wurde
          my $devtimer2=AttrVal($dev,'winOpenTimer2',$waittime);

          #Ein eventuell definierter "schöner" Name für das Device, der in der Meldung ausgegeben werden soll.
          #Ist der nicht angegeben, wird das Device-Alias genommen, fehlt auch das, wir einfach der
          #device-Name genommen.
          my $devname=AttrVal($dev,'winOpenName',AttrVal($dev,'alias',$dev));
         
          #Eine Art Typ (Tür oder Fenster), der bei mir quasi im Betreff der Offen-Meldung angegeben wird
          my $devtype=AttrVal($dev,'winOpenType','Fenster,Türe');

          #Hier wandeln wir noch den state des devices in deutschen Klartext um
          my $devstate='offen';
          $devstate='gekippt' if (ReadingsVal($dev,'state','') eq 'tilted');
         
          #Hier wird, sofern bereits eine Wiederholung der Offen-Meldung ausgegeben werden soll,
          #dies textlich auch so berücksichtigt.
          my $immer='noch ';
          $immer='immer noch ' if ($retrigger>0);

          #Jetzt wird der Ausgabebefehl für die Offenmeldung zusammengebaut
          #(Ich habe eine sub PushInfo, die Betreff und Text als Parameter erhält und aktuell
          # meine Meldungen über Pushover ausgibt)
          my $pushcmd=fhem( "set MyTTS tts ('$devname ist $immer $devstate');;" );
         
          #Sind wir schon beim Einrichten einer Folgemeldung, muss die Wartezeit für die Folgemeldungen
          #genommen werden.
          $waittime=$devtimer2 if ($retrigger);

          #Wir erhöhen hier den Trigger-Zähler um 1...
          $retrigger+=1;
          #... und fügen das Re-Triggern als weitere Code-Zeile für das at-DEF an.
          #das sorgt dann dafür, dass diese Funktion hier nach Ablauf des Timers einfach wieder
          #getriggert wird, um einen neuen Timer anzulegen für die Folgemeldung
          $pushcmd.="winOpenStart('$dev','$retrigger');;" if($retrigger < $maxtrigger);

         
          #Nachdem wir hier alles zusammen haben,
          #legen wir den Timer (das at) an und legen ihn freundlicherweise in den, bzw. die
          #selben Räumen ab, wie auch das auslösende device.
          fhem("define $devtimer at +$waittime {$pushcmd}");
          fhem("attr $devtimer room ".AttrVal($dev,'room','Unsorted'));
        }
    }
}

sub winOpenStop($) {
    #Dazu muss das entsprechende device (TK/FK) per Name hierher übergeben werden

    #Den übergebenen device-Namen holen
    my ($dev)=@_;

    #Den Namen des Timers zusammenbauen
    my $devtimer=$dev.'_OpenTimer';
       
    #Existiert ein Timer diesen Namens, so wird er jetzt gelöscht und das war's auch schon.
    if ($defs{$devtimer}) {
        fhem("delete $devtimer");
    }
}


und so sind die Aktoren angelegt:

defmod MAX_11fea5 MAX ShutterContact 11fea5
attr MAX_11fea5 userattr winOpenMaxTrigger winOpenTimer winOpenTimer2 winOpenType:Fenster,Türe winOpenName
attr MAX_11fea5 IODev ml
attr MAX_11fea5 alarmDevice Sensor
attr MAX_11fea5 alarmSettings alarm0,|MAX_11fea5:opened|Kueche Tür|on
attr MAX_11fea5 alias Fenster Küche Balkontür
attr MAX_11fea5 devStateIcon closed:10px-kreis-gruen opened:10px-kreis-rot
attr MAX_11fea5 event-on-change-reading state
attr MAX_11fea5 fp_Erdgeschoss 414,83,0, ,MAX_11fea5
attr MAX_11fea5 fp_Terminal_test 221,51,0, ,MAX_11fea5
attr MAX_11fea5 group Heizung
attr MAX_11fea5 room 03_Küche,C_MAX
attr MAX_11fea5 winOpenMaxTrigger 3
attr MAX_11fea5 winOpenName Die Terrassentüre in der Küche
attr MAX_11fea5 winOpenTimer 00:10:00
attr MAX_11fea5 winOpenTimer2 00:05:00
attr MAX_11fea5 winOpenType Türe

setstate MAX_11fea5 closed
setstate MAX_11fea5 2016-12-16 15:39:51 MAXLAN_error 0
setstate MAX_11fea5 2016-12-16 15:39:51 MAXLAN_errorInCommand
setstate MAX_11fea5 2016-12-16 15:39:51 MAXLAN_initialized 1
setstate MAX_11fea5 2016-12-16 15:39:51 MAXLAN_isAnswer 0
setstate MAX_11fea5 2016-12-16 15:39:51 MAXLAN_valid 1
setstate MAX_11fea5 2016-12-16 15:39:51 battery ok
setstate MAX_11fea5 2016-12-16 13:54:30 firmware 1.0
setstate MAX_11fea5 2016-12-16 13:54:30 groupid 2
setstate MAX_11fea5 2016-12-16 15:39:51 onoff 0
setstate MAX_11fea5 2016-12-16 15:39:51 state closed
setstate MAX_11fea5 2016-12-16 13:54:30 testresult 2
Gruß Martin

marty29ak

Hat niemand eine Idee warum die erste offen Meldung sofort kommt und nicht wie eingestellt nach 10 Minuten?

So ist das echt nervig wenn jedes mal beim raus und rein gehen die Meldung kommt.
Gruß Martin

birdy

Hallo zusammen

Ich verwende seit längerem die flexible Fenster-/Tür-Offen Überwachung, welche ich für meine Bedürfnisse etwas angepasst habe.
Das funktioniert soweit ganz gut. Der Lösung von Benni war eine tolle Vorlage und hat mir sehr viel geholfen.

Ich verwende MAX Fensterkontakte, die erzeugen den STATE opened.

Darum habe ich den Notify wie folgt erweitert.
Internals:
   DEF        .*:(open|opened|tilted) {winOpenStart($NAME)}
   NAME       winOpen.OpenNotify
   NR         54
   NTFY_ORDER 50-winOpen.OpenNotify
   REGEXP     .*:(open|opened|tilted)
   STATE      2016-12-20 09:49:34
   TYPE       notify
   Readings:
     2016-12-20 00:27:27   state           active
Attributes:

soweit ist noch alles ok.

Inzwischen habe ich mir einen HM-SCI-3-FM (3-Kanal-Funk-Schließerkontakt-Interfac) gekauft. Der erzeugt den STATE open und läuft somit in den oben definierten Notify. Dieser offene Schalter hat natürlich nichts mit einem offenen Fenster zu tun, und soll nicht in die Fensterüberwachung laufen. Ich habe also für den HM-SCI-3-FM via eventMap "offen" für open definiert.

Das scheint gem. Event monitor auch zu funktionieren, und wird dort auch wie folgt ausgewiesen.
2016-12-20 09:41:12 CUL_HM HM_3A8ED3_Sw_01 offen
Trotzden wird der oben definierte Notify ausgelöst. Obwohl der doch eigentlich auf "offen" gar nicht anspringen sollte ...!?

Wo ist meine Fehlüberlegung. Was ist die Erklärung dazu?

Gruss birdy
FHEM  @Debian bullseye @Proxmox VE 8.4.1
GMKtec mit AMD Ryzen 7 5700U
CUL 433(a-culfw), CUL 868(SlowRF), Max-Cube CUN geflash, HM-CFG-USB-2 (HMALND)

Benni

Zitat von: birdy am 20 Dezember 2016, 10:39:25
Dieser offene Schalter hat natürlich nichts mit einem offenen Fenster zu tun, und soll nicht in die Fensterüberwachung laufen.

Das Problem ist in meiner ursprünglichen Methode bereits berücksichtigt:


...
        #Aus dem device, sofern vorhanden das Attribut winOpenMaxTrigger auslesen, das
        #angibt, wie oft eine Meldung ausgegeben werden soll.
        #Fehlt dieses Attribut oder ist 0, dann wird für das device gar keine Offen-Meldung ausgegeben
        my $maxtrigger=AttrVal($dev,'winOpenMaxTrigger',0);
   
        if($maxtrigger) {
...




birdy

Danke Benni

Da hast Du natürlich recht.
Meine Frage bezieht sich ja nicht direkt auf Deinen Code, der ist absolut ok.
Ich verstehe in diesem Zusammenhang einfach nicht warum mit "offen" der auf "open" definierte Notify ausgelöst wird?

Gruss birdy
FHEM  @Debian bullseye @Proxmox VE 8.4.1
GMKtec mit AMD Ryzen 7 5700U
CUL 433(a-culfw), CUL 868(SlowRF), Max-Cube CUN geflash, HM-CFG-USB-2 (HMALND)

marty29ak

#118
Hallo birdy,
ich kann dir bei deinem Problem leider nicht helfen.
Du schreibst aber das du auch die Max! Sensoren verwendest.
Ist es bei dir auch so das die erste Meldung offen sofort nach dem öffnen kommt und nicht erst nach der eingestellten Zeit?

Ps.: Hat sich erledigt, ich habe das winOpen.Open Notify mit einem sleep ergänzt:

.*:(opened) sleep 120; {winOpenStart($NAME)}
Gruß Martin

birdy

#119
Hallo marty29ak

Ja an den Fenstern verwende ich MAX! Sensoren.
Ist aber bezüglich meinem "Problem" nicht von Bedeutung.

Ok, mein Problem hat nichts direkt mit Benni's Code zu tun. Werde meine Frage in einem andren Bereich stellen  ???
FHEM  @Debian bullseye @Proxmox VE 8.4.1
GMKtec mit AMD Ryzen 7 5700U
CUL 433(a-culfw), CUL 868(SlowRF), Max-Cube CUN geflash, HM-CFG-USB-2 (HMALND)