| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- # 30_ENECSYSGW.pm
- # ENECSYS Gateway Device
- #
- # (c) 2014 Arno Willig <akw@bytefeed.de>
- #
- # $Id: 30_ENECSYSGW.pm 5117 2014-03-03 19:33:15Z akw $
- 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 <name> ENECSYSGW [<host>] [<interval>]</code><br />
- <br />
- Defines an ENECSYSGW device with address <host>.<br /><br />
- The gateway will be polled every <interval> 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
|