ECMD / ECMDDevice Verhalten von set ... cmd und postproc in Verbindung mit state

Begonnen von Joe_D, 16 Dezember 2019, 20:01:17

Vorheriges Thema - Nächstes Thema

Joe_D

Hallo Zusammen,

habe ein selbstgebasteltes Device, das Stromstoßrelais zum Schalten von z.B. Lampen verwendet.
Um ein Relais zu schalten, muss folgender String gesendet werden:
S0:1 (Bedeutet: Setze Ausgang 1 von Baugruppe 0)

Eigentlich gibt es keine Antwort, ob geschaltet wurde oder nicht. Die Antwort kommt asychron vom Device und das sendet z.B.:
I0:00000001 (Bedeutet: Eingang 1 von Baugruppe 0 ist auf 1, alle anderen Eingänge sind 0)

Für das ECMD hinterlasse ich aber nach dem Schalten ein
ok

Die Klassendefinition sieht bei mir so aus:
params modnr pin
set on cmd { if (ReadingsVal("%NAME","internal","") eq "off") { return "S%modnr:%pin\n"; } else { return undef; }}
set on expect "ok\v"
set on postproc { s/\v//; $_ }

set off cmd { if (ReadingsVal("%NAME","internal","") eq "on") { return "S%modnr:%pin\n"; } else { return undef; }}
set off expect "ok\v"
set off postproc { s/\v//; $_ }

state internal

reading internal match "I%modnr:.*\v"
reading internal postproc { my $oldstate=ReadingsVal("%NAME","internal",""); my $np=%pin-1; s/^I%modnr:.{$np}[1].*\v$/on/; my $newstate=$_ eq "on" ? "on" : "off"; if ($newstate ne $oldstate) { $_=$newstate; } else { $_= undef; } }


Bei meinen Spielereien sind mir 2 Dinge aufgefallen:

1.) "set on cmd" möchte immer was senden, es geht einfach nicht "nichts" zu senden - weder mit undef noch mit "" (Leerstring).
In der Klassendefinition z.B. bei "set on cmd" habe ich ja extra eine Prüfung eingebaut, wenn mein 'internal'-Reading, das den aktuellen Zustand in "reading internal postproc" zugewiesen bekommt auf "on" steht dann soll eben nicht nochmal was geschickt werden, ist bei Stromstoßschaltern doof - nur ECMD ignoriert undef (und auch ""):

2019.12.16 16:57:35 5: IOServer: sending command <nothing>
2019.12.16 16:57:35 5: SW:
2019.12.16 16:57:38 2: IOServer: first attempt to read timed out, trying to close and open the device.


Gibt es einen Grund, das undef und "" gesendet werden? Oder ist das ein Bug?

Wenn die roten Zeilen in 66_ECMD.pm (ab Zeile 678) hinzugefügt werden, wird ab sofort nur noch ein "gefülltes" Kommando versendet:
ZitatECMD_Log $hash, 5, "command split into " . ($#ecmds+1) . " parts, requestSeparator is " .
    dq($requestSeparator) if($#ecmds>0);
  foreach my $ecmd (@ecmds) {
    if (defined($ecmd) && $ecmd ne "") {
        ECMD_Log $hash, 5, "sending command " . dq($ecmd);
        my $msg .= $ecmd;
        if(defined($expect)) {
          $answer= ECMD_SimpleExpect($hash, $msg, $expect);
          $answer= "" unless(defined($answer));
          ECMD_Log $hash, 5, "received answer " . dq($answer);
          $answer.= $responseSeparator if(defined($responseSeparator) && ($#ecmds>0));
          $ret.= $answer;
        } else {
          ECMD_SimpleWrite($hash, $msg);
        }
    }
  }


2.) reading internal postproc kann zwar undef oder "" zurückgeben, es wird aber das state verändert, obwohl ich doch explizit state internal angegeben habe  :o

In 67_ECMDDevice.pm ab Zeile 122:
ZitatECMDDevice_Changed($$$)
{
        my ($hash, $cmd, $value)= @_;
        #Debug "Device changed: $cmd $value";

        readingsBeginUpdate($hash);

        readingsBulkUpdate($hash, $cmd, $value) if(defined($value) && $value ne "");

        my $state;
        my $classname= $hash->{fhem}{classname};
        my $IOhash= $hash->{IODev};
        if(defined($IOhash->{fhem}{classDefs}{$classname}{state})) {
          if($cmd eq $IOhash->{fhem}{classDefs}{$classname}{state}) {
            $state= defined($value) ? $value : "?";
            #Debug "cmd= $cmd, setting state to $state (OVERRIDE)";
          }

Das heisst ich kann zwar verhindern, das mein Reading 'internal' gesetzt wird (blauer Code), aber der State (der ja den Wert vom Reading 'internal' bekommen sollte) wird dann leider auf "?" gesetzt (roter Code)...

Gibt es einen Grund, das der State auf ? gesetzt wird, wenn ich ein reading damit "verbinde" und ich das nicht gesetzt haben will?

Durch Änderung der roten Zeile oben durch folgendes erhalte ich mein gewünschtes Verhalten:

$state= defined($value) && %value ne "" ? $value : undef;

Nun kann ich wie ein wilder auf "on" klicken und wenn die Lampe schon leuchtet wird kein weiteres Kommando gesendet (wie durch die perl-Skripte in set on/off cmd gewünscht).
Ebenfalls kann die Rückantwort z.B. hundertmal "Lampe leuchtet" sein, der State und das Reading 'internal' werden nur beim Wechsel des Zustands gesetzt (wie eben durch die perl-Skripte in postproc gewünscht).

Gruß

   Jochen