Aus Hash-Referenz alle Readings von Device X deren Namen numerisch sind in Hash

Begonnen von TomLee, 28 Dezember 2021, 11:46:14

Vorheriges Thema - Nächstes Thema

TomLee

Hallo,

aufgrund diesem Thread stell ich mir diese Frage,  dazu hab ich mir auch schon was zusammengereimt, es bleibt aber das Gefühl das ich es umständlich angehe, am Ende hätte ich gerne in einem Hash (%h) das Ergebnis oder (das ist noch nicht weiter gedacht) die Referenz dazu in einem Reading abgelegt.


Das ist ein Test-Dummy, alles ignorieren bitte, nur die Reading(namen) sind wichtig:
defmod Demo dummy
attr Demo devStateIcon {package ui_Table;;\
ring(::ReadingsVal($name,"Test",0),0,100,0,120,'magenta',"200,1",undef,0,1)}
attr Demo eventMap /on-for-timer 3:dret.zu/
attr Demo readingList Test
attr Demo room Test
attr Demo setList test1:a,b,c,d,e on off
attr Demo useSetExtensions 1
attr Demo userReadings fluri {my $t = $defs{'Demo'}->{READINGS};;}
attr Demo webCmd pushek

setstate Demo on
setstate Demo 2021-12-27 18:25:47 1 Flur
setstate Demo 2021-12-27 18:26:24 2 Oben
setstate Demo 2021-12-27 18:27:07 3 Kueche
setstate Demo 2021-10-25 12:15:00 Test 55
setstate Demo 2021-12-15 13:40:37 Test4 2.00
setstate Demo 2021-10-25 12:15:00 Zeit 5
setstate Demo 2021-12-28 00:08:38 fluri HASH(0x6374810)
setstate Demo 2021-12-15 12:49:29 liste a,b,c,d,e
setstate Demo 2021-12-28 00:08:38 state on


{my $t = $defs{'Demo'}->{READINGS};;my ($i,%h);;for my $key (keys %$t) {$key eq  $key+0 ? $h{$key} = ReadingsVal('Demo',$key,'none') : next};;return my $z=join(", ",map { "$_=>$h{$_}" } keys %h);;}
->
2=>Oben, 1=>Flur, 3=>Kueche


Kann dazu bitte jemand was sagen, erläutern wie man es korrekt / womöglich einfacher angeht ?

Beta-User

Weiß ja nicht recht...

Also: du hast durchnummerierte Readings, weißt aber nicht wie viele? Es gibt eine Maximalzahl? Oder man könnte auf Verdacht mit einer hohen Nummer starten?
Am Ende soll ein "gejointes Array" mit den Reading-Werten in der Reihenfolge der Nummern kommen?

Dann (Pseudocode, musst das drumrum noch anpassen):
for (1..$max) { my $val = ReadingsVal($name,$_,0); last if !defined $val; push @arr, $val}; return join q{,}, @arr;
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

TomLee

Versteh ich nicht, warum soll ich das begrenzen müssen ?
Ich prüf doch in der Schleife ob es ein numerischer Wert ist, sonst gehts einfach weiter.

Beta-User

Bin erst mal davon ausgegangen, dass es einen "Klartext-Setter" geben soll, statt eines "1-n"-Setters nur mit Nummern. Also muss irgendwie von Text auf die Nummer geschlossen werden. Der einfachste (lesbare) Weg in diese Richtung ist m.E. eigentlich nicht Hash, sondern ARRAY, indem du aus dem "setter-Reading" mit allen Namen wieder ein Array splittest. Dabei bleibt die Sortierung erhalten, wenn du ausschließlich numerisch vorgehst und bei Array bleibst.
Dann hast du "nur" das Problem, dass das Zielgerät den ersten Eintrag mit "1" benennt, du aber in "0 bis ..." denken musst, also immer vor dem Senden noch +1 rechnen mußt.

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

TomLee

Also: du hast durchnummerierte Readings, weißt aber nicht wie viele? Es gibt eine Maximalzahl? Oder man könnte auf Verdacht mit einer hohen Nummer starten?

Ja, die Anzahl ist halt abhängig wieviele Zonen man anlegt und das ist sicherlich/vermutlich begrenzt, weiß es aber nicht.

Am Ende soll ein "gejointes Array" mit den Reading-Werten in der Reihenfolge der Nummern kommen?

Am Ende will ich wie geschrieben nur den Hash oder die Referenz dazu, das return in meinem Beispiel war nur zum zeigen das mein Code klappt.

Beta-User

Na ja, wenn wirklich ein "Text-Hash" am Ende stehen soll, und es beliebig viele Lücken in der Nummerierung geben soll, geht es tendenziell m.E. nur so, wie du das gemacht hast.
Gibt es keine Lücken, würde ich das mit einer numerischen for-Schleife machen (Endwert z.B. 100 Zonen), die halt fertig ist, wenn der (in meinem Beispiel auch fehlerhaft mit "0" belegte Defaultwert "undef" kommt. Dann sind die "unwichtigen" Readings raus.

Ein "sort" vor keys %h würde vermutlich der Lesbarkeit dienen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

TomLee

Der einfachste (lesbare) Weg in diese Richtung ist m.E. eigentlich nicht Hash, sondern ARRAY, ...

Ok, versteh ich, dann halt mit Array, mit dem Hash anzugehen hätt mich aber der ganze Weg zum Ziel interessiert.

Beta-User

Na ja, egal wie man es angeht, du musst halt irgendwie mit diesem Zwischenergebnis eine Vorstellung verbinden, wie es weitergehen soll. Klar kannst du das eventMap-Attribut leichter schreiben, wenn du deine Hash-Variante da reinknödelst. Das macht aber noch lange nicht aus dem "multiple-choice-setter" irgendwas für die Sauger-firmware verwertbares, von daher war mein Vorschlag eben, direkt die Klartext-Zonen zu joinen, damit man auf die via ReadingsVal zugreifen kann (das kann doch die neue Variante in FHEMWEB, oder?). Danach muss man eben die "Text-Liste" wieder in eine "Nummern-Liste" übersetzen. Auch kein Spaß, aber machbar...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

TomLee

ZitatKlar kannst du das eventMap-Attribut leichter schreiben ...

Noch keinen einen Gedanken hab ich daran verschwendet eventMap in mein weiteres vorgehen mit einzubeziehen, falsche Glaskugel heute  :).

Beta-User

Zitat von: TomLee am 28 Dezember 2021, 12:51:48
falsche Glaskugel heute  :) .
Weiß nicht...

Mein erster Vorschlag war direkt, lesbare, richtig sortierte, kommaseparierte Array-Listen zu bilden, damit man damit "wähl- und lesbare" setter (multiple strict-Widget) bilden kann.
Du wolltest unbedingt Hashes haben, (erst) das hat meine Glaskugel dann beim nochmaligen Blick in den bezogenen Thread getrübt ::) ...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

TomLee

Ja, immer noch Hash  8). Kannst du bitte nachvollziehen warum Fhem sich aufhängt bei der letzten Schleife ?

ZUm testen kann man den dummy oben nehmen.

Zitat{my $t = $defs{'Demo'}->{READINGS};;my ($i,%h);;for my $key (keys %$t) {$key eq  $key+0 ? $h{ReadingsVal('Demo',$key,'none')} = $key : next};; my @s = split(',',qw(Kueche,Flur,Oben));;my @u;;for (@s){push (@s,$h{$_})};;join ',',@s}

edit:

In @s wären jetzt die Rückgabewerte von dem multiple-strict.

edit2:

::)

Zitat{my $t = $defs{'Demo'}->{READINGS};;my ($i,%h);;for my $key (keys %$t) {$key eq  $key+0 ? $h{ReadingsVal('Demo',$key,'none')} = $key : next};; my @s = split(',',qw(Kueche,Flur,Oben));;my @u;;for (@s){push (@s,$h{$_})};;join ',',@s}

vs.

Zitat{my $t = $defs{'Demo'}->{READINGS};;my ($i,%h);;for my $key (keys %$t) {$key eq  $key+0 ? $h{ReadingsVal('Demo',$key,'none')} = $key : next};; my @s = split(',',qw(Kueche,Flur,Oben));;my @u;;for (@s){push (@u,$h{$_})};;join ',',@u}

TomLee

Davon ab das es mit UG/DreameZ10Pro/MapData/segments:.* json_segments wieder ganz andere Voraussetzungen sind, mein ich könnte man es mit dem Hash so angehen ?

userReading:
zone_all {my $t = $defs{$name}->{READINGS};;my ($i,%h);;for my $key (keys %$t) {$key eq  $key+0 ? $h{ReadingsVal($name,$key,'none')} = $key : next};;join(",",sort keys %h);;}

setList:
zones:{'multiple-strict,'.ReadingsVal($name,'zone_all','')} {my $t = $defs{$NAME}->{READINGS};;my ($i,%h);;for my $key (keys %$t) {$key eq  $key+0 ? $h{ReadingsVal($NAME,$key,'none')} = $key : next}; my @s = split(',', $EVTPART1);;my @u;for (@s){push (@u,$h{$_})};my $jr = encode_json(\@s);return 'UG/DreameZ10Pro/MapSegmentationCapability/clean/set { "segment_ids": '.$jr.', "iterations": 1, "customOrder": true }';}

Ich kanns nicht testen, du hast denk ich verstanden um was es geht, natürlich kann man hier und da was anders machen/optimieren, grundsätzlich hatte ich es mir so in etwa vorgestellt.