DOS -> UNIX

git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@4572 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
bentele
2014-01-06 10:03:00 +00:00
parent 5b58e6b5f0
commit 95fbf858cf

View File

@@ -1,364 +1,364 @@
############################################################################## ##############################################################################
# #
# 70_EFR.pm # 70_EFR.pm
# #
# a module to show smartmeter data # a module to show smartmeter data
# #
# written 2013 by Gabriel Bentele <gabriel at bentele.de>> # written 2013 by Gabriel Bentele <gabriel at bentele.de>>
# #
# $Id: 70_EFR.pm 3799 2013-08-26 18:15:33Z bentele $ # $Id: 70_EFR.pm 3799 2013-08-26 18:15:33Z bentele $
# #
# Version = 0.7 # Version = 0.8
# #
############################################################################## ##############################################################################
# #
# define <name> EFR <host> <port> [<interval> [<timeout>]] # define <name> EFR <host> <port> [<interval> [<timeout>]]
# #
# If <interval> is positive, new values are read every <interval> seconds. # If <interval> is positive, new values are read every <interval> seconds.
# If <interval> is 0, new values are read whenever a get request is called # If <interval> is 0, new values are read whenever a get request is called
# on <name>. The default for <interval> is 300 (i.e. 5 minutes). # on <name>. The default for <interval> is 300 (i.e. 5 minutes).
# #
# get <name> <key> # get <name> <key>
# #
############################################################################## ##############################################################################
# { "obis":"8181C78227FF","value":""}, [03] Kundennummer # { "obis":"8181C78227FF","value":""}, [03] Kundennummer
# { "obis":"8181C78205FF","value":"xxxxx"}, [04] Vorname # { "obis":"8181C78205FF","value":"xxxxx"}, [04] Vorname
# { "obis":"8181C78206FF","value":"xxxxx"}, [05] Nachname # { "obis":"8181C78206FF","value":"xxxxx"}, [05] Nachname
# { "obis":"8181C78207FF","value":"xxxxx"}, [06] Anschrift # { "obis":"8181C78207FF","value":"xxxxx"}, [06] Anschrift
# { "obis":"0100000000FF","value":"xxxxx"}, [07] Eigentums- bzw. Z<>hlernummer # { "obis":"0100000000FF","value":"xxxxx"}, [07] Eigentums- bzw. Z<>hlernummer
# { "obis":"010000090B00","value":"dd.mm.yyyy,hh:mm"}], "values" : [ [08] Zeitangabe (Datum , Uhrzeit) # { "obis":"010000090B00","value":"dd.mm.yyyy,hh:mm"}], "values" : [ [08] Zeitangabe (Datum , Uhrzeit)
# {"obis":"0101010800FF","value":41.42,"unit":"kWh" }, [09] BEZUG Wirkleistung Energiez<65>hlwerk - Summenz<6E>hlwerk abrechnungsrelevant (Tariflos) # {"obis":"0101010800FF","value":41.42,"unit":"kWh" }, [09] BEZUG Wirkleistung Energiez<65>hlwerk - Summenz<6E>hlwerk abrechnungsrelevant (Tariflos)
# {"obis":"0101010801FF","value":33.53,"unit":"kWh"}, [10 BEZUG Wirkleistung Energiez<65>hlwerk NT # {"obis":"0101010801FF","value":33.53,"unit":"kWh"}, [10 BEZUG Wirkleistung Energiez<65>hlwerk NT
# {"obis":"0100010700FF","value":313.07,"unit":"W"}, [11] Momentanleistung <20>ber alle 3 Phasen saldierend # {"obis":"0100010700FF","value":313.07,"unit":"W"}, [11] Momentanleistung <20>ber alle 3 Phasen saldierend
# {"obis":"0100150700FF","value":209.40,"unit":"W"}, [12] Momentanleistung Phase L1 # {"obis":"0100150700FF","value":209.40,"unit":"W"}, [12] Momentanleistung Phase L1
# {"obis":"0100290700FF","value":14.27,"unit":"W"}, [13] Momentanleistung Phase L2 # {"obis":"0100290700FF","value":14.27,"unit":"W"}, [13] Momentanleistung Phase L2
# {"obis":"01003D0700FF","value":89.40,"unit":"W"}, [14] Momentanleistung Phase L3 # {"obis":"01003D0700FF","value":89.40,"unit":"W"}, [14] Momentanleistung Phase L3
# {"obis":"010020070000","value":237.06,"unit":"V"}, [15] Phasenspannung U1 # {"obis":"010020070000","value":237.06,"unit":"V"}, [15] Phasenspannung U1
# {"obis":"010034070000","value":236.28,"unit":"V"}, [16] Phasenspannung U2 # {"obis":"010034070000","value":236.28,"unit":"V"}, [16] Phasenspannung U2
# {"obis":"010048070000","value":236.90,"unit":"V"}, [17] Phasenspannung U3 # {"obis":"010048070000","value":236.90,"unit":"V"}, [17] Phasenspannung U3
# {"obis":"01000E070000","value":49.950,"unit":"Hz"} ] }} [18] Netzfrequenz # {"obis":"01000E070000","value":49.950,"unit":"Hz"} ] }} [18] Netzfrequenz
############################################################################## ##############################################################################
package main; package main;
use strict; use strict;
use IO::Socket::INET; use IO::Socket::INET;
use Blocking; use Blocking;
use MIME::Base64; use MIME::Base64;
my @gets = ('lastPower','PowerTotal','Power_L1','Power_L2','Power_L3'); my @gets = ('lastPower','PowerTotal','Power_L1','Power_L2','Power_L3');
sub sub
EFR_Initialize($) EFR_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "energy_Define"; $hash->{DefFn} = "energy_Define";
$hash->{UndefFn} = "energy_Undef"; $hash->{UndefFn} = "energy_Undef";
$hash->{GetFn} = "energy_Get"; $hash->{GetFn} = "energy_Get";
$hash->{StateFn} = "energy_State"; $hash->{StateFn} = "energy_State";
$hash->{SetFn} = "energy_Set"; $hash->{SetFn} = "energy_Set";
} }
sub sub
energy_State($$$$) energy_State($$$$)
{ {
my ($hash, $tim, $vt, $val) = @_; my ($hash, $tim, $vt, $val) = @_;
$hash->{READINGS}{$vt}{VAL} = $val; $hash->{READINGS}{$vt}{VAL} = $val;
$hash->{READINGS}{$vt}{TIME} = TimeNow(); $hash->{READINGS}{$vt}{TIME} = TimeNow();
Log3 $hash, 4, "energy_State: time: $tim name: $vt value: $val"; Log3 $hash, 4, "energy_State: time: $tim name: $vt value: $val";
return undef; return undef;
} }
sub sub
energy_Set($$$$) energy_Set($$$$)
{ {
my ($hash, $tim, $vt, $val) = @_; my ($hash, $tim, $vt, $val) = @_;
Log3 $hash, 4, "SET device: $tim name: $vt value: $val"; Log3 $hash, 4, "SET device: $tim name: $vt value: $val";
$hash->{READINGS}{$vt}{VAL} = $val; $hash->{READINGS}{$vt}{VAL} = $val;
$hash->{READINGS}{$vt}{TIME} = TimeNow(); $hash->{READINGS}{$vt}{TIME} = TimeNow();
if ( $vt eq "?"){ if ( $vt eq "?"){
return "Unknown argument ?, choose one of Interval"; return "Unknown argument ?, choose one of Interval";
} }
if ( $vt eq "Interval"){ if ( $vt eq "Interval"){
$hash->{Interval} = $val; $hash->{Interval} = $val;
} }
return undef; return undef;
} }
sub sub
energy_Define($$) energy_Define($$)
{ {
my ($hash, $def) = @_; my ($hash, $def) = @_;
my @args = split("[ \t]+", $def); my @args = split("[ \t]+", $def);
if (int(@args) < 3) if (int(@args) < 3)
{ {
return "energy_Define: too few arguments. Usage:\n" . return "energy_Define: too few arguments. Usage:\n" .
"define <name> EFR <host> [<interval> [<timeout>]]"; "define <name> EFR <host> [<interval> [<timeout>]]";
} }
my $name = $args[0]; my $name = $args[0];
$hash->{NAME} = $name; $hash->{NAME} = $name;
$hash->{Host} = $args[2]; $hash->{Host} = $args[2];
$hash->{Port} = 80; $hash->{Port} = 80;
$hash->{Interval} = int(@args) >= 4 ? int($args[3]) : 300; $hash->{Interval} = int(@args) >= 4 ? int($args[3]) : 300;
$hash->{Timeout} = int(@args) >= 5 ? int($args[4]) : 4; $hash->{Timeout} = int(@args) >= 5 ? int($args[4]) : 4;
Log3 $hash, 4, "$hash->{NAME} will read from EFR at $hash->{Host}:$hash->{Port} " ; Log3 $hash, 4, "$hash->{NAME} will read from EFR at $hash->{Host}:$hash->{Port} " ;
$hash->{Rereads} = 2; # number of retries when reading curPwr of 0 $hash->{Rereads} = 2; # number of retries when reading curPwr of 0
$hash->{UseSVTime} = ''; # use the SV time as timestamp (else: TimeNow()) $hash->{UseSVTime} = ''; # use the SV time as timestamp (else: TimeNow())
$hash->{STATE} = 'Initializing'; $hash->{STATE} = 'Initializing';
my $timenow = TimeNow(); my $timenow = TimeNow();
for my $get (@gets) for my $get (@gets)
{ {
$hash->{READINGS}{$get}{VAL} = -1 ; $hash->{READINGS}{$get}{VAL} = -1 ;
$hash->{READINGS}{$get}{TIME} = $timenow; $hash->{READINGS}{$get}{TIME} = $timenow;
} }
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{Interval}, "energy_Update", $hash, 0); InternalTimer(gettimeofday()+$hash->{Interval}, "energy_Update", $hash, 0);
Log3 $hash, 3, "$hash->{NAME} will read from EFR at $hash->{Host}:$hash->{Port} " ; Log3 $hash, 3, "$hash->{NAME} will read from EFR at $hash->{Host}:$hash->{Port} " ;
return undef; return undef;
} }
sub sub
energy_Update($) energy_Update($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $ip = $hash->{Host}; my $ip = $hash->{Host};
my $port = $hash->{Port}; my $port = $hash->{Port};
my $interval = $hash->{Interval}; my $interval = $hash->{Interval};
$hash->{helper}{RUNNING_PID} = BlockingCall("energy_DoUpdate", $name."|".$ip."|".$port."|".$interval, "energy_energyDone", 120, "energy_energyAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID})); $hash->{helper}{RUNNING_PID} = BlockingCall("energy_DoUpdate", $name."|".$ip."|".$port."|".$interval, "energy_energyDone", 120, "energy_energyAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
} }
sub sub
energy_DoUpdate($){ energy_DoUpdate($){
my ($string) = @_; my ($string) = @_;
my ($name, $ip, $port,$interval) = split("\\|", $string); my ($name, $ip, $port,$interval) = split("\\|", $string);
my $success = 0; my $success = 0;
my %readings = (); my %readings = ();
my $timenow = TimeNow(); my $timenow = TimeNow();
my $timeout = 10; my $timeout = 10;
my $counts = 0 ; my $counts = 0 ;
my $summary = 0 ; my $summary = 0 ;
my $url="/json.txt?LogName=user\&LogPSWD=user"; my $url="/json.txt?LogName=user\&LogPSWD=user";
#my $url="/efr/efr.txt"; #my $url="/efr/efr.txt";
my $socket ; my $socket ;
my $buf ; my $buf ;
my $message ; my $message ;
$socket = new IO::Socket::INET ( $socket = new IO::Socket::INET (
PeerAddr => $ip, PeerAddr => $ip,
PeerPort => $port, PeerPort => $port,
Proto => 'tcp', Proto => 'tcp',
Reuse => 0, Reuse => 0,
Timeout => $timeout Timeout => $timeout
); );
if (defined ($socket) and $socket and $socket->connected()) if (defined ($socket) and $socket and $socket->connected())
{ {
print $socket "GET $url HTTP/1.0\r\n\r\n"; print $socket "GET $url HTTP/1.0\r\n\r\n";
$socket->autoflush(1); $socket->autoflush(1);
while ((read $socket, $buf, 1024) > 0) while ((read $socket, $buf, 1024) > 0)
{ {
$message .= $buf; $message .= $buf;
} }
$socket->close(); $socket->close();
Log3 $name, 4, "Socket closed"; Log3 $name, 4, "Socket closed";
$success = 0; $success = 0;
}else{ }else{
Log3 $name, 3, "$name Cannot open socket ..."; Log3 $name, 3, "$name Cannot open socket ...";
$success = 1; $success = 1;
} }
$message = encode_base64($message,""); $message = encode_base64($message,"");
if ( $success == 0 ){ if ( $success == 0 ){
my $back = $name ."|". $message; my $back = $name ."|". $message;
return "$name|$message" ; return "$name|$message" ;
}else{ }else{
return "$name|-1"; return "$name|-1";
} }
} }
sub sub
energy_energyDone($) energy_energyDone($)
{ {
my ($string) = @_; my ($string) = @_;
return unless(defined($string)); return unless(defined($string));
my (@a) = split("\\|", $string); my (@a) = split("\\|", $string);
my $hash = $defs{$a[0]}; my $hash = $defs{$a[0]};
my $message = decode_base64($a[1]); my $message = decode_base64($a[1]);
my @array; my @array;
my $log = ""; my $log = "";
my $timenow = TimeNow(); my $timenow = TimeNow();
delete($hash->{helper}{RUNNING_PID}); delete($hash->{helper}{RUNNING_PID});
if(!$hash->{LOCAL}) { if(!$hash->{LOCAL}) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{Interval}, "energy_Update", $hash, 1); InternalTimer(gettimeofday()+$hash->{Interval}, "energy_Update", $hash, 1);
} }
if ($hash->{Interval} > 0) { if ($hash->{Interval} > 0) {
InternalTimer(gettimeofday() + $hash->{Interval}, "energy_Update", $hash, 0); InternalTimer(gettimeofday() + $hash->{Interval}, "energy_Update", $hash, 0);
} }
if ( $message ne "-1" ) if ( $message ne "-1" )
{ {
@array=split(/\{/,$message); @array=split(/\{/,$message);
my $powernow = $array[11]; my $powernow = $array[11];
$powernow =~ m/value":(.*),"unit":/; $powernow =~ m/value":(.*),"unit":/;
$powernow = $1; $powernow = $1;
$hash->{READINGS}{lastPower}{VAL} = $powernow; $hash->{READINGS}{lastPower}{VAL} = $powernow;
$hash->{READINGS}{lastPower}{TIME} = $timenow; $hash->{READINGS}{lastPower}{TIME} = $timenow;
my $powercounter = $array[10]; my $powercounter = $array[10];
$powercounter =~ m/value":(.*),"unit":/; $powercounter =~ m/value":(.*),"unit":/;
$powercounter = $1; $powercounter = $1;
$hash->{READINGS}{PowerTotal}{VAL} = $powercounter; $hash->{READINGS}{PowerTotal}{VAL} = $powercounter;
$hash->{READINGS}{PowerTotal}{TIME} = $timenow; $hash->{READINGS}{PowerTotal}{TIME} = $timenow;
my $powerU1 = $array[12]; my $powerU1 = $array[12];
$powerU1 =~ m/value":(.*),"unit":/; $powerU1 =~ m/value":(.*),"unit":/;
$powerU1 = $1; $powerU1 = $1;
$hash->{READINGS}{Power_L1}{VAL} = $powerU1; $hash->{READINGS}{Power_L1}{VAL} = $powerU1;
$hash->{READINGS}{Power_L1}{TIME} = $timenow; $hash->{READINGS}{Power_L1}{TIME} = $timenow;
my $powerU2 = $array[13]; my $powerU2 = $array[13];
$powerU2 =~ m/value":(.*),"unit":/; $powerU2 =~ m/value":(.*),"unit":/;
$powerU2 = $1; $powerU2 = $1;
$hash->{READINGS}{Power_L2}{VAL} = $powerU2; $hash->{READINGS}{Power_L2}{VAL} = $powerU2;
$hash->{READINGS}{Power_L2}{TIME} = $timenow; $hash->{READINGS}{Power_L2}{TIME} = $timenow;
my $powerU3 = $array[14]; my $powerU3 = $array[14];
$powerU3 =~ m/value":(.*),"unit":/; $powerU3 =~ m/value":(.*),"unit":/;
$powerU3 = $1; $powerU3 = $1;
$hash->{READINGS}{Power_L3}{VAL} = $powerU3; $hash->{READINGS}{Power_L3}{VAL} = $powerU3;
$hash->{READINGS}{Power_L3}{TIME} = $timenow; $hash->{READINGS}{Power_L3}{TIME} = $timenow;
$log = "PowerTotal: $powercounter lastPower: $powernow Power_L1: $powerU1 Power_L2: $powerU2 Power_L3: $powerU3"; $log = "PowerTotal: $powercounter lastPower: $powernow Power_L1: $powerU1 Power_L2: $powerU2 Power_L3: $powerU3";
push @{$hash->{CHANGED}}, $log; push @{$hash->{CHANGED}}, $log;
DoTrigger($hash->{NAME}, undef) if ($init_done); DoTrigger($hash->{NAME}, undef) if ($init_done);
Log3 $hash, 4, "$hash->{NAME} write log file: $log"; Log3 $hash, 4, "$hash->{NAME} write log file: $log";
if ( $hash->{STATE} eq 'Initializing' || $hash->{STATE} eq 'disconnected' ){ if ( $hash->{STATE} eq 'Initializing' || $hash->{STATE} eq 'disconnected' ){
$hash->{STATE} = 'Connected'; $hash->{STATE} = 'Connected';
} }
}else{ }else{
$hash->{STATE} = 'disconnected'; $hash->{STATE} = 'disconnected';
Log3 $hash, 3, "$hash->{NAME} can't update - device send a error"; Log3 $hash, 3, "$hash->{NAME} can't update - device send a error";
} }
Log3 $hash, 5, "$hash->{NAME} loop done " ; Log3 $hash, 5, "$hash->{NAME} loop done " ;
return undef; return undef;
} }
sub sub
energy_energyAborted($) energy_energyAborted($)
{ {
my ($hash) = @_; my ($hash) = @_;
Log3 $hash, 3, "$hash->{NAME} energy_energyAborted"; Log3 $hash, 3, "$hash->{NAME} energy_energyAborted";
delete($hash->{helper}{RUNNING_PID}); delete($hash->{helper}{RUNNING_PID});
} }
sub sub
energy_Get($@) energy_Get($@)
{ {
my ($hash, @args) = @_; my ($hash, @args) = @_;
return 'energy_Get needs two arguments' if (@args != 2); return 'energy_Get needs two arguments' if (@args != 2);
energy_Update($hash) unless $hash->{Interval}; energy_Update($hash) unless $hash->{Interval};
my $get = $args[1]; my $get = $args[1];
my $val = -1; my $val = -1;
if (defined($hash->{READINGS}{$get})) { if (defined($hash->{READINGS}{$get})) {
$val = $hash->{READINGS}{$get}{VAL}; $val = $hash->{READINGS}{$get}{VAL};
} else { } else {
return "energy_Get: no such reading: $get"; return "energy_Get: no such reading: $get";
} }
if ( $get eq "?"){ if ( $get eq "?"){
return "Unknown argument ?, choose one of lastPower PowerTotal Power_L1 Power_L2 Power_L3"; return "Unknown argument ?, choose one of lastPower PowerTotal Power_L1 Power_L2 Power_L3";
} }
Log3 $hash, 3, "$args[0] $get => $val"; Log3 $hash, 3, "$args[0] $get => $val";
return $val; return $val;
} }
sub sub
energy_Undef($$) energy_Undef($$)
{ {
my ($hash, $args) = @_; my ($hash, $args) = @_;
RemoveInternalTimer($hash) if $hash->{Interval}; RemoveInternalTimer($hash) if $hash->{Interval};
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID})); BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
return undef; return undef;
} }
1; 1;
=pod =pod
=begin html =begin html
<a name="EFR"></a> <a name="EFR"></a>
<h3>EFR</h3> <h3>EFR</h3>
<ul><p> <ul><p>
This module supports EFR Power Meter.<br> This module supports EFR Power Meter.<br>
The electricity meter will be polled in a defined interval for new values. The electricity meter will be polled in a defined interval for new values.
</p> </p>
<b>Define</b><br> <b>Define</b><br>
<code>define &lt;name&gt; EFR &lt;host&gt; &lt;port&gt; [&lt;interval&gt; &lt;timeout&gt;]</code><br> <code>define &lt;name&gt; EFR &lt;host&gt; &lt;port&gt; [&lt;interval&gt; &lt;timeout&gt;]</code><br>
<p> <p>
Example:<br> Example:<br>
define StromZ1 EFR 192.168.178.20 <br> define StromZ1 EFR 192.168.178.20 <br>
define StromZ2 EFR 192.168.10.25 300 60 <br> define StromZ2 EFR 192.168.10.25 300 60 <br>
</p> </p>
<b>Set</b><br> <b>Set</b><br>
set &lt;name&gt; &lt;value&gt; &lt;nummber&gt;<br>where value is one of:<br><br> set &lt;name&gt; &lt;value&gt; &lt;nummber&gt;<br>where value is one of:<br><br>
<ul> <ul>
<li><code>Interval</code> </li> <li><code>Interval</code> </li>
</ul> </ul>
<br>Example:<br> <br>Example:<br>
set &lt;name&gt; not implemented <br><br> set &lt;name&gt; not implemented <br><br>
<b>Get</b><br> <b>Get</b><br>
get &lt;name&gt; &lt;value&gt; <br>where value is one of:<br> get &lt;name&gt; &lt;value&gt; <br>where value is one of:<br>
<ul> <ul>
<li><code>lastPower </code></li> <li><code>lastPower </code></li>
<li><code>PowerTotal </code></li> <li><code>PowerTotal </code></li>
<li><code>Power_L1 </code></li> <li><code>Power_L1 </code></li>
<li><code>Power_L2 </code></li> <li><code>Power_L2 </code></li>
<li><code>Power_L3 </code></li> <li><code>Power_L3 </code></li>
<li><code>Interval </code> </li> <li><code>Interval </code> </li>
</ul> </ul>
<br>Example:<br> <br>Example:<br>
get &lt;name&gt; lastPower<br><br> get &lt;name&gt; lastPower<br><br>
</ul> </ul>
=end html =end html
=cut =cut