14_Hideki.pm 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. ##############################################
  2. # $Id: 14_Hideki.pm 15450 2017-11-18 21:34:47Z Sidey $
  3. # The file is taken from the SIGNALduino project
  4. # see http://www.fhemwiki.de/wiki/SIGNALduino
  5. # and was modified by a few additions
  6. # to support Hideki Sensors
  7. # S. Butzek, HJGode, Ralf9 2015-2017
  8. #
  9. package main;
  10. use strict;
  11. use warnings;
  12. use POSIX;
  13. #use Data::Dumper;
  14. #####################################
  15. sub
  16. Hideki_Initialize($)
  17. {
  18. my ($hash) = @_;
  19. $hash->{Match} = "^P12#75[A-F0-9]{17,30}"; # Laenge (Anhahl nibbles nach 0x75 )noch genauer spezifizieren
  20. $hash->{DefFn} = "Hideki_Define";
  21. $hash->{UndefFn} = "Hideki_Undef";
  22. $hash->{AttrFn} = "Hideki_Attr";
  23. $hash->{ParseFn} = "Hideki_Parse";
  24. $hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1"
  25. ." ignore:0,1"
  26. ." windDirCorr windSpeedCorr"
  27. ." $readingFnAttributes";
  28. $hash->{AutoCreate}=
  29. { "Hideki.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"} };
  30. }
  31. #####################################
  32. sub
  33. Hideki_Define($$)
  34. {
  35. my ($hash, $def) = @_;
  36. my @a = split("[ \t][ \t]*", $def);
  37. return "wrong syntax: define <name> Hideki <code>".int(@a)
  38. if(int(@a) < 3);
  39. $hash->{CODE} = $a[2];
  40. $hash->{lastMSG} = "";
  41. my $name= $hash->{NAME};
  42. $modules{Hideki}{defptr}{$a[2]} = $hash;
  43. #$hash->{STATE} = "Defined";
  44. #AssignIoPort($hash);
  45. return undef;
  46. }
  47. #####################################
  48. sub
  49. Hideki_Undef($$)
  50. {
  51. my ($hash, $name) = @_;
  52. delete($modules{Hideki}{defptr}{$hash->{CODE}}) if($hash && $hash->{CODE});
  53. return undef;
  54. }
  55. #####################################
  56. sub
  57. Hideki_Parse($$)
  58. {
  59. my ($iohash,$msg) = @_;
  60. my (undef ,$rawData) = split("#",$msg);
  61. my $name = $iohash->{NAME};
  62. my @a = split("", $msg);
  63. Log3 $iohash, 4, "Hideki_Parse $name incomming $msg";
  64. # decrypt bytes
  65. my $decodedString = decryptBytes($rawData); # decrpyt hex string to hex string
  66. #convert dectypted hex str back to array of bytes:
  67. my @decodedBytes = map { hex($_) } ($decodedString =~ /(..)/g);
  68. if (!@decodedBytes)
  69. {
  70. Log3 $iohash, 4, "$name decrypt failed";
  71. return '';
  72. }
  73. my $sensorTyp=getSensorType($decodedBytes[3]);
  74. Log3 $iohash, 4, "Hideki_Parse SensorTyp = $sensorTyp decodedString = $decodedString";
  75. if (!Hideki_crc(\@decodedBytes))
  76. {
  77. Log3 $iohash, 4, "$name crc failed";
  78. return '';
  79. }
  80. my $id=substr($decodedString,2,2); # get the random id from the data
  81. my $channel=0;
  82. my $temp="";
  83. my $hum=0;
  84. my $rain=0;
  85. my $unknown=0;
  86. my $windchill=0;
  87. my $windspeed=0;
  88. my $windgust=0;
  89. my $winddir=0;
  90. my $winddirdeg=0;
  91. my $winddirtext;
  92. my $rc;
  93. my $val;
  94. my $bat;
  95. my $deviceCode;
  96. my $model= "Hideki_$sensorTyp";
  97. my $count=0;
  98. my $comfort=0;
  99. ## 1. Detect what type of sensor we have, then call specific function to decode
  100. if ($sensorTyp==30){
  101. ($channel, $temp) = decodeThermo(\@decodedBytes); # decodeThermoHygro($decodedString);
  102. $hum = 10 * ($decodedBytes[6] >> 4) + ($decodedBytes[6] & 0x0f);
  103. $bat = ($decodedBytes[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
  104. $count = $decodedBytes[3] >> 6; # verifiziert, MSG_Counter
  105. $comfort = ($decodedBytes[7] >> 2 & 0x03); # comfort level
  106. if ($comfort == 0) { $comfort = 'Hum. OK. Temp. uncomfortable (>24.9 or <20)' }
  107. elsif ($comfort == 1) { $comfort = 'Wet. More than 69% RH' }
  108. elsif ($comfort == 2) { $comfort = 'Dry. Less than 40% RH' }
  109. elsif ($comfort == 3) { $comfort = 'Temp. and Hum. comfortable' }
  110. $val = "T: $temp H: $hum";
  111. Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp, humidity=$hum, comfort=$comfort";
  112. }elsif($sensorTyp==31){
  113. ($channel, $temp) = decodeThermo(\@decodedBytes);
  114. $bat = ($decodedBytes[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
  115. $count = $decodedBytes[3] >> 6; # verifiziert, MSG_Counter
  116. $val = "T: $temp";
  117. Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp";
  118. }elsif($sensorTyp==14){
  119. ($channel, $rain) = decodeRain(\@decodedBytes); # decodeThermoHygro($decodedString);
  120. $bat = ($decodedBytes[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
  121. $count = $decodedBytes[3] >> 6; # UNVERIFIZIERT, MSG_Counter
  122. $val = "R: $rain";
  123. Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, rain=$rain, unknown=$unknown";
  124. }elsif($sensorTyp==12){
  125. ($channel, $temp) = decodeThermo(\@decodedBytes); # decodeThermoHygro($decodedString);
  126. ($windchill,$windspeed,$windgust,$winddir,$winddirdeg,$winddirtext) = wind(\@decodedBytes);
  127. $bat = ($decodedBytes[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
  128. $count = $decodedBytes[3] >> 6; # UNVERIFIZIERT, MSG_Counter
  129. $val = "T: $temp Ws: $windspeed Wg: $windgust Wd: $winddirtext";
  130. Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp, Wc=$windchill, Ws=$windspeed, Wg=$windgust, Wd=$winddir, WdDeg=$winddirdeg, Wdtxt=$winddirtext";
  131. }elsif($sensorTyp==13){
  132. ($channel, $temp) = decodeThermo(\@decodedBytes); # decodeThermoHygro($decodedString);
  133. $bat = ($decodedBytes[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
  134. $count = $decodedBytes[3] >> 6; # UNVERIFIZIERT, MSG_Counter
  135. $val = "T: $temp";
  136. Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp";
  137. Log3 $iohash, 4, "$name Sensor Typ $sensorTyp currently not full supported, please report sensor information!";
  138. }
  139. else{
  140. Log3 $iohash, 4, "$name Sensor Typ $sensorTyp not supported, please report sensor information!";
  141. return "";
  142. }
  143. my $longids = AttrVal($iohash->{NAME},'longids',0);
  144. if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/)))
  145. {
  146. $deviceCode=$model . "_" . $id . "." . $channel;
  147. Log3 $iohash,4, "$name using longid: $longids model: $model";
  148. } else {
  149. $deviceCode = $model . "_" . $channel;
  150. }
  151. Log3 $iohash, 5, "deviceCode: $deviceCode";
  152. my $def = $modules{Hideki}{defptr}{$iohash->{NAME} . "." . $deviceCode};
  153. $def = $modules{Hideki}{defptr}{$deviceCode} if(!$def);
  154. if(!$def) {
  155. Log3 $iohash, 1, "$name Hideki: UNDEFINED sensor $sensorTyp detected, code $deviceCode";
  156. return "UNDEFINED $deviceCode Hideki $deviceCode";
  157. }
  158. my $hash = $def;
  159. $name = $hash->{NAME};
  160. return "" if(IsIgnored($name));
  161. #Log3 $name, 4, "Hideki: $name ($msg)";
  162. my $WindSpeedCorr = AttrVal($name,"windSpeedCorr",0);
  163. if ($WindSpeedCorr > 0 && $sensorTyp == 12) {
  164. $windspeed = sprintf("%.2f", $windspeed * $WindSpeedCorr);
  165. $windgust = sprintf("%.2f", $windgust * $WindSpeedCorr);
  166. Log3 $name, 4, "$name Hideki_Parse: WindSpeedCorr=$WindSpeedCorr, WindSpeed=$windspeed, WindGust=$windgust";
  167. }
  168. if (!defined(AttrVal($hash->{NAME},"event-min-interval",undef)))
  169. {
  170. my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
  171. if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
  172. Log3 $iohash, 4, "$deviceCode Dropped ($decodedString) due to short time. minsecs=$minsecs";
  173. return "";
  174. }
  175. }
  176. $hash->{lastReceive} = time();
  177. $def->{lastMSG} = $decodedString;
  178. #Log3 $name, 4, "Hideki update $name:". $name;
  179. readingsBeginUpdate($hash);
  180. readingsBulkUpdate($hash, "state", $val);
  181. readingsBulkUpdate($hash, "battery", $bat) if ($bat ne "");
  182. readingsBulkUpdate($hash, "channel", $channel) if ($channel ne "");
  183. readingsBulkUpdate($hash, "temperature", $temp) if ($temp ne "");
  184. readingsBulkUpdate($hash, "package_number", $count) if ($count ne "");
  185. if ($sensorTyp == 30) { # temperature, humidity
  186. readingsBulkUpdate($hash, "humidity", $hum) if ($hum ne "");
  187. readingsBulkUpdate($hash, "comfort_level", $comfort) if ($comfort ne "");
  188. }
  189. elsif ($sensorTyp == 14) { # rain
  190. readingsBulkUpdate($hash, "rain", $rain);
  191. }
  192. elsif ($sensorTyp == 12) { # wind
  193. readingsBulkUpdate($hash, "windChill", $windchill);
  194. readingsBulkUpdate($hash, "windGust", $windgust);
  195. readingsBulkUpdate($hash, "windSpeed", $windspeed);
  196. readingsBulkUpdate($hash, "windDirection", $winddir);
  197. readingsBulkUpdate($hash, "windDirectionDegree", $winddirdeg);
  198. readingsBulkUpdate($hash, "windDirectionText", $winddirtext);
  199. }
  200. readingsEndUpdate($hash, 1); # Notify is done by Dispatch
  201. return $name;
  202. }
  203. # check crc for incoming message
  204. # in: hex string with encrypted, raw data, starting with 75
  205. # out: 1 for OK, 0 for failed
  206. # sample "75BDBA4AC2BEC855AC0A00"
  207. sub Hideki_crc{
  208. #my $Hidekihex=shift;
  209. #my @Hidekibytes=shift;
  210. my @Hidekibytes = @{$_[0]};
  211. #push @Hidekibytes,0x75; #first byte always 75 and will not be included in decrypt/encrypt!
  212. #convert to array except for first hex
  213. #for (my $i=1; $i<(length($Hidekihex))/2; $i++){
  214. # my $hex=Hideki_decryptByte(hex(substr($Hidekihex, $i*2, 2)));
  215. # push (@Hidekibytes, $hex);
  216. #}
  217. my $cs1=0; #will be zero for xor over all (bytes>>1)&0x1F except first byte (always 0x75)
  218. #my $rawData=shift;
  219. #todo add the crc check here
  220. my $count=($Hidekibytes[2]>>1) & 0x1f;
  221. my $b;
  222. #iterate over data only, first byte is 0x75 always
  223. for (my $i=1; $i<$count+2 && $i<scalar @Hidekibytes; $i++) {
  224. $b = $Hidekibytes[$i];
  225. $cs1 = $cs1 ^ $b; # calc first chksum
  226. }
  227. if($cs1==0){
  228. return 1;
  229. }
  230. else{
  231. return 0;
  232. }
  233. }
  234. # return decoded sensor type
  235. # in: one byte
  236. # out: one byte
  237. # Der Typ eines Sensors steckt in Byte 3:
  238. # Byte3 & 0x1F Device
  239. # 0x0C Anemometer
  240. # 0x0D UV sensor
  241. # 0x0E Rain level meter
  242. # 0x1E Thermo/hygro-sensor
  243. # 0x1F Thermo sensor
  244. sub getSensorType{
  245. return $_[0] & 0x1F;
  246. }
  247. # decrypt bytes of hex string
  248. # in: hex string
  249. # out: decrypted hex string
  250. sub decryptBytes{
  251. my $Hidekihex=shift;
  252. #create array of hex string
  253. my @Hidekibytes = map { Hideki_decryptByte(hex($_)) } ($Hidekihex =~ /(..)/g);
  254. my $result="75"; # Byte 0 is not encrypted
  255. for (my $i=1; $i<scalar (@Hidekibytes); $i++){
  256. $result.=sprintf("%02x",$Hidekibytes[$i]);
  257. }
  258. return $result;
  259. }
  260. sub Hideki_decryptByte{
  261. my $byte = shift;
  262. #printf("\ndecryptByte 0x%02x >>",$byte);
  263. my $ret2 = ($byte ^ ($byte << 1) & 0xFF); #gives possible overflow to left so c3->145 instead of 45
  264. #printf(" %02x\n",$ret2);
  265. return $ret2;
  266. }
  267. # decode byte array and return channel, temperature
  268. # input: decrypted byte array starting with 0x75, passed by reference as in mysub(\@array);
  269. # output <return code>, <channel>, <temperature>
  270. # was unable to get this working with an array ref as input, so switched to hex string input
  271. sub decodeThermo {
  272. my @Hidekibytes = @{$_[0]};
  273. #my $Hidekihex = shift;
  274. #my @Hidekibytes=();
  275. #for (my $i=0; $i<(length($Hidekihex))/2; $i++){
  276. # my $hex=hex(substr($Hidekihex, $i*2, 2)); ## Mit split und map geht es auch ... $str =~ /(..?)/g;
  277. # push (@Hidekibytes, $hex);
  278. #}
  279. my $channel=0;
  280. my $temp=0;
  281. $channel = $Hidekibytes[1] >> 5;
  282. # //Internally channel 4 is used for the other sensor types (rain, uv, anemo).
  283. # //Therefore, if channel is decoded 5 or 6, the real value set on the device itself is 4 resp 5.
  284. if ($channel >= 5) {
  285. $channel--;
  286. }
  287. my $sensorId = $Hidekibytes[1] & 0x1f; # Extract random id from sensor
  288. #my $devicetype = $Hidekibytes[3]&0x1f;
  289. $temp = 100 * ($Hidekibytes[5] & 0x0f) + 10 * ($Hidekibytes[4] >> 4) + ($Hidekibytes[4] & 0x0f);
  290. ## // temp is negative?
  291. if (!($Hidekibytes[5] & 0x80)) {
  292. $temp = -$temp;
  293. }
  294. $temp = $temp / 10;
  295. return ($channel, $temp);
  296. }
  297. # decode byte array and return channel and total rain in mm
  298. # input: decrypted byte array starting with 0x75, passed by reference as in mysub(\@array);
  299. # output <return code>, <channel>, <totalrain>
  300. # was unable to get this working with an array ref as input, so switched to hex string input
  301. sub decodeRain {
  302. my @Hidekibytes = @{$_[0]};
  303. #my $Hidekihex = shift;
  304. #my @Hidekibytes=();
  305. #for (my $i=0; $i<(length($Hidekihex))/2; $i++){
  306. # my $hex=hex(substr($Hidekihex, $i*2, 2)); ## Mit split und map geht es auch ... $str =~ /(..?)/g;
  307. # push (@Hidekibytes, $hex);
  308. #}
  309. my $channel=0;
  310. my $rain=0;
  311. my $unknown;
  312. #my $tests=0;
  313. #additional checks?
  314. #if($Hidekibytes[2]==0xCC){
  315. # $tests+=1;
  316. #}
  317. #if($Hidekibytes[6]==0x66){
  318. # $tests+=1;
  319. #}
  320. # possibly test if $tests==2 for sanity check
  321. #printf("SANITY CHECK tests=%i\n", $tests);
  322. $unknown = $Hidekibytes[6];
  323. $channel = $Hidekibytes[1] >> 5;
  324. # //Internally channel 4 is used for the other sensor types (rain, uv, anemo).
  325. # //Therefore, if channel is decoded 5 or 6, the real value set on the device itself is 4 resp 5.
  326. if ($channel >= 5) {
  327. $channel--;
  328. }
  329. my $sensorId = $Hidekibytes[1] & 0x1f; # Extract random id from sensor
  330. $rain = ($Hidekibytes[4] + $Hidekibytes[5]*0xff)*0.7;
  331. return ($channel, $rain, $unknown);
  332. }
  333. # P12#758BB244074007400F00001C6E7A01
  334. sub wind {
  335. my @Hidekibytes = @{$_[0]};
  336. my @winddir_name=("N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW");
  337. my $windspeed;
  338. my $windchill;
  339. my $windgust;
  340. my $winddir;
  341. my $winddirdeg;
  342. my $winddirtext;
  343. $windchill = 100 * ($Hidekibytes[7] & 0x0f) + 10 * ($Hidekibytes[6] >> 4) + ($Hidekibytes[6] & 0x0f);
  344. ## windchill is negative?
  345. if (!($Hidekibytes[7] & 0x80)) {
  346. $windchill = -$windchill;
  347. }
  348. $windchill = $windchill / 10;
  349. $windspeed = ($Hidekibytes[9] & 0x0f ) * 100 + ($Hidekibytes[8] >> 4) * 10 + ($Hidekibytes[8] & 0x0f);
  350. $windgust = ($Hidekibytes[10] >> 4) * 100 + ($Hidekibytes[10] & 0x0f) * 10 + ($Hidekibytes[9] >> 4);
  351. $winddir = ($Hidekibytes[11] >> 4);
  352. $winddirtext = $winddir_name[$winddir];
  353. $winddirdeg = $winddir * 22.5;
  354. return ($windchill,$windspeed,$windgust,$winddir,$winddirdeg,$winddirtext);
  355. }
  356. sub
  357. Hideki_Attr(@)
  358. {
  359. my @a = @_;
  360. # Make possible to use the same code for different logical devices when they
  361. # are received through different physical devices.
  362. return if($a[0] ne "set" || $a[2] ne "IODev");
  363. my $hash = $defs{$a[1]};
  364. my $iohash = $defs{$a[3]};
  365. my $cde = $hash->{CODE};
  366. delete($modules{Hideki}{defptr}{$cde});
  367. $modules{Hideki}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
  368. return undef;
  369. }
  370. 1;
  371. =pod
  372. =item summary Supports various rf sensors with hideki protocol
  373. =item summary_DE Unterst&uumltzt verschiedenen Funksensoren mit hideki Protokol
  374. =begin html
  375. <a name="Hideki"></a>
  376. <h3>Hideki</h3>
  377. <ul>
  378. The Hideki module is a module for decoding weather sensors, which use the hideki protocol. Known brands are Bresser, Cresta, TFA and Hama.
  379. <br><br>
  380. <a name="Hideki_define"></a>
  381. <b>Supported Brands</b>
  382. <ul>
  383. <li>Hama</li>
  384. <li>Bresser</li>
  385. <li>TFA Dostman</li>
  386. <li>Arduinos with remote Sensor lib from Randy Simons</li>
  387. <li>Cresta</li>
  388. <li>Hideki (Anemometer | UV sensor | Rain level meter | Thermo/hygro-sensor)</li>
  389. <li>all other devices, which use the Hideki protocol</li>
  390. </ul>
  391. Please note, currently temp/hum devices are implemented. Please report data for other sensortypes.
  392. <a name="Hideki_define"></a>
  393. <b>Define</b>
  394. <ul>
  395. <code>define &lt;name&gt; Hideki &lt;code&gt; </code> <br>
  396. <br>
  397. &lt;code&gt; is the address of the sensor device and
  398. is build by the sensor type and the channelnumber (1 to 5) or if the attribute longid is specfied an autogenerated address build when inserting
  399. the battery (this adress will change every time changing the battery).<br>
  400. If autocreate is enabled, the device will be defined via autocreate. This is also the preferred mode of defining such a device.
  401. </ul>
  402. <a name="Hideki_readings"></a>
  403. <b>Generated readings</b>
  404. <ul>
  405. <li>state (T:x H:y B:z)</li>
  406. <li>temperature (&deg;C)</li>
  407. <li>humidity (0-100)</li>
  408. <li>battery (ok or low)</li>
  409. <li>channel (The Channelnumber (number if)</li>
  410. <br><i>- Hideki only -</i>
  411. <li>comfort_level (Status: Humidity OK... , Wet. More than 69% RH, Dry. Less than 40% RH, Temperature and humidity comfortable)</li>
  412. <li>package_number (reflect the package number in the stream starting at 1)</li><br>
  413. </ul>
  414. <a name="Hideki_unset"></a>
  415. <b>Set</b> <ul>N/A</ul><br>
  416. <a name="Hideki_unget"></a>
  417. <b>Get</b> <ul>N/A</ul><br>
  418. <a name="Hideki_attr"></a>
  419. <b>Attributes</b>
  420. <ul>
  421. <li><a href="#do_not_notify">do_not_notify</a></li>
  422. <li><a href="#eventMap">eventMap</a></li>
  423. <li><a href="#ignore">ignore</a></li>
  424. <li><a href="#showtime">showtime</a></li>
  425. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  426. </ul>
  427. <br>
  428. </ul>
  429. =end html
  430. =begin html_DE
  431. <a name="Hideki"></a>
  432. <h3>Hideki</h3>
  433. <ul>
  434. Das Hideki module dekodiert empfangene Nachrichten von Wettersensoren, welche das Hideki Protokoll verwenden.
  435. <br><br>
  436. <a name="Hideki_define"></a>
  437. <b>Unterstuetzte Hersteller</b>
  438. <ul>
  439. <li>Hama</li>
  440. <li>Bresser</li>
  441. <li>TFA Dostman</li>
  442. <li>Arduinos with remote Sensor lib from Randy Simons</li>
  443. <li>Cresta</li>
  444. <li>Hideki (Anemometer | UV sensor | Rain level meter | Thermo/hygro-sensor)</li>
  445. <li>Alle anderen, welche das Hideki Protokoll verwenden</li>
  446. </ul>
  447. Hinweis, Aktuell sind nur temp/feuchte Sensoren implementiert. Bitte sendet uns Daten zu anderen Sensoren.
  448. <a name="Hideki_define"></a>
  449. <b>Define</b>
  450. <ul>
  451. <li><code>define &lt;name&gt; Hideki &lt;code&gt; </code></li>
  452. <li>
  453. <br>
  454. &lt;code&gt; besteht aus dem Sensortyp und der Kanalnummer (1..5) oder wenn das Attribut longid im IO Device gesetzt ist aus einer Zufallsadresse, die durch den Sensor beim einlegen der
  455. Batterie generiert wird (Die Adresse aendert sich bei jedem Batteriewechsel).<br>
  456. </li>
  457. <li>Wenn autocreate aktiv ist, dann wird der Sensor automatisch in FHEM angelegt. Das ist der empfohlene Weg, neue Sensoren hinzuzuf&uumlgen.</li>
  458. </ul>
  459. <br>
  460. <a name="Hideki_readings"></a>
  461. <b>Generated Readings</b>
  462. <ul>
  463. <li>state (T:x H:y B:z)</li>
  464. <li>temperature (&deg;C)</li>
  465. <li>humidity (0-100)</li>
  466. <li>battery (ok oder low)</li>
  467. <li>channel (Der Sensor Kanal)</li>
  468. <br><i>- Hideki spezifisch -</i>
  469. <li>comfort_level (Status: Humidity OK... , Wet größer 69% RH, Dry weiniger als 40% RH, Temperature and humidity comfortable)</li>
  470. <li>package_number (Paketnummer in der letzten Signalfolge, startet bei 1)</li><br>
  471. </ul>
  472. <a name="Hideki_unset"></a>
  473. <b>Set</b> <ul>N/A</ul><br>
  474. <a name="Hideki_unget"></a>
  475. <b>Get</b> <ul>N/A</ul><br>
  476. <a name="Hideki_attr"></a>
  477. <b>Attribute</b>
  478. <ul>
  479. <li><a href="#do_not_notify">do_not_notify</a></li>
  480. <li><a href="#eventMap">eventMap</a></li>
  481. <li><a href="#ignore">ignore</a></li>
  482. <li><a href="#showtime">showtime</a></li>
  483. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  484. </ul>
  485. <br>
  486. </ul>
  487. =end html_DE
  488. =cut