Variablen werden in Modul immer wieder neu angelegt (nach Modul update)

Bei meinem Discovery Modul lege ich die Variablen via MaintainVariable variable an, welche in einer einer for each schleife liegt. Das funktioniert auch einwandfrei.

Problem: Bei einem Modulupdate (Änderung in Readme) werden die Variablen neu erstellt? Die Namen usw haben sie nicht geändert auch nicht die Anzahl.

Ich habe >MaintainVariable schon oft im Einsatz gehabt, aber mit For Each scheint es Probleme zu geben?


foreach ($data as $meter) {

				$i++;

				$meterid = $meter->meterId;
				$manufacturerId = $meter->manufacturerId;
				$serialnumber = $meter->serialNumber;
				$fullSerialNumber = $meter->fullSerialNumber;
				$locationStreet = $meter->location->street;
				$locationStreetNumber = $meter->location->streetNumber;
				$locationzip = $meter->location->zip;
				$locationCity = $meter->location->city;
				$locationCountry = $meter->location->country;
				$meterlocation = $locationStreet." ".$locationStreetNumber." ".$locationzip." ".$locationCity." ".$locationCountry;
				$this->MaintainVariable($i.'meterlocation', $this->Translate('Meter ').$i.$this->Translate(' Location'), vtString, '', $vpos++, isset($meter));


Die Basis Infos sind unverändert, weswegen ich nicht wirklich verstehe warum das passiert?

Der letzte Parameter sagt ja ob die Variable angelegt oder gelöscht wird.
Ist isset($meter) auch Mal false ? Dann werden die gelöscht.
Michael

Kann es sein, dass in einer Initialisierungsphase isset($meter) false ist? Dann würden die Variablen möglicherweise gelöscht werden und später dann wieder neu erstellt werden.

Ansonsten sollte MaintainVariable genau wie RegisterVariable keine Variablen neu anlegen.

Gute Fragen. Also die Variablen verschwinden nicht! Es kommen die gleichen wieder hinzu und der Server befüllt dann die neuen.

Könnte ich das Maintain und die Anlage der Variablen auch in eine andere Funktion legen? Dann mache ich das Erstellen über einen Knopfdruck und muss mir nicht über isset behelfen oder muss das Anlegen der Variablen in „apply_changes“ liegen?

Was genau meinst du dann mit „die Variablen werden neu erstellt“? Ich hatte das so verstanden, dass es gänzlich neue Variablenobjekte sind, sprich andere ObjektID etc. . Verstehe ich das richtig? Oder magst du das nochmal genauer spezifizieren.

Die ‚gleichen‘ geht nicht, weil der ident einmalig ist. Dann würde die ObjektID sich nicht ändern.
Vermutlich passiert das bei Update so schnell, dass du das löschen und neu anlegen der Variablen nichts siehst.
Um das zu verstehen ist aber mehr nötig als nur dein Code Snippet.

Willst du den überhaupt auch Variablen löschen?
Wenn nein, dann benutze doch einfach Registervariable.
Michael

Hi,

er legt sie in der Tat neu an - das ist ja das komische. Es wird nichts gelöscht! Somit sollte auch Register keinen Unterschied machen, da ja wie gesagt nicht gelöscht wird?

OK … es wird nicht gelöscht sondern er legt die Zähler nochmal an … nur anhand der „anderen“ Zählernummer. Also Zähler 1 wird 2 und umgekehrt.

Code ist hier: Discovergy_Smartmeter/module.php at master · elueckel/Discovergy_Smartmeter · GitHub

Du gehst das das JSON einfach der Reihe nach durch.
Die Reihenfolge ist ja aber nicht fest vorgegeben.
Mal kommt Zähler X an Position 1 mal Y an Position 1.

Hier wäre es sinnvoll das JSON und die enthaltenen Werte anhand der festen SerialNumber oder meterID zu ermiteln.

Viel besser wäre es, du machst zwei Instanzen.
Einen IO welcher die Daten holt, nach Zählern zerlegt und alles an die Devices per SendDataToChild pusht.
Und eine Device-Instanz wo die SerialNumber oder meterID als Eigenschaft und Filter eingetragen wird.
Dann hat jeder Zähler seine Instanz, seine Variablen und es kommt nix durcheinander.

Michael

Danke wir immer … Patenr child habe ich nicht gemacht. Wird probiert. :nerd_face:

Evtl. ist es einfacher pro Zähler eine Category anzulegen und die mit der Zähler ID zu versehen? Das könnte doch auch gehen oder komme ich hier ins gleiche Thema.

Bei den 2 Objekten - das fordert mich dann mal wieder aus der Komfortzone :-). Der Parent würde die Datenholen - also Zähler und auch Daten. Nach dem Anlagen der Parents (IO Instanz) werden dann die Children (Zähler automatisch erstellt) oder müsste ich diese manuell erstellen. Hast Du hier ein Beispiel wo es zum Einsatz kommt? Homematic? Enocean?

Also wenn es so ist wie ich denke, dann habe ich den kompletten Transfer in IO Instanz und die Zähler im Child als „Geräte Instanz“? Wie Beim erstmailgen erstellen müsste dann der Zähler ein Dropdown haben, der die verfügbaren Zähler anzeigt und sie dann entsprechend konfiguriert?

Sorry - das ist jetzt eine Stufe über meiner bisherigen Spielerei :slight_smile:

Also wenn du es nach den best practice und den Richtlinien für den Store machen willst, dann gehen schon Mal keine Kategorie oder Dummy-Module.
Auch automatisches Anlegen der Zähler Instanzen ist nicht erlaubt.

Dann hast du wirklich das volle Programm.
Inklusive Konfigurator welcher die Zähler Instanzen erstellt.

So wie ich die API verstehe, Holst du einmal alle bekannten Zähler und die Messwerte einzeln pro Zähler, richtig?

Ich wollte dir das hier zusammenfassend schreiben, aber das ist doch etwas viel.

Ich suche mal ein Beispiel aus meinen Modulen und verlinke es dir und etwas pseudo Code wie das ablaufen kann.
Michael

Top!

Ich denke das Modul hat viel Potential, da Discovergy bei irgendwie allen Smartmeter Anbietern zumindest gefühlt im Einsatz ist.

Generell geht es folgender Maßen:

  1. /meter gibt einem die mit dem Account verlinken Meter (ein JSON Objekt)
  2. /last-reading mit meter-uid hintendran dann die aktuellen Daten.

Als 1. braucht man die Meter … die lege ich auch als erstes an. Dann kann man basierend auf den Meter (UID) die Daten ziehen, wobei sich die Stromzähler unterscheiden (aktuell 2 ESY und EMH) und dann gibt es noch Gas (wobei der nur einen Wert liefert).

Ich habe dann auch noch vor die Strompreise alle 15 Minuten oder so zu berechnen (also kWh x Preis) und das am besten mit aWATTar.

Als Script habe ich das alles - als Modul ist es irgendwie etwas komplizierter, aber auch spannend. Das mit Modulen hintereinander habe ich aber noch nicht gemacht, aber ich lerne gerne. Hier bin ich aber noch nicht sicher, ob eine zentrale „IO“ Instanz Sinn ergibt? Wenn dann würde die nur fürs Anlegen da sein - die Zähler müssen dann selber holen.

Es sei, man würde die IO wirklich nur für das Anlegen und die Verwaltung der Kennworts nutzen und dann ziehen die Childinstanz eigenständig die Werte? Der fühlt sich doof an, da den Parent so richtig keine braucht - außer halt beim erstellen.

Sorry - denke laut.

Warum Sorry? :smiley:
Pio hat gerade die Doku für den Datenaustausch etwas erweitert. Das wäre der erste Anlaufpunkt um die PHP-Funktionen des SDK kennen zu lernen, bzw. wie die zusammenhängen.

Der IO muss die Daten laden, nur er hat die Zugangsdaten.
Das macht er entweder selber zyklisch, oder aus Anforderung der Meter-Instanzen.
Ersteres ist aber doof, da dann nur
a) ein Intervall für alle gilt
b) der Datenaustausch in beide Richtungen funktionieren muss (mehr Aufwand)

Ich habe mal ein paar PDF angehängt, da ich tatsächlich kein einfaches Modul öffentlich habe. Die werden dann immer schnell kompliziert :slight_smile:

Für den Anfang am besten den Modul-Generator von der Symcon Website benutzen.
Drei Module eintragen, einen IO, ein Device und ein Konfigurator.
Den Konfigurator würde ich zum schluss machen, da kann ich auch gerne helfen; aktuell weniger Zeit aber am WE schon eher.

IO
In den IO kommen die Zugangsdaten und ein Buffer (RegisterBuffer).
Im / Nach dem Applychanges, wenn die Zugangsdaten okay sind. Alle Daten von /meter laden und in den Buffer schreiben (sind für den Konfigurator).
Deine Funktion GetMeterReading so anpassen, dass die nur ein Meter ausliest (im PDF ReadValues). Die MeterID wird als Parameter übergeben.
Das json direkt mit return zurückgeben.

Dann die Funktion ForwardData anpassen; anstatt ‚Buffer‘ habe ich im PDF ‚Function‘ benutzt.
Wenn im JSON ‚Function‘ = ReadMeter ist, dann ReadValues+MeterID aufrufen und das Ergebniss mit return zurück zum Child (Meter-Device)
Wenn im JSON ‚Function‘ = ListMeters ist, dann bekommd der Child (=Konfigurator) das JSON aus dem /meter Buffer.
Die Daten laden automatisch in der Instanz welche dem IO die Anfrage gesendet hat (siehe SendDataToParent im Device).

Device
Hat als Eigenschaft seinen Intervall und die MeterID; zum testen hast du ja die MeterID, so das wir erstmal keinen Konfigurator brauchen.
Außerdem einen Timer registrieren.

Wenn der Timer zuschlägt, ein JSON für den Datenaustausch zusammenbauen mit ‚Function‘ = ReadMeter und ‚MeterID‘ = Eigenschaft MeterID. Das JSON mit SendDataToParent an den IO senden, der Rückgabewert ist dann dein JSON-String mit den Values (siehe ForwardData im IO).
Das JSON wie bisher verarbeiten und die Variablen befüllen.
Es reicht wenn die Variablen zu diesem Zeitpunkt erst erstellt werden.
Also anstatt:


SetValue($this->GetIDForIdent(....

So:


$this->MaintainVariable...
$this->SetVaule($Ident,$Value);

oder halt


$this->RegisterVariableFloat(.....
$this->SetVaule($Ident,$Value);

Michael

IO.pdf (255 KB)

Konfigurator.pdf (200 KB)

Meter.pdf (217 KB)

Dickes Dankeschön für die Übersicht. Ich werde evtl. einen einfacheren Weg gehen in dem ich dem User Hilfestellung bei der Konfiguration gebe um die UID und den Typ zu wählen. Das mit Parent und Child für diesen Anwendungsfall ist m.E. der Overkill für einen simplen Anwendungsfall. Mal schauen … ich hoffe ich komme am WE weiter.

Genau dafür ist es aber gedacht.
Eine Instanz in Symcon bildet immer nur ein Gerät ab und nie mehrere.
Auch wenn es erst kompliziert klingt, das Verständnis hilft einem auch zu verstehen was da so im Hintergrund abläuft.
Michael

Danke für alle die Infos - ich denke das werte ich mal in einem zukünftigen Modul einsetzen wenn es Sinn macht.

Ich habe es jetzt so gelöst, dass ein Anwender via Knopfdruck die IDs angezeigt bekommt und dann via Cut and Paste kopiert. Das war’s. Danach läuft alles „wie beim alten“, aber ohne das iterieren durch das Objekt. Vorteil ist auch, dass ich mit meinen begrenzten Kenntnissen jetzt auch die Verauchskalkulation sicherer darstellen kann. Mein Ziel ist hier am WE fertig zu werden und das möglichst mit Tarif und Verbrauchskalkulation - das liefert einen echten Mehrwert - das anlegen von Zählern passiert hoffentlich alle 10 Jahre oder so.