Ankündigung

Einklappen
Keine Ankündigung bisher.

openHAB || Volkszähler

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #16
    habe jetzt auch den stromzäher zum laufen bekommen. erstmal aber nur per bash script welches alle 5 min (cron) die daten per rest an openhab weitergibt.

    script ist mehr eine quick and dirty lösung....

    Code:
    #!/bin/bash
    #
    #default
    stty -F /dev/ttyUSB0 sane
    #mode einstellen
    stty -F /dev/ttyUSB0 300 parenb -parodd cs7 -cstopb raw hupcl cread clocal -crtscts \
    -ignbrk -brkint -ignpar -parmrk inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc \
    -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab1 bs0 vt0 ff1 \
    -isig -icanon iexten -echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
    
    tmpFile=$(mktemp)
    exec 3>$tmpFile
    
    # speichern im Hintergrund
    sed -u -e '' /dev/ttyUSB0 >&3 &
    trap "sleep 1; kill -TERM $!" 0
    exec 3>&- # schliesse FD
    
    # init senden
    echo $'\x2f\x3f\x21\x0d' > /dev/ttyUSB0
    sleep 2
    echo $'\x06\x30\x30\x30\x0d' > /dev/ttyUSB0
    sleep 10
    
    RESULT=`cat $tmpFile | grep -oP '1\.8\.0\*00\(.*\)' | grep -oP '\(.*\)' | grep -oP '[1-9][0-9]+\.[0-9]+'`
                                      
    curl -X PUT -H "Content-Type: text/plain" -d $RESULT "http://192.168.0.50:8080/rest/items/Strom_Zaehler/state"
                                                      
    rm $tmpFile
    exit

    Kommentar


      #17
      Guten morgen,

      ich habe ein kleines phyton Script für meinen Zähler geschrieben, auch sehr quick und sehr dirty, mich würden aber noch deine items interessieren, da ich mich mit der REST API noch nicht beschäftigt habe.

      Gruss
      Norbert

      Kommentar


        #18
        wie die REST API benutzt wird siehst du in meinem Bash Script meine openhab config sieht wie folgt aus

        info.items
        Code:
        Number Strom_Zaehler
        Number Strom_Letzter_Tagesverbrauch        "Tagesverbrauch"
        Number Strom_Aktueller_Tagesverbrauch     "Tagesverbrauch [%.2f KWh]"    <energy> (Information)
        Number Strom_Aktueller_Verbrauch         "Aktueller Verbrauch [%d Watt]"    <energy> (Information)
        Number Strom_Min_Verbrauch                 "Min Verbrauch [%d Watt]"    <energy> (Information)
        Number Strom_Max_Verbrauch                 "Max Verbrauch [%d Watt]"    <energy> (Information)
        db4o.persist
        Code:
            Strom_Zaehler : strategy = everyChange
            Strom_Aktueller_Tagesverbrauch : strategy = everyChange, restoreOnStartup
            Strom_Aktueller_Verbrauch : strategy = everyChange, restoreOnStartup
            Strom_Min_Verbrauch : strategy = everyChange, restoreOnStartup
            Strom_Max_Verbrauch : strategy = everyChange, restoreOnStartup
        rrd4j.persist
        Code:
            Strom_Aktueller_Verbrauch : strategy = everyMinute, restoreOnStartup
            Strom_Letzter_Tagesverbrauch : strategy = everyMinute, restoreOnStartup
        strom.rules
        Code:
        import org.openhab.core.library.types.*
        import org.openhab.core.persistence.*
        import org.openhab.model.script.actions.*
        
        rule "Init Strom"
        when
            System started
        then
        
            if( !(Strom_Letzter_Tagesverbrauch.state instanceof DecimalType) ) postUpdate(Strom_Letzter_Tagesverbrauch, 0 )
        
            if( !(Strom_Aktueller_Tagesverbrauch.state instanceof DecimalType) ) postUpdate(Strom_Aktueller_Tagesverbrauch, 0 )
        
            if( !(Strom_Aktueller_Verbrauch.state instanceof DecimalType) ) postUpdate(Strom_Aktueller_Verbrauch, 0 )
        
            if( !(Strom_Min_Verbrauch.state instanceof DecimalType) ) postUpdate(Strom_Min_Verbrauch, 0 )
            if( !(Strom_Max_Verbrauch.state instanceof DecimalType) ) postUpdate(Strom_Max_Verbrauch, 0 )
        end
        
        rule "Letzter Tagesstromverbrauch"
        when
               Time cron "15 0 0 * * ?"
        then
        
            postUpdate(Strom_Letzter_Tagesverbrauch, Strom_Zaehler.historicState(now.toDateMidnight) as DecimalType - Strom_Zaehler.historicState(now.toDateMidnight.toDateTime.minusMinutes(1440)) as DecimalType )
        
            postUpdate(Strom_Min_Verbrauch, Strom_Zaehler.state as DecimalType )
            postUpdate(Strom_Max_Verbrauch, Strom_Zaehler.state as DecimalType )
        end
        
        rule "Stromverbrauch"
        when
               Time cron "30 0/5 * * * ?"
        then
        
            var Number Letzter_Zaehler = Strom_Zaehler.historicState(now.minusMinutes(5)) as DecimalType
            var Number Aktuell_Zaehler = Strom_Zaehler.state as DecimalType
            
            postUpdate(Strom_Aktueller_Tagesverbrauch, Aktuell_Zaehler - Strom_Zaehler.minimumSince(now.toDateMidnight).state as DecimalType )
            
            var Number Aktuell = ( Aktuell_Zaehler - Letzter_Zaehler ) * 12 * 1000
            
            postUpdate(Strom_Aktueller_Verbrauch, Aktuell )
        
            if( (Strom_Min_Verbrauch.state as DecimalType) > Aktuell ){
                
                postUpdate(Strom_Min_Verbrauch, Aktuell )
            }
            
            if( (Strom_Max_Verbrauch.state as DecimalType) < Aktuell ){
                
                postUpdate(Strom_Max_Verbrauch, Aktuell )
            }
        end
        per REST API greife ich nur auf das "Strom_Zaehler" item zu. Dieses wird alle 5 min aktualisiert. Alles andere wird per Rule berechnet.

        Kommentar


          #19
          Guten Abend,

          Ich habe ein Python-Script (Cron Aufruf) für meinen EMH EHZ am raspberry geschrieben, ich nutze deine items und rules außer den Momentanverbrauch, da ich den direkt auslese. Ist alles quick und extrem dirty, geht aber:
          Code:
          from ctypes import *
          import sys
          import serial
          import httplib
          
          ser = serial.Serial(
              port='/dev/ttyAMA0',\
              baudrate=9600,\
              parity=serial.PARITY_NONE,\
              stopbits=serial.STOPBITS_ONE,\
              bytesize=serial.EIGHTBITS,\
                  timeout=10)
          
          while True:
              c = ser.read(500)
              break
          
          block=c.encode("hex")
          Wert="070100010800ff63018201621e52ff56"
          Index=block.find(Wert)+32
          Ende=Index+10
          Zaehler = block[Index:Ende]
          Stand=str(float(int(Zaehler,16))/10000)
          Wert2="0701000f0700ff0101621b52ff55"
          Index2=block.find(Wert2)+28
          Ende2=Index2+8
          Zaehler2 = block[Index2:Ende2]
          Verbrauch=str(float(int(Zaehler2,16))/10)
          connection = httplib.HTTPConnection('192.168.178.22:8080')
          connection.request('PUT', '/rest/items/Strom_Zaehler/state', Stand)
          result = connection.getresponse()
          
          connection2 = httplib.HTTPConnection('192.168.178.22:8080')
          connection2.request('PUT', '/rest/items/Strom_Aktueller_Verbrauch/state', Verbrauch)
          result = connection2.getresponse()
          pass
          Gruss
          Norbert

          Kommentar


            #20
            Guten Abend,

            bei mir ist der aktuelle Tagesverbrauch mit deiner Regel exorbitant hoch >1000 kWh, der letzte Tagesverbrauch stimmt aber. Hat das Problem noch jemand anders?
            Ich hab den Momentanverbrauch auskommentiert, da ich den ja direkt vom Zähler bekomme und der stimmt auch.
            Code:
            import org.openhab.core.library.types.*
            import org.openhab.core.persistence.*
            import org.openhab.model.script.actions.*
            
            rule "Init Strom"
            when
                System started
            then
            	if( !(Strom_Letzter_Tagesverbrauch.state instanceof DecimalType) ) postUpdate(Strom_Letzter_Tagesverbrauch, 0 )
                if( !(Strom_Aktueller_Tagesverbrauch.state instanceof DecimalType) ) postUpdate(Strom_Aktueller_Tagesverbrauch, 0 )
                if( !(Strom_Aktueller_Verbrauch.state instanceof DecimalType) ) postUpdate(Strom_Aktueller_Verbrauch, 0 )
                if( !(Strom_Min_Verbrauch.state instanceof DecimalType) ) postUpdate(Strom_Min_Verbrauch, 0 )
                if( !(Strom_Max_Verbrauch.state instanceof DecimalType) ) postUpdate(Strom_Max_Verbrauch, 0 )
            end
            
            rule "Letzter Tagesstromverbrauch"
            when
                   Time cron "15 0 0 * * ?"
            then
                postUpdate(Strom_Letzter_Tagesverbrauch, Strom_Zaehler.historicState(now.toDateMidnight) as DecimalType - Strom_Zaehler.historicState(now.toDateMidnight.toDateTime.minusMinutes(1440)) as DecimalType )
                postUpdate(Strom_Min_Verbrauch, Strom_Zaehler.state as DecimalType )
                postUpdate(Strom_Max_Verbrauch, Strom_Zaehler.state as DecimalType )
            end
            
            rule "Stromverbrauch"
            when
                   Time cron "30 0/5 * * * ?"
            then
                //var Number Letzter_Zaehler = Strom_Zaehler.historicState(now.minusMinutes(5)) as DecimalType
                var Number Aktuell_Zaehler = Strom_Zaehler.state as DecimalType
                postUpdate(Strom_Aktueller_Tagesverbrauch, Aktuell_Zaehler - Strom_Zaehler.minimumSince(now.toDateMidnight).state as DecimalType )
                var Number Aktuell = Strom_Aktueller_Verbrauch.historicState(now.minusMinutes(5)) as DecimalType
                //postUpdate(Strom_Aktueller_Verbrauch, Aktuell )
            	if( (Strom_Min_Verbrauch.state as DecimalType) > Aktuell ){
                postUpdate(Strom_Min_Verbrauch, Aktuell )
                }
                if( (Strom_Max_Verbrauch.state as DecimalType) < Aktuell ){
                postUpdate(Strom_Max_Verbrauch, Aktuell )
                }
            end

            Kommentar


              #21
              Hallo,

              es könnte daran liegen das als Bezugsgrösse "Strom_Zaehler.minimumSince" genommen wird. Wenn jetzt aus irgendeinem Grund das Minimum 0 ist kommt als Ergebnis der Gesamtzählerstand raus.

              du könntest die Rechnung mal in

              Strom_Zaehler.historicState(now.toDateMidnight) ändern

              Viele Grüße

              Holger

              Kommentar


                #22
                Aloha,

                ich habe mir die Scripte angeschaut und ein wenig angepasst/geändert.
                Mein EHZ Zähler sendet die Daten allerdings bereits in ASCII und auch mit anderer Parität/Stopbit.

                Wer es gebrauchen kann schaut einfach hier:

                vzlogger.py
                Code:
                #!/usr/bin/python
                
                from ctypes import *
                import httplib
                import os.path
                import sys
                import serial
                import time
                
                csvFile=os.path.join('/Users/admin/Desktop/','vzlogger.csv')
                
                def str2float(z):
                  try:
                    z = float(z)
                  except ValueError:
                    print 'UNINITIALIZED VALUE!'
                    z = float(0)
                  return "{:09.3f}".format(z)
                
                def readVal(type,value):
                  if type == 'nummer':
                    Wert="1-0:0.0.0" # Zaehlernummer
                  else:
                    Wert="1-0:1.8.1" # Zaehlerstand
                  index=value.find(Wert)
                  start=value.find('(', index)
                  ende=value.find(')', index)
                  result = value[start+1:ende]
                  if type == 'zaehler':
                    return str2float(result)
                  return result
                    
                serST = serial.Serial(
                    port='/dev/cu.SLAB_USBtoUART5',\
                    baudrate=9600,\
                    parity=serial.PARITY_EVEN,\
                    stopbits=serial.STOPBITS_ONE,\
                    bytesize=serial.SEVENBITS,\
                        timeout=10)
                
                serWP = serial.Serial(
                    port='/dev/cu.SLAB_USBtoUART',\
                    baudrate=9600,\
                    parity=serial.PARITY_EVEN,\
                    stopbits=serial.STOPBITS_ONE,\
                    bytesize=serial.SEVENBITS,\
                        timeout=10)
                
                while True:
                    cST = serST.read(180)
                    cWP = serWP.read(180)
                    break
                
                print '======'+time.strftime("%d-%m-%y %H:%M:%S")+'======'
                print cST
                print '------'
                print cWP
                print '------'
                
                ### GET CURRENT VALUES ZAEHLERNUMMER & ZAEHLERSTAND FROM COUNTER
                ### Stromzaehlernummer ST=Strom WP=Heizung
                NummerST = readVal('nummer',cST)
                NummerWP = readVal('nummer',cWP)
                ZaehlerST = readVal('zaehler',cST)
                ZaehlerWP = readVal('zaehler',cWP)
                
                print 'Strom        : ' + str(NummerST) + " -> " + str(ZaehlerST)
                print 'NummerWP     : ' + str(NummerWP) + " -> " + str(ZaehlerWP)
                print '---'
                
                ### SEND NEW VALUES
                # Actual count via rest API
                connectionST = httplib.HTTPConnection('127.0.0.1', 8080)
                connectionST.request('PUT', '/rest/items/Zaehler_Strom/state', str(ZaehlerST))
                resultST = connectionST.getresponse()
                
                connectionWP = httplib.HTTPConnection('127.0.0.1', 8080)
                connectionWP.request('PUT', '/rest/items/Zaehler_WP/state', str(ZaehlerWP))
                resultWP = connectionWP.getresponse()
                
                # Write CSV file
                today = (time.strftime("%Y-%m-%d ")) + (time.strftime("%H:%M:%S"))
                if os.path.isfile(csvFile):
                  print 'CSV file exists. Appending data....'
                  fileObj = open(csvFile, 'a')
                else:
                  print 'CSV file does not exist. Creating new one...'
                  fileObj = open(csvFile, 'w')
                  fileObj.write('Date & Time;Zaehler Strom;Zaehler Heizung')
                  fileObj.write('\n')
                print 'Path: ' + os.path.abspath(fileObj.name)
                fileObj.write(today+';'+str(ZaehlerST)+';'+str(ZaehlerWP))
                fileObj.write('\n')
                fileObj.close()
                pass
                In openhab sieht meine Rule so aus:

                strom.rule
                Code:
                import org.openhab.core.library.types.*
                import org.openhab.core.persistence.*
                import org.openhab.model.script.actions.*
                import org.joda.time.*
                
                val int MONDAY = 1
                var int powerOld = -1
                var int heatingOld = -1
                
                rule Stromverbrauch
                when
                	// Check every minute
                	Time cron "0 * * * * ?"
                then 
                	var powerWeek_Int = 0 
                	var heatingWeek_Int = 0
                	// Actual values / counter
                	var powerNow = (Zaehler_Strom.historicState(now,"db4o").state as DecimalType)
                	var heatingNow = (Zaehler_WP.historicState(now,"db4o").state as DecimalType)
                
                	// Actual values / counter as Integer
                	var powerNow_Int = (powerNow*1000).intValue()
                	var heatingNow_Int = (heatingNow*1000).intValue()
                	var powerConsumption = powerNow_Int - powerOld
                	var heatingConsumption = heatingNow_Int - heatingOld
                
                	if(powerOld == -1) {
                		Verbrauch_Strom.postUpdate(0)
                		Verbrauch_WP.postUpdate(0)
                		logInfo("FILE", "Initialize old powerNow="+powerOld+" heatingNow="+heatingOld)
                	} else {		
                		Verbrauch_Strom.postUpdate(powerConsumption)
                		Verbrauch_WP.postUpdate(heatingConsumption)
                	}
                	// SAVE OLD Power/Heating usage
                	powerOld = powerNow_Int
                	heatingOld = heatingNow_Int
                	
                	var powerMidnight_Int = ((Zaehler_Strom.historicState(now.toDateMidnight,"db4o").state as DecimalType)*1000).intValue()
                	var heatingMidnight_Int = ((Zaehler_WP.historicState(now.toDateMidnight,"db4o").state as DecimalType)*1000).intValue()
                	
                	if(now.getDayOfWeek != 1) {
                		var DateMidnight beginOfWeek = now.minusDays(now.getDayOfWeek - 1).toDateMidnight
                		powerWeek_Int = ((Zaehler_Strom.historicState(beginOfWeek,"db4o").state as DecimalType)*1000).intValue()
                		heatingWeek_Int = ((Zaehler_WP.historicState(now.toDateMidnight.withDayOfWeek(1),"db4o").state as DecimalType)*1000).intValue()	
                	} else{
                		powerWeek_Int = powerMidnight_Int
                		heatingWeek_Int = heatingMidnight_Int
                	}
                
                	var powerConsumptionDay = powerNow_Int - powerMidnight_Int
                	var heatingConsumptionDay = heatingNow_Int - heatingMidnight_Int
                	var powerConsumptionWeek = powerNow_Int - powerWeek_Int
                	var heatingConsumptionWeek = heatingNow_Int - heatingWeek_Int
                
                	Power_Daily.postUpdate(powerConsumptionDay)
                	Heating_Daily.postUpdate(heatingConsumptionDay)
                	Power_Weekly.postUpdate(powerConsumptionWeek)
                	Heating_Weekly.postUpdate(heatingConsumptionWeek)
                	Int_Zaehler_Strom.postUpdate(powerNow.intValue())
                	Int_Zaehler_WP.postUpdate(heatingNow.intValue())	
                end
                Ich hoffe es hilft dem einen oder anderen weiter.
                Bei Fragen meldet euch einfach.

                P.S.: Ich habe zwei EHZ Zähler, einen für Hausstrom und einen für die Wärmepumpe

                Kommentar


                  #23
                  Vielen Dank, wird mir bestimmt weiter helfen.

                  Zitat von pheno Beitrag anzeigen
                  Bei Fragen meldet euch einfach.
                  Wie sieht deine Sitemap aus, um die entsprechenden Grafiken zu zeichnen?

                  Kommentar


                    #24
                    Hi Juun,

                    du kannst ein Chart item folgendermaßen in die Sitemap einbauen:

                    Code:
                    Chart item=Weather_Chart period=D refresh=3600 visibility=[Weather_Chart_Period==1]
                    Aber die RRA's in openHAB waren mir zu unflexibel und starr, daher habe ich das ganze in Cacti gemacht. Ich muss die Grafiken noch einbinden, aber das könnte ich dann mit Image oder WebView machen.

                    Allerdings habe ich jetzt die cometVISU für mich entdeckt und bastele bereits daran

                    Kommentar


                      #25
                      Danke pheno,

                      So habe ich es schon länger drin, klappt nur leider nicht. Muss mir dann mal wieder Zeit nehmen. Immer hin klappt jetzt die Anzeige des Tagesverbrauches.

                      Ja, cometVisu ist bestimmt ein guter Weg, aber wie gesagt.. basteln...

                      Kommentar


                        #26
                        Poste doch deine sitemap und deine items Datei, dann schaue ich mir das ganze an. Ein Screenshot wie es momentan aussieht wäre auch hilfreich.

                        Kommentar


                          #27
                          Sehr nett, danke. Ich habe aber den Fehler gefunden (glaube ich). Meine Presistence Strategie war auf "everyChange", für Grafiken muss es aber, so weit ich weiss, eine Cronexpression sein.

                          Mal abwarten, wird bestimmt klappen. Sonst komme ich gerne auf dein Angebot zurück.

                          Kommentar


                            #28
                            ...also meine rrd4j.persist sieht folgendermaßen aus:
                            Code:
                            // persistence strategies have a name and a definition and are referred to in the "Items" section
                            Strategies {
                                    everyMinute : "0 * * * * ?"
                                    everyHour   : "0 0 * * * ?"
                                    everyDay    : "0 0 0 * * ?"
                                    default = everyChange
                            }
                            
                            Items {
                                    // let's only store power consumption values in rrd
                                    Int_Zaehler_Strom, Int_Zaehler_WP, Verbrauch_Strom, Verbrauch_WP : strategy = everyMinute, everyHour, everyDay, everyChange, restoreOnStartup
                            }

                            Kommentar


                              #29
                              Ich verwende nur "everyMinute", jetzt klappt es auch.

                              Zur Berechnung des Tagesverbrauches verwendest du ja die Werte aus der "db4o" presistence. Gibt es dafür einen bestimmten Grund? Kann man nicht für alles "rrd4j" nehmen?

                              Kommentar


                                #30
                                Hi Juun,

                                nun ich wollte gerne auch auf längere Sicht auf die genauen Zählerwerte zurückgreifen z.B. Den genauen Stand letztes Jahr Dezember und daher speichere ich die genauen Werte in der db4o. Die rrd4j nutze ich eigentlich gar nicht mehr, da ich alle werte via Cacti in einem externen RRA speichere. Muss nur noch mal die Charts in openHAB einbinden.
                                gtx, Manolo

                                P.S.: Schön das es jetzt bei dir funktioniert!

                                Kommentar

                                Lädt...
                                X