Frage zu structure

Begonnen von dt2510, 29 März 2019, 12:14:00

Vorheriges Thema - Nächstes Thema

dt2510

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.

CoolTux

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.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

dt2510

#2
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 ...

CoolTux

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}
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

dt2510

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 !!

CoolTux

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
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

dt2510

#6
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 ;)

DeeSPe

#7
[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
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

dt2510

#8
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 %

edit

hab's gefunden - ReadingsVal, AttrVal und InternalVal machen prinzipiell das gleiche nur eben für Readings, Attribute oder Internals

DeeSPe

Genau wie bei ReadingsVal, ReadingsNum, AttrVal und AttrNum ist der letzte übergebene Parameter der Default-Wert falls das Internal nicht existiert.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe