Archiv - geloggte Werte beim übertragen umrechnen

Hallo zusammen,
in meiner Symcon-Welt koexistieren Homematic, Z-Wave und noch ein paar andere friedlich. Ärgerlich ist dabei, dass Homematic und Z-Wave die Leistung nicht gleich erfassen. Homematic --> Wh, Z-Wave --> kWh. Der Plan ist also jetzt alle Homematics per Umrehcnen-Modul zukünftig in kwH anzeigen zu lassen. Damit fallen ein paar neue Variablen an, die dann zukünftig geloggt werden. Allerdings möcht ich natürlich nicht die bisher erfassten Verbräuche verlieren. Bei der Waschmaschine sind das immerhin etwas über 1,2 Millionen geloggte Einzelwerte.
Umkopieren von einer Variablen in eine andere ist einfach. Dafür gibt es im Archiv eine Funktion. Aber wie dabei von Wh ind kWh umrechnen? Die Archiv-Steuerung (AC_GetLoggedValues) hat als „harte“ Grenze jeweils 10.000 Werte pro Aufruf. Das ist nur schwer umzusetzen. Hat hier jemand eine Idee oder Lösung? Kann man irgendwie per foreach-Schleife alle Werte einer Archivvariablen auslesen und dann wieder schreiben?

Hierfür gibt es aktuell keine einfache Lösung. Du könntest das aber per Skript machen. Beim Auslesen würde ich eine while-Schleife verwenden. Lies „alle“ Datensätze aus (Startzeit = 0, Endzeit = 0, Limit = 0). Wenn du dabei 10.000 Datensätze zurückbekommst, dann liest du beim Zeitstempel des letzten Wertes - 1 als Endzeit weiter ein. Ich würde empfehlen, die Datensätze stufenweise zu bearbeiten, also in 10.000er-Häppchen, und nicht etwa alle in ein großes Array werfen. Das könnte bei sehr vielen Datensätzen zu viel für den Arbeitsspeicher werden.

Okay - dann per Skript. Allerdings bin ich in Python sicherer als in php. Die Idee ist das auf Dateiebene per Python zu erledigen. Dazu habe ich zum Testen das Archiv von meinem Symcon-Raspi auf meinen normalen Rechner kopiert. Folgender Pythoncode erledigt das in einer handvoll Sekunden:


import pandas as pd
import os

ip_vars = {25315: 19961,
               17856: 12566,
               40446: 11566,
               19679: 65233}
data_dir = r"D:\python\source\repos\IP_Archive_Copy	estdaten\db"
for key, value in ip_vars.items():
    for dir_, _, files in os.walk(data_dir):
        for file_name in files:
            if file_name ==  str(key) + ".csv":
                file_old = os.path.join(dir_, file_name)
                file_new = os.path.join(dir_, str(value)+".csv")
                df = pd.read_csv(file_old,
                                    sep=",",
                                    decimal=".",
                                    header=None,
                                    names=["timestamp", "val"])
                df.val=round(df.val/1000,3)
                df.to_csv(file_new, index=False, header=False)

Bisher habe ich das noch nicht umgesetzt, da ich bezüglich Ip-Symcon noch Fragen habe:

[ol]
[li]Im Archiv werden bei den Z-Waves (kWh) zwei Nachkommastellen angezeigt. Dividiere ich meine Homematics durch 1000 und runde entsprechend entstehen dadurch identische Werte (mit unterschiedlichem Zeitstempel). Ist wahrscheinlich besser diese rauszufiltern oder?
[/li][li]Reicht es, wenn ich die ensprechenden Messaktoren außer Betrieb nehme oder sollte ich besser Symcon während der Anpassungen am Archiv stoppen?
[/li][/ol]

Und klar - vorher ein Backup…

Im Voraus vielen Dank für Antwort und Hilfe.

Ich verstehe, dass du das Problem in einer dir bekannten Sprache umsetzen möchtest, kann dich da aber nicht wirklich weiter unterstützen.

Eine Anpassung der Laufzeit sollte in den meisten Fällen keine Probleme machen, wenn allerdings die Zugriffe unglücklich gleichzeitig passieren, dann kann da schon was passieren. Insbesondere da du vorher ein Backup gemacht hast, würde ich persönlich wahrscheinlich einfach loslegen und es bei Fehlschlag nochmal probieren. In meiner Rolle als Symcon-Mitarbeiter muss ich dir aber natürlich sagen, dass du ein Rumgebastel am Archiv natürlich auf eigenes Risiko machst und maximale Vorsicht bieten solltest, also das ganze am besten gar nicht machst und ansonsten auf jeden Fall IP-Symcon vorher beenden solltest. Entscheide für dich :wink:

Ich habe das Umrechnen und kopieren auf eine neue Variable wier zuvor beschrieben mit Python auf Dateiebene gelöst. Ich fasse den Lösungsweg hier nochmal zusammen, da es doch noch einen Fallstrick gab. Dementsprechend gibt es auch den aktualiserten verwendeten Python-Code.
Ausgangssituation: Ich setze IP-Symcon auf einem Raspberry Pi ein. Die Datenkorrektur habe ich auf meinem Windowsrechner durchgeführt. (Ich arbeite nicht gern mit der Konsole…)

Schritt 1: Erstellen der neuen Variablen:
Die neuen Variablen sollen durch das Umrechnen-Modul automatisch mit einem Wert befüllt werden, wenn von Homematic ein neuer Wert an den ENERGY_COUNTER geliefert wird. Dementsprechend habe ich die neuen (zusätzlichen) Variablen entsprechend der Anleitung im Modul erzeugt. Wichitg: auch bei diesem Weg zunächst nicht die Aufzeichnung im Archiv aktivieren.

Schritt 2: Backup von IP-Symcon durchführen!

Schritt 3: Kopieren der Datenbank
Im Schritt 2 wurde bereits der IP-Symcon-Dienst auf dem Raspi beendet. Per Konsole wird nun das gesamte Vezeichnis „db“ kopiert. Im meinem Fall erst aufs NAS und von dort mit Windows in das Arbeitsverzeichnis.

Schritt 4: Konfiguration des Python-Skripts
Das Dictionary ip_vars enthält die alten und neuen Symcon -Variablen. Z. B. ist bei 25315: 19961 links die alte und rechts die neue Variable. Die Anzahl der Variablen ist egal - mein Skript durchläuft das Dictionary als Schleife. Wichtig ist die Variablenpärchen entsprechend als Key: Value in das Dictionary zu schreiben.

Schritt 5: Skript ausführen:
Im Gegensatz zur ersten Version meines Skripts aus dem 3. Post habe ich das Ganze so angepasst, dass die neuen Variablen in ein neues Verzeichnis kopiert werden. Die Verzeichnisstruktur bleibt erhalten, so dass später nur die neuen Variablen kopiert werden.

Schritt 6: Neue Variablen zurück kopieren:
Da die Verzeichnisstruktur des Ordners „db“ erhalten geblieben ist und nur die neuen Variablen im Ergebnis erzeugt wurden, kann der gesamte Ordner wieder auf seinen Platz auf dem Raspi kopiert werden.

Schritt 7: Neue Variablen „aktivieren“:
Symcon-Dienst starten, Aufzeichnung der Variablen aktivieren und reaggregieren. Fertig!

Wichitger Hinweis für die CSVs:
Windows und Linux haben andere Sonderzeichen für den Zeilenumbruch. In der ersten Version des Skripts wird der Windows-Zeilenumbruch erzeugt. Eine Anpassung meines Skripts erzwingt den Linux-Zeilenumbruch. Mit der Windows-Version kann Symcon auf dem Raspi nichts anfangen! Dies muss für anderer OS, bzw. OS-Kombinationen evtl. angepasst werden!
Die Aufteilung in das Ausgangsverzeichnis (im Skript data_dir) und das Ausgabeverzeichnis (new_dir) erlaubt theoretisch auch das Zurückkopieren bei laufendem Symcon zu machen. Ich habe mich dagegen entschieden, weil es im Grunde nur ein paar Minuten bringt.

Nun noch das am Ende verwendete Skript:


import pandas as pd
import os

ip_vars = {31581: 51805,
           17856: 10127,
           25315: 42434,
           40446: 13397,
           19679: 33306}
data_dir = r"D:\python\source\repos\IP_Archive_Copy\IP_Archive_Copy\IP_Archive_Copy	estdaten\db_old"
new_dir = r"D:\python\source\repos\IP_Archive_Copy\IP_Archive_Copy\IP_Archive_Copy	estdaten\db"
for key, value in ip_vars.items():
    for dir_, _, files in os.walk(data_dir):
        for file_name in files:
            if file_name ==  str(key) + ".csv":
                new_path = os.path.join(new_dir, os.path.relpath(dir_, data_dir)) 
                
                file_old = os.path.join(dir_, file_name)
                file_new = os.path.join(new_path, str(value)+".csv")
                df = pd.read_csv(file_old,
                                    sep=",",
                                    decimal=".",
                                    header=None,
                                    names=["timestamp", "val"])
                df.val=round(df.val/1000,3)
                if not os.path.exists(new_path):
                    os.makedirs(new_path)
                with open(file_new, mode='w', newline='
') as f:
                    df.to_csv(f, index=False, header=False, line_terminator='
')

Noch eine Anmerkung zu der Thematik: Beruflich arbeite ich im Datenmangement mit GIS-Systemen (Smallworld, Postgis). Dort würden wir den Weg, eine Variable zur Anzeige in einer anderen SI-Einheit doppelt zu führen niemals akzeptieren. Doppelte Datenhaltung ist ein no-go. Ein Umrechnen on-the-fly ist eigentlich der einzig sinnvolle Weg. Vieleicht doch mal ein zukünftiges Feature von IP-Symcon? Mich würde es jedenfalls freuen.