Hallo zusammen,
folgender Code funktioniert prima (uiState). Die $_recommendList und $_onoffList enthalten jeweils ca. 8 bzw. 14 Elemente. Ich würde gerne erreichen, dass nach 5 Elementen eine neue Zeile begonnen wird. Ich kann mir im Package eine Counterfunktion definieren, aber ich müsste innerhalb der FOR-Schleife eine Möglichkeit haben, abhängig vom Rückgabewert der Counterfkt ein "|" einzufügen oder eben auch nicht. Also ganz konkret, wird das "|" am Ende des Statements ICON($SELF_pickicon([$SELF:$_$2]))| eingefügt oder nicht. Ginge sowas?
{
package ui_Table; ## Package für uiTable-Funktionen
sub $SELF_pickicon {
my ($pos)=@_;
my $icon="general_aus\@grey";
if ($pos eq "keepOn" || $pos eq "switchOn" || $pos eq "on" ) {
$icon="general_an\@green";
} elsif ($pos eq "switchOff") {
$icon="general_aus\@red";
}
return $icon;
}
$TABLE = "border-collapse:separate;border-spacing: 10px 1px;border-left-width:10px;border-right-width:10px";
}
style("Recommendation","Darkorange")|""
FOR (@{$_recommendList},"$_$1"|ICON($SELF_pickicon([$SELF:$_$2]))|)
style(" ","Darkorange")
style("Status Device","Darkorange")|""
FOR (@{$_onoffList},"$_$1"|ICON($SELF_pickicon([$SELF:$_$2]))|)
style(" ","Darkorange")
Du musst mir hier die ganze Definition posten, also mit den beiden Array-Listen: $_recommendList und $_onoffList
Gerne, auch wenn sich mir nicht ganz erschließt wie das hilft, denn der Zeilenumbruch hat ja nichts mit dem Array als solches zu tun. Das gesamte DOIF hat ca. 600 Zeilen und wird bei Dir sicher nicht 1:1 laufen wegen der gerätespezifischen Anpassungen. Ich paste mal hier den Teil, wie die beiden Arrays befüllt werden. Aber nochmal: es geht ja nicht darum, dass der Code nicht funktioniert. Da ist alles prima. Auch der uiState funktioniert prima. Es geht nur um die Frage, ob ich einen Zeilenumbruch mit Hilfe einer Prozedur auslösen kann.
subs {
###########################################################################################
### Lokale Helper Variablen ###############################################################
###########################################################################################
my @params;
my @rawData;
my $temp;
my @tempArray;
my $now = time();
###########################################################################################
### Globale Variablen #####################################################################
###########################################################################################
## Code Deleted
## Code Deleted
## Code Deleted
## Consumer Name, Peak, Normal - Zahlen in Watt
@params = qw/Known Peak Normal CalcRecommend ReadingActual ReadingRecommend WaitTimeNormal WaitTimeNow PriorityVsCar/;
@rawData = qw/
Sauna 0 7000 500 0 consumption.assumed.sauna 0 0 0 0
Ofen 0 5000 800 0 consumption.assumed.ofen 0 0 0 0
Kueche 0 3000 500 0 consumption.assumed.kueche 0 0 0 0
Unknown 0 100 100 0 consumption.assumed.unknown 0 0 0 0
Lampen 1 100 8 0 consumption.assumed.lampen 0 0 0 0
Kleinkram 1 0 0 0 consumption.measured.kleinkram 0 0 0 0
Heizung 1 300 300 0 consumption.assumed.heizung 0 0 0 0
Grundwasserpumpe 1 1000 1000 1 consumption.assumed.grundwasserpumpe consumption.recommend.grundwasserpumpe 990 990 1
Bewaesserung 1 1000 1000 1 consumption.assumed.bewaesserungspumpe consumption.recommend.bewaesserungspumpe 930 930 1
Klima 1 4000 800 1 consumption.assumed.klima consumption.recommend.klima 900 900 2
LuftTrocknerWkst 1 250 250 1 consumption.measured.lufttrocknerwkst consumption.recommend.lufttrocknerwkst 780 780 3
LuftTrocknerHobby 1 250 250 1 consumption.measured.lufttrocknerhobby consumption.recommend.lufttrocknerhobby 730 730 3
/;
for (my $i=0; $i < @rawData; $i+=(@params+1)) {
for (my $j=0; $j < @params; $j++) {
$_consumers{$rawData[$i]}{$params[$j]} = $rawData[$i+$j+1];
}
}
## Code Deleted
## Code Deleted
## Code Deleted
## nun gehen wir alle Unique-Values (aka Consumer) durch und erzeugen das Array für die UITable
foreach (sort keys %{ $_consumers }) {
push (@{$_onoffList},["$_",$_consumers{$_}{ReadingActual}.".mode"]);
push (@{$_recommendList},["$_",$_consumers{$_}{ReadingRecommend}]) if ($_consumers{$_}{ReadingRecommend} ne "0");
Log3("$SELF", 5, "$SELF: _onoffList: $_ $_consumers{$_}{ReadingActual}.mode");
Log3("$SELF", 5, "$SELF: _recommendList: $_ $_consumers{$_}{ReadingRecommend}");
}
## Code Deleted
## Code Deleted
## Code Deleted
}
Also die Tabelle ist zwar dynamisch aufbaubar, aber nach der Definition statisch. Dh. der Tabellenaufbau kann nicht geändert werden, ohne eine Neudefinition (defmod). Ich befürchte, dass eine "dynamische Definition" so, wie du es willst, nicht möglich ist, da hier ein eigener Parser den Aufbau bei der Definition auswertet.
Ich arbeite immer so, dass ich das Array zeilenweise aufbaue, ein Element eines zweidimensionalen Arrays ist also eine Zeile der Tabelle und das entspricht im Abstrakten einer Szene mit beliebig vielen Attributen pro Szene (Spalten), siehe hier die Beispiele:
https://wiki.fhem.de/wiki/DOIF/Automatisierung#Beschattungssteuerung_abh.C3.A4ngig_von_der_Zimmertemperatur_und_Sonneneinstrahlung_f.C3.BCr_mehrere_Szenarien_mit_Visualisierung
oder
https://wiki.fhem.de/wiki/DOIF/Automatisierung#Steuerung_von_Raumthermostaten_f.C3.BCr_mehrere_R.C3.A4ume_mit_GUI
vielleicht kannst du es auch so aufbauen.
Edit: Im zweiten Beispiel habe ich sogar zwei FOR-Schleifen ineinander geschachtelt,
das Zeilenende erreiche ich durch ein "" hinter dem |ZitatFOR (@{$_sc},\
("$1$1"|\
card([$1$2:measured-temp:col1d],undef,\
[$1$3:state] eq "off" ? "sani_floor_heating_neutral\@silver" : "sani_floor_heating\@red" ,15,25,\
undef,undef,"°C",\&temp_hue,"1,,fill:silver","130,1,1,1,1,,200",\
undef,undef,[$1$3:state:col1d:$_ eq "on" ? 1:0],0,5,0,0,"I-O",\&onoff_hue,"0,,fill:silver")|\
"Modus:".widget([$SELF:$1$1_mode],"select,auto,off"),,"aktuell:".widget([$1$2:desired-temp],"selectnumbers,18,0.5,22,1,lin","set")|\
FOR(@{$_Timer},\
("AT: ".widget([$SELF:$1$1_temp_at_$2],"selectnumbers,18,0.5,22,1,lin"),,"WE: ".widget([$SELF:$1$1_temp_we_$2],"selectnumbers,18,0.5,22,1,lin")|))\
""\
)\
)
Ich habs gepackt. So geht es!
defmod di_tester DOIF init {\
my $constItemsPerColumn = 5;;\
my $elementCount = int(rand(25))+11;;\
$_uiStateArrays = int($elementCount/$constItemsPerColumn)+1;;\
my $processed = 0;;\
my $readingName;;\
my @tempArray;;\
\
fhem("deletereading $SELF .*");;\
Log3("$SELF", 5, "$SELF: Anzahl Elemente: $elementCount, Anzahl Arrays: $_uiStateArrays");;\
\
for (my $i=0;; $i<$_uiStateArrays;; $i++) {\
@tempArray = ();;\
for (my $j=0;; $j<$constItemsPerColumn;; $j++) {\
$processed = $i*$constItemsPerColumn+$j;;\
$readingName = "zustand_".sprintf("%02d", $processed);;\
\
last if($processed==$elementCount);;\
\
push(@tempArray, $readingName);;\
push(@{$_zustaende},$readingName);; \
\
Log3("$SELF", 5, "$SELF: i: $i, j: $j, processed: $processed, readingName: $readingName");;\
}\
@{$_uiStateList{$i}} = @tempArray;; \
}\
\
for (my $i=0;; $i<$_uiStateArrays-1;; $i++) {\
Log3("$SELF", 5, "$SELF: readingName: $_") foreach(@{$_uiStateList{$i}});;\
} \
}\
\
setter {\
[+15];;\
set_Reading("$_",("on","off")[int(rand(2))],1) foreach (@{$_zustaende}) ;;\
}\
\
attr di_tester disable 0
attr di_tester room Labor
attr di_tester uiState {\
package ui_Table;;\
$TABLE = "border-collapse: separate;;border-spacing: 10px 1px";; \
}\
\
##$TC{0,2,4,6} = "style='font-size: normal;;text-align:right;;color: DarkOrange'";;\
\
FOR (0..$_uiStateArrays-1,\
FOR(@{$_uiStateList{$1}},\
"$2"|[$SELF:$2,"off"]| icon([$SELF:$2,"off"]) |\
)|""\
)\
attr di_tester verbose 5
Das Problem ist, dass ich beim FOR-Befehl keine Indizierung vorgesehen habe.
Man kann also nicht mit Zahlen hantieren, sondern nur mit Platzhaltern.
Daher kann man z. B. nicht einzelne Elemente eines Arrays durchzählen, sondern muss sie einzeln angeben mit $_$1, $_$2, ... (entspricht $1$1, $1$2, ...)
In deinem Beispiel ist die Anzahl der Spalten festgelegt (5), daher sollte man mit :
FOR (@{$_uiStateList},"$_$1"|"$_$2"|"$_$3"|"$_$4"|"$_$5")
die Tabelle darstellen können.
Flexibler wäre man mit einem echten Perl-for-Befehl, aber dieser ist an dieser Stelle im uiTable/uiState-Attribut nicht vorgesehen. Meine Idee war seinerzeit für den Nichtprogrammierer es einfacher zu machen, daher die Platzhalter und keine Laufvariablen mit Indizierungen.
Ich hab gerade meinen vorigen Beitrag editiert. GEHT!!!
Zitat von: eddy242 am 14 Oktober 2022, 21:43:25
Ich hab gerade meinen vorigen Beitrag editiert. GEHT!!!
gut, aber nur deswegen, weil du die Indizierung über einen Hash realisiert hast :)
Edit: Dann hast du schon mehr erreicht, als ich vorgesehen hatte
reicht mir :-) danke für den Support und das grossartige Modul
Zitat von: eddy242 am 14 Oktober 2022, 21:51:30
reicht mir :-) danke für den Support und das grossartige Modul
Es ist immer wieder spannend zu sehen, was die Leute so alles aus dem Modul rausholen :)