FHEM Forum

FHEM => Sonstiges => Thema gestartet von: NeuFehm am 03 Januar 2016, 21:25:20

Titel: Statusabfrage in *.classdef verarbeiten
Beitrag von: NeuFehm am 03 Januar 2016, 21:25:20
Liebe FHEM/PERL-Freunde,

ich muss in meiner classdef den Status einer "Lampe" (hier LED1) abfragen.
Wenn ich den Status der leuchtenden LED über die Kommandozeile abfrage "getstate LED1",
erhalte ich:
state:1

Da ich nur die "1" brauche, war meine Idee einen Substring zu erzeugen und in der classdef zu verwenden:
my $TLed1 = substr(fhem "getstate LED1",6,1);;\

Aber das erzeugt die Fehlermeldung im log:
myleds: sending command "Not enough arguments for substr at (eval 124) line 1, near "1)"\n"

Der einfache Programm-Gegencheck funktioniert einwandfrei:
my $TLed1 = 1;;\

Hat jemand eine Idee, wie ich eine Statusabfrage in der classdef verwenden kann?
Titel: Antw:Statusabfrage in *.classdef verarbeiten
Beitrag von: NeuFehm am 03 Januar 2016, 22:25:15
erledigt.
Habe den Code einfach "erweitert":
my $Status = fhem "getstate LED1";;\
my $TLed1 = substr($Status,6,1);;\
Titel: Antw:Statusabfrage in *.classdef verarbeiten
Beitrag von: viegener am 03 Januar 2016, 23:03:56
Ich würde Dir empfehlen Dich etwas in perl und auch in einige der (normalerweise vor allem für Entwickler relevanten) Dokumente im fhemwiki einzuarbeiten. Eigentlich schreibst Du ja perl-code.

Hintergrund:
- fhem "getstate LED1" ist eigentlich ein Aufruf der Funktion fhem also wäre es besser hier
fhem( "getstate LED1")
- Auf der anderen Seite wird hier ein Kommando zusammengebaut, dass dann in fhem erst wieder mühsam zerlegt und interpretiert werden muss. Wenn Du also bereits auf der perl-Ebene bist, wäre ein Aufruf der Funktion ReadingsVal() einfacher.
In diesem Fall wäre das vermutlich ReadingsVal("LED1", "state", "0") einfacher.
- Interessanterweise nehme ich an, dass das Ergebnis dann sogar einfach der Text (nur bestehend aus der 1) zurückgegeben wurde, denn ich vermute der Präfix "state:" kommt vermutlich aus dem getstate-Kommando.

Titel: Antw:Statusabfrage in *.classdef verarbeiten
Beitrag von: NeuFehm am 04 Januar 2016, 14:49:23
Oh das klingt gut.
Denn nun kann ich weiter "ausholen":
Im Prinzip habe ich 5 Ports in einem Byte zu schalten. Darum muss ich auch die anderen Ports/Geräte abfragen,
um eine Änderung am NUR am jeweiligen Gerät auszuführen und den Status der anderen Geräte zu belassen.
Allerdings möchte ich auch nicht alle Ports in FHEM definieren müssen, sodass ich eigentlich eine IF-Bedingung geplant hatte:
Wenn keine 0 oder 1 zurück, weil Device gar nicht da, dann einfach 0 nehmen.
Die ReadingsVal sehen so aus, als ob der DEFAULT-Wert genommen wird, wenn kein Wert zu diesem Reading vohanden ist.
Das wäre genau das, was ich bräuchte, dann würde für alle Gerräte/Ports, die er nicht kennt "0" zurückgeben und ich kann mir die ganzen IFs sparen ;)

Ich teste das heute mal :)
Titel: Antw:Statusabfrage in *.classdef verarbeiten
Beitrag von: NeuFehm am 04 Januar 2016, 15:07:30
Ich habe ersetzt:
my $Status = fhem "getstate LED1";;\
my $TLed1 = substr($Status,6,1);;\


mit:
my $TLed1 = ReadingsVal("LED1", "state", 0);;\

Gibt ein Fehler im log:
PERL WARNING: Illegal binary digit 'o' ignored at (eval 178) line 1.

Unabhängig von Hilfe, werde ich mich trotzdem in Perl weiter einarbeiten ;)
Titel: Antw:Statusabfrage in *.classdef verarbeiten
Beitrag von: NeuFehm am 04 Januar 2016, 15:56:40
Ahhh...der gibt ein "off" oder "on" zurück...
funktioniert also theoretisch schon mal :)

Muss nun nur noch den ReadinsVal in eine 0 bei "off" und 1 bei "on" umwandeln.

...Stunden später.....
Und da ich mich inzwischen noch ein bisschen mit Perl angefreundet habe,
habe ich gleich mal eine Subroutine probiert, die auch funktioniert ;)
Hier meine led.classdef
params T_Adresse T_Port
set on cmd {\
my $Led1 = onoff("Led1");;\
my $Led2 = onoff("Led2");;\
my $Led3 = onoff("Led3");;\
my $Relais1 = onoff("Relais1");;\
my $Relais2 = onoff("Relais2");;\
my $TLeer = 0;;\
my $DeziCode = oct("0b".$TLeer.$TLeer.$Led3.$Led2.$Led1.$TLeer.$Relais2.$Relais1);;\
chr(35).chr(84).chr(%T_Adresse).chr(80).chr(59).chr($DeziCode).chr(13).chr(10);;\
sub onoff {my $Port = shift;if ("%T_Port" eq $Port) {$Port=1} else {if (ReadingsVal("$Port", "state", "off") eq "on"){$Port=1} else {$Port=0}}};;\
}

set off cmd {\
my $Led1 = onoff("Led1");;\
my $Led2 = onoff("Led2");;\
my $Led3 = onoff("Led3");;\
my $Relais1 = onoff("Relais1");;\
my $Relais2 = onoff("Relais2");;\
my $TLeer = 0;;\
my $DeziCode = oct("0b".$TLeer.$TLeer.$Led3.$Led2.$Led1.$TLeer.$Relais2.$Relais1);;\
chr(35).chr(84).chr(%T_Adresse).chr(80).chr(59).chr($DeziCode).chr(13).chr(10);;\
sub onoff {my $Port = shift;if ("%T_Port" eq $Port) {$Port=0} else {if (ReadingsVal("$Port", "state", "off") eq "on"){$Port=1} else {$Port=0}}};;\
}


Und hier die entsprechenden Einträge in der fhem.cfg:
# LEDs definieren
define myleds ECMD serial /dev/ttyUSB0@9600
attr myleds classdefs myleddevice=/opt/fhem/led.classdef
attr myleds partial 1
attr myleds verbose 5
deleteattr myleds requestSeparator
attr mylampe split \r\n

define Led1 ECMDDevice myleddevice 33 Led1
attr Led1 IODev myleds
attr Led1 room Test

define Led2 ECMDDevice myleddevice 33 Led2
attr Led2 IODev myleds
attr Led2 room Test


Nun fällt mir in der fhem.cfg nur noch der wahrscheinlich überflüssige extra Parameter für den Devicenamen "Led1" auf.
Muss mal die commandref nach der passenden Variablen durchsuchen, oder hat gleich einer diese parat?