31_ENECSYSINV.pm 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # 30_ENECSYSINV.pm
  2. # ENECSYS Inverter Device
  3. #
  4. # (c) 2014 Arno Willig <akw@bytefeed.de>
  5. #
  6. # $Id: 31_ENECSYSINV.pm 5117 2014-03-03 19:33:15Z akw $
  7. package main;
  8. use strict;
  9. use warnings;
  10. use POSIX;
  11. use SetExtensions;
  12. sub ENECSYSINV_Initialize($)
  13. {
  14. my ($hash) = @_;
  15. # Provider
  16. # Consumer
  17. $hash->{Match} = ".*";
  18. $hash->{DefFn} = "ENECSYSINV_Define";
  19. $hash->{UndefFn} = "ENECSYSINV_Undefine";
  20. $hash->{ParseFn} = "ENECSYSINV_Parse";
  21. $hash->{AttrList} = "IODev ".$readingFnAttributes;
  22. $hash->{AutoCreate} = {
  23. "ENECSYSINV.*" => {
  24. GPLOT => "power4:Power,",
  25. FILTER => "%NAME:dcpower:.*"
  26. #ATTR => "event-min-interval:dcpower:120"
  27. }
  28. };
  29. }
  30. sub ENECSYSINV_Define($$)
  31. {
  32. my ($hash, $def) = @_;
  33. my @args = split("[ \t]+", $def);
  34. my $iodev;
  35. my $i = 0;
  36. foreach my $param ( @args ) {
  37. if ($param =~ m/IODev=(.*)/) {
  38. $iodev = $1;
  39. splice( @args, $i, 1 );
  40. last;
  41. }
  42. $i++;
  43. }
  44. return "Usage: define <name> ENECSYSINV <serial>" if(@args < 3);
  45. my ($name, $type, $code, $interval) = @args;
  46. $hash->{STATE} = 'Initialized';
  47. $hash->{CODE} = $code;
  48. AssignIoPort($hash,$iodev) if (!$hash->{IODev});
  49. if(defined($hash->{IODev}->{NAME})) {
  50. Log3 $name, 3, "$name: I/O device is " . $hash->{IODev}->{NAME};
  51. } else {
  52. Log3 $name, 1, "$name: no I/O device";
  53. }
  54. $modules{ENECSYSINV}{defptr}{$code} = $hash;
  55. return undef;
  56. }
  57. sub ENECSYSINV_Undefine($$)
  58. {
  59. my ($hash,$arg) = @_;
  60. my $code = $hash->{ID};
  61. $code = $hash->{IODev}->{NAME} ."-". $code if( defined($hash->{IODev}->{NAME}) );
  62. delete($modules{ENECSYSINV}{defptr}{$code});
  63. return undef;
  64. }
  65. sub ENECSYSINV_Parse($$)
  66. {
  67. my ($iodev, $msg, $local) = @_;
  68. my $ioName = $iodev->{NAME};
  69. my $serial = hex(unpack("H*", pack("V*", unpack("N*", pack("H*", substr($msg,0,8))))));
  70. my $hash = $modules{ENECSYSINV}{defptr}{$serial};
  71. if(!$hash) {
  72. my $ret = "UNDEFINED ENECSYSINV_$serial ENECSYSINV $serial";
  73. Log3 $ioName, 3, "$ret, please define it";
  74. DoTrigger("global", $ret);
  75. return "";
  76. }
  77. foreach my $mod (keys %{$modules{ENECSYSINV}{defptr}}) {
  78. my $hash = $modules{ENECSYSINV}{defptr}{"$mod"};
  79. if ($hash && $hash->{CODE} == $serial) {
  80. my $time1 = hex(substr($msg,18,4));
  81. my $time2 = hex(substr($msg,30,6));
  82. my $dcCurrent = 0.025*hex(substr($msg,46,4)); #25 mA units?
  83. my $dcPower = hex(substr($msg,50,4));
  84. my $efficiency = 0.001*hex(substr($msg,54,4));
  85. my $acFreq = hex(substr($msg,58,2));
  86. my $acVolt = hex(substr($msg,60,4));
  87. my $temperature = hex(substr($msg,64,2));
  88. my $lifekWh = (0.001*hex(substr($msg,66,4)))+hex(substr($msg,70,4));
  89. my $acPower = $dcPower * $efficiency;
  90. my $dcVolt = sprintf("%0.2f",$dcPower / $dcCurrent);
  91. readingsBeginUpdate($hash);
  92. readingsBulkUpdate($hash,"dccurrent",$dcCurrent);
  93. readingsBulkUpdate($hash,"dcpower",$dcPower);
  94. readingsBulkUpdate($hash,"dcvolt",$dcVolt);
  95. readingsBulkUpdate($hash,"acfrequency",$acFreq);
  96. readingsBulkUpdate($hash,"acvolt",$acVolt);
  97. readingsBulkUpdate($hash,"acpower",$acPower);
  98. readingsBulkUpdate($hash,"lifetime",$lifekWh);
  99. readingsBulkUpdate($hash,"efficiency",$efficiency);
  100. readingsBulkUpdate($hash,"temperature",$temperature);
  101. readingsBulkUpdate($hash,"state",$dcPower);
  102. readingsEndUpdate($hash, 1);
  103. return $hash->{NAME};
  104. }
  105. }
  106. }
  107. 1;
  108. =pod
  109. =begin html
  110. <a name="ENECSYSINV"></a>
  111. <h3>ENECSYSINV</h3>
  112. <ul>
  113. <br />
  114. <a name="ENECSYSINV_Define"></a>
  115. <b>Define</b>
  116. <ul>
  117. <code>define &lt;name&gt; ENECSYSINV &lt;id&gt; [&lt;interval&gt;]</code><br />
  118. <br />
  119. Defines an micro-inverter device connected to an <a href="#ENECSYSGW">ENECSYSGW</a>.<br /><br />
  120. Examples:
  121. <ul>
  122. <code>define SolarPanel1 ENECSYSINV 100123456</code><br />
  123. </ul>
  124. </ul><br />
  125. <a name="ENECSYSINV_Readings"></a>
  126. <b>Readings</b>
  127. <ul>
  128. <li>acfrequency<br />
  129. the alternating current frequency reported from the device. Should be around 50 Hz in Europe.</li>
  130. <li>acpower<br />
  131. the alternating current power</li>
  132. <li>acvolt<br />
  133. the alternating current voltage</li>
  134. <li>dccurrent<br />
  135. the direct current</li>
  136. <li>dcpower<br />
  137. the direct current power</li>
  138. <li>dcvolt<br />
  139. the direct current voltage</li>
  140. <li>efficiency<br />
  141. the efficiency of the inverter</li>
  142. <li>lifetime<br />
  143. the sum of collected energy of the inverter</li>
  144. <li>temperature<br />
  145. the temperature of the inverter</li>
  146. <li>state<br />
  147. the current state (equal to dcpower) </li>
  148. </ul><br />
  149. </ul><br />
  150. =end html
  151. =cut