Um die Fensteraktoren meiner Doppelfenster zusammenzufassen (nur ein Symbol für das Doppelfenster statt 2 und ein gemeinsamer - niedrigster - Batteriewert) habe ich eine structure angelegt:
define
define Wohnzimmerfenster structure MultiWindow MAX_17fe6e MAX_18012b
Um das reading "state" der beiden Fenster auswertbar zusammenzufassen stelle ich über ein stateFormat jeweils den ersten Buchstaben des readings "state" ein und erhalte so
- "cc" beide Fenster geschlossen (state "closed" und "closed")
- "oc" linkes Fenter offen (state "open" und "closed")
- "co" rechtes Fenter offen (state "closed" und "open")
- "oo" beide Fenster offen (state "open" und "open")
In TabletUI verwende ich dann ein Symbol Widget um das entsprechende Icon (Doppelfenster mit 0-2 offenen Flügeln) über "state" zuzuordnen.
stateFormat
attr Wohnzimmerfenster stateFormat {substr(ReadingsVal('MAX_17fe6e','state',''),0,1).substr(ReadingsVal('MAX_18012b','state',''),0,1)}
Den niedrigsten Batteriestatus ermittele ich in der 99_myUtils.pm ("ok" wird 100, "low" wird 1) und stelle den Wert im userReading "batteryPercent" ein
userReading
attr Wohnzimmerfenster userReadings batteryPercent {GetMultiWindowBatteries('MAX_17fe6e','MAX_18012b')}
Wie man sieht, muss ich hierzu jeweils die einzelnen devices angeben. Bei einem "normalen" device könnte ich mit $name arbeiten, gibt es hier etwas vergleichbares ?
Für stateFormat wäre noch die Reihenfolge (1. Element linkes Fenster, 2. Element rechtes Fenster) wichtig.
Das könntest Du hier auch, sofern der Name des Devices Verwendung finden soll in welchen Du das userReadings rein schreibst oder besser mit dessen Trigger Du arbeitest.
Ich könnte theoretisch stateFormat und userReadings in der Form
attr Wohnzimmerfenster stateFormat {GetMultiWindowState($name)}
attr Wohnzimmerfenster userReadings batteryPercent {GetMultiWindowBatteries($name)}
angeben. Allerdings müsste ich dann in den zugehörigen Perl-Funktionen auf die einzelnen Elemente der structure (hier: "MAX_17fe6e" und "MAX_18012b") zugreifen.
Aber ich habe keine Ahnung, wie ich die in Perl anspreche...
aktuell
sub GetMultiWindowBatteries($$) {
my ($myLeftWindow,$myRightWindow) = @_;
my $myResult = 100;
if (ReadingsVal($myLeftWindow,"battery","") eq "low") {$myResult = 1;}
if (ReadingsVal($myRightWindow,"battery","") eq "low") {$myResult = 1;}
return($myResult);
}
über $name
sub GetMultiWindowBatteries($) {
my ($myStructure) = @_;
my $myResult = 100;
if (ReadingsVal(?????,"battery","") eq "low") {$myResult = 1;}
if (ReadingsVal(?????,"battery","") eq "low") {$myResult = 1;}
return($myResult);
}
Wie ermittle ich Werte eines devices der structure ? Für die open/close Auswertung muß ich die devices auch in der richtigen Reihenfolge haben (linkes Fenster als erstes Element) oder über ein userAttr links/rechts zuweisen ...
Wenn ich Dich recht verstehe fehlt Dir die Info wo im Structure Device steht welche Objekte Teil der Structure sind. In Deinem Fall welche Fenster mit namen.
Steht zu mindest in der DEF drin. Wo anders wüsste ich auch nicht aktuell.
Den String aus der DEF bekommst Du mit
$defs{'STRUCTURENAME'}->{DEF}
Super :)
ich hab' es jetzt so gelöst:
attr Wohnzimmerfenster stateFormat {GetMultiWindowState($name)}
attr Wohnzimmerfenster userReadings batteryPercent {GetMultiWindowBatteries($name)}
sub GetMultiWindowState($) {
my ($myStructure) = @_;
my @myWindows = split(' ',$defs{$myStructure}->{DEF});
return(substr(ReadingsVal($myWindows[1],'state',''),0,1).substr(ReadingsVal($myWindows[2],'state',''),0,1));
}
sub GetMultiWindowBatteries($) {
my ($myStructure) = @_;
my @myWindows = split(' ',$defs{$myStructure}->{DEF});
my $myResult = 100;
if (ReadingsVal($myWindows[1],"battery","") eq "low") {$myResult = 1;}
if (ReadingsVal($myWindows[2],"battery","") eq "low") {$myResult = 1;}
return($myResult);
}
in "state" steht jetz "cc" usw. und in "batteryPercent" 100 bzw. 1, wenn eine Batterie "low" ist - Danke !!
Sieht gut aus.
Ein bisschen einfach ist
my (undef,$windowLeft,$windowRight) = split(' ',$defs{$myStructure}->{DEF});
Da Du die Anzahl der Objekte des Arrays ja kennst. Das nullte brauchst ja nicht, daher undef und dann halt eins und zwei.
Setzt natürlich voraus das Du bei der Definition immer erst das Linke und dann das Rechte genommen hast ;D
das ist sogar noch besser :)
sub GetMultiWindowState($) {
my ($myStructure) = @_;
my (undef,$myLeftWindow,$myRightWindow) = split(' ',$defs{$myStructure}->{DEF});
return(substr(Value($myLeftWindow),0,1).substr(Value($myRightWindow),0,1));
}
sub GetMultiWindowBatteries($) {
my ($myStructure) = @_;
my (undef,$myLeftWindow,$myRightWindow) = split(' ',$defs{$myStructure}->{DEF});
return(minNum(ReadingsVal($myLeftWindow,"batteryPercent",1),
ReadingsVal($myRightWindow,"batteryPercent",1)));
}
batteryPercent existiert schon als userReading, kann ich dann ja auch verwenden ;)
[Klugscheiß]
Statt über $defs{$myStructure}->{DEF} sollte der Endanwender besser über InternalVal($myStructure,"DEF","") gehen.
Und bei Verwendung von Zahlen ReadingsNum statt ReadingsVal benutzen.
Also:
my (undef,$myLeftWindow,$myRightWindow) = split(" ",InternalVal($myStructure,"DEF",""));
return minNum(ReadingsNum($myLeftWindow,"batteryPercent",100),ReadingsNum($myRightWindow,"batteryPercent",100));
[/Klugscheiß]
Gruß
Dan
Zitat von: DeeSPe am 29 März 2019, 15:15:49
[Klugscheiß]
Statt über $defs{$myStructure}->{DEF} sollte der Endanwender besser über InternalVal($myStructure,"DEF","") gehen.
Und bei Verwendung von Zahlen ReadingsNum statt ReadingsVal benutzen.
Also:
my (undef,$myLeftWindow,$myRightWindow) = split(" ",InternalVal($myStructure,"DEF",""));
return minNum(ReadingsNum($myLeftWindow,"batteryPercent",100),ReadingsNum($myRightWindow,"batteryPercent",100));
[/Klugscheiß]
Gruß
Dan
;D
ReadingsNum hab' ich schon drin, war hier noch "falsch".
Wo liegt der Unterschied bei InternalVal($myStructure,"DEF","") ? Welche Parameter kann man an die Funktion übergeben ?
Das ,1 bei ReadingsNum war schon korrekt, da ich den niedrigsten Wert haben möchte und wenn das userReading fehlt bekäme ich bei deiner Variante 100 % - bei meiner 1 %
edithab's gefunden - ReadingsVal, AttrVal und InternalVal machen prinzipiell das gleiche nur eben für Readings, Attribute oder Internals
Genau wie bei ReadingsVal, ReadingsNum, AttrVal und AttrNum ist der letzte übergebene Parameter der Default-Wert falls das Internal nicht existiert.
Gruß
Dan