Hallo Forum,
mein Plan war einzelne Relais (0-3) des Moduls zu schalten und den Status anzuzeigen. Mit Einschränkungen funktioniert die sache auch. Hier mal der Code für das Relais 0:
# Das Modul selbst
define TestRelais OWDevice 29.35A304000000
attr TestRelais model DS2408
define Relais_0 readingsProxy TestRelais:PIO.ALL
attr Relais_0 setFn {if($CMD eq "on") { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 0,1,0,0,0,0,1,1");;} else { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 1,1,1,1,1,1,1,1");;}}
attr Relais_0 setList on off fail
attr Relais_0 valueFn {if ($VALUE eq "1,1,1,1,1,1,1,1") { "off";; } elsif ($VALUE eq "0,1,0,0,0,0,1,1") { "on";; } else { "fail";; }}
attr Relais_0 webCmd on:off:fail
Wenn ich jetzt mit einem "set TestRelais PIO.ALL 0,1,0,0,0,1,1,1" sehe ich auch den Status "fail". Soweit so gut. Nehme ich jedoch das Modul vom Bus und schalte das Relais, sollte eigentlich ebenfalls ein "fail" angezeigt werden. Wenn ich ein "get TestRelais PIO.ALL" eingebe wenn das Modul vom Bus entfernt ist, sehe ich nichts. Eigentlich klar, da das Modul vom Bus entfernt ist. Warum bekomme ich jedoch nach dem schalten des Relais, wenn es nicht angeschaltet ist, kein "fail" ??
Bei diesem Modul ist es eigentlich nicht möglich den Status des Relais abzufragen. Man kann nur das Relais schalten und direkt nach dem schalten den Wert des PIO.ALL abfragen.
Wenn ich jetzt das Relais 1 schalten will brauche ich folgenden Code:
define Relais_1 readingsProxy TestRelais:PIO.ALL
attr Relais_1 setFn {if($CMD eq "on") { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 0,1,0,0,0,0,0,1");;} else { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 1,1,1,1,1,1,0,1");;}}
attr Relais_1 setList on off fail
attr Relais_1 valueFn {if ($VALUE eq "1,1,1,1,1,1,0,1") { "off";; } elsif ($VALUE eq "0,1,0,0,0,0,0,1") { "on";; } else { "fail";; }}
attr Relais_1 webCmd on:off:fail
Schalte ich jetzt das Relais 1 und das Modul ist am Bus, wird der Status des Relais 1 korrekt angezeigt, jedoch der Status des Relais 0 wird mit "fail" angezeigt.
Gibt es denn keine Möglichkeit die Statusanzeige nur nach dem schalten zu aktualisieren?
Tino
die valueFn wird aufgerufen wenn sich der wert des readings das du im define angibst ändert. egal wodurch. d.h. wenn ich das die ansteuerung richtig verstehe kannst du valueFn nicht verwenden.
wenn deine valuefn nichts tun soll musst sie undef zurück geben. also {undef} oder {return undef;}
wenn sich der aktuelle zustand nicht wirklich abfagen lässt musst du den zustand direkt nach dem schalten in setFn abfragen und state setzen.
warum du in der webCmd liste auch fail drin stehen hast verstehe ich nicht. du willst doch nicht per klick auf fail schalten oder ?
gruss
andre
Hallo,
erst mal vielen Dank für die Hilfe.
Das ich im webCmd noch ein fail drin stehen habe, ist noch auf meine Tests zurückzuführen. Wenn die Sache mal so läuft wie ich mir das vorstelle, kommt das natürlich raus.
In der setFn muß ich also nach dem fhem("set TestRelais PIO.ALL 0,1,0,0,0,0,0,1"), mit einem fhem("get TestRelais PIO.ALL") den Inhalt von PIO.ALL prüfen und davon abhängig mit einem fhem("set Relais_1 [on|off|fail]") den Staus setzen?
Warum wird jedoch nach dem schalten des Relais, z.B. auf ON, der Status ON angezeigt, auch wenn das Modul vom Bus entfernt ist?
Tino
ja. genau in der setFn den state setzen. aber mit setreading.
es sollte nichts angezeigt werden das nicjt auch gesetzt wird. dazu ist es aber in deinem fall wichtig falueFn undef zurück liefern zu lassen. sonst beeinflussen sich sie ausgänge gegenseitig weil der status nachträglich nicht mehr auszulesen geht.
gruss
andre
Hallo Andre,
ich werde die Sache heute Abend mal testen.
Vielen Dank für die Hilfe.
Tino
Hallo,
jetzt habe ich es geschafft das Relais zu schalten und wenn das Modul vom Bus entfernt ist, dass das Relais den Status "fail" hat.
Wenn ich aber das 2. Relais konfiguriere, und auch dieses schalte, wird mir der Status des 1. Relais mit "undef" angezeigt. Das gleiche Verhalten habe ich dann auch wenn ich wieder das 1. Relais schalte, wird der Status des 1. Relais richtig angezeigt, der des 2. Relais mit "undef".
Hab ich in der Definition der Relais noch einen Fehler?
define Relais_0 readingsProxy TestRelais:PIO.ALL
attr Relais_0 setFn {if($CMD eq "on") { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 0,1,0,0,0,0,1,1");;if (fhem("get TestRelais PIO.ALL") eq "0,1,0,0,0,0,1,1") {fhem("setreading Relais_0 state on");;} else {fhem("setreading Relais_0 state fail");;}} else { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 1,1,1,1,1,1,1,1");;if (fhem("get TestRelais PIO.ALL") eq "1,1,1,1,1,1,1,1") {fhem("setreading Relais_0 state off");;} else {fhem("setreading Relais_0 state fail");;}}}
attr Relais_0 setList on off fail
attr Relais_0 valueFn {"undef";;}
attr Relais_0 webCmd on:off
define Relais_1 readingsProxy TestRelais:PIO.ALL
attr Relais_1 setFn {if($CMD eq "on") { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 0,1,0,0,0,0,0,1");;if (fhem("get TestRelais PIO.ALL") eq "0,1,0,0,0,0,0,1") {fhem("setreading Relais_1 state on");;} else {fhem("setreading Relais_1 state fail");;}} else { fhem("set TestRelais strobe 1");; fhem("set TestRelais PIO.ALL 1,1,1,1,1,1,0,1");;if (fhem("get TestRelais PIO.ALL") eq "1,1,1,1,1,1,0,1") {fhem("setreading Relais_1 state off");;} else {fhem("setreading Relais_1 state fail");;}}}
attr Relais_1 setList on off fail
attr Relais_1 valueFn {"undef";;}
attr Relais_1 webCmd on:off
Tino
die valueFn muss undef zurückgeben. nicht "undef". also nicht einen string in dem undef steht sondern den perl wert undef.
noch ein vorschlag: der code für beide relais ist ziemlich ähnlich. ich sehe auf den ersten blick sogar nur einen unterschied. ich denke es wäre übersichtlicher und besser auf zusätzliche relais zu erweitern wenn du die komplette ansteuerung in eine sub in 99_myUtils.pm auslagerst und dann aus der setFn aufrufst und nur das was sich unterscheidet als parameter übergibst. also etwas in der art:my %mapping = ( 0 => { on => "0,1,0,0,0,0,1,1", off => "1,1,1,1,1,1,1,1" },
1 => { on => "0,1,0,0,0,0,0,1", off => "1,1,1,1,1,1,0,1" }, );
sub
myRelais($$)
{
my($id,$CMD) = @_;
my $code = $mapping{$id}->{$CMD};
return if( !defined($code) );
fhem("set TestRelais strobe 1");
fhem("set TestRelais PIO.ALL $code");
if( fhem("get TestRelais PIO.ALL") eq "$code") {
fhem("setreading Relais_$id state $CMD");
} else {
fhem("setreading Relais_$id state fail");
}
}
und dann in für Relais_0 als setFn:attr Relais_1 setFn {myRelais(0,$CMD);};
und für Relais_1:attr Relais_1 setFn {myRelais(1,$CMD);}
wenn du meherer der module hast kannst du natürlich auch noch $name und $DEVICE mit übergeben.
gruss
andre
Hallo Andre,
danke für den Tipp. Ja, das war auch der Plan wenn das Modul mal läuft.
Ich habe bisher ein Shell-Script das die Sache regelt. Ich werde dann mal das Script nach Perl portieren. Jetzt weiss ich zumindest wie ich die Sache angehen muss.
Tino
Hallo,
einen hab ich noch ...
Wie kann ich jetzt den Status der einzelnen Relais per Command abfragen, oder muß ich eine Varible vom Typ dummy definieren, diese dann setzen und an der entsprechenden Stelle abfragen?
Tino
du hattest doch oben gesagt das man die relais nicht wirklich nachträglich abfragen kann.
den zuletzt geschalteten zustand hast du doch als state deiner readingsProxies. also einfach Value("Relais_x")
was du noch zusätzlich machen könntest ist im haupt device für jedes relais mit setreading den zustand in ein reading stecken. aber ich wäre da vorsichtig weil du dir dann auch überlegen musst was passiert wenn dieses reading und state des jeweiligen readingsProxie nicht übereinstimmt. welches sollte gelten.
ein dummy brauchst du nicht.
gruss
andre
Hallo Andre,
vielen Dank.
Tino
Hallo,
ich hab mir gerade ein Script geschrieben und habe es in 99_Utils.pm unter der Zeile
"# start with your own functions below this line" und über der Zeile "# behind your last function, we need the following"
eingefügt. Nachdem die Sache nicht so funktioniert hat, habe ich die Sache mit dem Telnetzugang getestet:
fhem> {timed4channel(TestRelais,2,Relais_2,on);;}
darauf bekomme ich folgende Meldung:
Undefined subroutine @main::timed4channel called at (eval 21) line 1.
Ich habe die Datei 99_Utils.pm gespeichert und neu geladen. Das System habe ich auch durchgestartet. Trotzdem, der Fehler bleibt. Im Forum habe ich auch einige Meldungen zu diesem Fehler gesehen, jedoch keine Lösung gefunden.
Hat mir jemand einen Tipp ?
Tino
deine routine wurde nicht geladen.
mach mal ein 'reload 99_Utils' und schau was es für meldungen gibt.
ansonsten solltest du deine routinen in ein 99_myUtils.pm file tun. nicht in 99_Utils.pm. die wird beim update überschrieben.
schau mal im wiki. es gibt zwei regeln wie das file aufgebaut sein muss:
- es muss ein sub
myUtils_Initialize($$)
{
my ($hash) = @_;
}
geben
- am ende muss ein 1;
stehen
gruss
andre
Hallo,
jetzt klappt die Sache. Ich hab ne Datei 99_myUtils.pm angelegt, dort die Sachen reinkopiert, durchgestartet und schon läuft die Sache. In der Variablen @ sollte doch der Name des Gerätes drinstehen, oder?
In meinem Falle wäre das doch wohl doch "Relais_2"?
define Relais_2 readingsProxy TestRelais:PIO.ALL
Ich habe jetzt mal versucht diese Variable zu nutzen, jedoch ohne Erfolg.
Wie kann ich die Variable denn hier einbauen?
attr Relais_2 setFn {timed4channel($DEVICE,2,"Relais_2",$CMD);;
Tino
in @_ stehen die übergabe parameter. so kommst du z.b. dran: my($DEVICE,$name,$CMD) = @_;
die variablen namen die du innerhalb von deiner timed4channel sub verwendest müssen natürlich nicht die gleichen sein wie die die du übergibst. nur die reihenfolge ist wichtig.
gruss
andre
Hallo Andre,
irgendwie hab ich wohl die Doku falsch gelesen. Ich habe eigentlich die Variable $name gesucht. Gibt es eigentlich eine Doku in der ich die Systemvariablen finde? Bisher habe ich diese in verschiedenen Howto's und in deinen Antworten gefunden.
Vielen Dank für die Hilfe
Tino
so etwas wie systemvariablen gibt es nicht. das ist immer vom kontext abhängig. für die setFn gibt es $DEVICE, $READING, $CMD und $ARGS. ich glaube du hast auch noch $name zur verfügung. aber nur auf der obersten ebene. also innerhalb des {} der setFn. wenn du von dort eine eigene routine aufrufst musst du alles was du dort brauchst übergeben.
gruss
andre