63_EMGZ.pm 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. ##############################################
  2. # $Id: 63_EMGZ.pm 11984 2016-08-19 12:47:50Z rudolfkoenig $
  3. package main;
  4. use strict;
  5. use warnings;
  6. use Time::HiRes qw(gettimeofday);
  7. sub EMGZ_Get($@);
  8. sub EMGZ_Set($@);
  9. sub EMGZ_Define($$);
  10. sub EMGZ_GetStatus($);
  11. ###################################
  12. sub
  13. EMGZ_Initialize($)
  14. {
  15. my ($hash) = @_;
  16. $hash->{GetFn} = "EMGZ_Get";
  17. $hash->{SetFn} = "EMGZ_Set";
  18. $hash->{DefFn} = "EMGZ_Define";
  19. $hash->{AttrList} = "IODev dummy:1,0 model:EM1000GZ";
  20. }
  21. ###################################
  22. sub
  23. EMGZ_GetStatus($)
  24. {
  25. my ($hash) = @_;
  26. if(!$hash->{LOCAL}) {
  27. InternalTimer(gettimeofday()+300, "EMGZ_GetStatus", $hash, 0);
  28. }
  29. my $dnr = $hash->{DEVNR};
  30. my $name = $hash->{NAME};
  31. return "Empty status: dummy IO device" if(IsIoDummy($name));
  32. my $d = IOWrite($hash, sprintf("7a%02x", $dnr-1));
  33. if(!defined($d)) {
  34. my $msg = "EMGZ $name read error (GetStatus 1)";
  35. Log3 $name, 2, $msg;
  36. return $msg;
  37. }
  38. if($d eq ((pack('H*',"00") x 45) . pack('H*',"FF") x 6)) {
  39. my $msg = "EMGZ no device no. $dnr present";
  40. Log3 $name, 2, $msg;
  41. return $msg;
  42. }
  43. my $pulses=w($d,13);
  44. my $ec = 100; # fixed value
  45. my $cur_energy = $pulses / $ec; # ec = U/m^3
  46. my $cur_power = $cur_energy / 5 * 60; # 5minute interval scaled to 1h
  47. if($cur_power > 30) { # depending on "Anschlussleistung"
  48. my $msg = "EMGZ Bogus reading: curr. power is reported to be $cur_power";
  49. Log3 $name, 2, $msg;
  50. return $msg;
  51. }
  52. my %vals;
  53. $vals{"5min_pulses"} = $pulses;
  54. $vals{"act_flow_m3"} = sprintf("%0.3f", $cur_energy);
  55. $vals{"m3ph"} = sprintf("%.3f", $cur_power);
  56. $vals{"alarm_PA"} = w($d,45) . " Watt"; # nonsens
  57. $vals{"price_CF"} = sprintf("%.3f", w($d,47)/10000);
  58. $vals{"Rperm3_EC"} = $ec;
  59. $hash->{READINGS}{cum_m3}{VAL} = 0 if(!$hash->{READINGS}{cum_m3}{VAL});
  60. $vals{"cum_m3"} = sprintf("%0.3f",
  61. $hash->{READINGS}{cum_m3}{VAL} + $vals{"act_flow_m3"});
  62. my $tn = TimeNow();
  63. my $idx = 0;
  64. foreach my $k (keys %vals) {
  65. my $v = $vals{$k};
  66. $hash->{CHANGED}[$idx++] = "$k: $v";
  67. $hash->{READINGS}{$k}{TIME} = $tn;
  68. $hash->{READINGS}{$k}{VAL} = $v
  69. }
  70. if(!$hash->{LOCAL}) {
  71. DoTrigger($name, undef) if($init_done);
  72. }
  73. $hash->{STATE} = "$cur_power m3ph";
  74. Log3 $name, 4, "EMGZ $name: $cur_power m3ph / $vals{act_flow_m3}";
  75. return $hash->{STATE};
  76. }
  77. ###################################
  78. sub
  79. EMGZ_Get($@)
  80. {
  81. my ($hash, @a) = @_;
  82. my $d = $hash->{DEVNR};
  83. my $msg;
  84. if($a[1] ne "status" && int(@a) != 2) {
  85. return "unknown argument $a[1], choose one of status";
  86. }
  87. $hash->{LOCAL} = 1;
  88. my $v = EMGZ_GetStatus($hash);
  89. delete $hash->{LOCAL};
  90. return "$a[0] $a[1] => $v";
  91. }
  92. sub
  93. EMGZ_Set($@)
  94. {
  95. my ($hash, @a) = @_;
  96. my $name = $hash->{NAME};
  97. my $v = $a[2];
  98. my $d = $hash->{DEVNR};
  99. my $msg;
  100. if($a[1] eq "price" && int(@a) != 3) {
  101. $v *= 10000; # Make display and input the same
  102. $msg = sprintf("79%02x2f02%02x%02x", $d-1, $v%256, int($v/256));
  103. } else {
  104. return "Unknown argument $a[1], choose one of price";
  105. }
  106. return "" if(IsIoDummy($name));
  107. my $ret = IOWrite($hash, $msg);
  108. if(!defined($ret)) {
  109. $msg = "EMWZ $name read error (Set)";
  110. Log3 $name, 2, $msg;
  111. return $msg;
  112. }
  113. if(ord(substr($ret,0,1)) != 6) {
  114. $ret = "EMGZ Error occured: " . unpack('H*', $ret);
  115. Log3 $name, 2, $ret;
  116. return $ret;
  117. }
  118. return undef;
  119. }
  120. #############################
  121. sub
  122. EMGZ_Define($$)
  123. {
  124. my ($hash, $def) = @_;
  125. my @a = split("[ \t][ \t]*", $def);
  126. return "syntax: define <name> EMGZ devicenumber"
  127. if(@a != 3 || $a[2] !~ m,^[9]$,);
  128. $hash->{DEVNR} = $a[2];
  129. AssignIoPort($hash);
  130. EMGZ_GetStatus($hash);
  131. return undef;
  132. }
  133. 1;
  134. =pod
  135. =item summary EM1000GZ devices communicating over the EM1010PC
  136. =item summary_DE EM1000GZ Ger&auml;te angebunden &uuml;ber ein EM1010PC
  137. =begin html
  138. <a name="EMGZ"></a>
  139. <h3>EMGZ</h3>
  140. <ul>
  141. <a name="EMGZdefine"></a>
  142. <b>Define</b>
  143. <ul>
  144. <code>define &lt;name&gt; EMGZ &lt;device-number&gt;</code>
  145. <br><br>
  146. Define up to 4 EM1000GZ attached to the EM1010PC. The device number must
  147. be between 9 and 12.
  148. Defining an EMGZ will schedule an internal task, which reads the
  149. status of the device every 5 minutes, and triggers notify/filelog commands.
  150. <br><br>
  151. Example:
  152. <ul>
  153. <code>define emgz EMGZ 9</code><br>
  154. </ul>
  155. </ul>
  156. <a name="EMGZset"></a>
  157. <b>Set</b>
  158. <ul>
  159. <code>set EMGZdevice &lt;param&gt; &lt;value&gt;</code><br><br>
  160. where param is:
  161. <ul>
  162. <li>price<br>
  163. The price of one KW in EURO (use e.g. 0.20 for 20 Cents). It is used
  164. only on the EM1010PC display, it is of no interest for FHEM.</li>
  165. </ul>
  166. </ul>
  167. <br>
  168. <a name="EMGZget"></a>
  169. <b>Get</b>
  170. <ul>
  171. <code>get EMGZ status</code>
  172. <br><br>
  173. This is the same command which is scheduled every 5 minutes internally.
  174. </ul>
  175. <br>
  176. <a name="EMGZattr"></a>
  177. <b>Attributes</b>
  178. <ul>
  179. <li><a href="#model">model</a> (EM1000GZ)</li>
  180. <li><a href="#attrdummy">dummy</a></li>
  181. <li><a href="#IODev">IODev</a></li><br>
  182. </ul>
  183. <br>
  184. </ul>
  185. =end html
  186. =cut