userattr oder userReadings ?

Begonnen von dt2510, 04 Januar 2019, 09:45:46

Vorheriges Thema - Nächstes Thema

dt2510

Ich nutze aktuell zur Automatisierung User Attribute um z.B. Schaltzustände von Lampen für Tag/Nacht zu hinterlegen. Da es in dem Bereich selten Änderungen gibt, kann ich diese in der Weboberfläche von FHEM durchführen. Ich überlege allerdings in meinem Frontend (ich nutze TabletUI) einen Konfigurationsdialog einzubauen. Prinzipiell wäre folgendes in einer 99_myUtils.pm möglich:

fhem("attr Lampe DefaultNacht on");

Nachteil: die Änderung wird nicht in die fhem.cfg übernommen und wäre bei einem Neustart nicht mehr vorhanden.

Alternativ könnte ich statt eines User Attributs auch ein User Reading verwenden:

fhem("setReading Lampe DefaultNacht on");

Vorteil: die Änderung muss nicht in der fhem.cfg hinterlegt werden, sondern wird automatisch in der Datei log/fhem.save gespeichert und ist auch nach einem Neustart noch vorhanden
Nachteil: kommt ein neues Device hinzu muss ich erst umständlich über die Weboberfläche die User Readings initialisieren und kann nicht wie bisher die Attribute in der fhem.cfg kopieren

Wie könnte ich das Problem am Besten lösen ?

Möglicher Lösungsansatz:
- Defaultwerte als global userattr definieren (geht das auch für Devicegruppen ? Bei dimmbaren Lampen wäre es z.B. nicht on oder off sondern pct 50, bei Jalousien dim 80 usw.)
- beim Device die entsprechenden User Readings definieren
- den Defaultwert einsetzen, wenn das Reading noch nicht existiert (kann ich das überhaupt prüfen ?)

MadMax-FHEM

#1
Bei setreading fehlt mir der Zusammenhang zu userReadings!?

Du kannst doch einfach ein "setreading Devicename Readingname Value" aufrufen und ein Reading setzen...
Sofern es das Device gibt...

Wenn du nach dem "attr-Befehl" ein "save" aufrufst, wird es auch gespeichert und ist/wäre nach einem Neustart vorhanden...
Risiko: du speicherst (ungewollt) auch andere Änderungen...

EDIT: was willst du überhaupt (genau) erreichen?

Kurz, da nur Handy grad...

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

dt2510

#2
Die Änderung muss ja aus einer Perl Routine heraus erfolgen, entweder mit attr oder setReading. In beiden Fällen ist es eigentlich egal, ob es ein vorhandenes oder User-Element ist.
Ein Save würde NATÜRLICH auch andere Änderungen mit speichern weshalb ich das ungern in der 99_myUtils.pm ausführen wollte.
Mein Hauptproblem ist eigentlich die Initialisierung der userReadings für ein neues Device, ein Attribut kann ja bereits in der fhem.cfg gesetzt werden, ein (User) Reading meines Wissens nicht.

Hier mal ein Beispiel für eine Lampe:

attr FGS222_ID12 userattr AwayDay AwayNight BedDay BedNight HolidayDay HolidayNight HomeDay HomeNight Horizon
attr FGS222_ID12 AwayDay off
attr FGS222_ID12 AwayNight off
attr FGS222_ID12 BedDay off
attr FGS222_ID12 BedNight off
attr FGS222_ID12 HolidayDay off
attr FGS222_ID12 HolidayNight off
attr FGS222_ID12 HomeDay off
attr FGS222_ID12 HomeNight off
attr FGS222_ID12 Horizon REAL


In der Automation schalte ich dann abhängig von Homestatus und Day/Night beim angegebenen Horizont (bei Rolläden steht da z.B. CIVIL um sie früher morgens zu öffnen bzw. später abends zu schließen).

Kommt eine neue Lampe hinzu kopiere ich den Block einfach und passe den Namen des Devices an. Würde ich das Attribut aber über einen Konfigurationsdialog mit Perl ändern müsste ein Save folgen.

Würde ich stattdessen User Readings verwenden

attr FGS222_ID12 userReadings AwayDay AwayNight BedDay BedNight HolidayDay HolidayNight HomeDay HomeNight Horizon

könnte ich die Einstellungen für ein neues Device nicht in der fhem.cfg angeben, sondern müsste manuell für jedes Reading einen set Befehl absetzen. Die Änderung eines Wertes per Perl im Konfigurationsdialog wäre dafür aber kein Problem.

MadMax-FHEM

#3
Verstehe das mit den userReadings immer noch nicht!

Du hast in der commandref bzgl. userReadings gelesen!?

userAttr und userReadings sind (nicht nur vom Namen her) komplett unterschiedliche Dinge!

userAttr "erweitert" ein Gerät (oder wenn global: alle Geräte) um ein Attribut, das gesetzt werden kann...

...userReadings wird "getriggert" wenn ein Event bzgl. des Gerätes an dem es "hängt" erzeugt wird und dann "ausgewertet" und abhängig davon (was in der Auswertung steht) ein neues Reading erzeut bzw. mit einem neuen Wert gefüllt!

Nochmal: den setreading-Befehl kannst du einfach ausführen, sofern das Gerät existiert!

Ja du musst (wie bei den Attributen auch) die Readings "anlegen", also einmal pro gewünschtes Reading den "setreading" aufrufen und den gewünschten Wert setzen.

Das musst du für die Attribute doch auch!?
(und copy/paste in der fhem.cfg direkt wird nicht empfohlen!)
Ich würde bei den Attributen noch eine Kennung davor setzen (my oder was auch immer), um zwischen "echten" Attributen und "deinen privaten" unterscheiden zu können, nicht dass irgendwann ein Gerät eines deiner Attribute hat/bekommt (also nicht von dir per userAttr) und dann geht es durcheinander/schief...


Du kannst doch eine Routine schreiben, wenn es immer die selben Dinge sind die zu haben willst einfach so:


sub myInitializeNewDevice($)
{
  my ($Device)  = @_;

  fhem("setreading $Device AwayDay off");
  fhem("setreading $Device AwayNight off");
  fhem("setreading $Device BedDay off");
  fhem("setreading $Device BedNight off");
  fhem("setreading $Device HolidayDay off");
# usw.
}


Die kannst du dann in der FhemWeb-cmd aufrufen:

{myInitializeNewDevice("NameNeuesDevice")}

Und wenn du auch jeweils Werte übergeben willst geht das auch, dann muss halt die Sub entsprechend erweitert werden...

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

dt2510

#4
Der Unterschied zwischen User Attribut und User Reading ist mir schon klar, ich verwende Readings z.B. bei der Schaltung meiner Lampen per Bewegungsmelder.

attr FGS212_ID15 userReadings SaveState SaveMode Timed

Dort speichere ich bei Bewegung (das wäre der Trigger) den Status vor Bewegung (an oder aus), den Anlagenmodus vor Bewegung (AwayDay, AwayNight, ...) und ob der Bewegungsmelder Zeitgesteuert schaltet. Bei Bewegungsende (durch den Bewegungsmelder oder nach Ablauf der Zeit) wird der Zustand vor der Bewegung wieder hergestellt, sofern sich der Anlagenmodus nicht geändert hat (das wäre die Auswertung bei einem erneuten Trigger).
Attribute wären dort ungünstig, da sich die Werte häufig ändern und auch nach einem Neustart ggfs. noch benötigt werden.

Analog zu einer Programmiersprache verstehe ICH vereinfacht die Attribute als Konstanten und Readings als Variablen. Meine Attribute haben also per Definition schon einen Wert, die Readings sind bei neuen Devices undefiniert.

Klar copy/paste in der fhem.cfg wird nicht empfohlen, wen man weiß was man macht ist es aber unkritisch.

sub myInitializeNewDevice($) vereinfacht die Sache natürlich, aber wenn ich es mal vergesse spinnt die Automation für das Device rum - ebenso, wenn die fhem.save defekt oder nicht vorhanden ist.

Daher war meine Idee mit Readings zu arbeiten und diese zu Initialisieren, wenn sie nicht vorhanden sind - anderenfalls enthalten sie ja bereits einen Wert, der benötigt wird.

edit:

Kann ich ein setreading auch für ein Reading absetzen, was nicht vorhanden ist bzw. nicht mit attr userReadings definiert wurde ? Attribute MUSS ich mit userattr angeben um sie setzen zu können. Wenn dem so ist verstehe ich auch deine Verwirrung mit dem userReading ;) Das bräuchte ich dann in der Tat nicht.

edit #2:

die Vordefinition per attr Device userReadings Reading1 Reading2 .. ist in der Tat nicht nötig - setreading funktioniert auch ohne userReadings !

MadMax-FHEM

Zitat von: dt2510 am 04 Januar 2019, 11:34:49
die Vordefinition per attr Device userReadings Reading1 Reading2 .. ist in der Tat nicht nötig - setreading funktioniert auch ohne userReadings !

Exakt das war schon mein erster "Ansatz" ;)

Also das wollte ich "rüberbringen" mit: ein setreading kannst du IMMER EINFACH ausführen, sofern natürlich das Device existiert...

Ich sehe das so:

wenn sich Dinge nicht automatisch ändern, also "Konfigurationen" von Geräten sind die ich ab und an "händisch" anpasse (sowas habe ich auch, z.B. wann wie mein Luftentfeuchter anspringen soll oder bei welcher Außentemperatur[verlauf] die Heizung ein anderes Profil schalten soll etc.), dann mache ich das auch per userattr (aber mit my_... damit eine [zukünftige] Verwechslung ausgeschlossen ist [sein sollte]) weil ich dann ja auch auf den "save Knopf" drücken kann...

Alles was ich mir automatisch merken will "speichere" ich (per setreading) in einem Device (ab und an auch einen extra Dummy).

Du kannst neben der Initialisierung auch einfach folgendes machen (nur ein Beispiel, bzw. mache ich das so):


if(ReadingsVal("Device", "ReadingSpeicherwert","n.a.") eq "n.a.")
{
  fhem("setreading Device ReadingSpeicherwert INITIALWERT");
}


Bzw. wenn ich mit Zahlenwerten (und ReadingsNum arbeite) dann nehme ich für den Ersatzwert entweder bewusst was, was die Bedingung erfüllt oder eben bewusst NICHT je nach gewünschtem "Defaultverhalten" und setzte dann den Speicherwert auf irgendwas was ich haben will...

Neben dem Initialisieren gibt es eben beim Abfragen ja auch (genau deshalb) den "Ersatzwert"...

Muss man sich halt überlegen was man wo wie erreichen/haben will für den Fall dass der Wert (noch) nicht existiert...

Wenn du vergisst die Attribute zu kopieren passiert es dir ja auch genauso wie wenn du vergisst die Initialisierungsfunktion aufzurufen ;)

Wie so oft: es gibt viele Möglichkeiten...

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

rudolfkoenig

Eigentlich bzw. urspruenglich:
- gehoeren Attribute dem Benutzer. Damit er sich nicht vertippt und weiss, was er setzen kann, gibt es eine Liste der erlaubten Attribute. Diese Liste kann der Benutzer mit userAttr erweitern, fuer den eigenen Bedarf.
- gehoeren Readings dem Modul. Urspruenglich gab es keine Moeglichkeit, diese vom Benutzer zu setzen, deswegen auch keine Notwendigkeit einer Pruefung, oder einer Liste, die man erweitern muss.

Leider sind die die Grenzen zwischen diesen Konzepten inzwischen teilweise verwischt.

dt2510

Zitat von: MadMax-FHEM am 04 Januar 2019, 12:02:14
Du kannst neben der Initialisierung auch einfach folgendes machen (nur ein Beispiel, bzw. mache ich das so):


if(ReadingsVal("Device", "ReadingSpeicherwert","n.a.") eq "n.a.")
{
  fhem("setreading Device ReadingSpeicherwert INITIALWERT");
}


Bzw. wenn ich mit Zahlenwerten (und ReadingsNum arbeite) dann nehme ich für den Ersatzwert entweder bewusst was, was die Bedingung erfüllt oder eben bewusst NICHT je nach gewünschtem "Defaultverhalten" und setzte dann den Speicherwert auf irgendwas was ich haben will...

Die Idee hatte ich vorhin beim Essen auch schon ;)

Zitat von: rudolfkoenig am 04 Januar 2019, 12:03:11
Leider sind die die Grenzen zwischen diesen Konzepten inzwischen teilweise verwischt.

Ich kenne das aus eigener Erfahrung als Anwendungsentwickler ... stellt man dem Kunden etwas unreglementiertes (z.B. ein Notitzfeld) zur Verfügung wird es zu 99% für diverse Auswertungen "mißbraucht" ;)

Sobald ich ein (User-) Attribut aber als Variable verwenden möchte MUSS ich auf ein Reading ausweichen oder (so hab' ich es früher gemacht) 100te von dummies definieren.

dt2510

Ich habe jetzt ein Lösung gefunden, wie ich neue Devices einfach in meine Automation einbinde.

Im global Device habe ich 3 User Attribute hinzugefügt:

- automateOnDaylightChange
- automateOnHomestatusChange
- automationDevice

Hier lege ich fest ob, wann und wie ein Device automatisiert werden soll. Automatisiert werden kann (automateOn...) bei

- Wechsel Day/Night/Twilight
- Wechsel Home/Away/Bed/Holiday

Wie standardmäßig geschaltet wird regelt dann automationDevice:

- Switch (Lichtschalter ... default: off)
- Dimmer (dimmbares Licht ... default: 0 pct)
- Plug (Steckdose ... default: on, wenn Status Home, sonst off)
- Shutter (Rolladen ... default: dim 0 (geschlossen), wenn Night, sonst dim 98 (offen))

Auf diese Weise funktioniert die Automation schon, wenn ein gültiger Wert für automationDevice und mindestens ein automateOn-Attribut gesetzt ist. In der 99_myUtils.pm werden die Attribute dann entsprechend abgefragt, z.B.:

foreach my $myItem (devspec2array("automateOnHomestatusChange=1")) {
    ....
  }


Auf diese Weise muß ich weder die Attribute in der fhem.cfg kopieren (fehleranfällig) noch alle per setreading händisch definieren (aufwändig). Lediglich für abweichende Werte muss ich ein setreading ausführen. Die readings speichere ich unter dem Namen:

setOn[Homestatus][Daylight], also z.B.

setreading LampeX setOnHomeTwilight on

um die Lampe X bei Zwielicht anzuschalten.

Ein Konfigurationsdialog ist so problemlos realisierbar. Ob ein Device tageslichtabhängig, anwesenheitsabhängig oder beides ist muss man dann zwar noch in der Weboberfläche anpassen, allerdings ändert sich dort noch viel seltener etwas, als an den Zustandswerten.