2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

Added modules ENECSYSGW and ENECSYSINV

git-svn-id: https://svn.fhem.de/fhem/trunk@5115 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
akw 2014-03-03 19:24:20 +00:00
parent efabf6338e
commit ed15c50a02
3 changed files with 389 additions and 0 deletions

208
fhem/FHEM/30_ENECSYSGW.pm Normal file
View File

@ -0,0 +1,208 @@
# 30_ENECSYSGW.pm
# ENECSYS Gateway Device
#
# (c) 2014 Arno Willig <akw@bytefeed.de>
#
# $Id$
package main;
use strict;
use warnings;
use POSIX;
use MIME::Base64;
use XML::Simple;
sub ENECSYSGW_Initialize($)
{
my ($hash) = @_;
# Provider
$hash->{ReadFn} = "ENECSYSGW_Read";
$hash->{WriteFn} = "ENECSYSGW_Read";
$hash->{Clients} = ":ENECSYSDevice:";
# Consumer
$hash->{DefFn} = "ENECSYSGW_Define";
$hash->{NOTIFYDEV} = "global";
$hash->{NotifyFn} = "ENECSYSGW_Notify";
$hash->{UndefFn} = "ENECSYSGW_Undefine";
$hash->{AttrList} = "disable:1";
}
sub ENECSYSGW_Read($@)
{
my ($hash,$name,$id,$obj)= @_;
return ENECSYSGW_Call($hash);
}
sub ENECSYSGW_Define($$)
{
my ($hash, $def) = @_;
my @args = split("[ \t]+", $def);
return "Usage: define <name> ENECSYSGW <host> [interval]" if(@args < 3);
my ($name, $type, $host, $interval) = @args;
$interval = 10 unless defined($interval);
if ($interval < 5) { $interval = 5; }
$hash->{STATE} = 'Initialized';
$hash->{Host} = $host;
$hash->{INTERVAL} = $interval;
$hash->{Clients} = ":ENECSYSINV:";
my %matchList = ( "1:ENECSYSINV" => ".*" );
$hash->{MatchList} = \%matchList;
if( $init_done ) {
ENECSYSGW_OpenDev( $hash ) if( !AttrVal($name, "disable", 0) );
}
return undef;
}
sub ENECSYSGW_Notify($$)
{
my ($hash,$dev) = @_;
my $name = $hash->{NAME};
my $type = $hash->{TYPE};
return if($dev->{NAME} ne "global");
return if(!grep(m/^INITIALIZED|REREADCFG$/, @{$dev->{CHANGED}}));
return undef if( AttrVal($name, "disable", 0) );
ENECSYSGW_OpenDev($hash);
return undef;
}
sub ENECSYSGW_Undefine($$)
{
my ($hash,$arg) = @_;
RemoveInternalTimer($hash);
return undef;
}
sub ENECSYSGW_OpenDev($)
{
my ($hash) = @_;
$hash->{STATE} = 'Connected';
ENECSYSGW_GetUpdate($hash);
return undef;
}
sub ENECSYSGW_GetUpdate($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
if(!$hash->{LOCAL}) {
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "ENECSYSGW_GetUpdate", $hash, 0);
}
ENECSYSGW_Call($hash);
}
sub ENECSYSGW_Call($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
return undef if($attr{$name} && $attr{$name}{disable});
my $URL = "http://" . $hash->{Host} . "/ajax.xml";
my $ret = GetFileFromURL($URL, 5, undef, 1 );
if( !defined($ret) ) {
return undef;
} elsif($ret eq '') {
return undef;
} elsif($ret =~ /^error:(\d){3}$/) {
return "HTTP Error Code " . $1;
}
my $parser = new XML::Simple;
my $data = $parser->XMLin($ret,SuppressEmpty => 1);
my $rmsg = $data->{zigbeeData};
my $ConnectionStatus = $data->{connectionStatus};
my $ConnectionUptime = $data->{connectionUptime};
my $devicesInNetwork = $data->{devicesInNetwork};
my $timeSinceReset = $data->{timeSinceReset};
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"ConnectionStatus",$ConnectionStatus);
readingsBulkUpdate($hash,"ConnectionUptime",$ConnectionUptime);
readingsBulkUpdate($hash,"devicesInNetwork",$devicesInNetwork);
readingsBulkUpdate($hash,"timeSinceReset",$timeSinceReset);
readingsEndUpdate($hash, 1);
# Testing $rmsg = "WS=F4_3BQCaxjQAABMIIQEAAAIrFDADiAAAEAANAywyAOUOApsBJAAAB8";
return undef unless defined $rmsg;
$rmsg =~ s/\r//g;
$rmsg =~ s/\n//g;
$rmsg =~ s/_/\//g;
$rmsg =~ s/-/+/g;
readingsSingleUpdate($hash,"rawReading",$rmsg,1);
if ($rmsg =~ /^WS/ && length($rmsg)==57) {
$rmsg = unpack('H*', decode_base64(substr($rmsg,3,54))).'A';
Log3 $name, 4, "$name: Zigbee raw: $rmsg";
my $serial = hex(unpack("H*", pack("V*", unpack("N*", pack("H*", substr($rmsg,0,8))))));
my $dmsg = $rmsg;
Log3 $name, 4, "$name: $dmsg";
$hash->{"${name}_MSGCNT"}++;
$hash->{"${name}_TIME"} = TimeNow();
$hash->{RAWMSG} = $rmsg;
my %addvals = (RAWMSG => $rmsg);
Dispatch($hash, $dmsg, \%addvals);
}
if ($rmsg =~ /^WS/ && length($rmsg)!=57) { # other inverter strings (startup?)
Log3 $name, 4, "$name: Zigbee unknown data";
}
if ($rmsg =~ /^WZ/) { # gateway data
Log3 $name, 4, "$name: Zigbee gateway data";
}
return undef;
}
1;
=pod
=begin html
<a name="ENECSYSGW"></a>
<h3>ENECSYSGW</h3>
<ul>
Module to access the ENECSYS gateway (http://www.ENECSYS.com/products/gateway/).<br><br>
The actual micro-inverter devices are defined as <a href="#ENECSYSINV">ENECSYSINV</a> devices.
<br><br>
All newly found inverter devices are autocreated and added to the room ENECSYSINV.
<br><br>
<a name="ENECSYSGW_Define"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; ENECSYSGW [&lt;host&gt;] [&lt;interval&gt;]</code><br>
<br>
Defines an ENECSYSGW device with address &lt;host&gt;.<br><br>
The gateway will be polled every &lt;interval&gt; seconds. The default is 10 and minimum is 5.<br><br>
Examples:
<ul>
<code>define gateway ENECSYSGW 10.0.1.1</code><br>
</ul>
</ul><br>
</ul><br>
=end html
=cut

179
fhem/FHEM/31_ENECSYSINV.pm Normal file
View File

@ -0,0 +1,179 @@
# 30_ENECSYSINV.pm
# ENECSYS Inverter Device
#
# (c) 2014 Arno Willig <akw@bytefeed.de>
#
# $Id$
package main;
use strict;
use warnings;
use POSIX;
use SetExtensions;
sub ENECSYSINV_Initialize($)
{
my ($hash) = @_;
# Provider
# Consumer
$hash->{Match} = ".*";
$hash->{DefFn} = "ENECSYSINV_Define";
$hash->{UndefFn} = "ENECSYSINV_Undefine";
$hash->{ParseFn} = "ENECSYSINV_Parse";
$hash->{AttrList} = "IODev ".$readingFnAttributes;
$hash->{AutoCreate} = {
"ENECSYSINV.*" => {
GPLOT => "power4:Power,",
FILTER => "%NAME:dcpower:.*"
#ATTR => "event-min-interval:dcpower:120"
}
};
}
sub ENECSYSINV_Define($$)
{
my ($hash, $def) = @_;
my @args = split("[ \t]+", $def);
my $iodev;
my $i = 0;
foreach my $param ( @args ) {
if ($param =~ m/IODev=(.*)/) {
$iodev = $1;
splice( @args, $i, 1 );
last;
}
$i++;
}
return "Usage: define <name> ENECSYSINV <serial>" if(@args < 3);
my ($name, $type, $code, $interval) = @args;
$hash->{STATE} = 'Initialized';
$hash->{CODE} = $code;
AssignIoPort($hash,$iodev) if (!$hash->{IODev});
if(defined($hash->{IODev}->{NAME})) {
Log3 $name, 3, "$name: I/O device is " . $hash->{IODev}->{NAME};
} else {
Log3 $name, 1, "$name: no I/O device";
}
$modules{ENECSYSINV}{defptr}{$code} = $hash;
return undef;
}
sub ENECSYSINV_Undefine($$)
{
my ($hash,$arg) = @_;
my $code = $hash->{ID};
$code = $hash->{IODev}->{NAME} ."-". $code if( defined($hash->{IODev}->{NAME}) );
delete($modules{ENECSYSINV}{defptr}{$code});
return undef;
}
sub ENECSYSINV_Parse($$)
{
my ($iodev, $msg, $local) = @_;
my $ioName = $iodev->{NAME};
my $serial = hex(unpack("H*", pack("V*", unpack("N*", pack("H*", substr($msg,0,8))))));
my $hash = $modules{ENECSYSINV}{defptr}{$serial};
if(!$hash) {
my $ret = "UNDEFINED ENECSYSINV_$serial ENECSYSINV $serial";
Log3 $ioName, 3, "$ret, please define it";
DoTrigger("global", $ret);
return "";
}
foreach my $mod (keys %{$modules{ENECSYSINV}{defptr}}) {
my $hash = $modules{ENECSYSINV}{defptr}{"$mod"};
if ($hash && $hash->{CODE} == $serial) {
my $time1 = hex(substr($msg,18,4));
my $time2 = hex(substr($msg,30,6));
my $dcCurrent = 0.025*hex(substr($msg,46,4)); #25 mA units?
my $dcPower = hex(substr($msg,50,4));
my $efficiency = 0.001*hex(substr($msg,54,4));
my $acFreq = hex(substr($msg,58,2));
my $acVolt = hex(substr($msg,60,4));
my $temperature = hex(substr($msg,64,2));
my $lifekWh = (0.001*hex(substr($msg,66,4)))+hex(substr($msg,70,4));
my $acPower = $dcPower * $efficiency;
my $dcVolt = sprintf("%0.2f",$dcPower / $dcCurrent);
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"dccurrent",$dcCurrent);
readingsBulkUpdate($hash,"dcpower",$dcPower);
readingsBulkUpdate($hash,"dcvolt",$dcVolt);
readingsBulkUpdate($hash,"acfrequency",$acFreq);
readingsBulkUpdate($hash,"acvolt",$acVolt);
readingsBulkUpdate($hash,"acpower",$acPower);
readingsBulkUpdate($hash,"lifetime",$lifekWh);
readingsBulkUpdate($hash,"efficiency",$efficiency);
readingsBulkUpdate($hash,"temperature",$temperature);
readingsBulkUpdate($hash,"state",$dcPower);
readingsEndUpdate($hash, 1);
return $hash->{NAME};
}
}
}
1;
=pod
=begin html
<a name="ENECSYSINV"></a>
<h3>ENECSYSINV</h3>
<ul>
<br>
<a name="ENECSYSINV_Define"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; ENECSYSINV &lt;id&gt; [&lt;interval&gt;]</code><br>
<br>
Defines an micro-inverter device connected to an <a href="#ENECSYSGW">ENECSYSGW</a>.<br><br>
Examples:
<ul>
<code>define SolarPanel1 ENECSYSINV 100123456</code><br>
</ul>
</ul><br>
<a name="ENECSYSINV_Readings"></a>
<b>Readings</b>
<ul>
<li>acfrequency<br />
the alternating current frequency reported from the device. Should be around 50 Hz in Europe.</li>
<li>acpower<br />
the alternating current power</li>
<li>acvolt<br />
the alternating current voltage</li>
<li>dccurrent<br />
the direct current</li>
<li>dcpower<br />
the direct current power</li>
<li>dcvolt<br />
the direct current voltage</li>
<li>efficiency<br />
the efficiency of the inverter</li>
<li>lifetime<br />
the sum of collected energy of the inverter</li>
<li>temperature<br />
the temperature of the inverter</li>
<li>state<br />
the current state (equal to dcpower) </li>
</ul><br />
</ul><br>
=end html
=cut

View File

@ -87,7 +87,9 @@ FHEM/23_WEBIO_12DIGITAL.pm sachag http://forum.fhem.de Sonstiges
FHEM/23_WEBTHERM.pm betateilchen/sachag http://forum.fhem.de Sonstiges
FHEM/24_NetIO230B.pm rudolfkoenig/orphan http://forum.fhem.de Sonstiges
FHEM/30_HUEBridge.pm justme1968 http://forum.fhem.de Sonstige Systeme
FHEM/30_ENECSYSGW.pm akw http://forum.fhem.de Sonstige Systeme
FHEM/31_HUEDevice.pm justme1968 http://forum.fhem.de Sonstige Systeme
FHEM/31_ENECSYSINV.pm akw http://forum.fhem.de Sonstige Systeme
FHEM/31_LightScene.pm justme1968 http://forum.fhem.de Automatisierung
FHEM/32_SYSSTAT.pm justme1968 http://forum.fhem.de Unterstuetzende Dienste
FHEM/32_mailcheck.pm justme1968 http://forum.fhem.de Automatisierung