Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl -w
- # teile von http://www.ip-symcon.de/forum/threads/21407-Stromz%C3%A4hler-mit-RS485/page2 entnommen
- # 20130802 : ollir
- # vereinfachte Version von http://wiki.volkszaehler.org/hardware/channels/meters/power/drs155m
- #
- # http://wiki.volkszaehler.org/hardware/channels/meters/power/edl-ehz/e110
- #
- # 20151221 : RaymondP
- # less German: original code can be found somewhere at the previous links.
- # extended to work with Domoticz through the HTTP api: https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's
- #
- # Landis & Gyr E110
- # unverified, could not find documentation.
- # actually, I found some documentation. It was useless.
- # it should use protocol IEC_62056, but I'm totally unfamiliar with it and I'm lazy.
- # on top of that it was 139 pages and as usual they charge quite a lot of money for it.
- # we could probably do some block checking to verify data integrity and some other nice stuff. Someone should read it. :P
- #
- # debian (apt oriented) system:
- # apt-get install libdevice-serialport-perl libhttp-tiny-perl libdata-dumper-simple-perl
- use strict;
- use Device::SerialPort;
- use HTTP::Tiny;
- use Data::Dumper;
- my $settings = {
- domoticzUrl => 'http://10.0.0.5:8080',
- domoDevIDX => 243, #Electricity P1 smart meter
- # carefull, editing this might result in burned toast and dead unicorns.
- usbPort => '/dev/ttyUSB0',
- # dear mister original programmer, why? Oh well...
- commandInit => "/?!\r\n",
- commandRead => chr(0x06).chr(0x30).chr(0x30).chr(0x30).chr(0x0D).chr(0x0A), # ACK RS RS RS CR LF
- # readable
- mapped => {
- '2.18.1' => 'vLaag',
- '2.18.2' => 'vHoog',
- '2.18.0' => 'vTot',
- '3.28.1' => 'lLaag',
- '3.28.2' => 'lHoog',
- '3.28.0' => 'lTot',
- },
- };
- my ($STX, $ETX, $ACK) = (chr(0x02), chr(0x03), chr(0x06));
- my ($conn, $result);
- my $resultClean = {};
- # Initialisierung
- &initConnection;
- comms('read');
- &domoUpdate;
- print Dumper($resultClean);
- sub domoUpdate{
- my ($httpDomo, $uri, $httpResp);
- # should at least chech a little bit of sanity before updating
- if(! defined $resultClean->{vTot} || $resultClean->{vTot} < 1 || $resultClean->{lTot} < 1){
- return;
- }
- $httpDomo = HTTP::Tiny->new();
- $uri = sprintf(
- "%s/json.htm?type=command¶m=udevice&idx=%s&nvalue=0&svalue=%s;%s;%s;%s;%s;%s",
- $settings->{domoticzUrl},
- $settings->{domoDevIDX},
- $resultClean->{vLaag},
- $resultClean->{vHoog},
- $resultClean->{lLaag},
- $resultClean->{lHoog},
- 0, # actual usage power (Watt)
- 0 # actual return power (Watt)
- );
- $httpResp = $httpDomo->get($uri);
- # should catch error, but I guess it doens't really matter
- }
- sub initConnection{
- # hardly touched original code. If it works don't break it.
- $conn = Device::SerialPort->new($settings->{usbPort}) || die $!;
- $conn->baudrate(300);
- $conn->databits(7);
- $conn->parity("even");
- $conn->stopbits(1);
- $conn->handshake("none");
- $conn->write_settings;
- $conn->purge_all();
- $conn->read_char_time(3);
- $conn->read_const_time(10);
- # send initial command, does the device need this? Or should we check if the given usb tty is actually the right one?
- # so much questions, would be easier if I'd have the actual device.
- # Someone should buy me one.
- # Forget that, someone should buy me coffee!
- comms('init');
- }
- sub comms {
- my ($func) = @_;
- my ($cmd, $count, $raw, $response, %commandResult, @split);
- if($func eq 'init'){
- $conn->lookclear;
- $conn->write( $settings->{commandInit} );
- ($count,$response) = $conn->read(165);
- return;
- }
- if($func eq 'read') {
- $conn->lookclear;
- $conn->write( $settings->{commandRead} );
- ($count,$raw) = $conn->read(165);
- $response=uc(unpack('H*',$raw)); # nach hex wandeln
- # example response
- #$response = pack("H*",'02302E30302E362E30284638463230303030290D0A302E30302E362E31283136323332333039290D0A322E31382E31283031303039372E3539290D0A322E31382E32283030363935342E3632290D0A322E31382E30283031373035322E3231290D0A332E32382E31283030313330342E3632290D0A332E32382E32283030333135372E3534290D0A332E32382E302830303436322E313629');
- $response =~ s/$STX//;
- # no STX could identify a problem, not starting at beginning of string, serial fault
- # Note: I should probably also have ETX ath the end, but that's not in my example response. We probably don't read the full message or have wrong serial settings. But hey, who cares right?
- @split = split('\r\n', $response); # split on newline
- %commandResult = map { $_ =~ /([0-9\.]+)\((.+)\)/ } split('\r\n', $response); # map to key => val
- # just use stuff we might actually need.
- # Note: I have no idea what we might need, just guessing here.
- foreach my $key (keys %commandResult) {
- # we probably don't need serial numbers and stuff, who has wto of these anyway?
- if(! defined $settings->{mapped}->{$key}){
- next;
- }
- # make it a bit more human readable and strip zero padding.
- $resultClean->{$settings->{mapped}->{$key}} = sprintf('%.2f', $commandResult{$key});
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment