Ankündigung

Einklappen
Keine Ankündigung bisher.

Zählerabfrage als Wiregate Plugin

Einklappen
Dieses Thema ist geschlossen.
X
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • JuMi2006
    antwortet
    Zitat von NetFritz Beitrag anzeigen
    Hallo
    JuMi2006 schön das es bei Dir nun auch geht.
    Ich habe auch noch so einen Zähler von der Firma Itron einen ACE3000 Typ 260.
    Lt. Tante Google hat er auch IEC 62056-21 !

    Zitat von NetFritz Beitrag anzeigen
    Was hast Du den für einen Auslesekopf und wie bekommst Du die Daten ins Wiregate?
    Um die Zählerstände auszulesen reicht sicherlich die Daten alle 5min zu erfassen.
    Schreib-Lesekopf -> volkszaehler.org - wiki - IR-Schreib-Lesekopf -> Udo

    Dafür hab ich das Plugin gemacht. Kurz zur Erklärung, der Zähler sendet erst nachdem er eine Anfrage bekommen hat. Das Script sendet diese Abfrage und liest dann die Daten ein. Mein Zähler gibt nur den Stand aus daher wird das Plugin danach beendet. Die Werte werden dann in ein Log geschrieben, auf den Bus gesendet und in 3 unterschiedliche RRDs geschrieben. Dies passiert alle 5 Minuten -> cronjob

    Zitat von NetFritz Beitrag anzeigen
    Mein Zähler sendet aber auch die augenblickliche Leistung alle 2sec. mit.
    Da wäre es schön das auch alle 2sec. die Daten zu erfassen.
    Alle 2 Sekunden ist eher SML ... kann Deiner und meiner nicht.

    Zitat von NetFritz Beitrag anzeigen
    Vielleicht setze ich nochmal meinen Arduino dafür ein, den kann man dann mit einem Plugin abfragen.
    Gruß NetFritz
    Nicht nötig.

    Das einzige was Du rausbekommen musst ist wie Dein Wert im Zähler gesendet wird. Dafür eignet sich am besten hterm (google). Dort kannst Du schonmal schön sehen wie der Zähler welche Daten sendet. Am besten erstmal den Lesekopf besorgen. Ich brauche auch noch einen zweiten da mir mein EVU nun doch einen elektronischen Zähler für Haushaltsstrom einbaut. Hoffentlich sendet der dann noch die aktuelle Leistung.

    Gruß Mirko

    Einen Kommentar schreiben:


  • greentux
    antwortet
    Hallo Netfritz,

    bist Du Dir sicher, das der Zähler alle 2Sekunden alles sendet? Ich habe auch so einen, bisher aber nur die Anleitung gelesen, die anderes suggeriert. Die kW Impulse kommen automatisch, aber für die Daten will er einen Abfragecode gesendet bekommen

    Einen Kommentar schreiben:


  • NetFritz
    antwortet
    Hallo
    JuMi2006 schön das es bei Dir nun auch geht.
    Ich habe auch noch so einen Zähler von der Firma Itron einen ACE3000 Typ 260.
    Was hast Du den für einen Auslesekopf und wie bekommst Du die Daten ins Wiregate?
    Um die Zählerstände auszulesen reicht sicherlich die Daten alle 5min zu erfassen.

    Mein Zähler sendet aber auch die augenblickliche Leistung alle 2sec. mit.
    Da wäre es schön das auch alle 2sec. die Daten zu erfassen.
    Vielleicht setze ich nochmal meinen Arduino dafür ein, den kann man dann mit einem Plugin abfragen.
    Gruß NetFritz

    Einen Kommentar schreiben:


  • JuMi2006
    antwortet
    So hier mal eine überarbeitete Version.

    Neu:
    - Die Stelle des Zählerstandes wird zuverlässiger gefunden
    - RRD und Log-Datei werden, falls noch nicht vorhanden automatisch angelegt
    - Es müssten jetzt alle Zähler nach IEC 62056-21 damit auslesbar sein
    - Es werden 3 RRDs erzeugt mit dem Verbrauch in einer Auflösung von 24h, 1h, und 15 min

    Was noch nicht funktioniert ist das timeout .
    Für alle die es hier vielleicht lesen: der COUNTER Mode vom RRD verträgt nur Integer, kein Float - zumindest so mein Wissensstand.

    Ansonsten Aufruf durch cron alle 5 Minuten, 300 Baud ist eben langsam
    Damit kann es dann eigentlich auch ins SVN, es brauch nur noch nen schönen Namen.

    Code:
    #!/usr/bin/perl
    
    # Zählerabfrage für Zähler nach Protokoll IEC 62056-21 / OBIS
    # Ein Anfrage-Telegramm ist mit 300 Baud, 7 Bit, 1 Stoppbit
    # und gerader Paritaet zu senden. Das ist der Initialmodus von Geraeten,
    # die das Protokoll IEC 62056-21 implementieren.
    
    # Das Script ist angepasst auf EMH ITZ. Weitere Zaehler wie z.B. Elster AS1440, Siemens TD-3511 müssen
    # angepasst werden (Obis-Key).
    
    # !!! Wiederholung nur alle 3 Minuten da der Zähler nach Ende des Scriptes weiter sendet !!!
    
    # Basis des Scripts von volkszaehler.org / Autor: Andreas Schulze & Bugfix: Eric Schanze
    # DPT9 sub: makki / www.knx-user-forum.de
    # Erweiterung um RRD,KNX-Anbindung und gezielte Wertsuche auf Wiregate: JuMi2006 / www.knx-user-forum.de
    # Version: 0.1.2
    # Datum: 15.04.2012
    
    use warnings;
    use strict;
    use Device::SerialPort;
    use RRDs;
    
    ### KONFIGURATION ###
    my $device="/dev/ttyUSB-1-4";					#Schnittstelle
    my $request = "/?!\r\n";						#Anforderungstelegramm "/?!" \r\n entspricht CR-LF
    my $ga = "0/0/4";								#Gruppenadresse DPT9
    my $obiskey="1.8.0(";							#Schlüssel vor Anabe des Zählerstandes z.B. "1.8.0(0001234.5 kWh)"
    
    my $file = "/var/tmp/Zaehler.log";				#Logdatei wird automatisch angelegt!
    my $rrd_V24h = "/var/www/rrd/Verbrauch_24h.rrd";		#Verbrauch pro 24h
    my $rrd_V1h = "/var/www/rrd/Verbrauch_1h.rrd";			#Verbrauch pro 1h
    my $rrd_V15min = "/var/www/rrd/Verbrauch_15min.rrd";		#Verbrauch pro 15min
    
    ### ENDE KONFIGURATION ###
    
    ### RRD-Erstellen
    unless (-e $rrd_V24h) 
    {
    RRDs::create ($rrd_V24h,"DS:value:COUNTER:86500:0:10000000000","RRA:AVERAGE:0.5:1:365","RRA:AVERAGE:0.5:7:300","-s 86400");
    }
    unless (-e $rrd_V1h) 
    {
    RRDs::create ($rrd_V1h,"DS:value:COUNTER:3650:0:10000000000","RRA:AVERAGE:0.5:1:2400","RRA:AVERAGE:0.5:24:300","-s 3600");
    }
    unless (-e $rrd_V15min) 
    {
    RRDs::create ($rrd_V15min,"DS:value:COUNTER:300:0:10000000000","RRA:AVERAGE:0.5:1:2400","RRA:AVERAGE:0.5:12:300");
    }
    
    
    ### Seriellen Port initialisieren
    my $port = new Device::SerialPort($device) || die "can't open $device: $!";
    $port->baudrate(300)      || die 'fail setting baudrate';
    $port->databits(7)        || die 'fail setting databits';
    $port->stopbits(1)        || die 'fail setting stopbits';
    $port->parity("even")     || die 'fail setting parity';
    $port->write_settings     || die 'fail write settings';
    $port->rts_active(1);
    $port->dtr_active(1);
    $port->read_char_time(500);     # 0.5 seconds for each character
    $port->read_const_time(3000);   # 3 second per unfulfilled "read" call
    
    
    ### Anforderungstelegramm senden
    my $num_out = $port->write($request);
    die "write failed\n" unless ($num_out);
    die "write inclomplete\n" unless ($num_out == length($request));
    print "$num_out Bytes written\n";	
    
    ### AUSLESEN
    
    my $STALL_DEFAULT=5; # how many seconds to wait for new input
    my $timeout=$STALL_DEFAULT; 
    my $chars=0;
    my $buffer="";
    
    while ($timeout>0) {
            my ($count,$saw)=$port->read(255); 	# Liest 255 Zeichen je Durchlauf aus
            if ($count > 0) {
                    $chars+=$count;
                    $buffer.=$saw;
    		print $buffer;			# Ausgabe der eingelesenen Daten
     
    ### FILTER
    
    if ($buffer =~ /\Q$obiskey\E/)			# \Q \E entwertet alle Sonderzeichen dazwischen
    {
    my $pos=index($buffer,$obiskey);			# Anfangsposition des OBIS-Key finden
    #print ("Position: $pos","\n");			# Kontrolldruck der Anfangsposition
    my $value=substr($buffer,$pos+6,9);		# Wert extrahieren (OBIS-Key=6 Zeichen lang,Wert=9 Zeichen lang)
    print ($value," kWh","\n");				# Kontrolldruck Zählerstand
    
    my $val1 = int(substr $value,0,7);			### separiert die ersten 7 Zahlen im String z.B. "0001234"->1234
    my $val2 = int(substr $value,8);			### spariert die letzte Zahl im String (bei 9 Stellen) z.B. ".5"->5
    
    print ("val1: ",$val1,"\n");			### Zur Kontrolle in der Konsole
    print ("val2: ",$val2,"\n");			### Zur Kontrolle in der Konsole
    
    ### Wert in DPT9 umwandeln und in Konsole ausgeben
    my @hexdec = encode_dpt9($value);				
    my $hexval = sprintf("%x", $hexdec[0]) . " " . sprintf("%x", $hexdec[1]);
    print ($hexval,"\n");
    
    ### Wert an Gruppenadresse und RRD senden
    
    system("groupwrite ip:localhost $ga $hexval");	#Zählerstand auf Bus
    
    my $valrrd_V24h = int($value*86400); 	# Verbrauch 24h
    my $valrrd_V1h = int($value*3600); 		# Verbrauch 1h
    my $valrrd_V15min = int($value*900); 	# Verbrauch 15 min
    
    RRDs::update("$rrd_V24h", "N:$valrrd_V24h"); 
    RRDs::update("$rrd_V1h", "N:$valrrd_V1h");
    RRDs::update("$rrd_V15min", "N:$valrrd_V15min");
    
    ### Log der Zählerausgabe
    
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
    my $timestamp = printf "%4d-%02d-%02d %02d:%02d:%02d\n",$year+1900,$mon+1,$mday,$hour,$min,$sec;
    
    
    open(LOG,'>>',$file) || die "Fehler $!";
    print LOG ("\n",$year+1900,"-",$mon+1,"-",$mday," ",$hour,":",$min,":",$sec," \; ",$value);
    close LOG;	
    
    $port->close || die "can't close $device: $!";	# Port schließen
    last;							# Schleife verlassen
    
    ### ENDE FILTER
    }	
            
    }
            else {
                    $timeout--;
            }
    }
    
    if ($timeout<=0) {
    					$port->close || die "can't close $device: $!";        
    					print "Waited $STALL_DEFAULT seconds and never saw what I wanted\n";
    		}
    
    
    ### SUBS
    sub encode_dpt9 { # 2byte signed float
        my $state = shift;
        my $data;
    
    	my $sign = ($state <0 ? 0x8000 : 0);
        my $exp  = 0;
        my $mant = 0;
    
        $mant = int($state * 100.0);
        while (abs($mant) > 2047) {
            $mant /= 2;
            $exp++;
        }
        $data = $sign | ($exp << 11) | ($mant & 0x07ff);
        return $data >> 8, $data & 0xff;
    }

    Einen Kommentar schreiben:


  • makki
    antwortet
    Bitte nur Hinweise und als solche verstehen:

    Zitat von JuMi2006 Beitrag anzeigen
    Konkret fehlt Dir vor den Variablen ein "my" -> my $key z.B. oder das "use strict" entfernen.
    letzteres bitte nicht, das ist nicht nur schlechter sondern IMHO tödlicher Coding-Style; Wer einen Stück Code schreibt, dem ist zuzumuten, sich vorher auszudenken, welche Variablen er gerne benutzen würde, wenn diese ohne "use strict" mehr oder minder zufällig zur Laufzeit definiert werden ist dem Chaos Tür&Tor geöffnet, kleinste Tippfehler usw. führen zu scheinbar komischem Verhalten, das ist crap..

    Führe das Script nicht als Wiregate-Plugin aus, das wird entweder im Timeout enden oder andere Sachen einfach blockieren.
    Richtig, das geht so hier und heute nicht (es gibt aber ein schwaches Licht am Horizont was den Timeout angeht )
    Crontab tuts dafür.. Ich finds manchmal cool, das man auch 25.000 andere Sachen benutzen kann, die wir garnicht angedacht haben

    Makki

    Einen Kommentar schreiben:


  • lio123
    antwortet
    Ich habe einen EMH EHZ-H Zähler-also SML.
    Mit Konsole usw. hört's bei mir dann auf-wird dann damit auch nichts mit einem Schnellschuss.

    GRüße,
    Lio

    Einen Kommentar schreiben:


  • greentux
    antwortet
    Tja so langsam finde ich keine Ausreden mehr, meinen Zähler ans Netz zu bringen... So ein Mist...

    Einen Kommentar schreiben:


  • JuMi2006
    antwortet
    Welches Script benutzt Du?
    Das von NetFritz ist für Zähler auf SML-Basis. Was hast Du für einen Zähler?
    Mein EMH spricht kein SML, hat aber natürlich auch die OBIS-Kennzahlen.

    Konkret fehlt Dir vor den Variablen ein "my" -> my $key z.B. oder das "use strict" entfernen. Was das an anderer Stelle bewirkt weiß der Linux-DAU vor meinem Monitor aber nicht .

    Führe das Script nicht als Wiregate-Plugin aus, das wird entweder im Timeout enden oder andere Sachen einfach blockieren.

    Putty und Konsole sind angesagt - nach ein paar Tagen wird man richtig schnell damit.

    Einen Kommentar schreiben:


  • lio123
    antwortet
    danke,

    aber ich seh' gerade, dass ich wohl noch ein anderes Problem habe?
    Was ist da los?
    Angehängte Dateien

    Einen Kommentar schreiben:


  • JuMi2006
    antwortet
    Ich sehe gerade dass die ganze Abfrage nochmal überarbeitet werden muss da sie nicht ganz sicher ist. Die Position stimmt ab und an nicht, da muss man wohl nochmal filtern. Mit den 300 Baud und den Zeilenumbrüchen macht das aber irgendwie keinen Spaß. Vielleicht doch erst alles auslesen, ein timeout einbauen und dann den entsprechenden String suchen?

    Einen Kommentar schreiben:


  • JuMi2006
    antwortet
    Ersetze für einen Durchlauf
    Code:
    print LOG ("\n",$year+1900,"-",$mon+1,"-",$mday," ",$hour,":",$min,":",$sec," ; ",$value);
    durch

    Code:
    print LOG $s;
    Dann bekommst Du die ganze Ausgabe bis Zeichen Nummer ($position) in die Textdatei. Die musst Du vorher aber anlegen, so weit war ich noch nicht. Dann kannst Du im guten Editor die richtige Stelle ablesen.

    Oder einfach per Try&Error ausprobieren bis es passt ;-).

    Einen Kommentar schreiben:


  • lio123
    antwortet
    gibt es ein Tool um die Endposition des Zählerstandes zu ermitteln?
    -Habe zwar den Stand, aber muss ich alle Zeichen von Hand Zählen?

    Einen Kommentar schreiben:


  • lio123
    antwortet
    Hallo

    -hat sich das Warten gelohnt?
    Ich werde es rausfinden!
    EMH-Zähler und VolksKopf vorhanden!

    Grüße,
    Lio

    Einen Kommentar schreiben:


  • 2ndsky
    antwortet
    Zitat von JuMi2006 Beitrag anzeigen
    Zählerabfrage für einen EMH-ITZ mit IR-Schreib-/Lesekopf. Hardware habe ich von volkszähler.org und das ganze läuft als Perl-Plugin via cron alle 5 Minuten.
    Hey Mirko,

    super, dass du es schon hinbekommen hast. Dann hoffe ich mein Opto Kopf kommt bald und das ich dann auch mal Zeit habe, das WG auf'm Bau in Betrieb zu nehmen. Vielen Dank für die Arbeit die du dir gemacht hast und das du es hier veröffentlichst!

    Einen Kommentar schreiben:


  • makki
    antwortet
    Gut

    Zitat von JuMi2006 Beitrag anzeigen
    2 kleine Probleme/Fragen noch:

    1. Das rrd sieht komisch aus / stimmt nicht -> falsch angelegt !?
    Vermutlich..
    RRD's werden vom WG Defaultmässig als GAUGE (gut Temperatur, Luftfeuchte, absolutwerte) angelegt.
    Richtig wäre hier aber COUNTER, einmal richtig angelegt sollte das passen.. (update_rrd in Plugins kann man das auch initial mitgeben, bei einem Standalone-Programm wäre es wohl am saubersten den relevanten Teil davon zu übernehmen, ggfs. das RRD dort selbst richtig anzulegen.

    2. Der Wert aus dem Log/Konsole (1774,9) stimmt nicht 100% mit dem Bus überein 1774,08) !?
    Das ist normal, das liegt zum einen evtl. daran, wie so ein Rechner einen float (IEEE754) intern behandelt, Chris M hatte das mal schön erklärt, zum anderen an dem das der DPT9, wenn man 32bit unscharfe floating-pointarithmetik in 16bit packt und danach wieder anschaut kommt nicht bis auf die 8. Nachkommastelle dasselbe raus, da beide leicht unscharf sind..

    Beim (genauen) vergleichen von Werten sollte man darauf übrigens achten, ansonsten ist es meist vernachlässigbarer Pillefuzz, weil unterm Strich stimmts..

    Makki

    P.S.: Eine Anmerkung noch, nicht wirklich lebenswichtig aber: einen klaren Lizenz-Header, Hinweise auf alle beteiligten wäre immer gut.
    Es geht jetzt nicht um das encode_dpt9, auch wenn ich die wirklich selbst geschreiben habe, weil 2 sehr ähnliche aber falsche durchs Netz fleuchen;
    Sondern darum das man irgendwann wenn man das einsetzt klar nachvollziehen kann, wo das herkommt und Rechtssicherheit besteht; im privaten Bereich eher sekundär, im gewerblichen nicht, daher sollte der Author über die Lizenz eine Aussage treffen, wie er das meint, weil geposteter Quellcode ist noch lange nicht "Freeware"

    P.S2.:use utf8; ist redundant, kostet aber ne Menge Speicher, in Quellcode/Kommentaren/Dateinamen mag ich gerne dringend empfehlen, auf Umlaute und sonstige Sonderzeichen zu verzichten, spart viel Trouble..

    Makki

    Einen Kommentar schreiben:

Lädt...
X