DS2408 mit hoher Frequenz mittels Alarming auslesen

Begonnen von Oliver Vallant, 27 Dezember 2016, 23:05:44

Vorheriges Thema - Nächstes Thema

eldrik

#45
jo hatte zwischenzeitlich (vor 10 sek.) auch ein positives Ergebnis in dem ich

die if Abfrage nach if ($type eq "DS2408" && defined($defs{$name})) {

abgeändert hatte.

Da die latch.ALL und sensed.ALL Ausgabe getrennt durch Komma werden steht jetzt in jedem zweiteren latch und sensed ein Komma :D

Edit: ah das ist in deiner letzten Version schon geändert :)

Ich musste jetzt nur noch

fhem("set ".$name." latch.ALL 11111111");

nach

fhem("set ".$name." latch.ALL 1,1,1,1,1,1,1,1");

abändern, damit der DS2408 nicht weiter als alarmed gekennzeichnet ist.

Greetz
Eldrik

habeIchVergessen

die Hochkommata werden notwendig, wenn Sonderzeichen im Namen stehen.

event_on_change_reading und die proxies funktionieren wie erwartet?

eldrik

Zitat von: habeIchVergessen am 15 Dezember 2017, 17:22:15
die Hochkommata werden notwendig, wenn Sonderzeichen im Namen stehen.

event_on_change_reading und die proxies funktionieren wie erwartet?

Proxies reagieren wie gewohnt, für event-on-change-reading habe ich bisher noch nicht gesetzt.

Besten Dank soweit für die Unterstützung!

Greetz
Eldrik

Oliver Vallant

Hallo endik,
mein Fehler. Hatte die Konstanten nicht in meinem Snippet mitkopiert.

Zitat
kann es sein, dass in den myUtils Beispielen
Code:
       fhem("set ".$name." latch.BYTE ".owOFF);
Code:
       fhem("set ".$name." latch." .$port." ".owOFF);

das owOFF unbeabsichtigt hineingeraten ist und hier eine 0 stehen müsste?

Es fehlt natürlich...

# 1-wire Values für on/off
use constant owON => 11;
use constant owOFF => 10;


Oliver

Oliver Vallant

Hallo Eldrik,

Zitat von: eldrik am 14 Dezember 2017, 18:29:06
Diesem habe ich das userattr autoClearAlarm:01234567 gegeben und per por 0 und set_alarm 133333333 entsprechend aktiviert.

Öffne ich nun ein Fenster bei dem ich über zwei Kontakte (sensed.0 und sensed.1 Fenster geschlossen beide jeweils Status 0) erkenne, ob dieses gekippt oder vollständig geöffnet ist, wird mir nur die Änderung des sensed.0 (1) angezeigt, der Status von sensed.1 bleibt bei 0 und der geänderte Status an sensed.1 (1) wird erst angezeigt wenn ich das userattr abändere auf autoClearAlarm:234567 hierdurch bleibt der Sensor dann aber dauerhaft im Alarm State was ja nicht Sinn und Zweck der Übung war :)

Dafür hätte ich wie oben geschrieben zwei Einsatzfälle unterschieden:
1) Du brauchst nur den Sensed-State nach dem getriggerten Alarm: Dann kann das latch sofort danach zurückgesetzt werden, wofür im userattr autoClearAlarm die entsprechende channel Nummer eingetragen haben muss. Ich verwende dies zB. bei 2Kanal Stomstoßrelais, an welchem ich bei 2.Kanal den aktuellen Schaltzustand (kann ja auch von Hand betätigt werden, oder unklarer Einschaltzustand) einlese. Um mir hier für jeden Kanal ein notify zu sparen, nutze ich das autoClearAlarm.
2) Für Aktionen nach einem latch State, führe ich als erste Aktion im notify ein set <OWDevice> latch.Y 10> aus, um das latch des  channels wieder rückzusetzen.

Oliver

Oliver Vallant

Hallo HabeIchVergessen,

Zitat von: habeIchVergessen am 14 Dezember 2017, 20:09:00
mit 2 Lesezugriffen können alle latches und sensed Werte gelesen werden.
dies bitweise in einer Schleife zu tun ist nicht resourcenschonend.
auch das Rücksetzen aller latches nach der Verarbeitung der ersten gesetzten, ist suboptimal und auch der Grund, warum nur 1x sensed ausgelesen wird (isLatched muss dafür gesetzt sein; funktioniert also genau 1x!).

Ist richtig. Da einerseits OWServer via OWHTTP auf OWFS zugreift und OWFS ohnedies cached und die Abfrage nicht auf den BUS selbst hinausläuft, bin ich gar nicht auf die Idee gekommen. Auch setze ich den DS2408 für Zimmerschalter (Licht, Rollos etc.) ein und da werden selten innerhalb einer Sek. mehr als eine Taste betätigt. Deine Lösung ist aber eleganter ... werde asap bei mir umstellen.
Oliver

Oliver Vallant

Hallo Eldrik und HabIchVergessen,

das größte Optimierungspotential bzl. Reaktionszeit zwischen Schalterbetätigung und Schalten eines Relais (zB. Licht im Raum) besteht in der zyklischen Abfrage des Alarms (1-wire Conditional Search) selbst. Ich habe derzeit ein at pro Sekunde laufen, welches über OWServer den Parameter /uncached/alarm des OWFS holt. Bei Eldiks Fenster ist 1sec+Aktion ausreichend, beim Lichteinschalten des Raumlichtes oder bei Rollos, also unmittelbarer User-Interaktion, gerade noch akzeptabel.
Ich kenne Leider FHEM intern zu wenig. Wo im System könnte man am elegantesten "get <OWServer>  /uncached/alarm" abfragen, um zumindest 2x besser 3x Sekunde den Alarm-State zu bekommen und gleichzeitig das System nicht unnötig zu blockieren.

Danke, Oliver

Dr. Boris Neubert

       my $latches = fhem("get ".$name." latch.ALL");
       my $sensed = fhem("get ".$name." sensed.ALL");


Ich weiß nicht genau, wie der Prozess aussieht, in welchem die Daten ausgelesen werden.

get liest immer den augenblickliche Wert vom Server, und zwar entweder ungecachete oder gecachete Daten, je nachdem, ob das Attribut uncached gesetzt ist oder nicht.

Wenn das OWDevice mit Polling definiert wurde, liegen die Werte ja schon vor, mit einem maximalen Alter wie das Polling-Intervall. Dann ist

ReadingsVal($name, "latch.ALL")

effizienter.
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

habeIchVergessen

bzgl. Effizienz ist ein Roundtrip zum 1Wire-Device mit Auslesen aller latch- und sensed-Werte + Rücksetzen der latches das Optimum.

Im Zusammenhang mit ConditionalSearch macht ein "cached"-Zugriff keinen Sinn. Das die gecachten Daten veraltet sind, triff mit hoher Wahrscheinlichkeit zu.

Oliver Vallant

#54
Nach meinen Tests funktioniert interessanter Weise set <OWServer latch.ALL 0,0,0,0,0,0,0,0 (alarm flags müssen ja zurückgesetzt werden) nicht. Wohl aber kann ich mit get latch.ALL die latches mit Komma getrennt auslesen. Was funktioniert ist set latch.BYTE 10 für alle Löschen und set latch.BYTE 11 für alle setzten. Mir ist bereits bei set PIO,Y aufgefallen, dass beim Setzten immer 10 statt 0 und 11 statt 1 verwendet werden muss. Keine Ahnung, ob dies im OWServer oder in OWFS so erforderlich ist.

Bei mir funktioniert demnach folgender Code:


# 1-wire Values für on/off
use constant owON => 11;
use constant owOFF => 10;

sub getBUSalarm($) {
  my ($bus) = @_;
  my $res = fhem("get ".$bus." /uncached/alarm");
  my @devices= split("\n", $res);

  #---proceed alarmed device at this 1-wire---
  for my $device (@devices) {
    my @line = split(" ", $device);
    my $type = @line[1];
    my $name = @line[2];
    Log3 $name, 4, "Alarmed: ".$name." Type: ".$type;

    #--- device dependant treatment---
    if ($type eq "DS2408" && defined($defs{"$name"})) {
      my $rhash=$defs{"$name"};
      my $latches = fhem("get ".$name." latch.ALL");
      my $sensed = fhem("get ".$name." sensed.ALL");
      Log3 $name, 4, "ports at device $name: latches $latches, sensed: $sensed";
   
      readingsBeginUpdate($rhash);
      #--- DS2408 has 8 ports---
      for (my $port=0; $port <= 7; $port++) {
        readingsBulkUpdate($rhash, "latch." . $port, substr($latches, $port * 2, 1));
        readingsBulkUpdate($rhash, "sensed." . $port, substr($sensed, $port * 2, 1));
      }
      readingsEndUpdate($rhash, 1);

      #---Port gets cleared---
      fhem("set ".$name." latch.BYTE ".owOFF);
      Log3 $name, 4, "Alarm cleared for " .$name;
    }
  } 
  return undef;
}


Vorteile:

  • Die Unterscheidung autoClearedAlarm und explizites rücksetzen des Alarms im Notify entfällt, da nun die Notifies jedenfalls getriggert werden. Dh. die autoClearedAlarm Attribut Definition und Behandlung entfällt
  • Auch mehrere gleichzeitige Inputs am DS2408 werden abgearbeitet

Das ultima ratio wäre natürlich, dass man das gesamte Auslesen der latch states eigentlich entfallen lassen kann (und gewinnt ein paar ms), da es ohnedies am Ende zurückgesetzt wird. Dh. wenn man nur auf sensed Notifys nutzt und die latched Trigger nicht benötigt kann man reduzieren auf:


# 1-wire Values für on/off
use constant owON => 11;
use constant owOFF => 10;

sub getBUSalarmWithoutLatches($) {
  my ($bus) = @_;
  my $res = fhem("get ".$bus." /uncached/alarm");
  my @devices= split("\n", $res);

  #---proceed alarmed device at this 1-wire---
  for my $device (@devices) {
    my @line = split(" ", $device);
    my $type = @line[1];
    my $name = @line[2];
    Log3 $name, 4, "Alarmed: ".$name." Type: ".$type;

    #--- device dependant treatment---
    if ($type eq "DS2408" && defined($defs{"$name"})) {
      my $rhash=$defs{"$name"};
      my $sensed = fhem("get ".$name." sensed.ALL");
      Log3 $name, 4, "Ports at device $name: sensed: $sensed";
   
      readingsBeginUpdate($rhash);
      #--- DS2408 has 8 ports---
      for (my $port=0; $port <= 7; $port++) {
        readingsBulkUpdate($rhash, "sensed." . $port, substr($sensed, $port * 2, 1));
      }
      readingsEndUpdate($rhash, 1);

      #---Port gets cleared---
      fhem("set ".$name." latch.BYTE ".owOFF);
      Log3 $name, 4, "Alarm cleared for " .$name;
    }
  } 
  return undef;
}


Oliver

Oliver Vallant

Hallo Boris,

ließe sich aus deiner Sicht die nunmehr optimierte getBUSalarm($) in dein Modul OWServer so integrieren, dass dieses zB. 2x pro Sekunde (vielleicht als Attribut einstellbar) aufgerufen wird. Wenn noch als set initBUSalarm die Initialisierung unten hinzukäme , hätte das Modul somit kompakt die 1-wire Alarming Behandlung integriert.

Oliver


sub initBUSalarm($) {
   my ($bus) = @_;
   my $res = fhem("get ".$bus." devices");
   my @devices= split("\n", $res);

   #---proceed device at this 1-wire---
   for my $device (@devices) {
     my @line = split(" ", $device);
     my $type = @line[1];
     my $name = @line[2];
     if ($type eq "DS2408") {
       fhem("set ".$name." set_alarm .133333333");
       fhem("set ".$name." por ".owOFF);
       fhem("set ".$name." latch.BYTE ".owOFF);
       Log3 $name, 3, "Init alarming (set_alarm 133333333, por 0, latch.BYTE 0) for device: ".$name." type: ".$type;
     }
     if ($type eq "DS18S20") {
       fhem("set ".$name." temphigh .125");
       fhem("set ".$name." templow .-50");
       Log3 $name, 3, "Init alarming (temphigh 125, templow -50) at device: ".$name." type: ".$type;
     }
   }
}

habeIchVergessen

Zitat von: Oliver Vallant am 16 Dezember 2017, 17:14:24
Das ultima ratio wäre natürlich, dass man das gesamte Auslesen der latch states eigentlich entfallen lassen kann (und gewinnt ein paar ms), da es ohnedies am Ende zurückgesetzt wird. Dh. wenn man nur auf sensed Notifys nutzt und die latched Trigger nicht benötigt kann man reduzieren auf:

Der IC kann die Zustandsänderung im Interval detektieren (latch) und den Zustand selbst (sensed).
Ich bezweifele, dass die reine Betrachtung von sensed zuverlässige Ergebnisse liefert, wenn  pro Interval eine Änderung mehr als 1x auftritt.

bzgl. neuer Funktion in OWSERVER/-DEVICE würde ich eine Funktion vorschlagen, die den Alarm zurücksetzt und die Werte zu latches sensed mitliefert. Also ein roundtrip zum Device (OWSERVER/OWHTTP/OWFS/Busmaster).

hat das schonmal jemand gemessen (roundtrip)?

Oliver Vallant

Ja richtig. Wenn zB. ein Impuls (sehr viel kleiner als das Abfrageintervall von /uncached/alarms) am pin anliegt, würde latch triggern und sensed nicht.