21_OWAD.pm 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815
  1. ########################################################################################
  2. #
  3. # OWAD.pm
  4. #
  5. # FHEM module to commmunicate with 1-Wire A/D converters DS2450
  6. #
  7. # Prof. Dr. Peter A. Henning
  8. # Norbert Truchsess
  9. #
  10. # $Id: 21_OWAD.pm 15339 2017-10-29 08:14:07Z phenning $
  11. #
  12. ########################################################################################
  13. #
  14. # This programm is free software; you can redistribute it and/or modify
  15. # it under the terms of the GNU General Public License as published by
  16. # the Free Software Foundation; either version 2 of the License, or
  17. # (at your option) any later version.
  18. #
  19. # The GNU General Public License can be found at
  20. # http://www.gnu.org/copyleft/gpl.html.
  21. # A copy is found in the textfile GPL.txt and important notices to the license
  22. # from the author is found in LICENSE.txt distributed with these scripts.
  23. #
  24. # This script is distributed in the hope that it will be useful,
  25. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. # GNU General Public License for more details.
  28. #
  29. ########################################################################################
  30. package main;
  31. use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
  32. use strict;
  33. use warnings;
  34. use GPUtils qw(:all);
  35. use Time::HiRes qw( gettimeofday );
  36. #add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
  37. BEGIN {
  38. if (!grep(/FHEM\/lib$/,@INC)) {
  39. foreach my $inc (grep(/FHEM$/,@INC)) {
  40. push @INC,$inc."/lib";
  41. };
  42. };
  43. };
  44. use ProtoThreads;
  45. no warnings 'deprecated';
  46. sub Log3($$$);
  47. my $owx_version="7.01";
  48. #-- fixed raw channel name, flexible channel name
  49. my @owg_fixed = ("A","B","C","D");
  50. my @owg_channel = ("A","B","C","D");
  51. #-- channel mode - fixed for now, see initialization
  52. my @owg_mode;
  53. #-- resolution in bit - fixed for now, see initialization
  54. my @owg_resoln;
  55. #-- raw range in mV - fixed for now, see initialization
  56. my @owg_range;
  57. my %gets = (
  58. "id" => ":noArg",
  59. "reading" => ":noArg",
  60. "alarm" => ":noArg",
  61. "status" => ":noArg",
  62. "version" => ":noArg"
  63. );
  64. my %sets = (
  65. "initialize" => "",
  66. "interval" => "",
  67. "AAlarm" => "",
  68. "ALow" => "",
  69. "AHigh" => "",
  70. "BAlarm" => "",
  71. "BLow" => "",
  72. "BHigh" => "",
  73. "CAlarm" => "",
  74. "CLow" => "",
  75. "CHigh" => "",
  76. "DAlarm" => "",
  77. "DLow" => "",
  78. "DHigh" => ""
  79. );
  80. my %updates = (
  81. "present" => "",
  82. "reading" => "",
  83. "alarm" => "",
  84. "status" => ""
  85. );
  86. ########################################################################################
  87. #
  88. # The following subroutines are independent of the bus interface
  89. #
  90. # Prefix = OWAD
  91. #
  92. ########################################################################################
  93. #
  94. # OWAD_Initialize
  95. #
  96. # Parameter hash = hash of device addressed
  97. #
  98. ########################################################################################
  99. sub OWAD_Initialize ($) {
  100. my ($hash) = @_;
  101. $hash->{DefFn} = "OWAD_Define";
  102. $hash->{UndefFn} = "OWAD_Undef";
  103. $hash->{GetFn} = "OWAD_Get";
  104. $hash->{SetFn} = "OWAD_Set";
  105. $hash->{NotifyFn}= "OWAD_Notify";
  106. $hash->{InitFn} = "OWAD_Init";
  107. $hash->{AttrFn} = "OWAD_Attr";
  108. my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 ".
  109. "stateAL0 stateAL1 stateAH0 stateAH1 ".
  110. "interval ".
  111. $readingFnAttributes;
  112. for( my $i=0;$i<int(@owg_fixed);$i++ ){
  113. $attlist .= " ".$owg_fixed[$i]."Name";
  114. $attlist .= " ".$owg_fixed[$i]."Function";
  115. $attlist .= " ".$owg_fixed[$i]."Unit";
  116. $attlist .= " ".$owg_fixed[$i]."Alarm:none,low,high,both";
  117. $attlist .= " ".$owg_fixed[$i]."Low";
  118. $attlist .= " ".$owg_fixed[$i]."High";
  119. }
  120. $hash->{AttrList} = $attlist;
  121. #-- value globals
  122. $hash->{owg_status} = [];
  123. #$hash->{owg_state} = undef;
  124. #-- channel values - always the raw values from the device
  125. $hash->{owg_val} = ["","","",""];
  126. #-- alarm status 0 = disabled, 1 = enabled, but not alarmed, 2 = alarmed
  127. $hash->{owg_slow}=[0,0,0,0];
  128. $hash->{owg_shigh}=[0,0,0,0];
  129. #-- alarm values - always the raw values committed to the device
  130. $hash->{owg_vlow} = [];
  131. $hash->{owg_vhigh} = [];
  132. #-- make sure OWX is loaded so OWX_CRC is available if running with OWServer
  133. main::LoadModule("OWX");
  134. }
  135. #########################################################################################
  136. #
  137. # OWAD_Define - Implements DefFn function
  138. #
  139. # Parameter hash = hash of device addressed, def = definition string
  140. #
  141. #########################################################################################
  142. sub OWAD_Define ($$) {
  143. my ($hash, $def) = @_;
  144. my @a = split("[ \t][ \t]*", $def);
  145. my ($name,$model,$fam,$id,$crc,$interval,$scale,$ret);
  146. #-- default
  147. $name = $a[0];
  148. $interval = 300;
  149. $scale = "";
  150. $ret = "";
  151. #-- check syntax
  152. return "OWAD: Wrong syntax, must be define <name> OWAD [<model>] <id> [interval] or OWAD <fam>.<id> [interval]"
  153. if(int(@a) < 2 || int(@a) > 5);
  154. #-- different types of definition allowed
  155. my $a2 = $a[2];
  156. my $a3 = defined($a[3]) ? $a[3] : "";
  157. #-- no model, 12 characters
  158. if( $a2 =~ m/^[0-9|a-f|A-F]{12}$/ ) {
  159. $model = "DS2450";
  160. $fam = "20";
  161. $id = $a[2];
  162. if(int(@a)>=4) { $interval = $a[3]; }
  163. #-- no model, 2+12 characters
  164. } elsif( $a2 =~ m/^[0-9|a-f|A-F]{2}\.[0-9|a-f|A-F]{12}$/ ) {
  165. $fam = substr($a[2],0,2);
  166. $id = substr($a[2],3);
  167. if(int(@a)>=4) { $interval = $a[3]; }
  168. if( $fam eq "20" ){
  169. $model = "DS2450";
  170. CommandAttr (undef,"$name model DS2450");
  171. }else{
  172. return "OWAD: Wrong 1-Wire device family $fam";
  173. }
  174. #-- model, 12 characters
  175. } elsif( $a3 =~ m/^[0-9|a-f|A-F]{12}$/ ) {
  176. $model = $a[2];
  177. $id = $a[3];
  178. if(int(@a)>=5) { $interval = $a[4]; }
  179. if( $model eq "DS2450" ){
  180. $fam = "20";
  181. CommandAttr (undef,"$name model DS2450");
  182. }else{
  183. return "OWAD: Wrong 1-Wire device model $model";
  184. }
  185. } else {
  186. return "OWAD: $a[0] ID $a[2] invalid, specify a 12 or 2.12 digit value";
  187. }
  188. #-- determine CRC Code
  189. $crc = sprintf("%02x",OWX_CRC($fam.".".$id."00"));
  190. #-- Define device internals
  191. $hash->{ROM_ID} = "$fam.$id.$crc";
  192. $hash->{OW_ID} = $id;
  193. $hash->{OW_FAMILY} = $fam;
  194. $hash->{PRESENT} = 0;
  195. $hash->{INTERVAL} = $interval;
  196. $hash->{ERRCOUNT} = 0;
  197. $hash->{ERRSTATE} = 0;
  198. #-- Couple to I/O device
  199. AssignIoPort($hash);
  200. if( !defined($hash->{IODev}) or !defined($hash->{IODev}->{NAME}) ){
  201. return "OWAD: Warning, no 1-Wire I/O device found for $name.";
  202. } else {
  203. $hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0; #-- false for now
  204. }
  205. $main::modules{OWAD}{defptr}{$id} = $hash;
  206. #--
  207. readingsSingleUpdate($hash,"state","defined",1);
  208. Log 3, "OWAD: Device $name defined.";
  209. $hash->{NOTIFYDEV} = "global";
  210. if ($init_done) {
  211. OWAD_Init($hash);
  212. }
  213. return undef;
  214. }
  215. ######################################################################################
  216. #
  217. # OWAD_Notify Function -
  218. # Parameter hash = hash of device addressed
  219. # dev = device
  220. #
  221. ######################################################################################
  222. sub OWAD_Notify ($$) {
  223. my ($hash,$dev) = @_;
  224. if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
  225. OWAD_Init($hash);
  226. } elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
  227. }
  228. }
  229. #####################################################################################
  230. #
  231. # OWAD_Init Function -
  232. # Parameter hash = hash of device addressed
  233. #
  234. #
  235. ######################################################################################
  236. sub OWAD_Init ($) {
  237. my ($hash)=@_;
  238. #-- Start timer for updates
  239. RemoveInternalTimer($hash);
  240. InternalTimer(gettimeofday()+10, "OWAD_InitializeDevice", $hash, 0);
  241. return undef;
  242. }
  243. #######################################################################################
  244. #
  245. # OWAD_Attr - Set one attribute value for device
  246. #
  247. # Parameter hash = hash of device addressed
  248. # a = argument array
  249. #
  250. ########################################################################################
  251. sub OWAD_Attr(@) {
  252. my ($do,$name,$key,$value) = @_;
  253. my $hash = $defs{$name};
  254. my $ret;
  255. if ( $do eq "set") {
  256. ARGUMENT_HANDLER: {
  257. #-- interval modified at runtime
  258. $key eq "interval" and do {
  259. #-- check value
  260. return "OWAD: set $name interval, must be >= 0" if(int($value) < 0);
  261. #-- update timer
  262. $hash->{INTERVAL} = int($value);
  263. if ($init_done) {
  264. RemoveInternalTimer($hash);
  265. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0);
  266. }
  267. last;
  268. };
  269. #-- alarm settings modified at runtime
  270. $key =~ m/(.*)(Alarm|Low|High)/ and do {
  271. #-- safeguard against uninitialized devices
  272. return undef
  273. if( $hash->{READINGS}{"state"}{VAL} eq "defined" );
  274. $ret = OWAD_Set($hash,($name,$key,$value));
  275. last;
  276. };
  277. $key eq "IODev" and do {
  278. AssignIoPort($hash,$value);
  279. if( defined($hash->{IODev}) ) {
  280. $hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
  281. if ($init_done) {
  282. OWAD_Init($hash);
  283. }
  284. }
  285. last;
  286. };
  287. }
  288. } elsif ( $do eq "del" ) {
  289. ARGUMENT_HANDLER: {
  290. #-- should remove alarm setting, but does nothing so far
  291. $key =~ m/(.*)(Alarm)/ and do {
  292. last;
  293. }
  294. }
  295. }
  296. return $ret;
  297. }
  298. ########################################################################################
  299. #
  300. # OWAD_ChannelNames - find the real channel names
  301. #
  302. # Parameter hash = hash of device addressed
  303. #
  304. ########################################################################################
  305. sub OWAD_ChannelNames($) {
  306. my ($hash) = @_;
  307. my $name = $hash->{NAME};
  308. my $state = $hash->{READINGS}{"state"}{VAL};
  309. my ($cname,@cnama,$unit);
  310. for (my $i=0;$i<int(@owg_fixed);$i++){
  311. #-- name
  312. $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : "$owg_fixed[$i]";
  313. @cnama = split(/\|/,$cname);
  314. if( int(@cnama)!=2){
  315. push(@cnama,$cnama[0]);
  316. }
  317. $owg_channel[$i]=$cnama[0];
  318. #-- unit
  319. $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "V";
  320. if($unit eq "none"){
  321. $unit = "";
  322. }else{
  323. $unit = " ".$unit;
  324. }
  325. #-- put into readings
  326. $hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1];
  327. $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit;
  328. }
  329. }
  330. ########################################################################################
  331. #
  332. # OWAD_FormatValues - put together various format strings
  333. #
  334. # Parameter hash = hash of device addressed, fs = format string
  335. #
  336. ########################################################################################
  337. sub OWAD_FormatValues($) {
  338. my ($hash) = @_;
  339. my $name = $hash->{NAME};
  340. my $interface = $hash->{IODev}->{TYPE};
  341. my ($vval,$vlow,$vhigh,$vfunc,$ret);
  342. my $vfuncall = "";
  343. my $svalue = "";
  344. #-- insert initial values
  345. for( my $k=0;$k<int(@owg_fixed);$k++ ){
  346. #-- TODO $hash->{owg_val}->[..] might be undefined here?
  347. $vfuncall .= "\$hash->{owg_val}->[$k]=$hash->{owg_val}->[$k];";
  348. }
  349. my $alarm;
  350. my $galarm = 0;
  351. my $achange = 0;
  352. my $schange = 0;
  353. #-- alarm signatures
  354. my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "↓";
  355. my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "↑";
  356. my $stateal0 = defined($attr{$name}{stateAL0}) ? $attr{$name}{stateAL0} : "";
  357. my $stateah0 = defined($attr{$name}{stateAH0}) ? $attr{$name}{stateAH0} : "";
  358. #-- no change in any value if invalid reading
  359. for (my $i=0;$i<int(@owg_fixed);$i++){
  360. return "" if( (!defined($hash->{owg_val}->[$i])) || ($hash->{owg_val}->[$i] eq "") );
  361. }
  362. #-- obtain channel names
  363. OWAD_ChannelNames($hash);
  364. #-- put into READINGS
  365. readingsBeginUpdate($hash);
  366. #-- formats for output
  367. for (my $i=0;$i<int(@owg_fixed);$i++){
  368. if (defined($attr{$name}{$owg_fixed[$i]."Function"})){
  369. $vfunc = $attr{$name}{$owg_fixed[$i]."Function"};
  370. } else {
  371. $vfunc = "V$owg_fixed[$i]";
  372. }
  373. $hash->{tempf}{$owg_fixed[$i]}{function} = $vfunc;
  374. #-- replace by proper values (VA -> $hash->{owg_val}->[0] etc.)
  375. # careful: how to prevent {VAL} from being replaced ?
  376. for( my $k=0;$k<int(@owg_fixed);$k++ ){
  377. my $sstr = "V$owg_fixed[$k]";
  378. $vfunc =~ s/VAL/WERT/g;
  379. $vfunc =~ s/$sstr/\$hash->{owg_val}->[$k]/g;
  380. $vfunc =~ s/WERT/VAL/g;
  381. }
  382. #-- determine the measured value from the function
  383. $vfunc = $vfuncall.$vfunc;
  384. $vfunc = eval($vfunc);
  385. if( !$vfunc ){
  386. $vval = 0.0;
  387. } elsif( $vfunc ne "" ){
  388. $vval = $vfunc;
  389. } else {
  390. $vval = "???";
  391. }
  392. #-- low alarm value
  393. $vlow =$hash->{owg_vlow}->[$i];
  394. $main::attr{$name}{$owg_fixed[$i]."Low"}=$vlow;
  395. #-- high alarm value
  396. $vhigh=$hash->{owg_vhigh}->[$i];
  397. $main::attr{$name}{$owg_fixed[$i]."High"}=$vhigh;
  398. #-- string buildup for return value, STATE and alarm
  399. $svalue .= sprintf( "%s: %5.3f%s", $hash->{READINGS}{$owg_channel[$i]}{ABBR}, $vval,$hash->{READINGS}{$owg_channel[$i]}{UNIT});
  400. #-- Test for alarm condition
  401. $alarm = "none";
  402. #-- alarm signature low
  403. #-- TODO may be undefined here?
  404. if( $hash->{owg_slow}->[$i] == 0 ) {
  405. } else {
  406. $alarm="low";
  407. if( $vval > $vlow ){
  408. $hash->{owg_slow}->[$i] = 1;
  409. $svalue .= $stateal0;
  410. } else {
  411. $galarm = 1;
  412. $hash->{owg_slow}->[$i] = 2;
  413. $svalue .= $stateal1;
  414. }
  415. }
  416. #-- alarm signature high
  417. #-- TODO may be undefined here?
  418. if( $hash->{owg_shigh}->[$i] == 0 ) {
  419. } else {
  420. if( $alarm eq "low") {
  421. $alarm="both";
  422. }else{
  423. $alarm="high";
  424. }
  425. if( $vval < $vhigh ){
  426. $hash->{owg_shigh}->[$i] = 1;
  427. $svalue .= $stateah0;
  428. } else {
  429. $galarm = 1;
  430. $hash->{owg_shigh}->[$i] = 2;
  431. $svalue .= $stateah1;
  432. }
  433. }
  434. #-- put into READINGS
  435. $vval = sprintf( "%5.3f", $vval);
  436. readingsBulkUpdate($hash,"$owg_channel[$i]",$vval);
  437. #-- insert space
  438. if( $i<int(@owg_fixed)-1 ){
  439. $svalue .= " ";
  440. }
  441. }
  442. #-- STATE
  443. readingsBulkUpdate($hash,"state",$svalue);
  444. readingsEndUpdate($hash,1);
  445. if( $galarm != $hash->{ALARM} ){
  446. $hash->{ALARM} = $galarm;
  447. main::OWX_Alarms($hash->{IODev});
  448. }
  449. return $svalue;
  450. }
  451. ########################################################################################
  452. #
  453. # OWAD_Get - Implements GetFn function
  454. #
  455. # Parameter hash = hash of device addressed, a = argument array
  456. #
  457. ########################################################################################
  458. sub OWAD_Get($@) {
  459. my ($hash, @a) = @_;
  460. my $reading = $a[1];
  461. my $name = $hash->{NAME};
  462. my $model = $hash->{OW_MODEL};
  463. #-- ID of the device, hash of the busmaster
  464. my $owx_dev = $hash->{ROM_ID};
  465. my $master = $hash->{IODev};
  466. my $interface= $hash->{IODev}->{TYPE};
  467. my ($value,$value2,$value3) = (undef,undef,undef);
  468. my $ret = "";
  469. #-- check syntax
  470. return "OWAD: Get argument is missing @a"
  471. if(int(@a) != 2);
  472. #-- check argument
  473. my $msg = "OWAD: Get with unknown argument $a[1], choose one of ";
  474. $msg .= "$_$gets{$_} " foreach (keys%gets);
  475. return $msg
  476. if(!defined($gets{$a[1]}));
  477. #-- get id
  478. if($a[1] eq "id") {
  479. $value = $owx_dev;
  480. return "$name.id => $value";
  481. }
  482. #-- get version
  483. if( $a[1] eq "version") {
  484. return "$name.version => $owx_version";
  485. }
  486. #-- reset current ERRSTATE
  487. $hash->{ERRSTATE} = 0;
  488. #-- get reading according to interface type
  489. if($a[1] eq "reading") {
  490. #-- OWX interface
  491. if( $interface eq "OWX" ){
  492. $ret = OWXAD_GetPage($hash,"reading",1);
  493. }elsif( $interface eq "OWX_ASYNC" ){
  494. eval {
  495. $ret = OWX_ASYNC_RunToCompletion($hash,OWXAD_PT_GetPage($hash,"reading",1));
  496. };
  497. $ret = GP_Catch($@) if $@;
  498. #-- OWFS interface
  499. }elsif( $interface eq "OWServer" ){
  500. $ret = OWFSAD_GetPage($hash,"reading",1);
  501. #-- Unknown interface
  502. }else{
  503. return "OWAD: Get with wrong IODev type $interface";
  504. }
  505. #-- process result
  506. if( $master->{ASYNCHRONOUS} ){
  507. return undef;
  508. }else{
  509. if( defined($ret) ){
  510. $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
  511. return "OWAD: Could not get reading from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
  512. }
  513. return "OWAD: $name.reading => ".$hash->{READINGS}{"state"}{VAL};
  514. }
  515. }
  516. #-- get alarm values according to interface type
  517. if($a[1] eq "alarm") {
  518. #-- OWX interface
  519. if( $interface eq "OWX" ){
  520. $ret = OWXAD_GetPage($hash,"alarm",1);
  521. }elsif( $interface eq "OWX_ASYNC" ){
  522. eval {
  523. $ret = OWX_ASYNC_RunToCompletion($hash,OWXAD_PT_GetPage($hash,"alarm",1));
  524. };
  525. $ret = GP_Catch($@) if $@;
  526. #-- OWFS interface
  527. }elsif( $interface eq "OWServer" ){
  528. $ret = OWFSAD_GetPage($hash,"alarm",1);
  529. #-- Unknown interface
  530. }else{
  531. return "OWAD: Get with wrong IODev type $interface";
  532. }
  533. #-- process result
  534. if( $master->{ASYNCHRONOUS} ){
  535. return undef;
  536. }else{
  537. if( defined($ret) ){
  538. $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
  539. return "OWAD: Could not get alarm values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
  540. }
  541. #-- assemble ouput string
  542. $value = "";
  543. for (my $i=0;$i<int(@owg_fixed);$i++){
  544. $value .= sprintf "%s:[%4.2f,%4.2f] ",$owg_channel[$i],
  545. $main::attr{$name}{$owg_channel[$i]."Low"},
  546. $main::attr{$name}{$owg_channel[$i]."High"};
  547. }
  548. return "OWAD: $name.alarm => $value";
  549. }
  550. }
  551. #-- get status values according to interface type
  552. if($a[1] eq "status") {
  553. #-- OWX interface
  554. if( $interface eq "OWX" ){
  555. $ret = OWXAD_GetPage($hash,"status",1);
  556. }elsif( $interface eq "OWX_ASYNC" ){
  557. eval {
  558. $ret = OWX_ASYNC_RunToCompletion($hash,OWXAD_PT_GetPage($hash,"status",1));
  559. };
  560. $ret = GP_Catch($@) if $@;
  561. #-- OWFS interface
  562. }elsif( $interface eq "OWServer" ){
  563. $ret = OWFSAD_GetPage($hash,"status",1);
  564. #-- Unknown interface
  565. }else{
  566. return "OWAD: Get with wrong IODev type $interface";
  567. }
  568. #-- process result
  569. if( $master->{ASYNCHRONOUS} ){
  570. #return "OWAD: $name getting status, please wait for completion";
  571. return undef;
  572. }else{
  573. if( defined($ret) ){
  574. $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
  575. return "OWAD: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
  576. }
  577. #-- assemble output string
  578. $value = "\n";
  579. for (my $i=0;$i<int(@owg_fixed);$i++){
  580. $value .= $owg_channel[$i].": ".$owg_mode[$i].", ";
  581. #$value .= "disabled ,"
  582. # if ( !($sb2 && 128) );
  583. $value .= sprintf "raw range %3.2f V, ",$owg_range[$i]/1000;
  584. $value .= sprintf "resolution %d bit, ",$owg_resoln[$i];
  585. if (!defined $hash->{owg_slow}->[$i]) {
  586. $value .= "low alarm undefined, ";
  587. } elsif( $hash->{owg_slow}->[$i]==0 ) {
  588. $value .= "low alarm disabled, ";
  589. } elsif( $hash->{owg_slow}->[$i]==1 ) {
  590. $value .= "low alarm enabled, ";
  591. } elsif( $hash->{owg_slow}->[$i]==2 ) {
  592. $value .= "alarmed low, ";
  593. }
  594. if (!defined $hash->{owg_shigh}) {
  595. $value .= "high alarm undefined";
  596. } elsif( $hash->{owg_shigh}->[$i]==0 ) {
  597. $value .= "high alarm disabled";
  598. } elsif( $hash->{owg_shigh}->[$i]==1 ) {
  599. $value .= "high alarm enabled";
  600. } elsif( $hash->{owg_shigh}->[$i]==2 ) {
  601. $value .= "alarmed high";
  602. }
  603. #-- insert space
  604. if( $i<int(@owg_fixed)-1 ){
  605. $value .= "\n";
  606. }
  607. }
  608. return "OWAD: $name.status => ".$value;
  609. }
  610. }
  611. }
  612. #######################################################################################
  613. #
  614. # OWAD_GetValues - Updates the reading from one device
  615. #
  616. # Parameter hash = hash of device addressed
  617. #
  618. ########################################################################################
  619. sub OWAD_GetValues($) {
  620. my $hash = shift;
  621. my $name = $hash->{NAME};
  622. my $model = $hash->{OW_MODEL};
  623. my $interface= $hash->{IODev}->{TYPE};
  624. my $value = "";
  625. my $ret = "";
  626. my ($ret1,$ret2,$ret3);
  627. #-- define warnings
  628. my $warn = "none";
  629. $hash->{ALARM} = "0";
  630. RemoveInternalTimer($hash);
  631. #-- auto-update for device disabled;
  632. return undef
  633. if( $hash->{INTERVAL} == 0 );
  634. #-- restart timer for updates
  635. InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0);
  636. #-- reset current ERRSTATE
  637. $hash->{ERRSTATE} = 0;
  638. #-- Get readings, alarms and status according to interface type
  639. if( $interface eq "OWX" ){
  640. $ret1 = OWXAD_GetPage($hash,"reading",0);
  641. $ret2 = OWXAD_GetPage($hash,"alarm",0);
  642. $ret3 = OWXAD_GetPage($hash,"status",1);
  643. }elsif( $interface eq "OWX_ASYNC" ){
  644. eval {
  645. OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"reading",0));
  646. OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"alarm",0));
  647. OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"status",1));
  648. };
  649. $ret .= GP_Catch($@) if $@;
  650. }elsif( $interface eq "OWServer" ){
  651. $ret1 = OWFSAD_GetPage($hash,"reading",0);
  652. $ret2 = OWFSAD_GetPage($hash,"alarm",0);
  653. $ret3 = OWFSAD_GetPage($hash,"status",1);
  654. }else{
  655. return "OWAD: GetValues with wrong IODev type $interface";
  656. }
  657. #-- process results
  658. $ret .= $ret1
  659. if( defined($ret1) );
  660. $ret .= $ret2
  661. if( defined($ret2) );
  662. $ret .= $ret3
  663. if( defined($ret3) );
  664. if( $ret ne "" ){
  665. return "OWAD: Could not get reading, alarm and status values from device $name, reason $ret";
  666. }
  667. return undef;
  668. }
  669. ########################################################################################
  670. #
  671. # OWAD_InitializeDevice - delayed setting of initial readings and channel names
  672. #
  673. # Parameter hash = hash of device addressed
  674. #
  675. ########################################################################################
  676. sub OWAD_InitializeDevice($) {
  677. my ($hash) = @_;
  678. my $name = $hash->{NAME};
  679. my $interface = $hash->{IODev}->{TYPE};
  680. my $ret="";
  681. my ($ret1,$ret2);
  682. #-- Initial readings
  683. $hash->{owg_val} = ["","","",""];
  684. #-- Initial alarm values
  685. for( my $i=0;$i<int(@owg_fixed);$i++) {
  686. $hash->{ERRCOUNT} = 0;
  687. #-- alarm enabling
  688. if( AttrVal($name,$owg_fixed[$i]."Alarm",undef) ){
  689. my $alarm = AttrVal($name,$owg_fixed[$i]."Alarm",undef);
  690. if( $alarm eq "none" ){
  691. $hash->{owg_slow}->[$i]=0;
  692. $hash->{owg_shigh}->[$i]=0;
  693. }elsif( $alarm eq "low" ){
  694. $hash->{owg_slow}->[$i]=1;
  695. $hash->{owg_shigh}->[$i]=0;
  696. }elsif( $alarm eq "high" ){
  697. $hash->{owg_slow}->[$i]=0;
  698. $hash->{owg_shigh}->[$i]=1;
  699. }elsif( $alarm eq "both" ){
  700. $hash->{owg_slow}->[$i]=1;
  701. $hash->{owg_shigh}->[$i]=1;
  702. }
  703. } else {
  704. $hash->{owg_slow}->[$i]=0;
  705. $hash->{owg_shigh}->[$i]=0;
  706. }
  707. #-- low alarm value - no checking for correct parameters
  708. if( AttrVal($name,$owg_fixed[$i]."Low",undef) ){
  709. $hash->{owg_vlow}->[$i] = $main::attr{$name}{$owg_fixed[$i]."Low"};
  710. } else {
  711. $hash->{owg_vlow}->[$i] = 0;
  712. }
  713. #-- high alarm value
  714. if( AttrVal($name,$owg_fixed[$i]."High",undef) ){
  715. $hash->{owg_vhigh}->[$i] = $main::attr{$name}{$owg_fixed[$i]."High"};
  716. } else {
  717. $hash->{owg_vhigh}->[$i] = 0;
  718. }
  719. }
  720. #-- resolution in bit - fixed for now
  721. @owg_resoln = (16,16,16,16);
  722. #-- raw range in mV - fixed for now
  723. @owg_range = (5120,5120,5120,5120);
  724. #-- mode - fixed for now
  725. @owg_mode = ("input","input","input","input");
  726. #-- OWX interface
  727. if( $interface eq "OWX" ){
  728. $ret1 = OWXAD_SetPage($hash,"status");
  729. $ret2 = OWXAD_SetPage($hash,"alarm");
  730. }elsif( $interface eq "OWX_ASYNC" ){
  731. eval {
  732. OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"status"));
  733. OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"alarm"));
  734. };
  735. $ret .= GP_Catch($@) if $@;
  736. #-- OWFS interface
  737. }elsif( $interface eq "OWServer" ){
  738. $ret1 = OWFSAD_SetPage($hash,"status");
  739. $ret2 = OWFSAD_SetPage($hash,"alarm");
  740. }
  741. #-- process results
  742. $ret .= $ret1
  743. if( defined($ret1) );
  744. $ret .= $ret2
  745. if( defined($ret2) );
  746. if( $ret ne "" ){
  747. return "OWAD: Could not initialize device $name, reason: ".$ret;
  748. }
  749. #-- Set state to initialized
  750. readingsSingleUpdate($hash,"state","initialized",1);
  751. return OWAD_GetValues($hash);
  752. }
  753. #######################################################################################
  754. #
  755. # OWAD_Set - Set one value for device
  756. #
  757. # Parameter hash = hash of device addressed
  758. # a = argument array
  759. #
  760. ########################################################################################
  761. sub OWAD_Set($@) {
  762. my ($hash, @a) = @_;
  763. my $key = $a[1];
  764. my $value = $a[2];
  765. #-- for the selector: which values are possible
  766. return join(" ", sort keys %sets) if(@a == 2);
  767. #-- check syntax
  768. return "OWAD: Set needs one parameter when setting this value"
  769. if( int(@a)!=3 );
  770. #-- check argument
  771. if( !defined($sets{$a[1]}) && !($key =~ m/.*(Alarm|Low|High)/) ){
  772. return "OWAD: Set with unknown argument $a[1]";
  773. }
  774. #-- define vars
  775. my $ret = undef;
  776. my $channon = undef;
  777. my $channo = undef;
  778. my $condx;
  779. my $name = $hash->{NAME};
  780. my $model = $hash->{OW_MODEL};
  781. #-- re-intialize
  782. if($key eq "initialize") {
  783. OWAD_InitializeDevice($hash);
  784. return undef;
  785. }
  786. #-- set new timer interval
  787. if($key eq "interval") {
  788. # check value
  789. return "OWAD: set $name interval must be >= 0"
  790. if(int($value) < 0);
  791. # update timer
  792. $hash->{INTERVAL} = int($value);
  793. RemoveInternalTimer($hash);
  794. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0);
  795. return undef;
  796. }
  797. #-- find out which channel we have
  798. my $tc =$key;
  799. if( $tc =~ s/(.*)(Alarm|Low|High)/$channon=$1/se ) {
  800. for (my $i=0;$i<int(@owg_fixed);$i++){
  801. if( $tc eq $owg_fixed[$i] ){
  802. $channo = $i;
  803. $channon = $tc;
  804. last;
  805. }
  806. }
  807. }
  808. return "OWAD: Cannot determine channel from parameter $a[1]"
  809. if( !(defined($channo)));
  810. #-- set these values depending on interface type
  811. my $interface= $hash->{IODev}->{TYPE};
  812. #-- set status values (alarm on or off)
  813. if( $key =~ m/(.*)(Alarm)/ ) {
  814. return "OWAD: Set with wrong value $value for $key, allowed is none/low/high/both"
  815. if($value ne "none" && $value ne "low" && $value ne "high" && $value ne "both");
  816. #-- put into attribute value
  817. if( $main::attr{$name}{$owg_fixed[$channo]."Alarm"} ne $value ){
  818. #Log 1,"OWAD: Correcting attribute value ".$owg_fixed[$channo]."Alarm";
  819. $main::attr{$name}{$owg_fixed[$channo]."Alarm"} = $value
  820. }
  821. #-- put into device
  822. if( $value eq "low" || $value eq "both" ){
  823. $hash->{owg_slow}->[$channo]=1;
  824. } else{
  825. $hash->{owg_slow}->[$channo]=0;
  826. }
  827. if( $value eq "high" || $value eq "both" ){
  828. $hash->{owg_shigh}->[$channo]=1;
  829. } else{
  830. $hash->{owg_shigh}->[$channo]=0;
  831. }
  832. #-- OWX interface
  833. if( $interface eq "OWX" ){
  834. $ret = OWXAD_SetPage($hash,"status");
  835. }elsif( $interface eq "OWX_ASYNC" ){
  836. eval {
  837. OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"status"));
  838. };
  839. $ret = GP_Catch($@) if $@;
  840. #-- OWFS interface
  841. }elsif( $interface eq "OWServer" ){
  842. $ret = OWFSAD_SetPage($hash,"status");
  843. } else {
  844. return "OWAD: Set with wrong IODev type $interface";
  845. }
  846. #-- process results
  847. if( defined($ret) ){
  848. return "OWAD: Could not set device $name, reason: ".$ret;
  849. }
  850. #-- set alarm values (alarm voltages)
  851. }elsif( $key =~ m/(.*)(Low|High)/ ) {
  852. #-- find upper and lower boundaries
  853. my $mmin = 0.0;
  854. my $mmax = $owg_range[$channo]/1000;
  855. return sprintf("OWAD: Set with wrong value $value for $key, range is [%3.1f,%3.1f]",$mmin,$mmax)
  856. if($value < $mmin || $value > $mmax);
  857. #-- round to those numbers understood by the device
  858. my $value2 = int($value*256000/$owg_range[$channo]+0.5)*$owg_range[$channo]/256000;
  859. if( $key =~ m/(.*)Low/ ){
  860. #-- put into attribute value
  861. if( $main::attr{$name}{$owg_fixed[$channo]."Low"} != $value2 ){
  862. Log 1,"OWAD: Correcting attribute value ".$owg_fixed[$channo]."Low";
  863. $main::attr{$name}{$owg_fixed[$channo]."Low"} = $value2
  864. }
  865. #-- put into device
  866. $hash->{owg_vlow}->[$channo] = $value2;
  867. } elsif( $key =~ m/(.*)High/ ){
  868. #-- put into attribute value
  869. if( $main::attr{$name}{$owg_fixed[$channo]."High"} != $value2 ){
  870. Log 1,"OWAD: Correcting attribute value ".$owg_fixed[$channo]."High";
  871. $main::attr{$name}{$owg_fixed[$channo]."High"} = $value2
  872. }
  873. #-- put into device
  874. $hash->{owg_vhigh}->[$channo] = $value2;
  875. }
  876. #-- OWX interface
  877. if( $interface eq "OWX" ){
  878. $ret = OWXAD_SetPage($hash,"alarm");
  879. }elsif( $interface eq "OWX_ASYNC" ){
  880. eval {
  881. OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"status"));
  882. };
  883. $ret = GP_Catch($@) if $@;
  884. #-- OWFS interface
  885. }elsif( $interface eq "OWServer" ){
  886. $ret = OWFSAD_SetPage($hash,"alarm");
  887. } else {
  888. return "OWAD: Set with wrong IODev type $interface";
  889. }
  890. #-- process results
  891. if( defined($ret) ){
  892. return "OWAD: Could not set device $name, reason: ".$ret;
  893. }
  894. }
  895. #-- process results - we have to reread the device
  896. OWAD_GetValues($hash);
  897. Log 4, "OWAD: Set $hash->{NAME} $key $value";
  898. return undef;
  899. }
  900. ########################################################################################
  901. #
  902. # OWAD_Undef - Implements UndefFn function
  903. #
  904. # Parameter hash = hash of device addressed
  905. #
  906. ########################################################################################
  907. sub OWAD_Undef ($) {
  908. my ($hash) = @_;
  909. delete($main::modules{OWAD}{defptr}{$hash->{OW_ID}});
  910. RemoveInternalTimer($hash);
  911. return undef;
  912. }
  913. ########################################################################################
  914. #
  915. # The following subroutines in alphabetical order are only for a 1-Wire bus connected
  916. # via OWFS
  917. #
  918. # Prefix = OWFSAD
  919. #
  920. ########################################################################################
  921. #
  922. # OWFSAD_GetPage - Get one memory page from device
  923. #
  924. # Parameter hash = hash of device addressed
  925. # page = "reading", "alarm" or "status"
  926. # final= 1 if FormatValues is to be called
  927. #
  928. ########################################################################################
  929. sub OWFSAD_GetPage($$$) {
  930. my ($hash,$page,$final) = @_;
  931. #-- ID of the device
  932. my $owx_add = substr($hash->{ROM_ID},0,15);
  933. #-- hash of the busmaster
  934. my $master = $hash->{IODev};
  935. my $name = $hash->{NAME};
  936. my ($rel,$rel2,@ral,@ral2,$i,$an,$vn);
  937. #-- reset presence
  938. $hash->{PRESENT} = 0;
  939. #=============== get the voltage reading ===============================
  940. if( $page eq "reading"){
  941. #-- get values - or should we rather use the uncached ones ?
  942. $rel = OWServer_Read($master,"/$owx_add/volt.ALL");
  943. return "no return from OWServer"
  944. if( !defined($rel) );
  945. return "empty return from OWServer"
  946. if( $rel eq "" );
  947. @ral = split(/,/,$rel);
  948. return "wrong data length from OWServer"
  949. if( int(@ral) != 4);
  950. for( $i=0;$i<int(@owg_fixed);$i++){
  951. $hash->{owg_val}->[$i]= int($ral[$i]*1000)/1000;
  952. }
  953. #=============== get the alarm reading ===============================
  954. } elsif ( $page eq "alarm" ) {
  955. #-- get values - or should we rather use the uncached ones ?
  956. $rel = OWServer_Read($master,"/$owx_add/set_alarm/voltlow.ALL");
  957. $rel2 = OWServer_Read($master,"/$owx_add/set_alarm/volthigh.ALL");
  958. return "no return from OWServer"
  959. if( (!defined($rel)) || (!defined($rel2)) );
  960. return "empty return from OWServer"
  961. if( ($rel eq "") || ($rel2 eq "") );
  962. @ral = split(/,/,$rel);
  963. @ral2= split(/,/,$rel2);
  964. return "wrong data length from OWServer"
  965. if( (int(@ral) != 4) || (int(@ral2) != 4) );
  966. for( $i=0;$i<int(@owg_fixed);$i++){
  967. $hash->{owg_vlow}->[$i] = int($ral[$i]*1000+0.5)/1000;
  968. $hash->{owg_vhigh}->[$i] = int($ral2[$i]*1000+0.5)/1000;
  969. }
  970. #=============== get the status reading ===============================
  971. } elsif ( $page eq "status" ) {
  972. #-- so far not clear, how to find out which type of operation we have.
  973. # We therefore ASSUME normal operation
  974. #-- normal operation
  975. #-- put into globals
  976. for( $i=0;$i<int(@owg_fixed);$i++){
  977. $owg_mode[$i] = "input";
  978. $owg_resoln[$i] = 16;
  979. $owg_range[$i] = 5120;
  980. }
  981. #-- get values - or should we rather use the uncached ones ?
  982. $rel = OWServer_Read($master,"/$owx_add/alarm/low.ALL");
  983. $rel2 = OWServer_Read($master,"/$owx_add/set_alarm/low.ALL");
  984. return "no return from OWServer"
  985. if( (!defined($rel)) || (!defined($rel2)) );
  986. return "empty return from OWServer"
  987. if( ($rel eq "") || ($rel2 eq "") );
  988. @ral = split(/,/,$rel);
  989. @ral2= split(/,/,$rel2);
  990. return "wrong data length from OWServer"
  991. if( (int(@ral) != 4) || (int(@ral2) != 4) );
  992. for( $i=0;$i<int(@owg_fixed);$i++){
  993. #-- low alarm disabled
  994. if( $ral2[$i]==0 ){
  995. $an = 0;
  996. }else {
  997. #-- low alarm enabled and not set
  998. if ( $ral[$i]==0 ){
  999. $an = 1;
  1000. #-- low alarm enabled and set
  1001. }else{
  1002. $an = 2;
  1003. }
  1004. }
  1005. $hash->{owg_slow}->[$i] = $an;
  1006. }
  1007. #-- get values - or should we rather use the uncached ones ?
  1008. $rel = OWServer_Read($master,"/$owx_add/alarm/high.ALL");
  1009. $rel2 = OWServer_Read($master,"/$owx_add/set_alarm/high.ALL");
  1010. return "no return from OWServer"
  1011. if( (!defined($rel)) || (!defined($rel2)) );
  1012. return "empty return from OWServer"
  1013. if( ($rel eq "") || ($rel2 eq "") );
  1014. @ral = split(/,/,$rel);
  1015. @ral2= split(/,/,$rel2);
  1016. return "wrong data length from OWServer"
  1017. if( (int(@ral) != 4) || (int(@ral2) != 4) );
  1018. for( $i=0;$i<int(@owg_fixed);$i++){
  1019. #-- low alarm disabled
  1020. if( $ral2[$i]==0 ){
  1021. $an = 0;
  1022. }else {
  1023. #-- low alarm enabled and not set
  1024. if ( $ral[$i]==0 ){
  1025. $an = 1;
  1026. #-- low alarm enabled and set
  1027. }else{
  1028. $an = 2;
  1029. }
  1030. }
  1031. $hash->{owg_shigh}->[$i] = $an;
  1032. }
  1033. }
  1034. #-- and now from raw to formatted values
  1035. $hash->{PRESENT} = 1;
  1036. if( $final==1 ){
  1037. my $value = OWAD_FormatValues($hash);
  1038. Log 5, $value;
  1039. }
  1040. return undef
  1041. }
  1042. ########################################################################################
  1043. #
  1044. # OWFSAD_SetPage - Set one page of device
  1045. #
  1046. # Parameter hash = hash of device addressed
  1047. # page = "alarm" or "status"
  1048. #
  1049. ########################################################################################
  1050. sub OWFSAD_SetPage($$) {
  1051. my ($hash,$page) = @_;
  1052. #-- ID of the device
  1053. my $owx_add = substr($hash->{ROM_ID},0,15);
  1054. #-- hash of the busmaster
  1055. my $master = $hash->{IODev};
  1056. my $name = $hash->{NAME};
  1057. my $i;
  1058. my @ral =(0,0,0,0);
  1059. my @ral2=(0,0,0,0);
  1060. #=============== set the alarm values ===============================
  1061. if ( $page eq "alarm" ) {
  1062. OWServer_Write($master, "/$owx_add/set_alarm/voltlow.ALL",join(',',@{$hash->{owg_vlow}}));
  1063. OWServer_Write($master, "/$owx_add/set_alarm/volthigh.ALL",join(',',@{$hash->{owg_vhigh}}));
  1064. #=============== set the status ===============================
  1065. } elsif ( $page eq "status" ) {
  1066. for( $i=0;$i<int(@owg_fixed);$i++){
  1067. if( $owg_mode[$i] eq "input" ){
  1068. #-- resolution (TODO: check !)
  1069. #
  1070. #-- alarm enabled
  1071. if( defined($hash->{owg_slow}->[$i]) ){
  1072. $ral[$i]=1
  1073. if($hash->{owg_slow}->[$i]>0);
  1074. }
  1075. if( defined($hash->{owg_shigh}->[$i]) ){
  1076. $ral2[$i]=1
  1077. if($hash->{owg_shigh}->[$i]>0);
  1078. }
  1079. }
  1080. }
  1081. OWServer_Write($master, "/$owx_add/set_alarm/low.ALL",join(',',@ral));
  1082. OWServer_Write($master, "/$owx_add/set_alarm/high.ALL",join(',',@ral2));
  1083. #=============== wrong page write attempt ===============================
  1084. } else {
  1085. return "wrong memory page write attempt";
  1086. }
  1087. return undef;
  1088. }
  1089. ########################################################################################
  1090. #
  1091. # The following subroutines in alphabetical order are only for a 1-Wire bus connected
  1092. # directly to the FHEM server
  1093. #
  1094. # Prefix = OWXAD
  1095. #
  1096. ########################################################################################
  1097. #
  1098. # OWXAD_BinValues - Process reading from one device - translate binary into raw
  1099. #
  1100. # Parameter hash = hash of device addressed
  1101. # context = mode for evaluating the binary data
  1102. # proc = processing instruction, also passed to OWX_Read.
  1103. # bitwise interpretation !!
  1104. # if 0, nothing special
  1105. # if 1 = bit 0, a reset will be performed not only before, but also after
  1106. # the last operation in OWX_Read
  1107. # if 2 = bit 1, the initial reset of the bus will be suppressed
  1108. # if 8 = bit 3, the fillup of the data with 0xff will be suppressed
  1109. # if 16= bit 4, the insertion will be at the top of the queue
  1110. # owx_dev = ROM ID of slave device
  1111. # crcpart = part of the data that needs to be part of the CRC check
  1112. # numread = number of bytes to receive
  1113. # res = result string
  1114. #
  1115. #
  1116. ########################################################################################
  1117. sub OWXAD_BinValues($$$$$$$) {
  1118. my ($hash, $context, $proc, $owx_dev, $crcpart, $numread, $res) = @_;
  1119. #-- hash of the busmaster
  1120. my $master = $hash->{IODev};
  1121. my $name = $hash->{NAME};
  1122. #-- inherit previous error
  1123. my $error = $hash->{ERRSTATE};
  1124. my @data = [];
  1125. my $value;
  1126. my $msg;
  1127. OWX_WDBGL($name,4,"OWXAD_BinValues: called for device $name in context $context with data ",$res);
  1128. my $final = ($context =~ /\.final$/ );
  1129. my ($ow_thn,$ow_tln);
  1130. #-- we have to get rid of the first 12 bytes
  1131. if( length($res) == 22 ){
  1132. $res=substr($res,12);
  1133. }
  1134. @data=split(//,$res);
  1135. $crcpart = $crcpart.substr($res,0,8);
  1136. #-- process results
  1137. if (int(@data) != 10){
  1138. $msg = "$name: invalid data length, ".int(@data)." instead of 10 bytes ";
  1139. $error = 1;
  1140. }elsif (OWX_CRC16($crcpart,$data[8],$data[9])==0){
  1141. $msg ="$name: invalid CRC ";
  1142. $error = 1;
  1143. }else{
  1144. $msg = "$name: no local error, inheritance = $error ";
  1145. }
  1146. OWX_WDBGL($name,5-4*$error,"OWXAD_BinValues: context $context ".$msg,$res);
  1147. if( $error ){
  1148. $hash->{ERRCOUNT}++;
  1149. $hash->{ERRSTATE} = 1;
  1150. };
  1151. #=============== get the voltage reading ===============================
  1152. if( $context =~ /^ds2450.getreading/ ){
  1153. for( my $i=0;$i<int(@owg_fixed);$i++){
  1154. $hash->{owg_val}->[$i]= (ord($data[2*$i])+256*ord($data[1+2*$i]) )/(1<<$owg_resoln[$i]) * $owg_range[$i]/1000;
  1155. }
  1156. #=============== get the alarm reading ===============================
  1157. } elsif ( $context =~ /^ds2450.getalarm/ ){
  1158. for( my $i=0;$i<int(@owg_fixed);$i++){
  1159. $hash->{owg_vlow}->[$i] = int(ord($data[2*$i])/256 * $owg_range[$i]+0.5)/1000;
  1160. $hash->{owg_vhigh}->[$i] = int(ord($data[1+2*$i])/256 * $owg_range[$i]+0.5)/1000;
  1161. }
  1162. #=============== get the status reading ===============================
  1163. } elsif ( $context =~ /^ds2450.getstatus/ ) {
  1164. my ($sb1,$sb2);
  1165. for( my $i=0;$i<int(@owg_fixed);$i++){
  1166. $sb1 = ord($data[2*$i]);
  1167. $sb2 = ord($data[1+2*$i]);
  1168. #Log 1,"VOR TEST sb1=$sb1 sb2=$sb2 UND mit 128 ist ".($sb1 && 128);
  1169. #-- normal operation
  1170. if( ($sb1 && 128)==0) {
  1171. #-- put into globals
  1172. $owg_mode[$i] = "input";
  1173. $owg_resoln[$i] = ($sb1 & 15);
  1174. $owg_resoln[$i] = 16
  1175. if ($owg_resoln[$i] == 0);
  1176. $owg_range[$i] = ($sb2 & 1) ? 5120 : 2560;
  1177. my $an;
  1178. #-- low alarm disabled
  1179. if( ($sb2 & 4)==0 ){
  1180. $an = 0;
  1181. }else {
  1182. #-- low alarm enabled and not set
  1183. if ( ($sb2 & 16)==0 ){
  1184. $an = 1;
  1185. #-- low alarm enabled and set
  1186. }else{
  1187. $an = 2;
  1188. }
  1189. }
  1190. $hash->{owg_slow}->[$i]= $an;
  1191. #-- high alarm disabled
  1192. if( ($sb2 & 8)==0 ){
  1193. $an = 0;
  1194. }else {
  1195. #-- high alarm enabled and not set
  1196. if ( ($sb2 & 32)==0 ){
  1197. $an = 1;
  1198. #-- high alarm enabled and set
  1199. }else{
  1200. $an = 2;
  1201. }
  1202. }
  1203. $hash->{owg_shigh}->[$i]= $an;
  1204. #-- output operation
  1205. } else {
  1206. $owg_mode[$i] = "output";
  1207. #-- assemble status string
  1208. $hash->{owg_status}->[$i] = $owg_mode[$i].", ";
  1209. $hash->{owg_status}->[$i] .= ($sb1 & 64 ) ? "ON" : "OFF";
  1210. }
  1211. }
  1212. }
  1213. #-- and now from raw to formatted values
  1214. $hash->{PRESENT} = 1;
  1215. if( ($final) && (!$error) ){
  1216. my $value = OWAD_FormatValues($hash);
  1217. }
  1218. return undef
  1219. }
  1220. ########################################################################################
  1221. #
  1222. # OWXAD_GetPage - Get one memory page from device
  1223. #
  1224. # Parameter hash = hash of device addressed
  1225. # page = "reading", "alarm" or "status"
  1226. # final= 1 if FormatValues is to be called
  1227. #
  1228. ########################################################################################
  1229. sub OWXAD_GetPage($$$@) {
  1230. my ($hash,$page,$final,$sync) = @_;
  1231. my ($select, $res, $res2, $res3, @data, $an, $vn);
  1232. #-- ID of the device, hash of the busmaster
  1233. my $owx_dev = $hash->{ROM_ID};
  1234. my $master = $hash->{IODev};
  1235. my ($i,$j,$k);
  1236. #-- reset presence
  1237. $hash->{PRESENT} = 0;
  1238. #=============== get the voltage reading ===============================
  1239. if( $page eq "reading") {
  1240. #-- issue the match ROM command \x55 and the start conversion command
  1241. #-- OLD OWX interface
  1242. if( !$master->{ASYNCHRONOUS} ){
  1243. OWX_Reset($master);
  1244. $res= OWX_Complex($master,$owx_dev,"\x3C\x0F\x00\xFF\xFF",0);
  1245. if( $res eq 0 ){
  1246. return "not accessible for conversion";
  1247. }
  1248. #-- conversion needs some 5 ms per channel
  1249. select(undef,undef,undef,0.02);
  1250. #-- NEW OWX interface
  1251. }else{
  1252. #### master slave context proc owx_dev data crcpart numread startread callback delay
  1253. # 1 additional reset after last action
  1254. OWX_Qomplex($master, $hash, "convert", 4, $owx_dev, "\x3C\x0F\x00\xFF\xFF", 0, 0, undef, undef, 0.02);
  1255. }
  1256. #-- issue the match ROM command \x55 and the read conversion page command
  1257. # \xAA\x00\x00
  1258. $select="\xAA\x00\x00";
  1259. #=============== get the alarm reading ===============================
  1260. } elsif ( $page eq "alarm" ) {
  1261. #-- issue the match ROM command \x55 and the read alarm page command
  1262. # \xAA\x10\x00
  1263. $select="\xAA\x10\x00";
  1264. #=============== get the status reading ===============================
  1265. } elsif ( $page eq "status" ) {
  1266. #-- issue the match ROM command \x55 and the read status memory page command
  1267. # \xAA\x08\x00 r
  1268. $select="\xAA\x08\x00";
  1269. #=============== wrong value requested ===============================
  1270. } else {
  1271. return "wrong memory page requested from $owx_dev";
  1272. }
  1273. my $context = "ds2450.get".$page.($final ? ".final" : "");
  1274. my $proc = ($final ? 1 : 0);
  1275. #-- OLD OWX interface
  1276. if( !$master->{ASYNCHRONOUS} ){
  1277. #-- reset the bus
  1278. OWX_Reset($master);
  1279. #-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes
  1280. $res=OWX_Complex($master,$owx_dev,$select,10);
  1281. return "$owx_dev not accessible in reading page $page"
  1282. if( $res eq 0 );
  1283. return "$owx_dev has returned invalid data"
  1284. if( length($res)!=22);
  1285. #-- for processing we also need the 3 command bytes
  1286. return OWXAD_BinValues($hash,$context,$proc,$owx_dev,$select,10,substr($res,12,10));
  1287. #-- NEW OWX interface
  1288. }else{
  1289. #### master slave context proc owx_dev data crcpart numread startread callback delay
  1290. # 1 additional reset after last action
  1291. OWX_Qomplex($master, $hash, $context, 0, $owx_dev, $select, $select, 22, 0, \&OWXAD_BinValues, 0.01);
  1292. return undef;
  1293. }
  1294. }
  1295. ########################################################################################
  1296. #
  1297. # OWXAD_SetPage - Set one page of device
  1298. #
  1299. # Parameter hash = hash of device addressed
  1300. # page = "alarm" or "status"
  1301. #
  1302. ########################################################################################
  1303. sub OWXAD_SetPage($$) {
  1304. my ($hash,$page) = @_;
  1305. my ($select, $res, $res2, $res3, @data);
  1306. #-- ID of the device, hash of the busmaster
  1307. my $owx_dev = $hash->{ROM_ID};
  1308. my $master = $hash->{IODev};
  1309. my ($i,$j,$k);
  1310. #=============== set the alarm values ===============================
  1311. if ( $page eq "alarm" ) {
  1312. #-- issue the match ROM command \x55 and the set alarm page command
  1313. # \x55\x10\x00 reading 8 data bytes and 2 CRC bytes
  1314. $select="\x55\x10\x00";
  1315. for( $i=0;$i<int(@owg_fixed);$i++){
  1316. $select .= sprintf "%c\xFF\xFF\xFF",int($hash->{owg_vlow}->[$i]*256000/$owg_range[$i]);
  1317. $select .= sprintf "%c\xFF\xFF\xFF",int($hash->{owg_vhigh}->[$i]*256000/$owg_range[$i]);
  1318. }
  1319. #=============== set the status ===============================
  1320. } elsif ( $page eq "status" ) {
  1321. my ($sb1,$sb2)=(0,0);
  1322. #-- issue the match ROM command \x55 and the set status memory page command
  1323. # \x55\x08\x00 reading 8 data bytes and 2 CRC bytes
  1324. $select="\x55\x08\x00";
  1325. for( $i=0;$i<int(@owg_fixed);$i++){
  1326. #if( $owg_mode[$i] eq "input" ){
  1327. if( 1 > 0){
  1328. #-- resolution (TODO: check !)
  1329. $sb1 = $owg_resoln[$i] & 15;
  1330. #-- alarm enabled
  1331. if( defined($hash->{owg_slow}->[$i]) ){
  1332. $sb2 = ( $hash->{owg_slow}->[$i] ne 0 ) ? 4 : 0;
  1333. }
  1334. if( defined($hash->{owg_shigh}->[$i]) ){
  1335. $sb2 += ( $hash->{owg_shigh}->[$i] ne 0 ) ? 8 : 0;
  1336. }
  1337. #-- range
  1338. $sb2 |= 1
  1339. if( $owg_range[$i] > 2560 );
  1340. } else {
  1341. $sb1 = 128;
  1342. $sb2 = 0;
  1343. }
  1344. $select .= sprintf "%c\xFF\xFF\xFF",$sb1;
  1345. $select .= sprintf "%c\xFF\xFF\xFF",$sb2;
  1346. }
  1347. #=============== wrong page write attempt ===============================
  1348. } else {
  1349. return "wrong memory page write attempt";
  1350. }
  1351. #-- OLD OWX interface
  1352. if( !$master->{ASYNCHRONOUS} ){
  1353. OWX_Reset($master);
  1354. $res=OWX_Complex($master,$owx_dev,$select,0);
  1355. if( $res eq 0 ){
  1356. return "device $owx_dev not accessible for writing";
  1357. }
  1358. #-- NEW OWX interface
  1359. }else{
  1360. #### master slave context proc owx_dev data crcpart numread startread callback delay
  1361. OWX_Qomplex($master, $hash, "ds2450.set", 0, $owx_dev, $select, 0, 0, 0, undef, undef);
  1362. }
  1363. return undef;
  1364. }
  1365. ########################################################################################
  1366. #
  1367. # OWXAD_PT_GetPage - Get one memory page from device
  1368. #
  1369. # Parameter hash = hash of device addressed
  1370. # page = "reading", "alarm" or "status"
  1371. # final= 1 if FormatValues is to be called
  1372. #
  1373. ########################################################################################
  1374. sub OWXAD_PT_GetPage($$$) {
  1375. my ($hash,$page,$final) = @_;
  1376. return PT_THREAD(sub {
  1377. my ($thread) = @_;
  1378. my ($res, $res2, $res3, @data, $an, $vn);
  1379. #-- ID of the device, hash of the busmaster
  1380. my $owx_dev = $hash->{ROM_ID};
  1381. my $master = $hash->{IODev};
  1382. my ($i,$j,$k);
  1383. PT_BEGIN($thread);
  1384. #=============== get the voltage reading ===============================
  1385. if( $page eq "reading") {
  1386. #-- issue the match ROM command \x55 and the start conversion command
  1387. $thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, "\x3C\x0F\x00\xFF\xFF", 0 );
  1388. $thread->{ExecuteTime} = gettimeofday() + 0.07; # was 0.02
  1389. PT_WAIT_THREAD($thread->{pt_execute});
  1390. die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
  1391. PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
  1392. delete $thread->{ExecuteTime};
  1393. #-- issue the match ROM command \x55 and the read conversion page command
  1394. # \xAA\x00\x00
  1395. $thread->{'select'}="\xAA\x00\x00";
  1396. #=============== get the alarm reading ===============================
  1397. } elsif ( $page eq "alarm" ) {
  1398. #-- issue the match ROM command \x55 and the read alarm page command
  1399. # \xAA\x10\x00
  1400. $thread->{'select'}="\xAA\x10\x00";
  1401. #=============== get the status reading ===============================
  1402. } elsif ( $page eq "status" ) {
  1403. #-- issue the match ROM command \x55 and the read status memory page command
  1404. # \xAA\x08\x00 r
  1405. $thread->{'select'}="\xAA\x08\x00";
  1406. #=============== wrong value requested ===============================
  1407. } else {
  1408. die "wrong memory page requested from $owx_dev";
  1409. }
  1410. #-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes
  1411. $thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $thread->{'select'}, 10 );
  1412. PT_WAIT_THREAD($thread->{pt_execute});
  1413. die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
  1414. my $response = $thread->{pt_execute}->PT_RETVAL();
  1415. my $res = OWXAD_BinValues($hash,"ds2450.get".$page.($final ? ".final" : ""),1,$owx_dev,$thread->{'select'},10,$response);
  1416. if ($res) {
  1417. die $res;
  1418. }
  1419. PT_END;
  1420. });
  1421. }
  1422. ########################################################################################
  1423. #
  1424. # OWXAD_PT_SetPage - Set one page of device
  1425. #
  1426. # Parameter hash = hash of device addressed
  1427. # page = "alarm" or "status"
  1428. #
  1429. ########################################################################################
  1430. sub OWXAD_PT_SetPage($$) {
  1431. my ($hash,$page) = @_;
  1432. return PT_THREAD(sub {
  1433. my ($thread) = @_;
  1434. my ($select, $res, $res2, $res3, @data);
  1435. #-- ID of the device, hash of the busmaster
  1436. my $owx_dev = $hash->{ROM_ID};
  1437. my $master = $hash->{IODev};
  1438. my ($i,$j,$k);
  1439. PT_BEGIN($thread);
  1440. #=============== set the alarm values ===============================
  1441. if ( $page eq "alarm" ) {
  1442. #-- issue the match ROM command \x55 and the set alarm page command
  1443. # \x55\x10\x00 reading 8 data bytes and 2 CRC bytes
  1444. $select="\x55\x10\x00";
  1445. for( $i=0;$i<int(@owg_fixed);$i++){
  1446. $select .= sprintf "%c\xFF\xFF\xFF",int($hash->{owg_vlow}->[$i]*256000/$owg_range[$i]);
  1447. $select .= sprintf "%c\xFF\xFF\xFF",int($hash->{owg_vhigh}->[$i]*256000/$owg_range[$i]);
  1448. }
  1449. #++Use of uninitialized value within @owg_vlow in multiplication at
  1450. #++/usr/share/fhem/FHEM/21_OWAD.pm line 1362.
  1451. #=============== set the status ===============================
  1452. } elsif ( $page eq "status" ) {
  1453. my ($sb1,$sb2)=(0,0);
  1454. #-- issue the match ROM command \x55 and the set status memory page command
  1455. # \x55\x08\x00 reading 8 data bytes and 2 CRC bytes
  1456. $select="\x55\x08\x00";
  1457. for( $i=0;$i<int(@owg_fixed);$i++){
  1458. #if( $owg_mode[$i] eq "input" ){
  1459. if( 1 > 0){
  1460. #-- resolution (TODO: check !)
  1461. $sb1 = $owg_resoln[$i] & 15;
  1462. #-- alarm enabled
  1463. if( defined($hash->{owg_slow}->[$i]) ){
  1464. $sb2 = ( $hash->{owg_slow}->[$i] ne 0 ) ? 4 : 0;
  1465. }
  1466. if( defined($hash->{owg_shigh}->[$i]) ){
  1467. $sb2 += ( $hash->{owg_shigh}->[$i] ne 0 ) ? 8 : 0;
  1468. }
  1469. #-- range
  1470. $sb2 |= 1
  1471. if( $owg_range[$i] > 2560 );
  1472. } else {
  1473. $sb1 = 128;
  1474. $sb2 = 0;
  1475. }
  1476. $select .= sprintf "%c\xFF\xFF\xFF",$sb1;
  1477. $select .= sprintf "%c\xFF\xFF\xFF",$sb2;
  1478. }
  1479. #=============== wrong page write attempt ===============================
  1480. } else {
  1481. PT_EXIT("wrong memory page write attempt");
  1482. }
  1483. #"setpage"
  1484. $thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $select, 0 );
  1485. PT_WAIT_THREAD($thread->{pt_execute});
  1486. die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
  1487. PT_END;
  1488. });
  1489. }
  1490. 1;
  1491. =pod
  1492. =item device
  1493. =item summary to control 1-Wire A/D converters DS2450
  1494. =begin html
  1495. <a name="OWAD"></a>
  1496. <h3>OWAD</h3>
  1497. <p>FHEM module to commmunicate with 1-Wire A/D converters<br /><br />
  1498. <br />This 1-Wire module works with the OWX interface module or with the OWServer interface module
  1499. (prerequisite: Add this module's name to the list of clients in OWServer).
  1500. Please define an <a href="#OWX">OWX</a> device or <a href="#OWServer">OWServer</a> device first. <br/></p>
  1501. <br /><h4>Example</h4>
  1502. <p>
  1503. <code>define OWX_AD OWAD 724610000000 45</code>
  1504. <br />
  1505. <code>attr OWX_AD DAlarm high</code>
  1506. <br />
  1507. <code>attr OWX_AD DName humidity</code>
  1508. <br />
  1509. <code>attr OWX_AD DUnit %</code>
  1510. <br />
  1511. <code>attr OWX_AD DFunction VD*31.907097-0.8088</code>
  1512. <br />
  1513. <code>attr OWX_AD DHigh 50.0</code>
  1514. <br />
  1515. </p><br />
  1516. <a name="OWADdefine"></a>
  1517. <h4>Define</h4>
  1518. <p>
  1519. <code>define &lt;name&gt; OWAD [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code> or <br/>
  1520. <code>define &lt;name&gt; OWAD &lt;fam&gt;.&lt;id&gt; [&lt;interval&gt;]</code>
  1521. <br /><br /> Define a 1-Wire A/D converter.<br /><br /></p>
  1522. <ul>
  1523. <li>
  1524. <code>[&lt;model&gt;]</code><br /> Defines the A/D converter model (and thus 1-Wire
  1525. family id), currently the following values are permitted: <ul>
  1526. <li>model DS2450 with family id 20 (default if the model parameter is
  1527. omitted)</li>
  1528. </ul>
  1529. </li>
  1530. <li>
  1531. <code>&lt;fam&gt;</code>
  1532. <br />2-character unique family id, see above
  1533. </li>
  1534. <li>
  1535. <code>&lt;id&gt;</code>
  1536. <br />12-character unique ROM id of the converter device without family id and CRC
  1537. code </li>
  1538. <li>
  1539. <code>&lt;interval&gt;</code>
  1540. <br />Measurement interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update. </li>
  1541. </ul>
  1542. <br />
  1543. <a name="OWADset"></a>
  1544. <h4>Set</h4>
  1545. <ul>
  1546. <li><a name="owad_interval">
  1547. <code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
  1548. interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update.</li>
  1549. </ul>
  1550. <br />
  1551. <a name="OWADget"></a>
  1552. <h4>Get</h4>
  1553. <ul>
  1554. <li><a name="owad_id">
  1555. <code>get &lt;name&gt; id</code></a>
  1556. <br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
  1557. <li><a name="owad_reading">
  1558. <code>get &lt;name&gt; reading</code></a><br />Obtain the measuement values. </li>
  1559. <li><a name="owad_alarm">
  1560. <code>get &lt;name&gt; alarm</code></a><br />Obtain the alarm values. </li>
  1561. <li><a name="owad_status">
  1562. <code>get &lt;name&gt; status</code></a><br />Obtain the i/o status values.
  1563. </li>
  1564. </ul>
  1565. <br />
  1566. <a name="OWADattr"></a>
  1567. <h4>Attributes</h4>
  1568. <ul>
  1569. <li><a name="owad_stateAL0"><code>attr &lt;name&gt; stateAL0 &lt;string&gt;</code></a>
  1570. <br />character string for denoting low normal condition, default is empty </li>
  1571. <li><a name="owad_stateAH0"><code>attr &lt;name&gt; stateAH0 &lt;string&gt;</code></a>
  1572. <br />character string for denoting high normal condition, default is empty </li>
  1573. <li><a name="owad_stateAL1"><code>attr &lt;name&gt; stateAL1 &lt;string&gt;</code></a>
  1574. <br />character string for denoting low alarm condition, default is ↓</li>
  1575. <li><a name="owad_stateAH1"><code>attr &lt;name&gt; stateAH1 &lt;string&gt;</code></a>
  1576. <br />character string for denoting high alarm condition, default is ↑</li>
  1577. <li><a name="owad_interval2">
  1578. <code>attr &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
  1579. interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update.</li>
  1580. </ul> For each of the following attributes, the channel identification A,B,C,D may be used. <ul>
  1581. <li><a name="owad_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
  1582. &lt;string&gt;[|&lt;string&gt;]</code></a>
  1583. <br />name for the channel [|short name used in state reading]. </li>
  1584. <li><a name="owad_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
  1585. &lt;string&gt;</code></a>
  1586. <br />unit of measurement for this channel used in state reading (default "V", set to "none" for empty). </li>
  1587. <li><a name="owad_cfunction"> <code>attr &lt;name&gt; &lt;channel&gt;Function
  1588. &lt;string&gt;</code></a>
  1589. <br />arbitrary functional expression involving the variables VA,VB,VC,VD. VA is replaced by
  1590. the (raw) measured voltage in channel A, etc. This attribute allows linearization of measurement
  1591. curves as well as the mixing of various channels. </li>
  1592. <li><a name="owad_calarm"><code>attr &lt;name&gt; &lt;channel&gt;Alarm
  1593. &lt;string&gt;</code></a>
  1594. <br />alarm setting in this channel, either both, low, high or none (default). </li>
  1595. <li><a name="owad_clow"><code>attr &lt;name&gt; &lt;channel&gt;Low
  1596. &lt;float&gt;</code></a>
  1597. <br />measurement value for low alarm. </li>
  1598. <li><a name="owad_chigh"><code>attr &lt;name&gt; &lt;channel&gt;High
  1599. &lt;float&gt;</code></a>
  1600. <br />measurement value for highalarm. </li>
  1601. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  1602. </ul>
  1603. =end html
  1604. =cut