Seite 1 von 90

Zählersensor HM-ES-TX-WM - Universelle Zählerstandberechnung

Verfasst: 07.06.2016, 15:43
von jmaus
Hallo Zusammen,

bereits seit einiger Zeit (> 1 Jahr) betreibe ich 3x HM-ES-TX-WM Sensoren in unserem Haus um nicht nur den Strom und Gasverbrauch überwachen zu können sondern sogar den Wasserverbrauch. Schnell bin ich hierbei auf gewisse Schwierigkeiten/Hindernisse bei der Auswertung der Werte des HM-ES-TX-WM gekommen die es notwendig machten mittels Skripten in meiner CCU Umgebung eigene Berechnungen anzustellen um nicht nur den Tagesverbrauch zu überwachen sondern auch den Wochen, Monat, usw. Verbrauch. Anfangs regelte ich dies mit separaten Skripten für alle drei HM-ES-TX-WM Sensoren die ich einsetzte, jedoch kam ich hierbei schnell zu dem Punkt das diese separaten Skripte immer schwerer wartbar wurden und ich eine Möglichkeit wollte alle drei Sensoren mit dem selben Programm/Skript auswerten zu lassen.
Ich machte mich also vor ein paar Monaten daran ein universelles Programm über die CCU-Umgebung zu entwickeln das mittels eines einzelnen Skriptes/Programmes alle meine HM-ES-TX-WM auf einmal abfragt und verschiedene Verbrauchsberechnungen anstellt und vordefinierte Systemvariablen dann füllt um somit für eine Weiterverarbeitung zur Verfügung zu stehen. Als Basis hierfür nahm ich die bereits an verschiedenen Stellen im Forum vorgestellten Einzellösungen/skripte um die HM-ES-TX-WM Werte auszulesen und in brauchbare Verbrauchswerte umzurechnen und erweiterte diese entsprechend. Und genau dieses Programm- bzw. den Skript dazu möchte ich hier nun vorstellen und hoffentlich auch zusammen mit euch in Zukunft weiter verbessern und eure Wünsche/Anregungen einfliessen lassen.

Features:
  • Universelles Programm/Skript für mehrere eingesetzte HM-ES-TX-WM in einer CCU.
  • Unterstützung von Strom (kWh), Gas (m3) und Wasserzähler (m3) Werten.
  • Berechnung/Darstellung des aktuellen Zählerstandes anhand von Referenzwerten.
  • Berechnung/Darstellung des aktuellen Verbrauches in (kWh bzw. m3/h) da die eigenen Leistungswerte des HM-ES-TX-WM bei stoppendem Verbrauch nicht aktualisiert werden.
  • Berechnung/Darstellung des Tages/Wochen/Monats-Verbrauches durch timer-gesteuerten Aufruf (jede Nacht).
  • Berechnung/Darstellung des Verbrauchswertes seit der letzten Zählerablesung.
  • Speicherung der vorherigen Verbrauchswerte (vorheriger Tag/Woche/Monat/Jahr) zum besseren Vergleich.
  • Automatische Erkennung/Berücksichtigung des Überlaufens von Zählerwerten im HM-ES-TX-WM (z.B. bei >839 kWh Stromverbrauch).
  • Darstellung des Verbrauchswertes (und entsprechende Berechnung der Kosten) seit der letzten Ablesung durch den Energieversorger in der Standard "Energie-Zähler CCU" Anzeige.
Installation/Inbetriebnahme:
  1. Namensgebung der HM-ES-TX-WM Damit das Auswerteprogramm und der Skript korrekt funktionieren müssen alle eingesetzten HM-ES-TX-WM Geräte eine eineindeutige Namensgebung besitzen die den jeweiligen Zählertyp (Strom, Gas, Wasser) wiedergeben. Wichtig ist hierbei das der Name jeweils mit "-Typ" endet. D.h. für einen Stromzähler eben z.B. "Hausanschluss-Strom". Hier einmal ein Screenshot der Benennung meiner eingesetzten HM-ES-TX-WM:
    screenshot_99.png
    Eindeutige Namensgebung aller HM-ES-TX-WM mit Zählertypspezifizierung.
  2. Anlegen der notwendigen Systemvariablen Für jeden Typ (Strom, Gas, Wasser) eines eingesetzten HM-ES-TX-WM müssen in der CCU eine gewisse Menge an Systemvariablen eingerichtet werden. Der folgende Screenshot zeigt hierbei den Auszug der benötigten Systemvariablen für einen HM-ES-TX-WM der an einem Stromzähler betrieben wird. Wichtig ist hierbei das die Systemvariablen immer mit der jeweiligen Typenbezeichnung beginnen, in dem Falle eben "Strom ":
    Systemvariablen.png
    Auflistung der benötigen Systemvariablen je HM-ES-TX-WM Gerät (hier für Stromzähler).
  3. Anlegen eines neuen Programmes + Skriptes für Zählerauswertung Damit die Zählerauswertung regelmäßig erfolgt muss am Schluss in der CCU ein neues Programm angelegt werden das auf der einen Seite bei Veränderungen der Energie-Zähler werte bei Aktualisierung ausgelöst wird, aber eben auch durch einen täglichen Timer um genau 0:00 Uhr. Wichtig ist hierbei das man in dem Programm ALLE seine HM-ES-TX-WM Geräte in die erste "Wenn..." Bedingung einträgt und nicht für jedes HM-ES-TX-WM ein separates Programm macht. Das Programm sollte z.B. bei Einsatz von drei HM-ES-TX-WM Geräten (Gas, Strom, Wasser) wie folgt aussehen:
    screenshot_97.png
    Auswerteprogramm + Skripteinbindung für alle HM-ES-TX-WM.
    HINWEIS: Wenn man als Stromzähler die IEC Variante zum abgreifen der Zahlenwerte nutzt muss natürlich in dem Programm bei der Bedingung entsprechend "IEC Energie-Zähler Gerät" ausgewählt werden.
  4. Einfügen des notwendigen Skriptes zur Verbrauchsberechnung Damit die Verbrauchsberechnung durchführt wird muss nun am Schluss noch das folgende Skript unter "Aktivität: Dann..." eingefügt werden (Eigene Modifikationen/Anpassungen müssten daran eigentlich nicht notwendig sein):

    Code: Alles auswählen

    ! Universelle Zaehlerstandberechnung fuer HM-ES-TX-WM
    !
    ! Copyright (c) 2016-2023 Jens Maus <mail@jens-maus.de>
    !
    ! Version 1.5 (27.05.2023)
    
    ! Nun schauen wir wer uns aufgerufen hat (Device-Channel oder Timer) und welches Device
    ! es genau war (Nutzung der $src$ Variable) und danach entscheiden wir was wir
    ! zu tun haben.
    object counter = dom.GetObject("$src$");
    if(counter)
    {
      object sysvar = dom.GetObject(ID_SYSTEM_VARIABLES);
    
      ! Wenn TypeName vom Typ HSSDP ist dann wurde das Program durch ein Event
      ! eines Devices erzeugt, ansonsten durch ein CALENDARDP welches der
      ! Ausfuehrung durch das Zeitmodul entspricht
      if(counter.TypeName() == "HSSDP")
      {
        ! Nun holen wir unmittelbar am anfang alle counter relevanten Daten ab
        ! und speichern sie fuer spaeter zwischen und berechnen auch gleich
        ! noch differenzwerte
        integer diffTime = counter.Timestamp().ToInteger() - counter.LastTimestamp().ToInteger();
        real curValue = counter.Value();
        real lastValue = counter.LastValue();
    
        ! Nun extrahieren wir den Zaehlertyp (Gas, Wasser, Strom)
        ! aus dem Namen des Channel. Ein Device muss also immer mit "XXXXX-Gas"
        ! bzw. "XXXXXX-Wasser", etc. enden.
        object channel = dom.GetObject(counter.Channel());
        string type = channel.Name().StrValueByIndex("-",1);
    
        ! Nun holen wir alle notwendigen Systemvariablen zum Lesen und Speichern
        ! unserer verschiedenen Zaehlerwerte
        object c = sysvar.Get(type # " Referenz Zaehlerstand");
        object d = sysvar.Get(type # " Zaehlerstand");
        object e = sysvar.Get(type # " Verbrauch aktuell");
        object f = sysvar.Get(type # " Referenz Ablesung");
        object g = sysvar.Get(type # " Verbrauch letzte Ablesung");
        object h = sysvar.Get(type # " Referenz heute");
        object i = sysvar.Get(type # " Verbrauch heute");
        object j = sysvar.Get(type # " Referenz Woche");
        object k = sysvar.Get(type # " Verbrauch Woche");
        object l = sysvar.Get(type # " Referenz Monat");
        object m = sysvar.Get(type # " Verbrauch Monat");
        object n = sysvar.Get(type # " Referenz Kalenderjahr");
        object o = sysvar.Get(type # " Verbrauch Kalenderjahr"); 
    
        ! Nun schauen wir ob der Zaehler uebergelaufen ist (diffValue < 0) weil
        ! die Zaehlervariablen des HM-ES-TX-WM gerade beim Stromzaehler regelmaessig
        ! ueberlaufen.
        real diffValue = curValue - lastValue;
        if(diffValue < 0.0)
        {
          ! Der Zaehler scheint uebergelaufen zu sein -> ValueMax hinzuaddieren
          diffValue = diffValue + counter.ValueMax();
          
          ! "Referenz Zaehlerstand" dann um ValueMax erhoehen. Beim Stromzaehler
          ! muss aber erst das ganze noch in Watt umgerechnet werden.
          real a = c.Value();
          if(counter.HssType() == "ENERGY_COUNTER")
          {
            a = a * 1000.0;
            a = a + counter.ValueMax();
            c.State(a / 1000.0);
          }
          elseif(counter.HssType() == "GAS_ENERGY_COUNTER")
          {
            c.State(a + counter.ValueMax());
          }
        }
    
        ! Wenn dies ein Stromzaehler ist muessen wir die Werte von
        ! Watt zu Kilowatt konvertieren
        if(counter.HssType() == "ENERGY_COUNTER")
        {
          diffValue = diffValue / 1000.0;
          curValue = curValue / 1000.0;
        } 
    
        ! Aktuellen Verbrauch berechnen
        if(diffTime > 0) { e.State(3600.0 * diffValue / diffTime); }
    
        ! Aktuellen Zaehlerstand berechnen
        d.State(c.Value() + curValue);
    
        ! Nun alle Systemvariablen die fuer die Berechnung/Darstellung
        ! des Verbrauches da sind neu berechnen.
        g.State(d.Value() - f.Value());
        if(h.Value() != 0) { i.State(d.Value() - h.Value()); }
        else { i.State(d.Value() - c.Value()); } 
        if(j.Value() != 0) { k.State(d.Value() - j.Value()); } 
        else { k.State(d.Value() - c.Value()); } 
        if(l.Value() != 0) { m.State(d.Value() - l.Value()); } 
        else { m.State(d.State() - c.State()); } 
        if(n.Value() != 0) { o.State(d.Value() - n.Value()); } 
        else { o.State(d.Value() - c.Value()); }
    
        ! Wir aktualisieren auch noch den CCU internen Energiezaehler mit
        ! dem Wert der letzten Ablesung
        if(counter.HssType() == "ENERGY_COUNTER")
        {
          object oSysVarEnergyCounter = sysvar.Get("svEnergyCounter_" # channel.ID() # "_" # channel.Address());
          if(oSysVarEnergyCounter)
          {
            oSysVarEnergyCounter.State((d.Value() - f.Value()) * 1000.0);
          }
        }
        elseif(counter.HssType() == "GAS_ENERGY_COUNTER")
        {
          object oSysVarEnergyCounter = sysvar.Get("svEnergyCounterGas_" # channel.ID() # "_" # channel.Address());
          if(oSysVarEnergyCounter)
          {
            oSysVarEnergyCounter.State(d.Value() - f.Value());
          }
        }
    
        ! Die aktuelle Zeit in eine separate Systemvariable schreiben
        ! damit man direkt sehen kann wann die Zaehelrstaende das letzte
        ! mal aktualisiert wurden.
        sysvar.Get(type # " Aktualisierung").State(system.Date("%F %X"));
      }
      else
      {
        ! Tageszaehleraktualisierung fuer alle Hausanschluss-Zaehler
        ! Hier wird mittels eines Timers der taeglich immer genau um 00:00
        ! dieses Programm ausfuehrt die Systemvariablen aktualisiert die
        ! die Tages/Wochen/Monat/Jahreswerte beinhalten.
    
        ! Nur weitermachen wenn es wirklich Mitternacht ist
        if(system.Date("%H:%M") == "00:00")
        {
          string a="Gas,Strom,Wasser";
          string b;
          object c;
          object d;
          object e;
          object f;
    
          ! Nun ueber alle Hauszaehler iterieren
          foreach(b, a.Split(","))
          {
            ! momentaner Zaehlerstand
            c = sysvar.Get(b # " Zaehlerstand");
            if(c)
            {  
              ! Nach Wochenanfang pruefen
              if(system.Date("%a") == "Mon")
              {
                d = sysvar.Get(b # " Referenz Woche");
                e = sysvar.Get(b # " Verbrauch Woche");
                f = sysvar.Get(b # " Verbrauch letzte Woche");
      
                ! Verbrauch der letzten Woche speichern
                f.State(e.Value());
      
                ! Referenzwert der Woche speichern
                d.State(c.Value());
      
                ! Wochenverbrauch auf 0 setzen
                e.State(0);   
              }
    
              ! Nach Monatsanfang pruefen
              if(system.Date("%d") == "01")
              {
                d = sysvar.Get(b # " Referenz Monat");
                e = sysvar.Get(b # " Verbrauch Monat");
                f = sysvar.Get(b # " Verbrauch letzter Monat");
      
                ! Verbrauch des letzten Monats speichern
                f.State(e.Value());
      
                ! Referenzwert des Monats speichern
                d.State(c.Value());
          
                ! Monatsverbrauch auf 0 setzen
                e.State(0);       
          
                ! Nach Jahresanfang pruefen
                if(system.Date("%m") == "01")
                {
                  d = sysvar.Get(b # " Referenz Kalenderjahr");
                  e = sysvar.Get(b # " Verbrauch Kalenderjahr");
                  f = sysvar.Get(b # " Verbrauch letztes Kalenderjahr");
      
                  ! Verbrauch des letzten Kalenderjahr speichern
                  f.State(e.Value());
      
                  ! Referenzwert des Kalenderjahr speichern
                  d.State(c.Value());
            
                  ! Jahresverbrauch auf 0 setzen
                  e.State(0);       
                }
              }
    
              ! aktueller Tagesverbrauch speichern
              d = sysvar.Get(b # " Referenz heute");
              e = sysvar.Get(b # " Verbrauch heute");
              f = sysvar.Get(b # " Verbrauch gestern");
      
              ! Verbrauch der letzten Woche speichern
              f.State(e.Value());
      
              ! Referenzwert der Woche speichern
              d.State(c.Value());
    
              ! Tagesverbrauch auf 0 setzen
              e.State(0);
            }
          }
        }
      }
    }
    
Initiale Einrichtung/Anpassung Referenzwert Zählerstand (z.B. nach Batteriewechsel):
Damit die Berechnung des aktuellen Zählerstandes funktioniert muss man mittels des folgenden Skriptes die "XXXX Referenz Zaehlerstand" Variable anpassen (z.B. auch nachdem man die Batterien gewechselt hat):
  1. Wenn man einen IEC-Sensor am HM-ES-TX-WM einsetzt muss dieser Schritt nicht gemacht werden, da dieser immer den aktuellen Zählerstand direkt ausliest.
  2. Man geht zum jeweiligen Hausanschluss-Zähler (z.B. Stromzähler) und liest dort den aktuellen Verbrauchswert möglichst genau ab und schreibt sich diesen auf.
  3. Nun führt man mittels "Skript testen" unter der CCU zeitnah das folgende Skript aus. Hierbei muss beachten werden das man bei den Variablen "type" und "value" die entsprechenden Werte vorher einträgt:

    Code: Alles auswählen

    ! Skript um den initialen Referenzwert des Hausanschlusszaehlers
    ! der CCU mitzuteilen bzw. diesen zu aktualisieren.
    
    string type = "Strom"; ! 'Strom', 'Wasser' oder 'Gas'
    real value = XXX.XXX;  ! Zaehlerstand in kWh oder m3
    
    ! ACHTUNG: Ab hier KEINE Aenderungen mehr
    object device = dom.GetObject("Hausanschluss-" # type);
    if(device)
    {
      string channel = "GAS_ENERGY_COUNTER";
      if(type == "Strom") { channel = "ENERGY_COUNTER"; }
    
      object counter = dom.GetObject("BidCos-RF." # device.Address() # ":1." # channel);
      if(counter)
      {
        real curValue = counter.Value();
        if(type == "Strom") { curValue = curValue / 1000.0; }    
    
        object c = dom.GetObject(type # " Referenz Zaehlerstand");
        c.State(value - curValue);
        WriteLine("Referenz Zaehlerstand wurde gesetzt auf: " # value - curValue);
      }
    }
    
  4. Alle anderen "XXX Referenz XXXX" Systemvariablen sollten sich dann nach verstreichen der jeweiligen Zeit (Tag, Woche, Monat, Jahr) entsprechend selbst aktualisieren.
Initiale Einrichtung/Anpassung Referenzwert letzte Ablesung:
Damit bei der Berechnung der Verbrauch im Bezug auf die letzte Ablesung des Energieversorgers erfolgen kann muss jetzt noch mittels des folgenden Skriptes die Systemvariable "XXXX Referenz Ablesung" bei jedem neuen Ablesezyklus erfolgen:
  1. Man führt man mittels "Skript testen" unter der CCU das folgende Skript aus. Hierbei muss beachten werden das man unter Variablen "type" den Typ des Hauszählers (Strom, Wasser, Gas) angeben muss und unter "value" den Wert des Hausanschlusszählers bei der letzten Ablesung:

    Code: Alles auswählen

    ! Skript um den initialen Zählerstand des Hausanschlusszaehlers 
    ! bei der letzten Ablesung durch den Energieversorger der CCU mitzuteilen
    
    string type = "Strom"; ! 'Strom', 'Wasser' oder 'Gas'
    real value = XXX.XXX;  ! Zaehlerstand in kWh oder m3
    
    ! ACHTUNG: Ab hier KEINE Aenderungen mehr
    object a = dom.GetObject(type # " Referenz Ablesung");
    if(a)
    {
      a.State(value);
      WriteLine(a.Name() # " auf " # value # " gesetzt");
    }
    
Anpassung bei Zählerwechsel:
Da Energieversorger in regelmäßigen Abständen einen neuen/aktualisierten Hausanschlusszähler installieren muss somit auch bei jedem Zählerwechsel der aktualisierte Zählerstand mittels des folgenden Skriptes der CCU mitgeteilt werden:
  1. TODO
Beispiel/Zukunft:
Wie gesagt funktioniert die hier dargestellt Lösung bei mir bisher problemlos und berechnet alle Verbrauchswerte und Zählerstände absolut zuverlässig und korrekt. Eine Beispielsausgabe (wenn man die Systemvariablen dem jeweiligen Sensor direkt zuordnet) sieht dann z.B. wie folgt aus:
screenshot_100.png
Beispielsausgabe der Verbrauchswerte (Strom)
Natürlich habe ich noch gewisse mögliche Erweiterungen im Blick (z.B. Erkennung Batterietausch), aber ich wollte nun erst einmal meine Lösung hier publik tun und sehen wie groß die Resonanz ist und ob andere Nutzer noch andere Ideen für zukünftige Erweiterungen haben die man in diese Lösung mit aufnehmen könnte.

Änderungen:
  • v1.5 (27.05.2023): Kompatibilität mit Nutzung eines IEC Sensors verbessert.
  • v1.4 (01.01.2018): Kompatibilität zur IEC_ENERGY_COUNTER Nutzung hergestellt.
  • v1.3 (29.12.2017): Tageszählerreset überprüft nun ob Gas/Strom/Wasser Hauszähler existieren und ignoriert nicht existente Versionen.
  • v1.2 (26.12.2017): Skript-Optimierung.
  • v1.1 (08.11.2016): Die interne "Energie-Zähler CCU" Variable wird nun automatisch auf den Verbrauchswert seit der letzten Ablesung gesetzt.
  • v1.0 (07.06.2016): Initiale Version.

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 07.06.2016, 16:00
von Sammy
Hallo Jens,

Danke für Deine Mühen. Hab es in die Anfängertipps aufgenommen.

Gruß Sammy

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 15.07.2016, 18:51
von HMside
Hallo Jens,

würde dein Skript gerne für meinen Gaszähler einsetzen, allerdings habe ich das Problem, das ich mit dem Skript "Anpassung Referenzwerte" keinen Wert gesetzt bekomme.
Wenn ich es richtig verstanden habe, muss ich doch nur oben im Skript den Namen des Geräts (bei mir Zaehlersensor-Gas) sowie den aktuellen Zählerwert eintragen!?

EDIT:

Ich habe die beiden Werte nun mit folgenden Skripten gesetzt.

Code: Alles auswählen

string list="MEIN-AKTUELLER-ZÄHLER-WERT"; 
dom.GetObject('Gas Referenz Zaehlerstand ').State(list);
WriteLine(list);
und

Code: Alles auswählen

string list="ZÄHLER-WERT-DER-LETZTEN-ABLESUNG"; 
dom.GetObject('Gas Referenz Ablesung ').State(list);
WriteLine(list);
Viele Grüße
Andreas

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 16.07.2016, 19:59
von znyde
hi

danke für deine mühe
bekomme allerdings auch nicht die Referenz Zählerstand rein... :?

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 17.07.2016, 06:45
von tizeka
Hallo Jens,

recht herzlichen Dank für deine Mühe, nachdem ich den Zählersensor auch wirklich im Format "XXXXXX-Strom" bezeichnet hatte :roll:, lief das Script ohne Probleme.

Gruß,
Tillmann

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 25.07.2016, 15:06
von Wolfros
Hallo Jens,

leider bekomme ich keine Werte angezeigt.
Variabelle.JPG
Hier kann ich nicht eine Kanalzuordnung treffen
zaehler1.JPG

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 31.07.2016, 19:55
von rmaylahn
Hallo Jens,
ich habe 3 Stromzaehler (Photovoltaikstrom, Allgemeinstrom und Gesamtstrom).
Reicht es aus einfach 3 verschiedene Variablensätze, alle mit der Endung Strom, anzulegen um dein Script verwenden zu können ?


P.S: Hast Du schon eine Lösung für den Batteriewechsel, bzw. wie hast Du das für dich gelöst ?

Gruß, Rainer

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 01.08.2016, 08:57
von Cybertron
Hallo Jens,

die Thematik: mehrere Zähler eines Types (Strom Gas...) würde mich auch interessieren.
Ist das n Deinem Script überhaupt vorgesehen?

Gruss
Silvio

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 01.08.2016, 09:39
von jmaus
Cybertron hat geschrieben: die Thematik: mehrere Zähler eines Types (Strom Gas...) würde mich auch interessieren.
Ist das n Deinem Script überhaupt vorgesehen?
Nein, das ist momentan nicht vorgesehen da der Script die Systemvariablen immer nach dem jeweiligen "Typ" (Strom/Gas/Wasser) adressiert.

Re: Zählersensor HM-ES-TX-WM - Universelle Zählerstandberech

Verfasst: 15.08.2016, 17:08
von bibo09
Hi,

leider kommer ich bei den Punkt "Anpassung Referenzwerte" nicht weiter.
Habe mir die aktuellen Verbrauchswerte geholt und eingetragen. Wenn ich dann
die funktion Skript testen ausführe, bleibt die Ausgabe leer.
Gibt es dafür eine Lösung?

Gruß
bibo