14_SD_WS07.pm 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. ##############################################
  2. # $Id: 14_SD_WS07.pm 13215 2017-01-23 20:09:44Z Sidey $
  3. #
  4. # The purpose of this module is to support serval eurochron
  5. # weather sensors like eas8007 which use the same protocol
  6. # Sidey79 & Ralf9 2015-2016
  7. #
  8. package main;
  9. use strict;
  10. use warnings;
  11. #use Data::Dumper;
  12. sub
  13. SD_WS07_Initialize($)
  14. {
  15. my ($hash) = @_;
  16. $hash->{Match} = "^P7#[A-Fa-f0-9]{6}F[A-Fa-f0-9]{2}"; ## pos 7 ist aktuell immer 0xF
  17. $hash->{DefFn} = "SD_WS07_Define";
  18. $hash->{UndefFn} = "SD_WS07_Undef";
  19. $hash->{ParseFn} = "SD_WS07_Parse";
  20. $hash->{AttrFn} = "SD_WS07_Attr";
  21. $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 showtime:1,0 " .
  22. "$readingFnAttributes ";
  23. $hash->{AutoCreate} =
  24. { "SD_WS07.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"} };
  25. }
  26. #############################
  27. sub
  28. SD_WS07_Define($$)
  29. {
  30. my ($hash, $def) = @_;
  31. my @a = split("[ \t][ \t]*", $def);
  32. return "wrong syntax: define <name> SD_WS07 <code> ".int(@a)
  33. if(int(@a) < 3 );
  34. $hash->{CODE} = $a[2];
  35. $hash->{lastMSG} = "";
  36. $hash->{bitMSG} = "";
  37. $modules{SD_WS07}{defptr}{$a[2]} = $hash;
  38. $hash->{STATE} = "Defined";
  39. my $name= $hash->{NAME};
  40. return undef;
  41. }
  42. #####################################
  43. sub
  44. SD_WS07_Undef($$)
  45. {
  46. my ($hash, $name) = @_;
  47. delete($modules{SD_WS07}{defptr}{$hash->{CODE}})
  48. if(defined($hash->{CODE}) &&
  49. defined($modules{SD_WS07}{defptr}{$hash->{CODE}}));
  50. return undef;
  51. }
  52. ###################################
  53. sub
  54. SD_WS07_Parse($$)
  55. {
  56. my ($iohash, $msg) = @_;
  57. #my $rawData = substr($msg, 2);
  58. my $name = $iohash->{NAME};
  59. my (undef ,$rawData) = split("#",$msg);
  60. #$protocol=~ s/^P(\d+)/$1/; # extract protocol
  61. my $model = "SD_WS07";
  62. my $hlen = length($rawData);
  63. my $blen = $hlen * 4;
  64. my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
  65. Log3 $name, 4, "SD_WS07_Parse $model ($msg) length: $hlen";
  66. # 4 8 9 12 24 28 36
  67. # 0011 0110 1 010 000100000010 1111 00111000 0000 eas8007
  68. # 0111 0010 1 010 000010111100 1111 00000000 0000 other device from anfichtn
  69. # ID Bat CHN TMP ?? HUM
  70. #my $hashumidity = FALSE;
  71. ## Todo: Change decoding per model into a foreach
  72. #foreach $key (keys %models) {
  73. # ....
  74. #}
  75. my $bitData2 = substr($bitData,0,8) . ' ' . substr($bitData,8,1) . ' ' . substr($bitData,9,3);
  76. $bitData2 = $bitData2 . ' ' . substr($bitData,12,12) . ' ' . substr($bitData,24,4) . ' ' . substr($bitData,28,8);
  77. Log3 $iohash, 5, $model . ' converted to bits: ' . $bitData2;
  78. my $id = substr($rawData,0,2);
  79. my $bat = int(substr($bitData,8,1)) eq "1" ? "ok" : "low";
  80. my $channel = oct("0b" . substr($bitData,9,3)) + 1;
  81. my $temp = oct("0b" . substr($bitData,12,12));
  82. my $bit24bis27 = oct("0b".substr($bitData,24,4));
  83. my $hum = oct("0b" . substr($bitData,28,8));
  84. if ($hum==0)
  85. {
  86. $model=$model."_T";
  87. } else {
  88. $model=$model."_TH";
  89. }
  90. if ($hum > 100) {
  91. return ''; # Eigentlich muesste sowas wie ein skip rein, damit ggf. spaeter noch weitre Sensoren dekodiert werden koennen.
  92. }
  93. if ($temp > 700 && $temp < 3840) {
  94. return '';
  95. } elsif ($temp >= 3840) { # negative Temperaturen, muss noch ueberprueft und optimiert werden
  96. $temp -= 4095;
  97. }
  98. $temp /= 10;
  99. Log3 $iohash, 4, "$model decoded protocolid: 7 sensor id=$id, channel=$channel, temp=$temp, hum=$hum, bat=$bat";
  100. my $deviceCode;
  101. my $longids = AttrVal($iohash->{NAME},'longids',0);
  102. if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/)))
  103. {
  104. $deviceCode=$model.'_'.$id.$channel;
  105. Log3 $iohash,4, "$name using longid: $longids model: $model";
  106. } else {
  107. $deviceCode = $model . "_" . $channel;
  108. }
  109. #print Dumper($modules{SD_WS07}{defptr});
  110. my $def = $modules{SD_WS07}{defptr}{$iohash->{NAME} . "." . $deviceCode};
  111. $def = $modules{SD_WS07}{defptr}{$deviceCode} if(!$def);
  112. if(!$def) {
  113. Log3 $iohash, 1, 'SD_WS07: UNDEFINED sensor ' . $model . ' detected, code ' . $deviceCode;
  114. return "UNDEFINED $deviceCode SD_WS07 $deviceCode";
  115. }
  116. #Log3 $iohash, 3, 'SD_WS07: ' . $def->{NAME} . ' ' . $id;
  117. my $hash = $def;
  118. $name = $hash->{NAME};
  119. return "" if(IsIgnored($name));
  120. Log3 $name, 4, "SD_WS07: $name ($rawData)";
  121. if (!defined(AttrVal($hash->{NAME},"event-min-interval",undef)))
  122. {
  123. my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
  124. if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
  125. Log3 $hash, 4, "$deviceCode Dropped due to short time. minsecs=$minsecs";
  126. return "";
  127. }
  128. }
  129. $hash->{lastReceive} = time();
  130. $hash->{lastMSG} = $rawData;
  131. $hash->{bitMSG} = $bitData2;
  132. my $state = "T: $temp". ($hum>0 ? " H: $hum":"");
  133. readingsBeginUpdate($hash);
  134. readingsBulkUpdate($hash, "state", $state);
  135. readingsBulkUpdate($hash, "temperature", $temp) if ($temp ne"");
  136. readingsBulkUpdate($hash, "humidity", $hum) if ($hum ne "" && $hum != 0 );
  137. readingsBulkUpdate($hash, "battery", $bat) if ($bat ne "");
  138. readingsBulkUpdate($hash, "channel", $channel) if ($channel ne "");
  139. readingsEndUpdate($hash, 1); # Notify is done by Dispatch
  140. return $name;
  141. }
  142. sub SD_WS07_Attr(@)
  143. {
  144. my @a = @_;
  145. # Make possible to use the same code for different logical devices when they
  146. # are received through different physical devices.
  147. return if($a[0] ne "set" || $a[2] ne "IODev");
  148. my $hash = $defs{$a[1]};
  149. my $iohash = $defs{$a[3]};
  150. my $cde = $hash->{CODE};
  151. delete($modules{SD_WS07}{defptr}{$cde});
  152. $modules{SD_WS07}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
  153. return undef;
  154. }
  155. 1;
  156. =pod
  157. =item summary Supports weather sensors protocl 7 from SIGNALduino
  158. =item summary_DE Unterst&uumltzt Wettersensoren mit Protokol 7 vom SIGNALduino
  159. =begin html
  160. <a name="SD_WS07"></a>
  161. <h3>Wether Sensors protocol #7</h3>
  162. <ul>
  163. The SD_WS07 module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br>
  164. <br>
  165. <b>Known models:</b>
  166. <ul>
  167. <li>Eurochon EAS800z</li>
  168. <li>Technoline WS6750/TX70DTH</li>
  169. </ul>
  170. <br>
  171. New received device are add in fhem with autocreate.
  172. <br><br>
  173. <a name="SD_WS07_Define"></a>
  174. <b>Define</b>
  175. <ul>The received devices created automatically.<br>
  176. The ID of the defice is the cannel or, if the longid attribute is specified, it is a combination of channel and some random generated bits at powering the sensor and the channel.<br>
  177. If you want to use more sensors, than channels available, you can use the longid option to differentiate them.
  178. </ul>
  179. <br>
  180. <a name="SD_WS07 Events"></a>
  181. <b>Generated readings:</b>
  182. <br>Some devices may not support all readings, so they will not be presented<br>
  183. <ul>
  184. <li>State (T: H:)</li>
  185. <li>temperature (&deg;C)</li>
  186. <li>humidity: (The humidity (1-100 if available)</li>
  187. <li>battery: (low or ok)</li>
  188. <li>channel: (The Channelnumber (number if)</li>
  189. </ul>
  190. <br>
  191. <b>Attributes</b>
  192. <ul>
  193. <li><a href="#do_not_notify">do_not_notify</a></li>
  194. <li><a href="#ignore">ignore</a></li>
  195. <li><a href="#model">model</a> ()</li>
  196. <li><a href="#showtime">showtime</a></li>
  197. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  198. </ul>
  199. <a name="SD_WS07_Set"></a>
  200. <b>Set</b> <ul>N/A</ul><br>
  201. <a name="SD_WS07_Parse"></a>
  202. <b>Set</b> <ul>N/A</ul><br>
  203. </ul>
  204. =end html
  205. =begin html_DE
  206. <a name="SD_WS07"></a>
  207. <h3>SD_WS07</h3>
  208. <ul>
  209. Das SD_WS07 Module verarbeitet von einem IO Geraet (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
  210. <br>
  211. <b>Unterst&uumltzte Modelle:</b>
  212. <ul>
  213. <li>Eurochon EAS800z</li>
  214. <li>Technoline WS6750/TX70DTH</li>
  215. <li>TFA 30320902</li>
  216. <li>FreeTec Aussenmodul fuer Wetterstation NC-7344</li>
  217. </ul>
  218. <br>
  219. Neu empfangene Sensoren werden in FHEM per autocreate angelegt.
  220. <br><br>
  221. <a name="SD_WS07_Define"></a>
  222. <b>Define</b>
  223. <ul>Die empfangenen Sensoren werden automatisch angelegt.<br>
  224. Die ID der angelgten Sensoren ist entweder der Kanal des Sensors, oder wenn das Attribut longid gesetzt ist, dann wird die ID aus dem Kanal und einer Reihe von Bits erzeugt, welche der Sensor beim Einschalten zufaellig vergibt.<br>
  225. </ul>
  226. <br>
  227. <a name="SD_WS07 Events"></a>
  228. <b>Generierte Readings:</b>
  229. <ul>
  230. <li>State (T: H:)</li>
  231. <li>temperature (&deg;C)</li>
  232. <li>humidity: (Luftfeuchte (1-100)</li>
  233. <li>battery: (low oder ok)</li>
  234. <li>channel: (Der Sensor Kanal)</li>
  235. </ul>
  236. <br>
  237. <b>Attribute</b>
  238. <ul>
  239. <li><a href="#do_not_notify">do_not_notify</a></li>
  240. <li><a href="#ignore">ignore</a></li>
  241. <li><a href="#model">model</a> ()</li>
  242. <li><a href="#showtime">showtime</a></li>
  243. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  244. </ul>
  245. <a name="SD_WS071_Set"></a>
  246. <b>Set</b> <ul>N/A</ul><br>
  247. <a name="SD_WS07_Parse"></a>
  248. <b>Set</b> <ul>N/A</ul><br>
  249. </ul>
  250. =end html_DE
  251. =cut