41_OREGON.pm 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. #################################################################################
  2. # $Id: 41_OREGON.pm 16945 2018-07-04 20:06:40Z Sidey $
  3. #
  4. # Module for FHEM to decode Oregon sensor messages
  5. #
  6. # derived from 18_CUL-HOERMANN.pm
  7. #
  8. # This code is derived from http://www.xpl-perl.org.uk/.
  9. # Thanks a lot to Mark Hindess who wrote xPL.
  10. #
  11. # Special thanks to RFXCOM, http://www.rfxcom.com/, for their
  12. # help. I own an USB-RFXCOM-Receiver (433.92MHz, USB, order code 80002)
  13. # and highly recommend it.
  14. #
  15. # (c) 2010-2014 Copyright: Willi Herzig (Willi.Herzig@gmail.com)
  16. # modified & fixes Ralf9 2015-2016
  17. # fixes Sidey79 2016
  18. # This script is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  21. #
  22. ##################################
  23. #
  24. # Most of the subs are copied and modified from xpl-perl
  25. # from the following two files:
  26. # xpl-perl/lib/xPL/Utils.pm:
  27. # xpl-perl/lib/xPL/RF/Oregon.pm:
  28. #
  29. #SEE ALSO
  30. # Project website: http://www.xpl-perl.org.uk/
  31. # AUTHOR: Mark Hindess, soft-xpl-perl@temporalanomaly.com
  32. #
  33. #Copyright (C) 2007, 2009 by Mark Hindess
  34. #
  35. #This library is free software; you can redistribute it and/or modify
  36. #it under the same terms as Perl itself, either Perl version 5.8.7 or,
  37. #at your option, any later version of Perl 5 you may have available.
  38. #
  39. # values for "set global verbose"
  40. # 4: log unknown protocols
  41. # 5: log decoding hexlines for debugging
  42. #
  43. package main;
  44. use strict;
  45. use warnings;
  46. my $time_old = 0;
  47. sub
  48. OREGON_Initialize($)
  49. {
  50. my ($hash) = @_;
  51. $hash->{Match} = "^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*", #38-78
  52. $hash->{DefFn} = "OREGON_Define";
  53. $hash->{UndefFn} = "OREGON_Undef";
  54. $hash->{ParseFn} = "OREGON_Parse";
  55. $hash->{AttrList} = "IODev ignore:0,1 do_not_notify:1,0 showtime:1,0"
  56. ." $readingFnAttributes";
  57. }
  58. #####################################
  59. sub
  60. OREGON_Define($$)
  61. {
  62. my ($hash, $def) = @_;
  63. my @a = split("[ \t][ \t]*", $def);
  64. my $a = int(@a);
  65. #print "a0 = $a[0]";
  66. return "wrong syntax: define <name> OREGON code" if(int(@a) != 3);
  67. my $name = $a[0];
  68. my $code = $a[2];
  69. $hash->{CODE} = $code;
  70. #$modules{OREGON}{defptr}{$name} = $hash;
  71. $modules{OREGON}{defptr}{$code} = $hash;
  72. AssignIoPort($hash);
  73. return undef;
  74. }
  75. #####################################
  76. sub
  77. OREGON_Undef($$)
  78. {
  79. my ($hash, $name) = @_;
  80. delete($modules{OREGON}{defptr}{$name});
  81. return undef;
  82. }
  83. #########################################
  84. # From xpl-perl/lib/xPL/Util.pm:
  85. sub OREGON_hi_nibble {
  86. ($_[0]&0xf0)>>4;
  87. }
  88. sub OREGON_lo_nibble {
  89. $_[0]&0xf;
  90. }
  91. sub OREGON_nibble_sum {
  92. my $c = $_[0];
  93. my $s = 0;
  94. foreach (0..$_[0]-1) {
  95. $s += OREGON_hi_nibble($_[1]->[$_]);
  96. $s += OREGON_lo_nibble($_[1]->[$_]);
  97. }
  98. $s += OREGON_hi_nibble($_[1]->[$_[0]]) if (int($_[0]) != $_[0]);
  99. return $s;
  100. }
  101. # --------------------------------------------
  102. # From xpl-perl/lib/xPL/RF/Oregon.pm:
  103. # This function creates a simple key from a device type and message
  104. # length (in bits). It is used to as the index for the parts table.
  105. sub OREGON_type_length_key {
  106. ($_[0] << 8) + $_[1]
  107. }
  108. # --------------------------------------------
  109. # types from xpl-perl/lib/xPL/RF/Oregon.pm
  110. # Changes: Use pointers to subs for method to allow strict use
  111. my %types =
  112. (
  113. # THGR810 v3
  114. OREGON_type_length_key(0xfa28, 80) =>
  115. {
  116. part => 'THGR810', checksum => \&OREGON_checksum2, method => \&OREGON_common_temphydro,
  117. },
  118. # WTGR800 Temp hydro v3
  119. OREGON_type_length_key(0xfab8, 80) =>
  120. {
  121. part => 'WTGR800_T', checksum => \&OREGON_checksum2, method => \&OREGON_alt_temphydro,
  122. },
  123. # WTGR800 Anenometer v3
  124. OREGON_type_length_key(0x1a99, 88) =>
  125. {
  126. part => 'WTGR800_A', checksum => \&OREGON_checksum4, method => \&OREGON_wtgr800_anemometer,
  127. },
  128. # WGR800 v3
  129. OREGON_type_length_key(0x1a89, 88) =>
  130. {
  131. part => 'WGR800', checksum => \&OREGON_checksum4, method => \&OREGON_wtgr800_anemometer,
  132. },
  133. # UVN800 v3
  134. OREGON_type_length_key(0xda78, 72) =>
  135. {
  136. part => 'UVN800', checksum => \&OREGON_checksum7, method => \&OREGON_uvn800,
  137. },
  138. OREGON_type_length_key(0xea7c, 120) =>
  139. {
  140. part => 'UV138', checksum => \&OREGON_checksum1, method => \&OREGON_uv138,
  141. },
  142. OREGON_type_length_key(0xea4c, 80) =>
  143. {
  144. part => 'THWR288A', checksum => \&OREGON_checksum1, method => \&OREGON_common_temp,
  145. },
  146. # THN132N
  147. OREGON_type_length_key(0xea4c, 64) =>
  148. {
  149. part => 'THN132N', checksum => \&OREGON_checksum1, method => \&OREGON_common_temp,
  150. },
  151. #
  152. OREGON_type_length_key(0x9aec, 104) =>
  153. {
  154. part => 'RTGR328N', checksum => \&OREGON_checksum3, method => \&OREGON_rtgr328n_datetime,
  155. },
  156. #
  157. OREGON_type_length_key(0x9aea, 104) =>
  158. {
  159. part => 'RTGR328N', checksum => \&OREGON_checksum3, method => \&OREGON_rtgr328n_datetime,
  160. },
  161. # THGN122N,THGR122NX,THGR228N,THGR268
  162. OREGON_type_length_key(0x1a2d, 80) =>
  163. {
  164. part => 'THGR228N', checksum => \&OREGON_checksum2, method => \&OREGON_common_temphydro,
  165. },
  166. # THGR918
  167. OREGON_type_length_key(0x1a3d, 80) =>
  168. {
  169. part => 'THGR918', checksum => \&OREGON_checksum2, method => \&OREGON_common_temphydro,
  170. },
  171. # BTHR918
  172. OREGON_type_length_key(0x5a5d, 88) =>
  173. {
  174. part => 'BTHR918', checksum => \&OREGON_checksum5plus, method => \&OREGON_common_temphydrobaro,
  175. },
  176. # BTHR918N, BTHR968
  177. OREGON_type_length_key(0x5a6d, 88) =>
  178. {
  179. part => 'BTHR918N', checksum => \&OREGON_checksum5, method => \&OREGON_alt_temphydrobaro,
  180. },
  181. #
  182. OREGON_type_length_key(0x3a0d, 80) =>
  183. {
  184. part => 'WGR918', checksum => \&OREGON_checksum4, method => \&OREGON_wgr918_anemometer,
  185. },
  186. # RGR126, RGR682, RGR918:
  187. OREGON_type_length_key(0x2a1d, 80) =>
  188. {
  189. part => 'RGR918', checksum => \&OREGON_checksum6plus, method => \&OREGON_common_rain,
  190. },
  191. #
  192. OREGON_type_length_key(0x0a4d, 80) =>
  193. {
  194. part => 'THR128', checksum => \&OREGON_checksum2, method => \&OREGON_common_temp,
  195. },
  196. # THGR328N
  197. OREGON_type_length_key(0xca2c, 80) =>
  198. {
  199. part => 'THGR328N', checksum => \&OREGON_checksum2, method => \&OREGON_common_temphydro,
  200. },
  201. #
  202. OREGON_type_length_key(0xca2c, 120) =>
  203. {
  204. part => 'THGR328N', checksum => \&OREGON_checksum2, method => \&OREGON_common_temphydro,
  205. },
  206. # masked
  207. OREGON_type_length_key(0x0acc, 80) =>
  208. {
  209. part => 'RTGR328N', checksum => \&OREGON_checksum2, method => \&OREGON_common_temphydro,
  210. },
  211. # PCR800. v3
  212. OREGON_type_length_key(0x2a19, 92) =>
  213. {
  214. part => 'PCR800', checksum => \&OREGON_checksum8, method => \&OREGON_rain_PCR800,
  215. },
  216. # THWR800 v3
  217. OREGON_type_length_key(0xca48, 68) =>
  218. {
  219. part => 'THWR800', checksum => \&OREGON_checksum9, method => \&OREGON_common_temp,
  220. },
  221. OREGON_type_length_key(0x0adc, 64) => # masked to ?adc due to rolling code
  222. {
  223. part => 'RTHN318', checksum => \&OREGON_checksum1, method => \&OREGON_common_temp,
  224. },
  225. );
  226. # --------------------------------------------
  227. #my $DOT = q{.};
  228. # Important: change it to _, because FHEM uses regexp
  229. my $DOT = q{_};
  230. my @OREGON_winddir_name=("N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW");
  231. # --------------------------------------------
  232. # The following functions are changed:
  233. # - some parameter like "parent" and others are removed
  234. # - @res array return the values directly (no usage of xPL::Message)
  235. sub OREGON_temperature {
  236. my ($bytes, $dev, $res) = @_;
  237. my $temp =
  238. (($bytes->[6]&0x8) ? -1 : 1) *
  239. (OREGON_hi_nibble($bytes->[5])*10 + OREGON_lo_nibble($bytes->[5]) +
  240. OREGON_hi_nibble($bytes->[4])/10);
  241. push @$res, {
  242. device => $dev,
  243. type => 'temp',
  244. current => $temp,
  245. units => 'Grad Celsius'
  246. }
  247. }
  248. sub OREGON_humidity {
  249. my ($bytes, $dev, $res) = @_;
  250. my $hum = OREGON_lo_nibble($bytes->[7])*10 + OREGON_hi_nibble($bytes->[6]);
  251. my $hum_str = ['normal', 'comfortable', 'dry', 'wet']->[$bytes->[7]>>6];
  252. push @$res, {
  253. device => $dev,
  254. type => 'humidity',
  255. current => $hum,
  256. string => $hum_str,
  257. units => '%'
  258. }
  259. }
  260. sub OREGON_pressure {
  261. my ($bytes, $dev, $res, $forecast_nibble, $offset) = @_;
  262. $offset = 795 unless ($offset);
  263. my $hpa = $bytes->[8]+$offset;
  264. my $forecast = { 0xc => 'sunny',
  265. 0x6 => 'partly',
  266. 0x2 => 'cloudy',
  267. 0x3 => 'rain',
  268. }->{$forecast_nibble} || 'unknown';
  269. push @$res, {
  270. device => $dev,
  271. type => 'pressure',
  272. current => $hpa,
  273. units => 'hPa',
  274. forecast => $forecast,
  275. }
  276. }
  277. sub OREGON_simple_battery {
  278. my ($bytes, $dev, $res) = @_;
  279. my $battery_low = $bytes->[4]&0x4;
  280. #my $bat = $battery_low ? 10 : 90;
  281. my $battery = $battery_low ? "low" : "ok";
  282. push @$res, {
  283. device => $dev,
  284. type => 'battery',
  285. current => $battery,
  286. units => '%',
  287. },
  288. {
  289. device => $dev,
  290. type => 'batteryState',
  291. current => $battery,
  292. units => '',
  293. }
  294. }
  295. sub OREGON_percentage_battery {
  296. my ($bytes, $dev, $res) = @_;
  297. my $battery;
  298. my $batteryState;
  299. my $battery_level = 100-10*OREGON_lo_nibble($bytes->[4]);
  300. if ($battery_level > 50) {
  301. $battery = sprintf("ok %d%%",$battery_level);
  302. $batteryState="ok";
  303. } else {
  304. $battery = sprintf("low %d%%",$battery_level);
  305. $batteryState="low";
  306. }
  307. push @$res, {
  308. device => $dev,
  309. type => 'battery',
  310. current => $battery,
  311. units => '%',
  312. }, {
  313. device => $dev,
  314. type => 'batteryPercent',
  315. current => $battery_level,
  316. units => '%',
  317. },
  318. {
  319. device => $dev,
  320. type => 'batteryState',
  321. current => $batteryState,
  322. units => '',
  323. }
  324. }
  325. my @uv_str =
  326. (
  327. qw/low low low/, # 0 - 2
  328. qw/medium medium medium/, # 3 - 5
  329. qw/high high/, # 6 - 7
  330. 'very high', 'very high', 'very high', # 8 - 10
  331. );
  332. sub OREGON_uv_string {
  333. $uv_str[$_[0]] || 'dangerous';
  334. }
  335. sub OREGON_uv {
  336. my ($bytes, $dev, $res) = @_;
  337. my $uv = OREGON_lo_nibble($bytes->[5])*10 + OREGON_hi_nibble($bytes->[4]);
  338. my $risk = OREGON_uv_string($uv);
  339. push @$res, {
  340. device => $dev,
  341. type => 'uv',
  342. current => $uv,
  343. risk => $risk,
  344. }
  345. }
  346. sub OREGON_uv2 {
  347. my ($bytes, $dev, $res) = @_;
  348. my $uv = OREGON_hi_nibble($bytes->[4]);
  349. my $risk = OREGON_uv_string($uv);
  350. push @$res, {
  351. device => $dev,
  352. type => 'uv',
  353. current => $uv,
  354. risk => $risk,
  355. }
  356. }
  357. # Test if to use longid for device type
  358. sub OREGON_use_longid {
  359. my ($longids,$dev_type) = @_;
  360. return 0 if ($longids eq "");
  361. return 0 if ($longids eq "NONE");
  362. return 0 if ($longids eq "0");
  363. return 1 if ($longids eq "1");
  364. return 1 if ($longids eq "ALL");
  365. return 1 if(",$longids," =~ m/,$dev_type,/);
  366. return 0;
  367. }
  368. # --------------------------------------------------------
  369. sub OREGON_uv138 {
  370. my $type = shift;
  371. my $longids = shift;
  372. my $bytes = shift;
  373. my $device = sprintf "%02x", $bytes->[3];
  374. #my $dev_str = $type.$DOT.$device;
  375. my $dev_str = $type;
  376. if (OREGON_use_longid($longids,$type)) {
  377. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  378. }
  379. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  380. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  381. }
  382. my @res = ();
  383. OREGON_uv($bytes, $dev_str, \@res);
  384. OREGON_simple_battery($bytes, $dev_str, \@res);
  385. return @res;
  386. }
  387. sub OREGON_uvn800 {
  388. my $type = shift;
  389. my $longids = shift;
  390. my $bytes = shift;
  391. my $device = sprintf "%02x", $bytes->[3];
  392. #my $dev_str = $type.$DOT.$device;
  393. my $dev_str = $type;
  394. if (OREGON_use_longid($longids,$type)) {
  395. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  396. }
  397. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  398. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  399. }
  400. my @res = ();
  401. OREGON_uv2($bytes, $dev_str, \@res);
  402. OREGON_percentage_battery($bytes, $dev_str, \@res);
  403. return @res;
  404. }
  405. sub OREGON_wgr918_anemometer {
  406. my $type = shift;
  407. my $longids = shift;
  408. my $bytes = shift;
  409. my $device = sprintf "%02x", $bytes->[3];
  410. #my $dev_str = $type.$DOT.$device;
  411. my $dev_str = $type;
  412. if (OREGON_use_longid($longids,$type)) {
  413. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  414. }
  415. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  416. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  417. }
  418. my @res = ();
  419. my $dir = sprintf("%02x",$bytes->[5])*10 + OREGON_hi_nibble($bytes->[4]);
  420. my $dirname = $OREGON_winddir_name[$dir/22.5];
  421. my $speed = OREGON_lo_nibble($bytes->[7]) * 10 + sprintf("%02x",$bytes->[6])/10;
  422. my $avspeed = sprintf("%02x",$bytes->[8]) + OREGON_hi_nibble($bytes->[7]) / 10;
  423. push @res, {
  424. device => $dev_str,
  425. type => 'speed',
  426. current => $speed,
  427. average => $avspeed,
  428. units => 'mps',
  429. } , {
  430. device => $dev_str,
  431. type => 'direction',
  432. current => $dir,
  433. string => $dirname,
  434. units => 'degrees',
  435. }
  436. ;
  437. OREGON_percentage_battery($bytes, $dev_str, \@res);
  438. return @res;
  439. }
  440. # -----------------------------
  441. sub OREGON_wtgr800_anemometer {
  442. my $type = shift;
  443. my $longids = shift;
  444. my $bytes = shift;
  445. my $device = sprintf "%02x", $bytes->[3];
  446. #my $dev_str = $type.$DOT.$device;
  447. my $dev_str = $type;
  448. if (OREGON_use_longid($longids,$type)) {
  449. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  450. }
  451. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  452. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  453. }
  454. my @res = ();
  455. my $dir = OREGON_hi_nibble($bytes->[4]) % 16;
  456. my $dirname = $OREGON_winddir_name[$dir];
  457. $dir = $dir * 22.5;
  458. my $speed = OREGON_lo_nibble($bytes->[7]) * 10 + sprintf("%02x",$bytes->[6])/10;
  459. my $avspeed = sprintf("%02x",$bytes->[8]) + OREGON_hi_nibble($bytes->[7]) / 10;
  460. push @res, {
  461. device => $dev_str,
  462. type => 'speed',
  463. current => $speed,
  464. average => $avspeed,
  465. units => 'mps',
  466. } , {
  467. device => $dev_str,
  468. type => 'direction',
  469. current => $dir,
  470. string => $dirname,
  471. units => 'degrees',
  472. }
  473. ;
  474. OREGON_percentage_battery($bytes, $dev_str, \@res);
  475. return @res;
  476. }
  477. # -----------------------------
  478. sub OREGON_alt_temphydro {
  479. my $type = shift;
  480. my $longids = shift;
  481. my $bytes = shift;
  482. #
  483. my $hex_line = "";
  484. for (my $i=0;$i<=9;$i++) {
  485. $hex_line .= sprintf("%02x",$bytes->[$i]);
  486. }
  487. my $device = sprintf "%02x", $bytes->[3];
  488. #my $dev_str = $type.$DOT.$device;
  489. my $dev_str = $type;
  490. if (OREGON_use_longid($longids,$type)) {
  491. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  492. }
  493. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  494. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  495. }
  496. my @res = ();
  497. OREGON_temperature($bytes, $dev_str, \@res);
  498. OREGON_humidity($bytes, $dev_str, \@res);
  499. OREGON_percentage_battery($bytes, $dev_str, \@res);
  500. return @res;
  501. }
  502. # -----------------------------
  503. sub OREGON_alt_temphydrobaro {
  504. my $type = shift;
  505. my $longids = shift;
  506. my $bytes = shift;
  507. my @res = ();
  508. my $device = sprintf "%02x", $bytes->[3];
  509. #my $dev_str = $type.$DOT.$device;
  510. my $dev_str = $type;
  511. if (OREGON_use_longid($longids,$type)) {
  512. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  513. }
  514. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  515. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  516. }
  517. OREGON_temperature($bytes, $dev_str, \@res);
  518. OREGON_humidity($bytes, $dev_str, \@res);
  519. OREGON_pressure($bytes, $dev_str, \@res, OREGON_hi_nibble($bytes->[9]), 856);
  520. OREGON_percentage_battery($bytes, $dev_str, \@res);
  521. return @res;
  522. }
  523. # -----------------------------
  524. sub OREGON_rtgr328n_datetime {
  525. my $type = shift;
  526. my $longids = shift;
  527. my $bytes = shift;
  528. my $device = sprintf "%02x", $bytes->[3];
  529. #my $dev_str = $type.$DOT.$device;
  530. my $dev_str = $type;
  531. if (OREGON_use_longid($longids,$type)) {
  532. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  533. }
  534. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  535. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  536. }
  537. my $time =
  538. (
  539. OREGON_lo_nibble($bytes->[7]).OREGON_hi_nibble($bytes->[6]).
  540. OREGON_lo_nibble($bytes->[6]).OREGON_hi_nibble($bytes->[5]).
  541. OREGON_lo_nibble($bytes->[5]).OREGON_hi_nibble($bytes->[4])
  542. );
  543. my $day =
  544. [ 'Mon', 'Tue', 'Wed',
  545. 'Thu', 'Fri', 'Sat', 'Sun' ]->[($bytes->[9]&0x7)-1];
  546. my $date =
  547. 2000+(OREGON_lo_nibble($bytes->[10]).OREGON_hi_nibble($bytes->[9])).
  548. sprintf("%02d",OREGON_hi_nibble($bytes->[8])).
  549. OREGON_lo_nibble($bytes->[8]).OREGON_hi_nibble($bytes->[7]);
  550. #print STDERR "datetime: $date $time $day\n";
  551. my @res = ();
  552. push @res, {
  553. datetime => $date.$time,
  554. 'date' => $date,
  555. 'time' => $time,
  556. day => $day.'day',
  557. device => $dev_str,
  558. };
  559. return @res;
  560. }
  561. # -----------------------------
  562. sub OREGON_common_temp {
  563. my $type = shift;
  564. my $longids = shift;
  565. my $bytes = shift;
  566. my $device = sprintf "%02x", $bytes->[3];
  567. #my $dev_str = $type.$DOT.$device;
  568. my $dev_str = $type;
  569. if (OREGON_use_longid($longids,$type)) {
  570. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  571. }
  572. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  573. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  574. }
  575. my @res = ();
  576. OREGON_temperature($bytes, $dev_str, \@res);
  577. OREGON_simple_battery($bytes, $dev_str, \@res);
  578. return @res;
  579. }
  580. # -----------------------------
  581. sub OREGON_common_temphydro {
  582. my $type = shift;
  583. my $longids = shift;
  584. my $bytes = shift;
  585. my $device = sprintf "%02x", $bytes->[3];
  586. #my $dev_str = $type.$DOT.$device;
  587. my $dev_str = $type;
  588. if (OREGON_use_longid($longids,$type)) {
  589. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  590. }
  591. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  592. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  593. }
  594. my @res = ();
  595. OREGON_temperature($bytes, $dev_str, \@res);
  596. OREGON_humidity($bytes, $dev_str, \@res);
  597. OREGON_simple_battery($bytes, $dev_str, \@res);
  598. return @res;
  599. }
  600. # -----------------------------
  601. sub OREGON_common_temphydrobaro {
  602. my $type = shift;
  603. my $longids = shift;
  604. my $bytes = shift;
  605. my $device = sprintf "%02x", $bytes->[3];
  606. #my $dev_str = $type.$DOT.$device;
  607. my $dev_str = $type;
  608. if (OREGON_use_longid($longids,$type)) {
  609. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  610. }
  611. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  612. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  613. }
  614. my @res = ();
  615. OREGON_temperature($bytes, $dev_str, \@res);
  616. OREGON_humidity($bytes, $dev_str, \@res);
  617. OREGON_pressure($bytes, $dev_str, \@res, OREGON_lo_nibble($bytes->[9]));
  618. OREGON_simple_battery($bytes, $dev_str, \@res);
  619. return @res;
  620. }
  621. # -----------------------------
  622. sub OREGON_common_rain {
  623. my $type = shift;
  624. my $longids = shift;
  625. my $bytes = shift;
  626. my $device = sprintf "%02x", $bytes->[3];
  627. #my $dev_str = $type.$DOT.$device;
  628. my $dev_str = $type;
  629. if (OREGON_use_longid($longids,$type)) {
  630. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  631. }
  632. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  633. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  634. }
  635. my @res = ();
  636. my $rain = sprintf("%02x",$bytes->[5])*10 + OREGON_hi_nibble($bytes->[4]);
  637. my $train = OREGON_lo_nibble($bytes->[8])*1000 +
  638. sprintf("%02x", $bytes->[7])*10 + OREGON_hi_nibble($bytes->[6]);
  639. my $flip = OREGON_lo_nibble($bytes->[6]);
  640. #print STDERR "$dev_str rain = $rain, total = $train, flip = $flip\n";
  641. push @res, {
  642. device => $dev_str,
  643. type => 'rain',
  644. current => $rain,
  645. units => 'mm/h',
  646. } ;
  647. push @res, {
  648. device => $dev_str,
  649. type => 'train',
  650. current => $train,
  651. units => 'mm',
  652. };
  653. push @res, {
  654. device => $dev_str,
  655. type => 'flip',
  656. current => $flip,
  657. units => 'flips',
  658. };
  659. OREGON_simple_battery($bytes, $dev_str, \@res);
  660. return @res;
  661. }
  662. # -----------------------------
  663. # under development............
  664. sub OREGON_rain_PCR800 {
  665. my $type = shift;
  666. my $longids = shift;
  667. my $bytes = shift;
  668. #
  669. my $hexline = "";
  670. for (my $i=0;$i<=10;$i++) {
  671. $hexline .= sprintf("%02x",$bytes->[$i]);
  672. }
  673. my $device = sprintf "%02x", $bytes->[3];
  674. #my $dev_str = $type.$DOT.$device;
  675. my $dev_str = $type;
  676. if (OREGON_use_longid($longids,$type)) {
  677. $dev_str .= $DOT.sprintf("%02x", $bytes->[3]);
  678. }
  679. if (OREGON_hi_nibble($bytes->[2]) > 0) {
  680. $dev_str .= $DOT.sprintf("%d", OREGON_hi_nibble($bytes->[2]));
  681. }
  682. my @res = ();
  683. my $rain = OREGON_lo_nibble($bytes->[6])*10 + sprintf("%02x",$bytes->[5])/10 + OREGON_hi_nibble($bytes->[4])/100;
  684. $rain *= 25.4; # convert from inch to mm
  685. my $train = OREGON_lo_nibble($bytes->[9])*100 + sprintf("%02x",$bytes->[8]) +
  686. sprintf("%02x",$bytes->[7])/100 + OREGON_hi_nibble($bytes->[6])/1000;
  687. $train *= 25.4; # convert from inch to mm
  688. push @res, {
  689. device => $dev_str,
  690. type => 'rain',
  691. current => $rain,
  692. units => 'mm/h',
  693. } ;
  694. push @res, {
  695. device => $dev_str,
  696. type => 'train',
  697. current => $train,
  698. units => 'mm',
  699. };
  700. # hexline debugging
  701. #push @res, {
  702. # device => $dev_str,
  703. # type => 'hexline',
  704. # current => $hexline,
  705. # units => 'hex',
  706. # };
  707. OREGON_simple_battery($bytes, $dev_str, \@res);
  708. return @res;
  709. }
  710. # -----------------------------
  711. # CHECKSUM METHODS
  712. sub OREGON_checksum1 {
  713. my $hash = $_[1];
  714. my $c = OREGON_hi_nibble($_[0]->[6]) + (OREGON_lo_nibble($_[0]->[7]) << 4);
  715. my $s = ( ( OREGON_nibble_sum(6, $_[0]) + OREGON_lo_nibble($_[0]->[6]) - 0xa) & 0xff);
  716. Log3 $hash, 5, "OREGON: checksum1 = $c berechnet: $s";
  717. $s == $c;
  718. }
  719. sub OREGON_checksum2 {
  720. my $hash = $_[1];
  721. my $c = $_[0]->[8];
  722. my $s = ((OREGON_nibble_sum(8,$_[0]) - 0xa) & 0xff);
  723. Log3 $hash, 5, "OREGON: checksum2 = $c berechnet: $s";
  724. $s == $c;
  725. }
  726. sub OREGON_checksum3 {
  727. $_[0]->[11] == ((OREGON_nibble_sum(11,$_[0]) - 0xa) & 0xff);
  728. }
  729. sub OREGON_checksum4 {
  730. $_[0]->[9] == ((OREGON_nibble_sum(9,$_[0]) - 0xa) & 0xff);
  731. }
  732. sub OREGON_checksum5 {
  733. $_[0]->[10] == ((OREGON_nibble_sum(10,$_[0]) - 0xa) & 0xff);
  734. }
  735. sub OREGON_checksum5plus {
  736. my $hash = $_[1];
  737. my $c = ($_[0]->[10]);
  738. my $s = ((OREGON_nibble_sum(10,$_[0]) - 0xa) & 0xff);
  739. Log3 $hash, 5, "OREGON: checksum5plus = $c berechnet: $s";
  740. $s == $c;
  741. }
  742. sub OREGON_checksum6 {
  743. OREGON_hi_nibble($_[0]->[8]) + (OREGON_lo_nibble($_[0]->[9]) << 4) ==
  744. ((OREGON_nibble_sum(8,$_[0]) - 0xa) & 0xff);
  745. }
  746. sub OREGON_checksum6plus {
  747. my $hash = $_[1];
  748. my $c = OREGON_hi_nibble($_[0]->[8]) + (OREGON_lo_nibble($_[0]->[9]) << 4);
  749. my $s = (((OREGON_nibble_sum(8,$_[0]) + (($_[0]->[8] & 0x0f) - 0x00)) - 0xa) & 0xff);
  750. Log3 $hash, 5, "OREGON: checksum6plus = $c berechnet: $s";
  751. $s == $c;
  752. }
  753. sub OREGON_checksum7 {
  754. $_[0]->[7] == ((OREGON_nibble_sum(7,$_[0]) - 0xa) & 0xff);
  755. }
  756. sub OREGON_checksum8 {
  757. my $hash = $_[1];
  758. my $c = OREGON_hi_nibble($_[0]->[9]) + (OREGON_lo_nibble($_[0]->[10]) << 4);
  759. my $s = ( ( OREGON_nibble_sum(9, $_[0]) + OREGON_lo_nibble($_[0]->[9]) - 0xa) & 0xff);
  760. Log3 $hash, 5, "OREGON: checksum8 = $c berechnet: $s";
  761. $s == $c;
  762. }
  763. sub OREGON_checksum9 {
  764. my $hash = $_[1];
  765. my $c = OREGON_hi_nibble($_[0]->[6]) + (OREGON_lo_nibble($_[0]->[7]) << 4);
  766. my $s = ((OREGON_nibble_sum(6,$_[0]) - 0xa) & 0xff);
  767. Log3 $hash, 5, "OREGON: checksum9 = $c berechnet: $s";
  768. $s == $c;
  769. }
  770. sub OREGON_raw {
  771. $_[0]->{raw} or $_[0]->{raw} = pack 'H*', $_[0]->{hex};
  772. }
  773. # -----------------------------
  774. sub
  775. OREGON_Parse($$)
  776. {
  777. my ($iohash, $msg) = @_;
  778. my $longids = 1;
  779. if (defined($attr{$iohash->{NAME}}{longids})) {
  780. $longids = $attr{$iohash->{NAME}}{longids};
  781. #Log 1,"0: attr longids = $longids";
  782. }
  783. my $time = time();
  784. if ($time_old ==0) {
  785. Log3 $iohash, 5, "OREGON: decoding delay=0 hex=$msg";
  786. } else {
  787. my $time_diff = $time - $time_old ;
  788. Log3 $iohash, 5, "OREGON: decoding delay=$time_diff hex=$msg";
  789. }
  790. $time_old = $time;
  791. # convert to binary
  792. my $bin_msg = pack('H*', $msg);
  793. # convert string to array of bytes. Skip length byte
  794. my @rfxcom_data_array = ();
  795. foreach (split(//, substr($bin_msg,1))) {
  796. push (@rfxcom_data_array, ord($_) );
  797. }
  798. my $bits = ord($bin_msg);
  799. my $bitsMsg = $bits;
  800. my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; }
  801. my $type1 = $rfxcom_data_array[0];
  802. my $type2 = $rfxcom_data_array[1];
  803. my $type = ($type1 << 8) + $type2;
  804. my $sensor_id = unpack('H*', chr $type1) . unpack('H*', chr $type2);
  805. my $key = OREGON_type_length_key($type, $bits);
  806. my $rec = $types{$key} || $types{$key&0xfffff};
  807. if (!$rec) {
  808. $bits -= 4;
  809. $key = OREGON_type_length_key($type, $bits);
  810. $rec = $types{$key} || $types{$key&0xfffff};
  811. if (!$rec) {
  812. $bits -= 4;
  813. $key = OREGON_type_length_key($type, $bits);
  814. $rec = $types{$key} || $types{$key&0xfffff};
  815. if (!$rec) {
  816. Log3 $iohash, 4, "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bitsMsg message='$msg'.";
  817. return "";
  818. }
  819. }
  820. }
  821. Log3 $iohash, 5, "OREGON: sensor_id=$sensor_id BitsMsg=$bitsMsg Bits=$bits";
  822. # test checksum as defines in %types:
  823. my $checksum = $rec->{checksum};
  824. if ($checksum && !$checksum->(\@rfxcom_data_array, $iohash) ) {
  825. Log3 $iohash, 4, "OREGON: ERROR: checksum error sensor_id=$sensor_id (bits=$bits)";
  826. return "";
  827. }
  828. my $method = $rec->{method};
  829. unless ($method) {
  830. Log3 $iohash, 4, "OREGON: Possible message from Oregon part '$rec->{part}'";
  831. Log3 $iohash, 4, "OREGON: sensor_id=$sensor_id (bits=$bits)";
  832. return "";
  833. }
  834. my @res;
  835. if (! defined(&$method)) {
  836. Log3 $iohash, 4, "OREGON: Error: Unknown function=$method. Please define it in file $0";
  837. Log3 $iohash, 4, "OREGON: sensor_id=$sensor_id (bits=$bits)\n";
  838. return "";
  839. } else {
  840. @res = $method->($rec->{part}, $longids, \@rfxcom_data_array);
  841. }
  842. # get device name from first entry
  843. my $device_name = $res[0]->{device};
  844. #Log 1, "device_name=$device_name";
  845. my $def = $modules{OREGON}{defptr}{"$device_name"};
  846. if(!$def) {
  847. Log3 $iohash, 3, "OREGON: Unknown device $device_name, please define it";
  848. return "UNDEFINED $device_name OREGON $device_name";
  849. }
  850. # Use $def->{NAME}, because the device may be renamed:
  851. my $name = $def->{NAME};
  852. #Log 1, "name=$new_name";
  853. return "" if(IsIgnored($name));
  854. my $n = 0;
  855. my $tm = TimeNow();
  856. my $i;
  857. my $val = "";
  858. my $sensor = "";
  859. readingsBeginUpdate($def);
  860. foreach $i (@res){
  861. #print "!> i=".$i."\n";
  862. #printf "%s\t",$i->{device};
  863. if ($i->{type} eq "temp") {
  864. #printf "Temperatur %2.1f %s ; ",$i->{current},$i->{units};
  865. $val .= "T: ".$i->{current}." ";
  866. readingsBulkUpdate($def,"temperature",$i->{current});
  867. ##$sensor = "temperature";
  868. ##$def->{READINGS}{$sensor}{TIME} = $tm;
  869. ##$def->{READINGS}{$sensor}{VAL} = $i->{current};
  870. ##$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};*/
  871. }
  872. elsif ($i->{type} eq "humidity") {
  873. #printf "Luftfeuchtigkeit %d%s, %s ;",$i->{current},$i->{units},$i->{string};
  874. $val .= "H: ".$i->{current}." ";
  875. readingsBulkUpdate($def,"humidity",$i->{current});
  876. ##$sensor = "humidity";
  877. ##$def->{READINGS}{$sensor}{TIME} = $tm;
  878. ##$def->{READINGS}{$sensor}{VAL} = $i->{current};
  879. ##$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};
  880. }
  881. elsif ($i->{type} eq "battery") {
  882. #printf "Batterie %d%s; ",$i->{current},$i->{units};
  883. my @words = split(/\s+/,$i->{current});
  884. $val .= "BAT: ".$words[0]." "; #use only first word
  885. readingsBulkUpdate($def,"battery",$i->{current});
  886. ##$sensor = "battery";
  887. ##$def->{READINGS}{$sensor}{TIME} = $tm;
  888. ##$def->{READINGS}{$sensor}{VAL} = $i->{current};
  889. ##$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  890. } elsif ($i->{type} eq "batteryPercent" || $i->{type} eq "batteryState") {
  891. readingsBulkUpdate($def,$i->{type},$i->{current});
  892. }
  893. elsif ($i->{type} eq "pressure") {
  894. #printf "Luftdruck %d %s, Vorhersage=%s ; ",$i->{current},$i->{units},$i->{forecast};
  895. # do not add it due to problems with hms.gplot
  896. $val .= "P: ".$i->{current}." ";
  897. readingsBulkUpdate($def,"pressure",$i->{current});
  898. readingsBulkUpdate($def,"forecast",$i->{forecast});
  899. #$sensor = "pressure";
  900. #$def->{READINGS}{$sensor}{TIME} = $tm;
  901. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  902. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  903. #$sensor = "forecast";
  904. #$def->{READINGS}{$sensor}{TIME} = $tm;
  905. #$def->{READINGS}{$sensor}{VAL} = $i->{forecast};
  906. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{forecast};;
  907. }
  908. elsif ($i->{type} eq "speed") {
  909. $val .= "W: ".$i->{current}." ";
  910. $val .= "WA: ".$i->{average}." ";
  911. readingsBulkUpdate($def,"wind_speed",$i->{current});
  912. readingsBulkUpdate($def,"wind_avspeed",$i->{average});
  913. #$sensor = "wind_speed";
  914. #$def->{READINGS}{$sensor}{TIME} = $tm;
  915. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  916. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  917. #$sensor = "wind_avspeed";
  918. #$def->{READINGS}{$sensor}{TIME} = $tm;
  919. #$def->{READINGS}{$sensor}{VAL} = $i->{average};
  920. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{average};;
  921. }
  922. elsif ($i->{type} eq "direction") {
  923. $val .= "WD: ".$i->{current}." ";
  924. $val .= "WDN: ".$i->{string}." ";
  925. readingsBulkUpdate($def,"wind_dir",$i->{current} . " " . $i->{string});
  926. #$sensor = "wind_dir";
  927. #$def->{READINGS}{$sensor}{TIME} = $tm;
  928. #$def->{READINGS}{$sensor}{VAL} = $i->{current} . " " . $i->{string};
  929. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current} . " " . $i->{string};;
  930. }
  931. elsif ($i->{type} eq "rain") {
  932. $val .= "RR: ".$i->{current}." ";
  933. readingsBulkUpdate($def,"rain_rate",$i->{current});
  934. #$sensor = "rain_rate";
  935. #$def->{READINGS}{$sensor}{TIME} = $tm;
  936. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  937. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  938. }
  939. elsif ($i->{type} eq "train") {
  940. $val .= "TR: ".$i->{current}." ";
  941. readingsBulkUpdate($def,"rain_total",$i->{current});
  942. #$sensor = "rain_total";
  943. #$def->{READINGS}{$sensor}{TIME} = $tm;
  944. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  945. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  946. }
  947. elsif ($i->{type} eq "flip") {
  948. #$val .= "F: ".$i->{current}." ";
  949. readingsBulkUpdate($def,"rain_flip",$i->{current});
  950. #$sensor = "rain_flip";
  951. #$def->{READINGS}{$sensor}{TIME} = $tm;
  952. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  953. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  954. }
  955. elsif ($i->{type} eq "uv") {
  956. $val .= "UV: ".$i->{current}." ";
  957. $val .= "UVR: ".$i->{risk}." ";
  958. readingsBulkUpdate($def,"uv_val",$i->{current});
  959. readingsBulkUpdate($def,"uv_risk",$i->{risk});
  960. #$sensor = "uv_val";
  961. #$def->{READINGS}{$sensor}{TIME} = $tm;
  962. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  963. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  964. #$sensor = "uv_risk";
  965. #$def->{READINGS}{$sensor}{TIME} = $tm;
  966. #$def->{READINGS}{$sensor}{VAL} = $i->{risk};
  967. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{risk};;
  968. }
  969. elsif ($i->{type} eq "hexline") {
  970. readingsBulkUpdate($def,"hexline",$i->{current});
  971. #$sensor = "hexline";
  972. #$def->{READINGS}{$sensor}{TIME} = $tm;
  973. #$def->{READINGS}{$sensor}{VAL} = $i->{current};
  974. #$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};;
  975. }
  976. else {
  977. print "\nOREGON: Unknown: ";
  978. print "Type: ".$i->{type}.", ";
  979. print "Value: ".$i->{current}."\n";
  980. }
  981. }
  982. if ("$val" ne "") {
  983. # remove heading and trailing space chars from $val
  984. $val =~ s/^\s+|\s+$//g;
  985. Log3 $iohash, 4, "$name decoded Oregon: $val";
  986. readingsBulkUpdate($def, "state", $val);
  987. $def->{STATE} = $val;
  988. #$def->{TIME} = $tm;
  989. #$def->{CHANGED}[$n++] = $val;
  990. }
  991. #
  992. #$def->{READINGS}{state}{TIME} = $tm;
  993. #$def->{READINGS}{state}{VAL} = $val;
  994. #$def->{CHANGED}[$n++] = "state: ".$val;
  995. readingsEndUpdate($def, 1);
  996. #DoTrigger($name, undef);
  997. return $name;
  998. }
  999. 1;
  1000. =pod
  1001. =item summary interprets Oregon sensors received by a rf receiver
  1002. =item summary_DE interpretiert Oregon Sensoren von einem Funkempf&aumlngern
  1003. =begin html
  1004. <a name="OREGON"></a>
  1005. <h3>OREGON</h3>
  1006. <ul>
  1007. The OREGON module interprets Oregon sensor messages received by a RFXCOM or SIGNALduino or CUx receiver. You need to define a receiver (RFXCOM, SIGNALduino or CUx) first.
  1008. See <a href="#RFXCOM">RFXCOM</a>.
  1009. See <a href="#SIGNALduino">SIGNALduino</a>.
  1010. <br><br>
  1011. <a name="OREGONdefine"></a>
  1012. <b>Define</b>
  1013. <ul>
  1014. <code>define &lt;name&gt; OREGON &lt;deviceid&gt;</code> <br>
  1015. <br>
  1016. &lt;deviceid&gt; is the device identifier of the Oregon sensor. It consists of the sensors name and a one byte hex string (00-ff) that identifies the sensor. The define statement with the deviceid is generated automatically by autocreate. The following sensor names are used:
  1017. BTHR918, BTHR918N, PCR800 RGR918, RTGR328N, THN132N, THGR228N, THGR328N, THGR918, THR128, THWR288A, THGR810, UV138, UVN800, WGR918, WGR800, WTGR800_A, WTGR800_T.
  1018. <br>
  1019. The one byte hex string is generated by the Oregon sensor when is it powered on. The value seems to be randomly generated. This has the advantage that you may use more than one Oregon sensor of the same type even if it has no switch to set a sensor id. For exampple the author uses three BTHR918 sensors at the same time. All have different deviceids. The drawback is that the deviceid changes after changing batteries.
  1020. <br><br>
  1021. Example: <br>
  1022. <code>define Kaminzimmer OREGON BTHR918N_ab</code>
  1023. <br>
  1024. </ul>
  1025. <br>
  1026. <a name="OREGONset"></a>
  1027. <b>Set</b> <ul>N/A</ul><br>
  1028. <a name="OREGONget"></a>
  1029. <b>Get</b> <ul>N/A</ul><br>
  1030. <a name="OREGONattr"></a>
  1031. <b>Attributes</b>
  1032. <ul>
  1033. <li><a href="#IODev">IODev</a></li>
  1034. <li><a href="#do_not_notify">do_not_notify</a></li>
  1035. <li><a href="#ignore">ignore</a></li>
  1036. <li><a href="#showtime">showtime</a></li>
  1037. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  1038. </ul>
  1039. </ul>
  1040. =end html
  1041. =cut