Raymond-p

Landis & Gyr E110 > domoticz

Dec 20th, 2015
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 5.04 KB | None | 0 0
  1. #!/usr/bin/perl -w
  2.  
  3.  
  4. # teile von http://www.ip-symcon.de/forum/threads/21407-Stromz%C3%A4hler-mit-RS485/page2 entnommen
  5. # 20130802 : ollir
  6. # vereinfachte Version von http://wiki.volkszaehler.org/hardware/channels/meters/power/drs155m
  7. #
  8. # http://wiki.volkszaehler.org/hardware/channels/meters/power/edl-ehz/e110
  9. #
  10. # 20151221 : RaymondP
  11. # less German: original code can be found somewhere at the previous links.
  12. # extended to work with Domoticz through the HTTP api: https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's
  13. #
  14.  
  15. # Landis & Gyr E110
  16. # unverified, could not find documentation.
  17. # actually, I found some documentation. It was useless.
  18. # it should use protocol IEC_62056, but I'm totally unfamiliar with it and I'm lazy.
  19. # on top of that it was 139 pages and as usual they charge quite a lot of money for it.
  20. # we could probably do some block checking to verify data integrity and some other nice stuff. Someone should read it. :P
  21. #
  22.  
  23.  
  24. # debian (apt oriented) system:
  25. # apt-get install libdevice-serialport-perl libhttp-tiny-perl libdata-dumper-simple-perl
  26.  
  27.  
  28. use strict;
  29. use Device::SerialPort;
  30. use HTTP::Tiny;
  31.  
  32. use Data::Dumper;
  33.  
  34.  
  35. my $settings = {
  36.  
  37.         domoticzUrl => 'http://10.0.0.5:8080',
  38.         domoDevIDX  => 243, #Electricity P1 smart meter
  39.  
  40.         # carefull, editing this might result in burned toast and dead unicorns.
  41.         usbPort     =>  '/dev/ttyUSB0',
  42.        
  43.         # dear mister original programmer, why? Oh well...
  44.         commandInit => "/?!\r\n",
  45.         commandRead => chr(0x06).chr(0x30).chr(0x30).chr(0x30).chr(0x0D).chr(0x0A), # ACK RS RS RS CR LF
  46.  
  47.         # readable
  48.         mapped => {
  49.                 '2.18.1'    => 'vLaag',
  50.                 '2.18.2'    => 'vHoog',
  51.                 '2.18.0'    => 'vTot',
  52.                 '3.28.1'    => 'lLaag',
  53.                 '3.28.2'    => 'lHoog',
  54.                 '3.28.0'    => 'lTot',
  55.         },
  56.  
  57. };
  58.  
  59.  
  60.  
  61. my ($STX, $ETX, $ACK) = (chr(0x02), chr(0x03), chr(0x06));
  62.  
  63. my ($conn, $result);
  64. my $resultClean = {};
  65.  
  66.  
  67. # Initialisierung
  68. &initConnection;
  69.  
  70. comms('read');
  71.  
  72. &domoUpdate;
  73.  
  74. print Dumper($resultClean);
  75.  
  76.  
  77.  
  78. sub domoUpdate{
  79.     my ($httpDomo, $uri, $httpResp);
  80.  
  81.     # should at least chech a little bit of sanity before updating
  82.     if(! defined $resultClean->{vTot} || $resultClean->{vTot} < 1 || $resultClean->{lTot} < 1){
  83.         return;
  84.     }
  85.  
  86.     $httpDomo = HTTP::Tiny->new();
  87.  
  88.     $uri = sprintf(
  89.                 "%s/json.htm?type=command&param=udevice&idx=%s&nvalue=0&svalue=%s;%s;%s;%s;%s;%s",
  90.                 $settings->{domoticzUrl},
  91.                 $settings->{domoDevIDX},
  92.                 $resultClean->{vLaag},
  93.                 $resultClean->{vHoog},
  94.                 $resultClean->{lLaag},
  95.                 $resultClean->{lHoog},
  96.                 0, # actual usage power (Watt)
  97.                 0 # actual return power (Watt)
  98.             );
  99.  
  100.     $httpResp = $httpDomo->get($uri);
  101.  
  102.     # should catch error, but I guess it doens't really matter
  103. }
  104.  
  105.  
  106. sub initConnection{
  107.  
  108.     # hardly touched original code. If it works don't break it.
  109.     $conn = Device::SerialPort->new($settings->{usbPort}) || die $!;
  110.     $conn->baudrate(300);
  111.     $conn->databits(7);
  112.     $conn->parity("even");
  113.     $conn->stopbits(1);
  114.     $conn->handshake("none");
  115.     $conn->write_settings;
  116.  
  117.     $conn->purge_all();
  118.     $conn->read_char_time(3);
  119.     $conn->read_const_time(10);
  120.  
  121.     # send initial command, does the device need this? Or should we check if the given usb tty is actually the right one?
  122.     # so much questions, would be easier if I'd have the actual device.
  123.     # Someone should buy me one.
  124.     # Forget that, someone should buy me coffee!
  125.     comms('init');
  126.  
  127. }
  128.  
  129. sub comms {
  130.     my ($func) = @_;
  131.     my ($cmd, $count, $raw, $response, %commandResult, @split);
  132.  
  133.     if($func eq 'init'){
  134.  
  135.         $conn->lookclear;
  136.         $conn->write( $settings->{commandInit} );
  137.         ($count,$response) = $conn->read(165);
  138.  
  139.         return;
  140.     }
  141.  
  142.  
  143.     if($func eq 'read') {
  144.  
  145.         $conn->lookclear;
  146.         $conn->write( $settings->{commandRead} );
  147.         ($count,$raw) = $conn->read(165);
  148.  
  149.         $response=uc(unpack('H*',$raw)); # nach hex wandeln
  150.  
  151.         # example response
  152.         #$response = pack("H*",'02302E30302E362E30284638463230303030290D0A302E30302E362E31283136323332333039290D0A322E31382E31283031303039372E3539290D0A322E31382E32283030363935342E3632290D0A322E31382E30283031373035322E3231290D0A332E32382E31283030313330342E3632290D0A332E32382E32283030333135372E3534290D0A332E32382E302830303436322E313629');
  153.        
  154.  
  155.         $response =~ s/$STX//;
  156.         # no STX could identify a problem, not starting at beginning of string, serial fault
  157.         # 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?
  158.  
  159.         @split = split('\r\n', $response); # split on newline
  160.         %commandResult = map { $_ =~ /([0-9\.]+)\((.+)\)/ } split('\r\n', $response); # map to key => val
  161.  
  162.  
  163.         # just use stuff we might actually need.
  164.         # Note: I have no idea what we might need, just guessing here.
  165.  
  166.         foreach my $key (keys %commandResult) {
  167.  
  168.             # we probably don't need serial numbers and stuff, who has wto of these anyway?
  169.             if(! defined $settings->{mapped}->{$key}){
  170.                 next;
  171.             }
  172.  
  173.             # make it a bit more human readable and strip zero padding.
  174.             $resultClean->{$settings->{mapped}->{$key}} = sprintf('%.2f', $commandResult{$key});
  175.  
  176.         }
  177.  
  178.  
  179.     }
  180. }
Advertisement
Add Comment
Please, Sign In to add comment