14_SD_WS07.pm 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. ##############################################
  2. # $Id: 14_SD_WS07.pm 15450 2017-11-18 21:34:47Z 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-2017
  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}(#R[A-F0-9][A-F0-9]){0,1}\$"; ## 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, $rssi) = split("#",$msg);
  60. if (defined($rssi)) {
  61. $rssi = hex(substr($rssi,1));
  62. $rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74));
  63. }
  64. #$protocol=~ s/^P(\d+)/$1/; # extract protocol
  65. my $model = "SD_WS07";
  66. my $hlen = length($rawData);
  67. my $blen = $hlen * 4;
  68. my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
  69. if (defined($rssi)) {
  70. Log3 $name, 4, "$name SD_WS07_Parse $model ($msg) length: $hlen RSSI = $rssi";
  71. } else {
  72. Log3 $name, 4, "$name SD_WS07_Parse $model ($msg) length: $hlen";
  73. }
  74. # 4 8 9 12 24 28 36
  75. # 0011 0110 1 010 000100000010 1111 00111000 0000 eas8007
  76. # 0111 0010 1 010 000010111100 1111 00000000 0000 other device from anfichtn
  77. # ID Bat CHN TMP ?? HUM
  78. #my $hashumidity = FALSE;
  79. ## Todo: Change decoding per model into a foreach
  80. #foreach $key (keys %models) {
  81. # ....
  82. #}
  83. my $bitData2 = substr($bitData,0,8) . ' ' . substr($bitData,8,1) . ' ' . substr($bitData,9,3);
  84. $bitData2 = $bitData2 . ' ' . substr($bitData,12,12) . ' ' . substr($bitData,24,4) . ' ' . substr($bitData,28,8);
  85. Log3 $iohash, 5, $model . ' converted to bits: ' . $bitData2;
  86. my $id = substr($rawData,0,2);
  87. my $bat = int(substr($bitData,8,1)) eq "1" ? "ok" : "low";
  88. my $channel = oct("0b" . substr($bitData,9,3)) + 1;
  89. my $temp = oct("0b" . substr($bitData,12,12));
  90. my $bit24bis27 = oct("0b".substr($bitData,24,4));
  91. my $hum = oct("0b" . substr($bitData,28,8));
  92. if ($hum==0)
  93. {
  94. $model=$model."_T";
  95. } else {
  96. $model=$model."_TH";
  97. if ($hum < 10 || $hum > 99) {
  98. return '';
  99. }
  100. }
  101. if ($temp > 700 && $temp < 3840) {
  102. return '';
  103. } elsif ($temp >= 3840) { # negative Temperaturen, muss noch ueberprueft und optimiert werden
  104. $temp -= 4095;
  105. }
  106. $temp /= 10;
  107. Log3 $iohash, 4, "$name $model decoded protocolid: 7 sensor id=$id, channel=$channel, temp=$temp, hum=$hum, bat=$bat";
  108. my $deviceCode;
  109. my $longids = AttrVal($iohash->{NAME},'longids',0);
  110. if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/)))
  111. {
  112. $deviceCode=$model.'_'.$id.$channel;
  113. Log3 $iohash,4, "$name using longid: $longids model: $model";
  114. } else {
  115. $deviceCode = $model . "_" . $channel;
  116. }
  117. #print Dumper($modules{SD_WS07}{defptr});
  118. my $def = $modules{SD_WS07}{defptr}{$iohash->{NAME} . "." . $deviceCode};
  119. $def = $modules{SD_WS07}{defptr}{$deviceCode} if(!$def);
  120. if(!$def) {
  121. Log3 $iohash, 1, "$name SD_WS07: UNDEFINED sensor $model detected, code $deviceCode";
  122. return "UNDEFINED $deviceCode SD_WS07 $deviceCode";
  123. }
  124. #Log3 $iohash, 3, 'SD_WS07: ' . $def->{NAME} . ' ' . $id;
  125. my $hash = $def;
  126. $name = $hash->{NAME};
  127. return "" if(IsIgnored($name));
  128. Log3 $name, 4, "$iohash->{NAME} SD_WS07: $name ($rawData)";
  129. if (!defined(AttrVal($hash->{NAME},"event-min-interval",undef)))
  130. {
  131. my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
  132. if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
  133. Log3 $hash, 4, "$deviceCode Dropped due to short time. minsecs=$minsecs";
  134. return "";
  135. }
  136. }
  137. $hash->{lastReceive} = time();
  138. $hash->{lastMSG} = $rawData;
  139. $hash->{bitMSG} = $bitData2;
  140. my $state = "T: $temp". ($hum>0 ? " H: $hum":"");
  141. readingsBeginUpdate($hash);
  142. readingsBulkUpdate($hash, "state", $state);
  143. readingsBulkUpdate($hash, "temperature", $temp) if ($temp ne"");
  144. readingsBulkUpdate($hash, "humidity", $hum) if ($hum ne "" && $hum != 0 );
  145. readingsBulkUpdate($hash, "battery", $bat) if ($bat ne "");
  146. readingsBulkUpdate($hash, "channel", $channel) if ($channel ne "");
  147. readingsEndUpdate($hash, 1); # Notify is done by Dispatch
  148. if(defined($rssi)) {
  149. $hash->{RSSI} = $rssi;
  150. }
  151. return $name;
  152. }
  153. sub SD_WS07_Attr(@)
  154. {
  155. my @a = @_;
  156. # Make possible to use the same code for different logical devices when they
  157. # are received through different physical devices.
  158. return if($a[0] ne "set" || $a[2] ne "IODev");
  159. my $hash = $defs{$a[1]};
  160. my $iohash = $defs{$a[3]};
  161. my $cde = $hash->{CODE};
  162. delete($modules{SD_WS07}{defptr}{$cde});
  163. $modules{SD_WS07}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
  164. return undef;
  165. }
  166. 1;
  167. =pod
  168. =item summary Supports weather sensors protocl 7 from SIGNALduino
  169. =item summary_DE Unterst&uumltzt Wettersensoren mit Protokol 7 vom SIGNALduino
  170. =begin html
  171. <a name="SD_WS07"></a>
  172. <h3>Weather Sensors protocol #7</h3>
  173. <ul>
  174. The SD_WS07 module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br>
  175. <br>
  176. <b>Known models:</b>
  177. <ul>
  178. <li>Eurochon EAS800z</li>
  179. <li>Technoline WS6750/TX70DTH</li>
  180. </ul>
  181. <br>
  182. New received devices are added in FHEM with autocreate.
  183. <br><br>
  184. <a name="SD_WS07_Define"></a>
  185. <b>Define</b>
  186. <ul>The received devices are created automatically.<br>
  187. 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>
  188. If you want to use more sensors, than channels available, you can use the longid option to differentiate them.
  189. </ul>
  190. <br>
  191. <a name="SD_WS07 Events"></a>
  192. <b>Generated readings:</b>
  193. <br>Some devices may not support all readings, so they will not be presented<br>
  194. <ul>
  195. <li>state (T: H:)</li>
  196. <li>temperature (&deg;C)</li>
  197. <li>humidity: (the humidity 1-100)</li>
  198. <li>battery: (low or ok)</li>
  199. <li>channel: (the channelnumberf)</li>
  200. </ul>
  201. <br>
  202. <b>Attributes</b>
  203. <ul>
  204. <li><a href="#do_not_notify">do_not_notify</a></li>
  205. <li><a href="#ignore">ignore</a></li>
  206. <li><a href="#showtime">showtime</a></li>
  207. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  208. </ul>
  209. <a name="SD_WS07_Set"></a>
  210. <b>Set</b> <ul>N/A</ul><br>
  211. <a name="SD_WS07_Get"></a>
  212. <b>Get</b> <ul>N/A</ul><br>
  213. </ul>
  214. =end html
  215. =begin html_DE
  216. <a name="SD_WS07"></a>
  217. <h3>SD_WS07</h3>
  218. <ul>
  219. Das SD_WS07 Modul verarbeitet von einem IO Geraet (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
  220. <br>
  221. <b>Unterst&uumltzte Modelle:</b>
  222. <ul>
  223. <li>Eurochon EAS800z</li>
  224. <li>Technoline WS6750/TX70DTH</li>
  225. <li>TFA 30320902</li>
  226. <li>FreeTec Aussenmodul fuer Wetterstation NC-7344</li>
  227. </ul>
  228. <br>
  229. Neu empfangene Sensoren werden in FHEM per autocreate angelegt.
  230. <br><br>
  231. <a name="SD_WS07_Define"></a>
  232. <b>Define</b>
  233. <ul>Die empfangenen Sensoren werden automatisch angelegt.<br>
  234. Die ID der angelegten 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>
  235. </ul>
  236. <br>
  237. <a name="SD_WS07 Events"></a>
  238. <b>Generierte Readings:</b>
  239. <ul>
  240. <li>state: (T: H:)</li>
  241. <li>temperature: (&deg;C)</li>
  242. <li>humidity: (Luftfeuchte (1-100)</li>
  243. <li>battery: (low oder ok)</li>
  244. <li>channel: (Der Sensor Kanal)</li>
  245. </ul>
  246. <br>
  247. <b>Attribute</b>
  248. <ul>
  249. <li><a href="#do_not_notify">do_not_notify</a></li>
  250. <li><a href="#ignore">ignore</a></li>
  251. <li><a href="#showtime">showtime</a></li>
  252. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  253. </ul>
  254. <a name="SD_WS071_Set"></a>
  255. <b>Set</b> <ul>N/A</ul><br>
  256. <a name="SD_WS07_Get"></a>
  257. <b>Get</b> <ul>N/A</ul><br>
  258. </ul>
  259. =end html_DE
  260. =cut