DS2408 mit hoher Frequenz mittels Alarming auslesen

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

Vorheriges Thema - Nächstes Thema

Prof. Dr. Peter Henning

Da muss ich widersprechen. Jeder USB-Adapter hat eine eindeutige Seriennummer, die zur Identifikation des Stranges vollkommen ausreicht. Der zusätzliche DS2401 ist also überflüssig.
Sie kann darüber hinaus fest mit einem (Linux) I/O-Device verbunden werden, das unabhängig von der USB Enumeration beim Systemstart ist.

So ist z.B. bei meinen fünf 1-Wire Bussen derjenige im Dachgeschoss immer unter /dev/OWX_OG zu finden.

LG

pah


Dr. Boris Neubert

Das Feature get ... /uncached/alarm von Oliver ist ins Modul übernommen und steht ab morgen per Update zur Verfügung.
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

Oliver Vallant


eldrik

#33
Hi,

kann es sein, dass in den myUtils Beispielen

       fhem("set ".$name." latch.BYTE ".owOFF);

             fhem("set ".$name." latch." .$port." ".owOFF);

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

Ich habe tatsächlich erst heute einen Test in der Richtung machen können und bräuchte einen Tipp wie ich die nachfolgende Situation lösen könnte?

Einen Test DS2408 habe ich hierfür herangezogen, an dem einige Reed Kontakte hängen.

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 :)

Wahrscheinlich liegt es daran, dass beide Kontakte gleichzeitig unterbrochen werden?

Greetz
Eldrik

habeIchVergessen

#34
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!).

eldrik

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ückseiten aller latches nach der Verarbeitung der ersten gesetzten, ist suboptimal.

ich wäre an einer optimaleren Variante gemäß deiner Beschreibung interessiert!

Greetz
Eldrik

habeIchVergessen

#36
so sieht es nach meinem dafürhalten besser aus (ungetestet, da kein OWX/OWFS im Einsatz)

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") {
       my $latches = fhem("get ".$name." latch.ALL");
       my $sensed = fhem("get ".$name." sensed.ALL");

       #--- DS2408 has 8 ports---
       # ggf. Daten konvertieren, damit indiziert zugegriffen werden kann
       for (my $port=0; $port <= 7; $port++) {
         Log3 $name, 4, "Port at device ".$name.": ".$port." isLatched: ".$isLatched;
       }
       #---Port gets cleared if autoClearAlarm---
       # hier fehlt noch die Auswertung der Bits
       if ($autoClear != "")  {
         fhem("set ".$name." latch.ALL 1");
         Log3 $name, 4,"autoClearedAlarm on Port: ".$port;
       }
   }
   return undef;
}

eldrik

Hi,

die Variante will ich wohl gerne testen, jedoch teile ich die einzelnen Pins eines ds2408 bisher per readingsProxy (ds2408:sensed.1) in einzelne Geräte auf.

Wenn nun nur noch das reading latch.all oder sensed.all gefüllt wird wie kann ich geschickt darauf reagieren, ohne das jetzige Konstrukt massiv umbauen zu müssen?

Kann ich für die valuefn des readingsProxy eine Regex definieren, dass z.B. nur der Wert (0/1) der ersten Stelle ausgewertet wird?

Greetz
Eldrik

habeIchVergessen

latch.0 ... .7 enthalten Werte die von latch.ALL abweichen?

Wenn dem so sein sollte, dann geht immer noch ein manuelles Update der readings + event_on_changed_reading

eldrik

verstehe ich nicht oder nur halb :o

Mit get latch.ALL oder sensed.All erhält man ein 8 Zeichen langes Reading im FHEM OWDevice, dies ist die ressourcenschonendere Methode um sich den Zustand aller Pins auf einmal zu holen.

Meine readingsProxy Geräte reagieren, in ihrer Definition, aber nur auf den jeweiligen latch.0,1,2,3 usw. oder halt sensed.x Wert wenn sich dieser ändert, dafür müsste sich das jeweilige Einzelreading aber erst einmal im Fhem OWDevice ändern was nur geschieht wenn dieses explizit per get latch.0,1,2,3 usw. geholt werden würde (eine direkte Umsetzung des latch.ALL Wertes, auf die einzelnen latch.0 Readings, über das OWDevice Modul, wäre natürlich der Hit) was ja dem ressourcenschonenden Ansatz wiederspräche oder nicht?

Daher suche ich gerade nach einer geschickten Variante mit der es möglich ist nur auf den Wert X an Stelle Y des readings latch.ALL oder sensed.ALL zu reagieren.

Ohne dafür ein notify erstellen zu müssen, welches das latch oder sensed.ALL reading nimmt, in einen Array überführt und die einzelnen Werte mit einer Schleife wieder in passende latch.0,1,2,3 usw. Readings eines neu zu erstellenden Dummy Devices, welches ich anstelle des originalen ds2408 owdevice, für die readingsProxy Definition verwende, schreibt.  :D

Greetz
Eldrik

habeIchVergessen

#40
Zitat von: eldrik am 15 Dezember 2017, 12:32:36
eine direkte Umsetzung des latch.ALL Wertes, auf die einzelnen latch.0 Readings, über das OWDevice Modul, wäre natürlich der Hit)
ich würde erwarten, das sich immer beide Werte ändern (also latch.0 und latch.ALL, wenn ich einen der beiden lese). Warum das nicht so ist, kann nur Prof. P.H. beantworten.

mal aus 36_KeyValueProtocoll kopiert

      readingsBeginUpdate($rhash);

      my @kvPairs;
      my @data = split(',', substr($msg, 12 + length($parts[0]) + length($parts[1])));
      for my $i (0 .. $#data) {
        if(@kvPairs && index($data[$i], "=") == -1) {
          splice(@kvPairs, @kvPairs -1, 1, $kvPairs[@kvPairs -1] . "," . $data[$i]);
        }
        else {
          push(@kvPairs, $data[$i]);
        }
      }

      while (@kvPairs) {
        my $kvPairString = shift(@kvPairs);
        my @kvPair = split('=', $kvPairString, 2);

        my $value = $kvPair[1];

        my $key = $kvPair[0];
        $key =~ s/^\s+|\s+$//g;
        if (%mappings) {
          my $newKey = $mappings{$key};
          $key = $newKey if ($newKey);
        }

        readingsBulkUpdate($rhash, $key, $value);
      }

      readingsEndUpdate($rhash, 1);


interessant sind die drei Aufrufe
- readingsBeginUpdate($rhash);
- readingsBulkUpdate($rhash, $key, $value);
- readingsEndUpdate($rhash, 1);

damit werden alle neuen Werte in die entsprechenden readings geschrieben.
event_on_change_reading sorgt dafür, dass nur dann ein event geworfen wird, wenn sich der Wert ändert.

vor der for-Schleife (#--- DS2408 has 8 ports---) readingsBeginnUpdate aufrufen. in der Schleife readingsBulkUpdate für latch.x und sensed.x. Nach der Schleife readingsEndUpdate.

$rhash wirst du aus $defs lesen müssen. bitte mal testen (OW_29. entsprechend setzen)

{ Dumper $defs{"OW_29.xxxx"};; }

eldrik

Zitat von: habeIchVergessen am 15 Dezember 2017, 13:20:52
ich würde erwarten, das sich immer beide Werte ändern (also latch.0 und latch.ALL, wenn ich einen der beiden lese). Warum das nicht so ist, kann nur Prof. P.H. beantworten.

Nee die Module OWDevice und owserver sind nicht von PAH.


Zitat

mal aus 36_KeyValueProtocoll kopiert

      readingsBeginUpdate($rhash);

      my @kvPairs;
      my @data = split(',', substr($msg, 12 + length($parts[0]) + length($parts[1])));
      for my $i (0 .. $#data) {
        if(@kvPairs && index($data[$i], "=") == -1) {
          splice(@kvPairs, @kvPairs -1, 1, $kvPairs[@kvPairs -1] . "," . $data[$i]);
        }
        else {
          push(@kvPairs, $data[$i]);
        }
      }

      while (@kvPairs) {
        my $kvPairString = shift(@kvPairs);
        my @kvPair = split('=', $kvPairString, 2);

        my $value = $kvPair[1];

        my $key = $kvPair[0];
        $key =~ s/^\s+|\s+$//g;
        if (%mappings) {
          my $newKey = $mappings{$key};
          $key = $newKey if ($newKey);
        }

        readingsBulkUpdate($rhash, $key, $value);
      }

      readingsEndUpdate($rhash, 1);


interessant sind die drei Aufrufe
- readingsBeginUpdate($rhash);
- readingsBulkUpdate($rhash, $key, $value);
- readingsEndUpdate($rhash, 1);

damit werden alle neuen Werte in die entsprechenden readings geschrieben.
event_on_change_reading sorgt dafür, dass nur dann ein event geworfen wird, wenn sich der Wert ändert.

vor der for-Schleife (#--- DS2408 has 8 ports---) readingsBeginnUpdate aufrufen. in der Schleife readingsBulkUpdate für latch.x und sensed.x. Nach der Schleife readingsEndUpdate.

$rhash wirst du aus $defs lesen müssen. bitte mal testen (OW_29. entsprechend setzen)

{ Dumper $defs{"OW_29.xxxx"};; }


uff da muss ich mal schauen ob ich damit zurechtkomme!

Greetz
Eldrik

habeIchVergessen

Zitat von: eldrik am 15 Dezember 2017, 15:45:29
Nee die Module OWDevice und owserver sind nicht von PAH.
ich hatte auf 21_OWSWITCH.pm getippt.


Zitat von: eldrik am 15 Dezember 2017, 15:45:29
uff da muss ich mal schauen ob ich damit zurechtkomme!

ich habe mal das Beispiel von oben ergänzt

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, 1));
readingsBulkUpdate($rhash, "sensed." . $port, substr($sensed, $port, 1));
       }
   readingsEndUpdate($rhash, 1);
   
       #---Port gets cleared if autoClearAlarm---
       # hier fehlt noch die Auswertung der Bits
       #if ($autoClear != "")  {
         fhem("set ".$name." latch.ALL 11111111");
         Log3 $name, 4,"autoClearedAlarm on Port: ";
       #}
   }
   return undef;
}



eldrik

mit dem Beispiel geht er nicht

in die if Abfrage

if ($type eq "DS2408" && defined($defs{"\"" . $name . "\""})) {

nehme ich den && Teil weg kommen folgende Fehlermeldungen (den Rest habe ich abgeschnitten):

Zitat2017.12.15 16:36:54.266 1: ports at device DS2408_6D5E04000000: latches 1,1,0,0,0,0,0,0, sensed: 1,1,0,0,1,1,1,1
2017.12.15 16:36:54.266 1: ERROR: empty name in readingsBeginUpdate
2017.12.15 16:36:54.266 1: eval: {getBUSalarm3("myOWFS")}
2017.12.15 16:36:54.266 1: stacktrace:
2017.12.15 16:36:54.266 1:     main::readingsBeginUpdate           called by ./FHEM/99_myUtils.pm (86)
2017.12.15 16:36:54.266 1:     main::getBUSalarm3                  called by (eval 82502) (1)
2017.12.15 16:36:54.266 1:     (eval)                              called by fhem.pl (1090)
2017.12.15 16:36:54.266 1:     main::AnalyzePerlCommand            called by fhem.pl (1113)
2017.12.15 16:36:54.266 1:     main::AnalyzeCommand                called by fhem.pl (1037)
2017.12.15 16:36:54.266 1:     main::AnalyzeCommandChain           called by ./FHEM/90_at.pm (179)
2017.12.15 16:36:54.266 1:     main::at_Exec                       called by fhem.pl (3079)
2017.12.15 16:36:54.266 1:     main::HandleTimeout                 called by fhem.pl (630)

Greetz
Eldrik

habeIchVergessen

#44
- Zugriff auf $defs geändert


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 if autoClearAlarm---
       # hier fehlt noch die Auswertung der Bits
       #if ($autoClear != "")  {
         fhem("set ".$name." latch.ALL 11111111");
         Log3 $name, 4,"autoClearedAlarm on Port: ";
       #}
   }
   return undef;
}


Nachtrag: Zugriff auf $latches und $sensed geändert

Test:

{ Dumper $defs{"DS2408_6D5E04000000"};; }