[erledigt] Arrays in uiTable und DOIF-Perl

Begonnen von Sany, 24 Januar 2021, 15:58:41

Vorheriges Thema - Nächstes Thema

Sany

Hallo Damian und andere Wissende;-)

folgendes Problem: Ich habe verschiedene Homematic Thermstate: entweder Wandthermostat mit Relais für Fussbodenheizungsventil oder Wandthermostat gepeered mit Heizkörperthermostat sowie einen Heizkörperthermostat alleine. Jetzt gibts da diese wahrlich doofe Namensgebung der Kanäle:
Wandthermostat: xxx_Climate, beim Heizkörperthermostat heißt der xxx_Clima. Allerdings gibt es beim Heizkörperthermostat noch xxx_Climate und xxx_ClimaTeam.

Ich möchte nun ein generalisertes Perl-DOIF erstellen wo ich auf die Climate/Clima Kanäle mittels select-Widget sowie vom Code aus zugreifen kann. Ich brauche also ein array im Perl-Block sowie im uiTable. Um die Heizkörperthermostate auszublenden, die mit einem Wandthermostat verbunden sind, habe ich alle gewünschten Climate/Clima-Kanäle der group "selectedTH" zugeornet.

Was funktioniert:
uiTable:
WID([$SELF:sensorSelect],[@"HzgThermostat.*Clima.*"::$group =~ "selectedTh"]) ergibt ein Auswahlfeld, welches tatsächlich nur die gewünschten Thermostate enthält. Ist allerdings nur zur Demo geeignet, denn ich kann auf das Array ja nicht vom DOIF aus zugreifen.

im Perl-Block des DOIF, analog zu den Beispielen zur Generalisierung:
@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima(te)',,$group =~ 'selectedTh');
geht nicht, weil $group nicht funktioniert: (Global symbol "$group" requires explicit package name (did you forget to declare "my $group"?)
@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,AttrVal($_,"group","nix") =~ 'selectedTh'); funktioniert nur soweit, dass die condition group =~ "selectedTH" leider ignoriert wird.

Was noch dazu kommt: ich möchte, wenn das array erzeugt ist, per unshift (@{$_thDevs},  "---" , "all"); noch zwei Einträge an den Anfang hinzufügen, was auch funktioniert.

Was ich also nicht hinbekomme ist im Perlteil die Bedingung group =~ "selectedTH" richtig einzubauen und dann das array auch noch in uiTable zu verwenden. Ein
WID([$SELF:sensorSelect],@{$_thDevs}) bringt nur den ersten Eintrag der Liste und ansonsten Fehler im Log:
PERL WARNING: Bareword found where operator expected at (eval 8976836) line 1, near "@"HzgThermostat"
PERL WARNING:        (Missing operator before HzgThermostat?)
PERL WARNING: Bareword found where operator expected at (eval 8976836) line 1, at end of line
PERL WARNING:        (Missing operator before ?)


Geht das überhaupt, was ich da vorhabe? Und falls, ja, wie denn dann richtig?

Danke schon mal!


Sany
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

Zitat von: Sany am 24 Januar 2021, 15:58:41
im Perl-Block des DOIF, analog zu den Beispielen zur Generalisierung:
@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima(te)',,$group =~ 'selectedTh');
geht nicht, weil $group nicht funktioniert: (Global symbol "$group" requires explicit package name (did you forget to declare "my $group"?)

Die Bedingung muss ebenso, wie die anderen Übergabeparameter, in Anführungszeichen gesetzt werden. Sie soll ja nicht beim Aufruf der Funktion AggrDoIf ausgewertet werden, sie wird in den jeweiligen Schleifen innerhalb von AggrDoIf ausgewertet.

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima(te)',,"$group =~ 'selectedTh'");
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sany

Hallo Damian,
schon mal vielen Dank für die Antwort. Das Ganze soll ja in der subs{} ablaufen, damit es nach Start des DOIF vorhanden ist, so wie bei den Beispielen zur Automation, also:

subs{
@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,"$group =~ 'selectedTh'");
unshift (@{$_thDevs},  "---" , "all");
} ## endSubs

bringt leider immer noch den Fehler:
DOIF: error in defs block: Global symbol "$group" requires explicit package name (did you forget to declare "my $group"?) at (eval 10748711) line 3.

lasse ich den Filter weg, also
subs{

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,);

unshift (@{$_thDevs},  "---" , "all");
} ## endSubs

sind alle Thermostate im array drin (auch die, die ich mit dem Filter "beseitigen" möchte:
im list vom DOIF
   thDevs:
       ---
       all
       HzgThermostatAZ_Climate
       HzgThermostatBadHHK_Clima
       HzgThermostatBadHHK_ClimaTeam
       HzgThermostatBadHHK_Climate
       HzgThermostatBadOG_Climate
       HzgThermostatDiele_Climate
       HzgThermostatN_Climate
       HzgThermostatSZ_Climate
       HzgThermostatWC_Climate
       HzgThermostatWZ_Climate
       HzgThermostatY_Climate

schreibe ich den Filter mit den Anführungszeichen "andersrum"
subs{

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'$group =~ "selectedTh"');


unshift (@{$_thDevs},  "---" , "all");
} ## endSubs
gibts den Fehler nicht, aber die Funktion geht auch nicht, nur das unshift:
     thDevs:
       ---
       all


ich vermute das Problem aus der Richtung Namensraum, das $group in subs nicht bekannt ist. Kann man da was machen?
Oder bin ich da zu kompliziert unterwegs? Ich weiss halt nicht, wie ich die Devices sonst unterscheiden soll, also das Problem der Namensgebung Climate/Clima. Ansonsten unterscheiden die sich nur im attr model (HM-TC-IT-WM-W-EU/HM-CC-RT-DN)

Und dann noch die uiTable. Da sind bisher auch die Versuche gescheitert, das select-Widget aus dem array zu füttern. Nur wenn ich es direkt im WID erzeuge klappts, aber auch nur ohne Filter.
Ich denke, wenn das mit dem Filtern so nicht hinhaut müßte ich die Devices so umbenennen, dass ich sie mit der Regex ohne Filter alle treffe. Muss aber mal schauen, ob das bei den Homematic-Teilen so geht, also dass sie dann auch noch funktionieren, wenn man die Kanäle beliebig umbenennt....

Trotzdem schon mal vielen Dank für jedwede Hilfe!
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

Ja, das sind mal wieder Perl-Tücken, da habe ich selbst nicht aufgepasst. Es muss heißen:

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'$group =~ "selectedTh"');

Wenn $group innerhalb von doppelten Anführungszeichen angegeben wird, wird es sofort ausgewertet, $group soll aber als Variablenname weitergereicht werden und nicht sofort ausgewertet werden, deswegen einfache Anführungszeichen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sany

So, Teil 1 ist gelöst. Das mit $group =~ oder AttrVal in der condition hat es nicht geklappt. Ich hab mir mal die darunterliegende Funktion "AggrIntDoIf" in DOIF.pm angesehen, aber da bin ich noch zu weit weg, um das richtig zu verstehen. Mir ist aber der Vergleich mit einem Reading klar geworden und so habe ich einfach jedem Device, welches ich im array haben möchte, ein reading "mySelect" verpasst mit dem Inhalt "selectedTh".
Mit
subs{

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',"mySelect",'"selectedTh"');
##@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,);
##@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'"group =~ selectedTh"');
##@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'$group =~ "selectedTh"');
##@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,AttrVal($_,"group","nix") =~ "selectedTh");
unshift (@{$_thDevs},  "---" , "all");
} ## endSubs
funktioniert es jetzt, das array beinhaltet die gewünschten Devices. Die auskommentierten Zeilen zeigen meine gescheiterten Versuche...

Nun noch die uiTable. Hier führte bisher auch keiner meiner Versuche zum Ziel. Wie schon geschrieben kann ich die Aggregatsfunktion einbauen, also
WID([$SELF:sensorSelect],[@"HzgThermostat.*Clima.*":"mySelect":"selectedTh"]), das klappt auch, ich möchte da aber auch noch "---" und "all" am Anfang der Liste haben. Jetzt dachte ich, am einfachsten sollte doch das vorhandene array funktionieren, klappt aber nicht. Eine FOR-Scheife hat in diesem Fall vermutlich keinen Sinn. Kann das überhaupt gehen? Oder könnte man im DOIF-Perl Teil oder im uiTable Perl-Block etwas vorbereiten, um das Widget zu füllen?

Vielleicht hast Du ja noch eine Idee?

danke schon mal und morgen dann wieder.... (ich seh eh nur noch verdrehte regexes  :o :-\
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

Wundert mich, dass:

##@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'$group =~ "selectedTh"');

nicht funktioniert hatte. Müsste ich bei mir nachstellen.

Bei:

WID([$SELF:sensorSelect],[@"HzgThermostat.*Clima.*":"mySelect":"selectedTh"])


ist der zweite Parameter eine kommagetrennte Liste für die Select-Auswahl. Diese Liste braucht man nur zu erweitern:

WID([$SELF:sensorSelect],"---,all,".[@"HzgThermostat.*Clima.*":"mySelect":"selectedTh"])
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

Was mir noch zu $group einfällt, ist die Tatsache, dass in Group mehrere Gruppen per Komma getrennt drin stehen können, die Abfrage wäre dann vielmehr:


@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'"selectedTh" =~ $group');
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sany

Hi Damian,

vielen Dank für Deine Hilfe. Das mit der $group haut immer noch nicht hin. Es ist aber auch nicht mehr relevant: Es funktioniert ja mit dem Workaround eines readings, wie in meinem letzten Teil gepostet. Aber am Ende werde ich doch eine "händische" Arry-zuordnung vornehmen, sprich die nötigen Devices per Hand eintragen. Damit habe ich die Möglichkeit, die Reihenfolge zu beeinflussen, ohne nochmals workarounds zu bemühen. Am Ende brauche ich eine sortierte Liste meiner Thermostaten mit "---" und "all" davor. Und die Anzahl der Thermostaten ändert sich ja eher sehr, sehr selten.
Das mit dem Widget habe ich rausbekommen, wie ich das Array aus der DOIF-def verwenden kann:
WID([$SELF:sensorSelect],join(",",@{$_thDevs}))
So einfach kann es sein. Jetzt habe ich mein Select-Widget und kann weitermachen.

Wofür das Ganze: Ich habe mich in letzter Zeit mal um meine Thermostate gekümmert. Eigentlich liefen die alle mit einem Wochenprogramm (eher Tagesprogramm, da kaum Unterschiede zwischen den Tagen) und unbeeinflusst von fhem. So sollte das ja auch sein, sollte fhem mal streiken wird die Bude nicht kalt. Jetzt bin ich mal die Wochenprogramme angegangen, um die "autarke" Steuerung einfacher beeinflussen zu können. Voraussetzungen sind alle geschaffen, wo es geht sind 2 Wochenprogramme im Thermostat hinterlegt, beim Heizkörperthermostat die Listen angelegt, die per Befehl "umgeladen" werden können. Eine Übersicht ist schon fertig, wo alle Daten der Thermostate angezeigt werden (Ist,Soll,Fenster,Mode auto/manuell..,locked/unlocked,battery,Wochenprogram sowie Ventilstellung oder Ventil"switch"), eine Änderung ist aber eher selten nötig, weshalb ich das mit diesem DOIF mache. Ich wähle meine Thermostat aus der Select-liste, wähle per iconRadio-Widget z.B. Wochenprogramm 1 oder 2 und drücke dann einen Sendeknopf. Der abgesetzte Befehl wird mir vorher angezeigt, so wie er zusammengeklickt wird. Und wenn ich z.B. alle umstellen möchte, z.B. alle auf locked, dann eben all aus der Liste. Das widget wird dann wieder auf "---" gestellt. Das muss ich aber jetzt erst machen. Ein anderes DOIF ist bereits fertig, dort aber noch händisch eingetragene Devices. Dieses ist für den "Party-Mode" für einzelne oder alle Thermostate.

Trotz aller Versuche wäre es schon noch interessant, in der condition an dieser Stelle die Abfrage zum laufen zu bekommen, allein schon weil es ja im Widget und im normalen DOIF-Code klappt, nur nicht mit ::AggrDoIf in der subs.

Hier noch mal das "Gerüst", wie es nun funktioniert:
defmod di_UI_HzgThermostatSetMaster DOIF subs{ \
\
@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',"mySelect",'"selectedTh"');; ## gwünschte Devices: setreading HzgTher... mySelect selectedTh\
##@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',,'"selectedTh" =~ $group');;\
unshift (@{$_thDevs},  "---" , "all");; ## "---" und "all" an den Anfang der Liste\
} ## endSubs\
init {\
set_Reading("sensorSelect","---");;\
}
attr di_UI_HzgThermostatSetMaster readingList sensorSelect
attr di_UI_HzgThermostatSetMaster room DOIF_UI,Test
attr di_UI_HzgThermostatSetMaster uiTable {\
IMPORT ./FHEM/my_uiTable.tpl\
$TC{0..9} = "align='center'";;\

\
}\
\
WID([$SELF:sensorSelect],join(",",@{$_thDevs}))


Viele Grüße

Sany
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

Ich habe es nicht ganz verstanden. Funktioniert jetzt:

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima',"mySelect",'"selectedTh"');; ## gwünschte Devices: setreading HzgTher... mySelect selectedTh\

in subs oder nicht?
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sany

ja, das funktioniert. Hier wird aber das (von mir bei den Devices eingefügte) Reading mit einem Wert verglichen.
in der auskommentierten Zeile ist die Version, auf den Inhalt von group zu testen. Das klappt aber nicht, d.h. im Array erscheint kein device, nur das mit unshift hinzugefügte.
Im letzten Post habe ich das raw angehängt, das funktioniert so, also in der subs.
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

#10
Zitat von: Sany am 25 Januar 2021, 21:21:24
ja, das funktioniert. Hier wird aber das (von mir bei den Devices eingefügte) Reading mit einem Wert verglichen.
in der auskommentierten Zeile ist die Version, auf den Inhalt von group zu testen. Das klappt aber nicht, d.h. im Array erscheint kein device, nur das mit unshift hinzugefügte.
Im letzten Post habe ich das raw angehängt, das funktioniert so, also in der subs.

@{$_thDevs} = ::AggrDoIf('@','HzgThermostat.*Clima','','$group =~ /selectedTh/')

sollte klappen, die RegEx muss doch auf der rechten Seite stehen, statt / funktioniert auch " und du darfs den dritten Parameter nicht weglassen.

Edit: subs ist natürlich sehr statisch, es wird nur bei der Definition ausgewertet.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sany

Hi Damian,

jawohl, so klappt es, auch mit " statt /.

ZitatEdit: subs ist natürlich sehr statisch, es wird nur bei der Definition ausgewertet.
Ich denke mal für meinen Fall ist das ok, wie gesagt, Thermostate ändert man ja doch eher selten, da gibts vielleicht auch mal einen Neustart von fhem, z.B. nach Update. Es müsste aber auch im "normalen" Teil der DOIF-def funktionieren, dann halt mit irgendeinem trigger. dann wäre das array aktualisiert. Probier ich mal aus, vielleicht fällt mir auch ein use-case dazu ein.

Nochmals Danke!
Endziel ist dann eine GUI nur in uiTable ganz "ohne" fhem. Kann man mit f18 ja schön alles ausblenden, Menüs sind über icons realisiert. Davon aber später mal mehr, wenn es weiter fortgeschritten ist.

Gruß
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....