30_ENECSYSGW.pm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. # 30_ENECSYSGW.pm
  2. # ENECSYS Gateway Device
  3. #
  4. # (c) 2014 Arno Willig <akw@bytefeed.de>
  5. #
  6. # $Id: 30_ENECSYSGW.pm 5117 2014-03-03 19:33:15Z akw $
  7. package main;
  8. use strict;
  9. use warnings;
  10. use POSIX;
  11. use MIME::Base64;
  12. use XML::Simple;
  13. sub ENECSYSGW_Initialize($)
  14. {
  15. my ($hash) = @_;
  16. # Provider
  17. $hash->{ReadFn} = "ENECSYSGW_Read";
  18. $hash->{WriteFn} = "ENECSYSGW_Read";
  19. $hash->{Clients} = ":ENECSYSDevice:";
  20. # Consumer
  21. $hash->{DefFn} = "ENECSYSGW_Define";
  22. $hash->{NOTIFYDEV} = "global";
  23. $hash->{NotifyFn} = "ENECSYSGW_Notify";
  24. $hash->{UndefFn} = "ENECSYSGW_Undefine";
  25. $hash->{AttrList} = "disable:1";
  26. }
  27. sub ENECSYSGW_Read($@)
  28. {
  29. my ($hash,$name,$id,$obj)= @_;
  30. return ENECSYSGW_Call($hash);
  31. }
  32. sub ENECSYSGW_Define($$)
  33. {
  34. my ($hash, $def) = @_;
  35. my @args = split("[ \t]+", $def);
  36. return "Usage: define <name> ENECSYSGW <host> [interval]" if(@args < 3);
  37. my ($name, $type, $host, $interval) = @args;
  38. $interval = 10 unless defined($interval);
  39. if ($interval < 5) { $interval = 5; }
  40. $hash->{STATE} = 'Initialized';
  41. $hash->{Host} = $host;
  42. $hash->{INTERVAL} = $interval;
  43. $hash->{Clients} = ":ENECSYSINV:";
  44. my %matchList = ( "1:ENECSYSINV" => ".*" );
  45. $hash->{MatchList} = \%matchList;
  46. if( $init_done ) {
  47. ENECSYSGW_OpenDev( $hash ) if( !AttrVal($name, "disable", 0) );
  48. }
  49. return undef;
  50. }
  51. sub ENECSYSGW_Notify($$)
  52. {
  53. my ($hash,$dev) = @_;
  54. my $name = $hash->{NAME};
  55. my $type = $hash->{TYPE};
  56. return if($dev->{NAME} ne "global");
  57. return if(!grep(m/^INITIALIZED|REREADCFG$/, @{$dev->{CHANGED}}));
  58. return undef if( AttrVal($name, "disable", 0) );
  59. ENECSYSGW_OpenDev($hash);
  60. return undef;
  61. }
  62. sub ENECSYSGW_Undefine($$)
  63. {
  64. my ($hash,$arg) = @_;
  65. RemoveInternalTimer($hash);
  66. return undef;
  67. }
  68. sub ENECSYSGW_OpenDev($)
  69. {
  70. my ($hash) = @_;
  71. $hash->{STATE} = 'Connected';
  72. ENECSYSGW_GetUpdate($hash);
  73. return undef;
  74. }
  75. sub ENECSYSGW_GetUpdate($)
  76. {
  77. my ($hash) = @_;
  78. my $name = $hash->{NAME};
  79. if(!$hash->{LOCAL}) {
  80. RemoveInternalTimer($hash);
  81. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "ENECSYSGW_GetUpdate", $hash, 0);
  82. }
  83. ENECSYSGW_Call($hash);
  84. }
  85. sub ENECSYSGW_Call($)
  86. {
  87. my ($hash) = @_;
  88. my $name = $hash->{NAME};
  89. return undef if($attr{$name} && $attr{$name}{disable});
  90. my $URL = "http://" . $hash->{Host} . "/ajax.xml";
  91. my $ret = GetFileFromURL($URL, 5, undef, 1 );
  92. if( !defined($ret) ) {
  93. return undef;
  94. } elsif($ret eq '') {
  95. return undef;
  96. } elsif($ret =~ /^error:(\d){3}$/) {
  97. return "HTTP Error Code " . $1;
  98. }
  99. my $parser = new XML::Simple;
  100. my $data = $parser->XMLin($ret,SuppressEmpty => 1);
  101. my $rmsg = $data->{zigbeeData};
  102. my $ConnectionStatus = $data->{connectionStatus};
  103. my $ConnectionUptime = $data->{connectionUptime};
  104. my $devicesInNetwork = $data->{devicesInNetwork};
  105. my $timeSinceReset = $data->{timeSinceReset};
  106. readingsBeginUpdate($hash);
  107. readingsBulkUpdate($hash,"ConnectionStatus",$ConnectionStatus);
  108. readingsBulkUpdate($hash,"ConnectionUptime",$ConnectionUptime);
  109. readingsBulkUpdate($hash,"devicesInNetwork",$devicesInNetwork);
  110. readingsBulkUpdate($hash,"timeSinceReset",$timeSinceReset);
  111. readingsEndUpdate($hash, 1);
  112. # Testing $rmsg = "WS=F4_3BQCaxjQAABMIIQEAAAIrFDADiAAAEAANAywyAOUOApsBJAAAB8";
  113. return undef unless defined $rmsg;
  114. $rmsg =~ s/\r//g;
  115. $rmsg =~ s/\n//g;
  116. $rmsg =~ s/_/\//g;
  117. $rmsg =~ s/-/+/g;
  118. readingsSingleUpdate($hash,"rawReading",$rmsg,1);
  119. if ($rmsg =~ /^WS/ && length($rmsg)==57) {
  120. $rmsg = unpack('H*', decode_base64(substr($rmsg,3,54))).'A';
  121. Log3 $name, 4, "$name: Zigbee raw: $rmsg";
  122. my $serial = hex(unpack("H*", pack("V*", unpack("N*", pack("H*", substr($rmsg,0,8))))));
  123. my $dmsg = $rmsg;
  124. Log3 $name, 4, "$name: $dmsg";
  125. $hash->{"${name}_MSGCNT"}++;
  126. $hash->{"${name}_TIME"} = TimeNow();
  127. $hash->{RAWMSG} = $rmsg;
  128. my %addvals = (RAWMSG => $rmsg);
  129. Dispatch($hash, $dmsg, \%addvals);
  130. }
  131. if ($rmsg =~ /^WS/ && length($rmsg)!=57) { # other inverter strings (startup?)
  132. Log3 $name, 4, "$name: Zigbee unknown data";
  133. }
  134. if ($rmsg =~ /^WZ/) { # gateway data
  135. Log3 $name, 4, "$name: Zigbee gateway data";
  136. }
  137. return undef;
  138. }
  139. 1;
  140. =pod
  141. =begin html
  142. <a name="ENECSYSGW"></a>
  143. <h3>ENECSYSGW</h3>
  144. <ul>
  145. Module to access the ENECSYS gateway (http://www.ENECSYS.com/products/gateway/).<br /><br />
  146. The actual micro-inverter devices are defined as <a href="#ENECSYSINV">ENECSYSINV</a> devices.
  147. <br /><br />
  148. All newly found inverter devices are autocreated and added to the room ENECSYSINV.
  149. <br /><br />
  150. <a name="ENECSYSGW_Define"></a>
  151. <b>Define</b>
  152. <ul>
  153. <code>define &lt;name&gt; ENECSYSGW [&lt;host&gt;] [&lt;interval&gt;]</code><br />
  154. <br />
  155. Defines an ENECSYSGW device with address &lt;host&gt;.<br /><br />
  156. The gateway will be polled every &lt;interval&gt; seconds. The default is 10 and minimum is 5.<br /><br />
  157. Examples:
  158. <ul>
  159. <code>define gateway ENECSYSGW 10.0.1.1</code><br />
  160. </ul>
  161. </ul><br />
  162. </ul><br />
  163. =end html
  164. =cut