Moin,
Ich suche ein Perl snippet mit dem ich über alle Type=dummy iterieren kann und den Namen zurückbekomme (oder ein handle) anhand des Atributes ,,Adress". Im weiteren Verlauf will ich verschiedene Readings dieses Devices setzen.
Szenario:
Ich bekomme von einer Sonoff RF Bridge über MQTT Werte einiger 433 MHZ PIR und Türsensoren. Die übermittelten Werte sind Hexwerte, Bsp. BBEA8A. Nach meinen Beobachtungen sind die 2 ersten Bytes (BBEA) die Adresse und das letzte Byte steht für Geräteklasse (8 ) und Zustand (A = motion)
Jetzt könnte man ein kilometerlanges DOIF schreiben, was aber sehr aufwändig ist. Meine Idee war, für jeden Sensor einen Dummy haus.pir.hinterhof.1 anzulegen, mit einem Atribut address = ,,BBEA". Wenn der Hexwert also reinkommt, sollte die Funktion anhand der ersten 4 Zeichen den Dummy zu finden und dann über ein switch case und das letzte Zeichen ein entsprechendes Reading (hier motion = on) zu setzen.
Hier die Lösung, mit dem DOIF, die ich jetzt verwende. Das sind nur 4 Sensoren, es sollen aber mehr werden und auch noch 2 Bridges mehr.
([stadtweg.rfbridge1:RfReceived_Data] eq "5969EE") (set stadtweg.tk.hh.hoftuer open)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "5969E7") (set stadtweg.tk.hh.hoftuer closed) (set stadtweg.tk.hh.hoftuer Tamper on)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "5969EF") (set stadtweg.tk.hh.hoftuer Battery low)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "5969EB") (set stadtweg.tk.hh.hoftuer Tamper off)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "BBEA8A") (set stadtweg.pir.hh.1 on) (set stadtweg.pir.hh.1 off) (set stadtweg.pir.hh.1 Tamper on)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "BBEA8F") (set stadtweg.pir.hh.1 Battery low)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "BBEA8B") (set stadtweg.pir.hh.1 Tamper off)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "35628A") (set stadtweg.pir.vh.1 on) (set stadtweg.pir.vh.1 off) (set stadtweg.pir.vh.1 Tamper on)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "35628F") (set stadtweg.pir.vh.1 Battery low)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "35628B") (set stadtweg.pir.vh.1 Tamper off)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "49228A") (set stadtweg.pir.vh.2 on) (set stadtweg.pir.vh.2 off) (set stadtweg.pir.vh.2 Tamper on)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "49228F") (set stadtweg.pir.vh.2 Battery low)
DOELSEIF([stadtweg.rfbridge1:RfReceived_Data] eq "49228B") (set stadtweg.pir.vh.2 Tamper off)
Edit: Falls sich jemand für die Sensoren interessiert, sie sind von Keriu und was ich über das letze Byte bisher rausgefunden habe im Screenshot
my @devices = devspec2array("TYPE=dummy:FILTER=Adress=..*"
sollte glaube ich gehen ( ungetestet ) .... ( liefert die Namen )
gruss Byte09
Cool, danke für die schnelle Antwort
Ich habe für einen solchen Dummy mal ein userattr airaddress=5969 angelegt
Dies in die Kommandozeile von FHEM gekippt
{devspec2array("TYPE=dummy:FILTER=airaddress=5969")}
liefert eine "1". Ändere ich den Wert kommt eine "0". Also funktioniert das schon mal irgendwie :) Vermutlich ist das der Treffer count.
Zitat von: Waldmensch am 24 November 2019, 10:00:14
Cool, danke für die schnelle Antwort
Ich habe für einen solchen Dummy mal ein userattr airaddress=5969 angelegt
Dies in die Kommandozeile von FHEM gekippt
{devspec2array("TYPE=dummy:FILTER=airaddress=5969")}
liefert eine "1". Ändere ich den Wert kommt eine "0". Also funktioniert das schon mal irgendwie :) Vermutlich ist das der Treffer count.
so ist es , wenn du es so in die kommandozeile eingiebst erhälst du die anzahl der gefundenen treffer.
wenn du es wie oben geschrieben in perl verwendest werden alle treffer namentlich in das array 'devices' geschrieben .
in der kommandozeile erhälst du mit
list TYPE=dummy:FILTER=airaddress=5969
die Namen aller treffer.
ich könnte mir vorstellen, das es hier bestimmt auch eine DOIFspezifische Lösung gibt, da bin ich aber raus ;)
gruss Byte09
Du kannst die Filteroption im DOIF nutzen https://fhem.de/commandref_DE.html#DOIF_Filtern_nach_Zahlen
Ich würde es allerdings so im Perl-Modus machen:
DOIF {if ([stadtweg.rfbridge1:RfReceived_Data] =~ /^(\.\.\.\.)(\.)(\.)/ ){
my $adresse=$1;
my $type=$2;
my $zustand=$3;
...
Danach kannst du switch nutzen oder sonst was mit den obigen Variablen anstellen und die entsprechenden set-Befehle absetzen. Die Filter-Regex kannst du natürlich auch auf Hex-Zahlen einschränken, wenn erforderlich.
Jo, hatte mich schon kurz eingelesen in der Doku https://wiki.fhem.de/wiki/DevelopmentModuleAPI#devspec2array
Kannst Du mir noch einen Tipp geben, wie ich in der selben Funktion einen 5 sekunden timeout setzen kann, damit das Device nach "motion" wieder in "off" fällt? Ich würde das vermutlich mit einem fhem(define tmpAT at +00:00:05 set " . @devices[0] . " off"). Ist das eine gute Idee?
in der myUtils habe ich das jetzt so
############# 433MHZ Sensors ###########
sub
set433Sensors
{
if(length($_[0]) != 6) {
return;
}
my $airaddress = substr $_[0], 0, -2;
my @devices = devspec2array("TYPE=dummy:FILTER=airaddress=" . $airaddress);
if (@devices == 0){
return;
}
my $status = substr $_[0], -1;
if ($status == "7") { # close
fhem("set " . @devices[0] . " closed");
} elsif ($status == "A") { #motion
fhem("set " . @devices[0] . " on");
} elsif ($status == "B") { #tamper
fhem("set " . @devices[0] . " Tamper on");
} elsif ($status == "E") { #open
fhem("set " . @devices[0] . " open");
} elsif ($status == "F") { #battery
fhem("set " . @devices[0] . " Battery low");
} else { #unknown
fhem("set " . @devices[0] . " unknownState " . $status);
}
#return $airaddress . " - " . @devices[0] . " " . $status;
}
okay funkioniert alles wie gewünscht, danke für den Support. Falls jemand ein ähnliches Problem hat
Standard Dummy für PIR Sensor
defmod myPIR dummy
attr myPIR userattr airaddress
attr myPIR airaddress BBEA
attr myPIR devStateIcon .*off:10px-kreis-gruen .*on:10px-kreis-rot
attr myPIR group PIR
attr myPIR readingList Battery Tamper Status
Notify zum triggern der Funktion
defmod ntfy_Sensors433 notify rfbridge1:RfReceived_Data.* { set433Sensors($EVTPART1) }
99_myUtils.pm
sub
set433Sensors
{
if(length($_[0]) != 6) {
return;
}
my $airaddress = substr $_[0], 0, -2;
my @devices = devspec2array("TYPE=dummy:FILTER=airaddress=" . $airaddress);
if (@devices == 0){
return;
}
my $status = substr $_[0], -1;
if ($status == "7") { # close
fhem("set " . @devices[0] . " closed");
fhem("set " . @devices[0] . " Tamper on");
} elsif ($status == "A") { #motion
fhem("set " . @devices[0] . " on");
fhem("set " . @devices[0] . " Tamper on");
fhem("define tmp_" . @devices[0] . "_AT at +00:00:04 set " . @devices[0] . " off");
} elsif ($status == "B") { #tamper
fhem("set " . @devices[0] . " Tamper off");
} elsif ($status == "E") { #open
fhem("set " . @devices[0] . " open");
} elsif ($status == "F") { #battery
fhem("set " . @devices[0] . " Battery low");
} else { #unknown
fhem("set " . @devices[0] . " unknownState " . $status);
}
}