88_HMCCUCHN.pm 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. ######################################################################
  2. #
  3. # 88_HMCCUCHN.pm
  4. #
  5. # $Id: 88_HMCCUCHN.pm 16165 2018-02-13 10:55:01Z zap $
  6. #
  7. # Version 4.2.001
  8. #
  9. # (c) 2018 zap (zap01 <at> t-online <dot> de)
  10. #
  11. ######################################################################
  12. #
  13. # define <name> HMCCUCHN <ccudev> [readonly] [defaults]
  14. # [iodev=<iodevname>]
  15. #
  16. # set <name> config [device] <parameter>=<value> [...]
  17. # set <name> control <value>
  18. # set <name> datapoint <datapoint> <value> [...]
  19. # set <name> defaults
  20. # set <name> devstate <value>
  21. # set <name> <stateval_cmds>
  22. # set <name> on-till <timestamp>
  23. # set <name> on-for-timer <ontime>
  24. # set <name> pct <level> [{ <ontime> | 0 } [<ramptime>]]
  25. # set <name> toggle
  26. #
  27. # get <name> config [device] [<filter-expr>]
  28. # get <name> configdesc [device]
  29. # get <name> configlist [device] [<filtet-expr>]
  30. # get <name> datapoint <datapoint>
  31. # get <name> defaults
  32. # get <name> deviceinfo
  33. # get <name> devstate
  34. # get <name> update
  35. #
  36. # attr <name> ccucalculate <value>:<reading>[:<dp-list>][...]
  37. # attr <name> ccuflags { ackState, nochn0, trace }
  38. # attr <name> ccuget { State | Value }
  39. # attr <name> ccureadings { 0 | 1 }
  40. # attr <name> ccureadingfilter <filter-rule>[;...]
  41. # attr <name> ccureadingformat { name[lc] | address[lc] | datapoint[lc] }
  42. # attr <name> ccureadingname <oldname>:<newname>[;...]
  43. # attr <name> ccuverify { 0 | 1 | 2 }
  44. # attr <name> controldatapoint <datapoint>
  45. # attr <name> disable { 0 | 1 }
  46. # attr <name> peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command}
  47. # attr <name> hmstatevals <subst-rule>[;...]
  48. # attr <name> statedatapoint <datapoint>
  49. # attr <name> statevals <text1>:<subtext1>[,...]
  50. # attr <name> substexcl <reading-expr>
  51. # attr <name> substitute <subst-rule>[;...]
  52. #
  53. ######################################################################
  54. # Requires modules 88_HMCCU.pm, HMCCUConf.pm
  55. ######################################################################
  56. package main;
  57. use strict;
  58. use warnings;
  59. use SetExtensions;
  60. # use Time::HiRes qw( gettimeofday usleep );
  61. sub HMCCUCHN_Define ($@);
  62. sub HMCCUCHN_Set ($@);
  63. sub HMCCUCHN_Get ($@);
  64. sub HMCCUCHN_Attr ($@);
  65. ##################################################
  66. # Initialize module
  67. ##################################################
  68. sub HMCCUCHN_Initialize ($)
  69. {
  70. my ($hash) = @_;
  71. $hash->{DefFn} = "HMCCUCHN_Define";
  72. $hash->{SetFn} = "HMCCUCHN_Set";
  73. $hash->{GetFn} = "HMCCUCHN_Get";
  74. $hash->{AttrFn} = "HMCCUCHN_Attr";
  75. $hash->{parseParams} = 1;
  76. $hash->{AttrList} = "IODev ccucalculate ".
  77. "ccuflags:multiple-strict,ackState,nochn0,trace ccureadingfilter ".
  78. "ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
  79. "ccureadingname:textField-long ".
  80. "ccureadings:0,1 ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint ".
  81. "disable:0,1 hmstatevals:textField-long statedatapoint statevals substitute:textField-long ".
  82. "substexcl stripnumber peer:textField-long ". $readingFnAttributes;
  83. }
  84. ##################################################
  85. # Define device
  86. ##################################################
  87. sub HMCCUCHN_Define ($@)
  88. {
  89. my ($hash, $a, $h) = @_;
  90. my $name = $hash->{NAME};
  91. my $usage = "Usage: define $name HMCCUCHN {device} ['readonly'] ['defaults'] [iodev={iodevname}]";
  92. return $usage if (@$a < 3);
  93. my $devname = shift @$a;
  94. my $devtype = shift @$a;
  95. my $devspec = shift @$a;
  96. my $hmccu_hash = undef;
  97. # IO device can be set by command line parameter iodev
  98. if (exists ($h->{iodev})) {
  99. $hmccu_hash = $defs{$h->{iodev}} if (exists ($defs{$h->{iodev}}));
  100. }
  101. $hmccu_hash = HMCCU_FindIODevice ($devspec) if (!defined ($hmccu_hash));
  102. return "Cannot detect IO device" if (!defined ($hmccu_hash));
  103. return "Invalid or unknown CCU channel name or address"
  104. if (! HMCCU_IsValidChannel ($hmccu_hash, $devspec));
  105. my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($hmccu_hash, $devspec);
  106. return "Invalid or unknown CCU device name or address" if (!defined ($da));
  107. $hash->{ccuif} = $di;
  108. $hash->{ccuaddr} = $da;
  109. $hash->{ccuname} = $dn;
  110. $hash->{ccutype} = $dt;
  111. $hash->{channels} = 1;
  112. $hash->{statevals} = 'devstate';
  113. # Parse optional command line parameters
  114. my $n = 0;
  115. my $arg = shift @$a;
  116. while (defined ($arg)) {
  117. return $usage if ($n == 3);
  118. if ($arg eq 'readonly') { $hash->{statevals} = $arg; }
  119. elsif ($arg eq 'defaults') { HMCCU_SetDefaults ($hash); }
  120. else { return $usage; }
  121. $n++;
  122. $arg = shift @$a;
  123. }
  124. # Inform HMCCU device about client device
  125. AssignIoPort ($hash, $hmccu_hash->{NAME});
  126. readingsSingleUpdate ($hash, "state", "Initialized", 1);
  127. $hash->{ccudevstate} = 'active';
  128. return undef;
  129. }
  130. #####################################
  131. # Set attribute
  132. #####################################
  133. sub HMCCUCHN_Attr ($@)
  134. {
  135. my ($cmd, $name, $attrname, $attrval) = @_;
  136. my $hash = $defs{$name};
  137. if ($cmd eq "set") {
  138. return "Missing attribute value" if (!defined ($attrval));
  139. if ($attrname eq 'IODev') {
  140. $hash->{IODev} = $defs{$attrval};
  141. }
  142. elsif ($attrname eq 'statevals') {
  143. return "Device is read only" if ($hash->{statevals} eq 'readonly');
  144. $hash->{statevals} = "devstate";
  145. my @states = split /,/,$attrval;
  146. foreach my $st (@states) {
  147. my @statesubs = split /:/,$st;
  148. return "value := text:substext[,...]" if (@statesubs != 2);
  149. $hash->{statevals} .= '|'.$statesubs[0];
  150. }
  151. }
  152. }
  153. elsif ($cmd eq "del") {
  154. if ($attrname eq 'statevals') {
  155. $hash->{statevals} = "devstate";
  156. }
  157. }
  158. return undef;
  159. }
  160. #####################################
  161. # Set commands
  162. #####################################
  163. sub HMCCUCHN_Set ($@)
  164. {
  165. my ($hash, $a, $h) = @_;
  166. my $name = shift @$a;
  167. my $opt = shift @$a;
  168. my $rocmds = "clear config defaults:noArg";
  169. return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
  170. return undef if ($hash->{statevals} eq 'readonly' && $opt ne '?' &&
  171. $opt !~ /^(clear|config|defaults)$/);
  172. my $disable = AttrVal ($name, "disable", 0);
  173. return undef if ($disable == 1);
  174. my $hmccu_hash = $hash->{IODev};
  175. if (HMCCU_IsRPCStateBlocking ($hmccu_hash)) {
  176. return undef if ($opt eq '?');
  177. return "HMCCUCHN: CCU busy";
  178. }
  179. my $ccutype = $hash->{ccutype};
  180. my $ccuaddr = $hash->{ccuaddr};
  181. my $ccuif = $hash->{ccuif};
  182. my $statevals = AttrVal ($name, "statevals", '');
  183. my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
  184. my $result = '';
  185. my $rc;
  186. if ($opt eq 'datapoint') {
  187. my $usage = "Usage: set $name datapoint {datapoint} {value} [...]";
  188. my %dpval;
  189. while (my $objname = shift @$a) {
  190. my $objvalue = shift @$a;
  191. return HMCCU_SetError ($hash, $usage) if (!defined ($objvalue));
  192. return HMCCU_SetError ($hash, -8)
  193. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 2));
  194. $objvalue =~ s/\\_/%20/g;
  195. $objvalue = HMCCU_Substitute ($objvalue, $statevals, 1, undef, '');
  196. $objname = $ccuif.'.'.$ccuaddr.'.'.$objname;
  197. $dpval{$objname} = $objvalue;
  198. }
  199. return HMCCU_SetError ($hash, $usage) if (scalar (keys %dpval) < 1);
  200. foreach my $dpt (keys %dpval) {
  201. $rc = HMCCU_SetDatapoint ($hash, $dpt, $dpval{$dpt});
  202. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  203. }
  204. return HMCCU_SetState ($hash, "OK");
  205. }
  206. elsif ($opt eq 'control') {
  207. return HMCCU_SetError ($hash, -14) if ($cd eq '');
  208. return HMCCU_SetError ($hash, -8) if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, $cd, 2));
  209. my $objvalue = shift @$a;
  210. return HMCCU_SetError ($hash, "Usage: set $name control {value}") if (!defined ($objvalue));
  211. $objvalue =~ s/\\_/%20/g;
  212. $objvalue = HMCCU_Substitute ($objvalue, $statevals, 1, undef, '');
  213. my $objname = $ccuif.'.'.$ccuaddr.'.'.$cd;
  214. $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
  215. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  216. return HMCCU_SetState ($hash, "OK");
  217. }
  218. elsif ($opt =~ /^($hash->{statevals})$/) {
  219. my $cmd = $1;
  220. my $objvalue = ($cmd ne 'devstate') ? $cmd : shift @$a;
  221. return HMCCU_SetError ($hash, -13) if ($sd eq '');
  222. return HMCCU_SetError ($hash, -8)
  223. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $sd, 2));
  224. return HMCCU_SetError ($hash, "Usage: set $name devstate {value}") if (!defined ($objvalue));
  225. $objvalue =~ s/\\_/%20/g;
  226. $objvalue = HMCCU_Substitute ($objvalue, $statevals, 1, undef, '');
  227. my $objname = $ccuif.'.'.$ccuaddr.'.'.$sd;
  228. $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
  229. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  230. return HMCCU_SetState ($hash, "OK");
  231. }
  232. elsif ($opt eq 'toggle') {
  233. return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
  234. return HMCCU_SetError ($hash, -13) if ($sd eq '');
  235. return HMCCU_SetError ($hash, -8)
  236. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $sd, 2));
  237. my $tstates = $hash->{statevals};
  238. $tstates =~ s/devstate\|//;
  239. my @states = split /\|/, $tstates;
  240. my $stc = scalar (@states);
  241. my $objname = $ccuif.'.'.$ccuaddr.'.'.$sd;
  242. ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
  243. return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
  244. my $objvalue = '';
  245. my $st = 0;
  246. while ($st < $stc) {
  247. if ($states[$st] eq $result) {
  248. $objvalue = ($st == $stc-1) ? $states[0] : $states[$st+1];
  249. last;
  250. }
  251. else {
  252. $st++;
  253. }
  254. }
  255. return HMCCU_SetError ($hash, "Current device state doesn't match statevals")
  256. if ($objvalue eq '');
  257. $objvalue = HMCCU_Substitute ($objvalue, $statevals, 1, undef, '');
  258. $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
  259. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  260. return HMCCU_SetState ($hash, "OK");
  261. }
  262. elsif ($opt eq 'pct') {
  263. return HMCCU_SetError ($hash, "Can't find LEVEL datapoint for device type $ccutype")
  264. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "LEVEL", 2));
  265. my $objname = '';
  266. my $objvalue = shift @$a;
  267. return HMCCU_SetError ($hash, "Usage: set $name pct {value} [{ontime} [{ramptime}]]")
  268. if (!defined ($objvalue));
  269. my $timespec = shift @$a;
  270. my $ramptime = shift @$a;
  271. # Set on time
  272. if (defined ($timespec)) {
  273. return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
  274. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
  275. if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
  276. my (undef, $h, $m, $s) = GetTimeSpec ($timespec);
  277. return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM or HH:MM:SS")
  278. if (!defined ($h));
  279. $s += $h*3600+$m*60;
  280. my @lt = localtime;
  281. my $cs = $lt[2]*3600+$lt[1]*60+$lt[0];
  282. $s += 86400 if ($cs > $s);
  283. $timespec = $s-$cs;
  284. }
  285. if ($timespec > 0) {
  286. $objname = $ccuif.'.'.$ccuaddr.'.ON_TIME';
  287. $rc = HMCCU_SetDatapoint ($hash, $objname, $timespec);
  288. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  289. }
  290. }
  291. # Set ramp time
  292. if (defined ($ramptime)) {
  293. return HMCCU_SetError ($hash, "Can't find RAMP_TIME datapoint for device type $ccutype")
  294. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "RAMP_TIME", 2));
  295. $objname = $ccuif.'.'.$ccuaddr.'.RAMP_TIME';
  296. $rc = HMCCU_SetDatapoint ($hash, $objname, $ramptime);
  297. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  298. }
  299. # Set level
  300. $objname = $ccuif.'.'.$ccuaddr.'.LEVEL';
  301. $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
  302. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  303. return HMCCU_SetState ($hash, "OK");
  304. }
  305. elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
  306. return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
  307. return HMCCU_SetError ($hash, "No state value for 'on' defined")
  308. if ("on" !~ /($hash->{statevals})/);
  309. return HMCCU_SetError ($hash, -13) if ($sd eq '');
  310. return HMCCU_SetError ($hash, -8)
  311. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $sd, 2));
  312. return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type")
  313. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
  314. my $timespec = shift @$a;
  315. return HMCCU_SetError ($hash, "Usage: set $name $opt {ontime-spec}")
  316. if (!defined ($timespec));
  317. if ($opt eq 'on-till') {
  318. my (undef, $h, $m, $s) = GetTimeSpec ($timespec);
  319. return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM or HH:MM:SS")
  320. if (!defined ($h));
  321. $s += $h*3600+$m*60;
  322. my @lt = localtime;
  323. my $cs = $lt[2]*3600+$lt[1]*60+$lt[0];
  324. $s += 86400 if ($cs > $s);
  325. $timespec = $s-$cs;
  326. }
  327. # Set time
  328. my $objname = $ccuif.'.'.$ccuaddr.'.ON_TIME';
  329. $rc = HMCCU_SetDatapoint ($hash, $objname, $timespec);
  330. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  331. # Set state
  332. $objname = $ccuif.'.'.$ccuaddr.'.'.$sd;
  333. my $objvalue = HMCCU_Substitute ("on", $statevals, 1, undef, '');
  334. $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
  335. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  336. return HMCCU_SetState ($hash, "OK");
  337. }
  338. elsif ($opt eq 'clear') {
  339. my $rnexp = shift @$a;
  340. $rnexp = '.*' if (!defined ($rnexp));
  341. my @readlist = keys %{$hash->{READINGS}};
  342. foreach my $rd (@readlist) {
  343. delete ($hash->{READINGS}{$rd}) if ($rd ne 'state' && $rd ne 'control' && $rd =~ /$rnexp/);
  344. }
  345. }
  346. elsif ($opt eq 'config') {
  347. return HMCCU_SetError ($hash, "Usage: set $name config [device] {parameter}={value} [...]")
  348. if ((scalar keys %{$h}) < 1);
  349. my $ccuobj = $ccuaddr;
  350. my $par = shift @$a;
  351. if (defined ($par) && $par eq 'device') {
  352. ($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
  353. }
  354. my $rc = HMCCU_RPCSetConfig ($hash, $ccuobj, $h);
  355. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  356. return HMCCU_SetState ($hash, "OK");
  357. }
  358. elsif ($opt eq 'defaults') {
  359. my $rc = HMCCU_SetDefaults ($hash);
  360. return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0);
  361. return HMCCU_SetState ($hash, "OK");
  362. }
  363. else {
  364. return "HMCCUCHN: Unknown argument $opt, choose one of ".$rocmds
  365. if ($hash->{statevals} eq 'readonly');
  366. my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of clear config control datapoint defaults:noArg devstate";
  367. if ($hash->{statevals} ne '') {
  368. my @cmdlist = split /\|/,$hash->{statevals};
  369. shift @cmdlist;
  370. $retmsg .= ':'.join(',',@cmdlist) if (@cmdlist > 0);
  371. foreach my $sv (@cmdlist) {
  372. $retmsg .= ' '.$sv.':noArg';
  373. }
  374. $retmsg .= " toggle:noArg";
  375. $retmsg .= " on-for-timer on-till"
  376. if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "ON_TIME", 2));
  377. $retmsg .= " pct"
  378. if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "LEVEL", 2));
  379. }
  380. return $retmsg;
  381. }
  382. }
  383. #####################################
  384. # Get commands
  385. #####################################
  386. sub HMCCUCHN_Get ($@)
  387. {
  388. my ($hash, $a, $h) = @_;
  389. my $name = shift @$a;
  390. my $opt = shift @$a;
  391. return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
  392. my $disable = AttrVal ($name, "disable", 0);
  393. return undef if ($disable == 1);
  394. my $hmccu_hash = $hash->{IODev};
  395. if (HMCCU_IsRPCStateBlocking ($hmccu_hash)) {
  396. return undef if ($opt eq '?');
  397. return "HMCCUCHN: CCU busy";
  398. }
  399. my $ccutype = $hash->{ccutype};
  400. my $ccuaddr = $hash->{ccuaddr};
  401. my $ccuif = $hash->{ccuif};
  402. my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
  403. my $ccureadings = AttrVal ($name, "ccureadings", 1);
  404. my $result = '';
  405. my $rc;
  406. if ($opt eq 'devstate') {
  407. return HMCCU_SetError ($hash, -13) if ($sd eq '');
  408. return HMCCU_SetError ($hash, -8)
  409. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $sd, 1));
  410. my $objname = $ccuif.'.'.$ccuaddr.'.'.$sd;
  411. ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
  412. return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
  413. return $ccureadings ? undef : $result;
  414. }
  415. elsif ($opt eq 'datapoint') {
  416. my $objname = shift @$a;
  417. return HMCCU_SetError ($hash, "Usage: get $name datapoint {datapoint}")
  418. if (!defined ($objname));
  419. return HMCCU_SetError ($hash, -8)
  420. if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 1));
  421. $objname = $ccuif.'.'.$ccuaddr.'.'.$objname;
  422. ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
  423. return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
  424. return $ccureadings ? undef : $result;
  425. }
  426. elsif ($opt eq 'update') {
  427. my $ccuget = shift @$a;
  428. $ccuget = 'Attr' if (!defined ($ccuget));
  429. if ($ccuget !~ /^(Attr|State|Value)$/) {
  430. return HMCCU_SetError ($hash, "Usage: get $name update [{'State'|'Value'}]");
  431. }
  432. $rc = HMCCU_GetUpdate ($hash, $ccuaddr, $ccuget);
  433. return HMCCU_SetError ($hash, $rc) if ($rc < 0);
  434. return undef;
  435. }
  436. elsif ($opt eq 'deviceinfo') {
  437. my $ccuget = shift @$a;
  438. $ccuget = 'Attr' if (!defined ($ccuget));
  439. if ($ccuget !~ /^(Attr|State|Value)$/) {
  440. return HMCCU_SetError ($hash, "Usage: get $name deviceinfo [{'State'|'Value'}]");
  441. }
  442. my ($a, $c) = split(":", $hash->{ccuaddr});
  443. $result = HMCCU_GetDeviceInfo ($hash, $a, $ccuget);
  444. return HMCCU_SetError ($hash, -2) if ($result eq '');
  445. return HMCCU_FormatDeviceInfo ($result);
  446. }
  447. elsif ($opt eq 'config') {
  448. my $ccuobj = $ccuaddr;
  449. my $par = shift @$a;
  450. if (defined ($par)) {
  451. if ($par eq 'device') {
  452. ($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
  453. $par = shift @$a;
  454. }
  455. }
  456. $par = '.*' if (!defined ($par));
  457. my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamset", $par);
  458. return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
  459. return $ccureadings ? undef : $res;
  460. }
  461. elsif ($opt eq 'configlist') {
  462. my $ccuobj = $ccuaddr;
  463. my $par = shift @$a;
  464. if (defined ($par)) {
  465. if ($par eq 'device') {
  466. ($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
  467. $par = shift @$a;
  468. }
  469. }
  470. $par = '.*' if (!defined ($par));
  471. my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "listParamset", $par);
  472. return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
  473. return $res;
  474. }
  475. elsif ($opt eq 'configdesc') {
  476. my $ccuobj = $ccuaddr;
  477. my $par = shift @$a;
  478. if (defined ($par) && $par eq 'device') {
  479. ($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
  480. }
  481. my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamsetDescription", undef);
  482. return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
  483. return $res;
  484. }
  485. elsif ($opt eq 'defaults') {
  486. $result = HMCCU_GetDefaults ($hash, 0);
  487. return $result;
  488. }
  489. else {
  490. my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of devstate:noArg defaults:noArg datapoint";
  491. my ($a, $c) = split(":", $hash->{ccuaddr});
  492. my @valuelist;
  493. my $valuecount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 1, \@valuelist);
  494. $retmsg .= ":".join(",",@valuelist) if ($valuecount > 0);
  495. $retmsg .= " update:noArg deviceinfo config configlist configdesc:noArg";
  496. return $retmsg;
  497. }
  498. }
  499. 1;
  500. =pod
  501. =item device
  502. =item summary controls HMCCU client devices for Homematic CCU2 - FHEM integration
  503. =begin html
  504. <a name="HMCCUCHN"></a>
  505. <h3>HMCCUCHN</h3>
  506. <ul>
  507. The module implements Homematic CCU channels as client devices for HMCCU. A HMCCU I/O device must
  508. exist before a client device can be defined. If a CCU channel is not found execute command
  509. 'get devicelist' in I/O device.
  510. </br></br>
  511. <a name="HMCCUCHNdefine"></a>
  512. <b>Define</b><br/><br/>
  513. <ul>
  514. <code>define &lt;name&gt; HMCCUCHN {&lt;channel-name&gt; | &lt;channel-address&gt;}
  515. [readonly] [defaults] [iodev=&lt;iodev-name&gt;]</code>
  516. <br/><br/>
  517. If option 'readonly' is specified no set command will be available. With option 'defaults'
  518. some default attributes depending on CCU device type will be set. Default attributes are only
  519. available for some device types.<br/>
  520. The define command accepts a CCU2 channel name or channel address as parameter.
  521. <br/><br/>
  522. Examples:<br/>
  523. <code>define window_living HMCCUCHN WIN-LIV-1 readonly</code><br/>
  524. <code>define temp_control HMCCUCHN BidCos-RF.LEQ1234567:1</code>
  525. <br/><br/>
  526. The interface part of a channel address must not be specified. The default is 'BidCos-RF'.
  527. Channel addresses can be found with command 'get deviceinfo &lt;devicename&gt;' executed
  528. in I/O device.
  529. </ul>
  530. <br/>
  531. <a name="HMCCUCHNset"></a>
  532. <b>Set</b><br/><br/>
  533. <ul>
  534. <li><b>set &lt;name&gt; clear [&lt;reading-exp&gt;]</b><br/>
  535. Delete readings matching specified reading name expression. Default expression is '.*'.
  536. Readings 'state' and 'control' are not deleted.
  537. </li><br/>
  538. <li><b>set &lt;name&gt; config [device] [&lt;rpcport&gt;] &lt;parameter&gt;=&lt;value&gt;]
  539. [...]</b><br/>
  540. Set config parameters of CCU channel. This is equal to setting device parameters in CCU.
  541. Valid parameters can be listed by using commands 'get configdesc' or 'get configlist'.
  542. With option 'device' specified parameters are set in device instead of channel.
  543. </li><br/>
  544. <li><b>set &lt;name&gt; datapoint &lt;datapoint&gt; &lt;value&gt; [...]</b><br/>
  545. Set datapoint values of a CCU channel. If parameter <i>value</i> contains special
  546. character \_ it's substituted by blank.
  547. <br/><br/>
  548. Examples:<br/>
  549. <code>set temp_control datapoint SET_TEMPERATURE 21</code><br/>
  550. <code>set temp_control datapoint AUTO_MODE 1 SET_TEMPERATURE 21</code>
  551. </li><br/>
  552. <li><b>set &lt;name&gt; defaults</b><br/>
  553. Set default attributes for CCU device type. Default attributes are only available for
  554. some device types and for some channels of a device type.
  555. </li><br/>
  556. <li><b>set &lt;name&gt; devstate &lt;value&gt;</b><br/>
  557. Set state of a CCU device channel. The state datapoint of a channel must be defined
  558. by setting attribute 'statedatapoint' to a valid datapoint name.
  559. <br/><br/>
  560. Example:<br/>
  561. <code>set light_entrance devstate true</code>
  562. </li><br/>
  563. <li><b>set &lt;name&gt; &lt;statevalue&gt;</b><br/>
  564. Set state of a CCU device channel to <i>StateValue</i>. The state datapoint of a channel
  565. must be defined by setting attribute 'statedatapoint'. The available state values must
  566. be defined by setting attribute 'statevals'.
  567. <br/><br/>
  568. Example: Turn switch on<br/>
  569. <code>
  570. attr myswitch statedatapoint STATE<br/>
  571. attr myswitch statevals on:true,off:false<br/>
  572. set myswitch on
  573. </code>
  574. </li><br/>
  575. <li><b>set &lt;name&gt; toggle</b><br/>
  576. Toggle state datapoint between values defined by attribute 'statevals'. This command is
  577. only available if attribute 'statevals' is set. Toggling supports more than two state
  578. values.
  579. <br/><br/>
  580. Example: Toggle blind actor<br/>
  581. <code>
  582. attr myswitch statedatapoint LEVEL<br/>
  583. attr myswitch statevals up:100,down:0<br/>
  584. set myswitch toggle
  585. </code>
  586. </li><br/>
  587. <li><b>set &lt;name&gt; on-for-timer &lt;ontime&gt;</b><br/>
  588. Switch device on for specified number of seconds. This command is only available if
  589. channel contains a datapoint ON_TIME. The attribute 'statevals' must contain at least a
  590. value for 'on'. The attribute 'statedatapoint' must be set to a writeable datapoint.
  591. <br/><br/>
  592. Example: Turn switch on for 300 seconds<br/>
  593. <code>
  594. attr myswitch statedatapoint STATE<br/>
  595. attr myswitch statevals on:true,off:false<br/>
  596. set myswitch on-for-timer 300
  597. </code>
  598. </li><br/>
  599. <li><b>set &lt;name&gt; on-till &lt;timestamp&gt;</b><br/>
  600. Switch device on until <i>timestamp</i>. Parameter <i>timestamp</i> can be a time in
  601. format HH:MM or HH:MM:SS. This command is only available if channel contains a datapoint
  602. ON_TIME. The attribute 'statevals' must contain at least a value for 'on'. The Attribute
  603. 'statedatapoint' must be set to a writeable datapoint.
  604. </li><br/>
  605. <li><b>set &lt;name&gt; pct &lt;value&gt; [&lt;ontime&gt; [&lt;ramptime&gt;]]</b><br/>
  606. Set datapoint LEVEL of a channel to the specified <i>value</i>. Optionally a <i>ontime</i>
  607. and a <i>ramptime</i> (both in seconds) can be specified. This command is only available
  608. if channel contains at least a datapoint LEVEL and optionally datapoints ON_TIME and
  609. RAMP_TIME. The parameter <i>ontime</i> can be specified in seconds or as timestamp in
  610. format HH:MM or HH:MM:SS. If <i>ontime</i> is 0 it's ignored. This syntax can be used to
  611. modify the ramp time only.
  612. <br/><br/>
  613. Example: Turn dimmer on for 600 second. Increase light to 100% over 10 seconds<br>
  614. <code>
  615. attr myswitch statedatapoint LEVEL<br/>
  616. attr myswitch statevals on:100,off:0<br/>
  617. set myswitch pct 100 600 10
  618. </code>
  619. </li><br/>
  620. </ul>
  621. <br/>
  622. <a name="HMCCUCHNget"></a>
  623. <b>Get</b><br/><br/>
  624. <ul>
  625. <li><b>get &lt;name&gt; config [device] [&lt;filter-expr&gt;]</b><br/>
  626. Get configuration parameters of CCU channel. If attribute 'ccureadings' is 0 results
  627. are displayed in browser window. Parameters can be filtered by <i>filter-expr</i>.
  628. Parameters to be stored as readings must be part of 'ccureadingfilter'. If option
  629. 'device' is specified parameters of device are read.
  630. </li><br/>
  631. <li><b>get &lt;name&gt; configdesc [device]</b><br/>
  632. Get description of configuration parameters of CCU channel or device if option 'device'
  633. is specified.
  634. </li><br/>
  635. <li><b>get &lt;name&gt; configlist [device] [&lt;filter-expr&gt;]</b><br/>
  636. Get configuration parameters of CCU channel. Parameters can be filtered by
  637. <i>filter-expr</i>. With option 'device' device parameters are listed.
  638. </li><br/>
  639. <li><b>get &lt;name&gt; datapoint &lt;datapoint&gt;</b><br/>
  640. Get value of a CCU channel datapoint.
  641. </li><br/>
  642. <li><b>get &lt;name&gt; defaults</b><br/>
  643. Display default attributes for CCU device type.
  644. </li><br/>
  645. <li><b>get &lt;name&gt; deviceinfo [{State | <u>Value</u>}]</b><br/>
  646. Display all channels and datapoints of device with datapoint values and types.
  647. </li><br/>
  648. <li><b>get &lt;name&gt; devstate</b><br/>
  649. Get state of CCU device. Default datapoint STATE can be changed by setting
  650. attribute 'statedatapoint'. Command will fail if state datapoint does not exist in
  651. channel.
  652. </li><br/>
  653. <li><b>get &lt;name&gt; update [{State | <u>Value</u>}]</b><br/>
  654. Update all datapoints / readings of channel. With option 'State' the device is queried.
  655. This request method is more accurate but slower then 'Value'.
  656. </li>
  657. </ul>
  658. <br/>
  659. <a name="HMCCUCHNattr"></a>
  660. <b>Attributes</b><br/><br/>
  661. <ul>
  662. To reduce the amount of events it's recommended to set attribute 'event-on-change-reading'
  663. to '.*'.
  664. <br/><br/>
  665. <li><b>ccucalculate &lt;value-type&gt;:&lt;reading&gt;[:&lt;dp-list&gt;[;...]</b><br/>
  666. Calculate special values like dewpoint based on datapoints specified in
  667. <i>dp-list</i>. The result is stored in <i>reading</i>. The following <i>values</i>
  668. are supported:<br/>
  669. dewpoint = calculate dewpoint, <i>dp-list</i> = &lt;temperature&gt;,&lt;humidity&gt;<br/>
  670. abshumidity = calculate absolute humidity, <i>dp-list</i> = &lt;temperature&gt;,&lt;humidity&gt;<br/>
  671. inc = increment datapoint value considering reset of datapoint, <i>dp-list</i> = &lt;counter-datapoint&gt;<br/>
  672. min = calculate minimum continuously, <i>dp-list</i> = &lt;datapoint&gt;<br/>
  673. max = calculate maximum continuously, <i>dp-list</i> = &lt;datapoint&gt;<br/>
  674. sum = calculate sum continuously, <i>dp-list</i> = &lt;datapoint&gt;<br/>
  675. avg = calculate average continuously, <i>dp-list</i> = &lt;datapoint&gt;<br/>
  676. Example:<br/>
  677. <code>dewpoint:taupunkt:1.TEMPERATURE,1.HUMIDITY</code>
  678. </li><br/>
  679. <li><b>ccuflags {nochn0, trace}</b><br/>
  680. Control behaviour of device:<br/>
  681. ackState: Acknowledge command execution by setting STATE to error or success.<br/>
  682. nochn0: Prevent update of status channel 0 datapoints / readings.<br/>
  683. trace: Write log file information for operations related to this device.
  684. </li><br/>
  685. <li><b>ccuget {State | <u>Value</u>}</b><br/>
  686. Set read access method for CCU channel datapoints. Method 'State' is slower than 'Value'
  687. because each request is sent to the device. With method 'Value' only CCU is queried.
  688. Default is 'Value'.
  689. </li><br/>
  690. <li><b>ccureadings {0 | <u>1</u>}</b><br/>
  691. If set to 1 values read from CCU will be stored as readings. Default is 1.
  692. </li><br/>
  693. <li><b>ccureadingfilter &lt;filter-rule[;...]&gt;</b><br/>
  694. Only datapoints matching specified expression are stored as readings.<br/>
  695. Syntax for <i>filter-rule</i> is either:<br/>
  696. [N:]{&lt;channel-name&gt;|&lt;channel-number&gt;}!&lt;RegExp&gt; or:<br/>
  697. [N:][&lt;channel-number&gt;.]&lt;RegExp&gt;<br/>
  698. If <i>channel-name</i> or <i>channel-number</i> is specified the following rule
  699. applies only to this channel.
  700. By default all datapoints will be stored as readings. Attribute ccudef-readingfilter
  701. of I/O device will be checked before this attribute.<br/>
  702. If a rule starts with 'N:' the filter is negated which means that a reading is
  703. stored if rule doesn't match.
  704. </li><br/>
  705. <li><b>ccureadingformat {address[lc] | name[lc] | datapoint[lc]}</b><br/>
  706. Set format of reading names. Default for virtual device groups is 'name'. The default for all
  707. other device types is 'datapoint'. If set to 'address' format of reading names
  708. is channel-address.datapoint. If set to 'name' format of reading names is
  709. channel-name.datapoint. If set to 'datapoint' format is channel-number.datapoint. With
  710. suffix 'lc' reading names are converted to lowercase.
  711. </li><br/>
  712. <li><b>ccureadingname &lt;old-readingname-expr&gt;:[+]&lt;new-readingname&gt;[;...]</b><br/>
  713. Set alternative or additional reading names or group readings. Only part of old reading
  714. name matching <i>old-readingname-exptr</i> is substituted by <i>new-readingname</i>.
  715. If <i>new-readingname</i> is preceded by '+' an additional reading is created. If
  716. <i>old-readingname-expr</i> matches more than one reading the values of these readings
  717. are stored in one reading. This makes sense only in some cases, i.e. if a device has
  718. several pressed_short datapoints and a reading should contain a value if any button
  719. is pressed.<br/><br/>
  720. Examples:<br/>
  721. <code>
  722. # Rename readings 0.LOWBAT and 0.LOW_BAT as battery<br/>
  723. attr mydev ccureadingname 0.(LOWBAT|LOW_BAT):battery<br/>
  724. # Add reading battery as a copy of readings LOWBAT and LOW_BAT.<br/>
  725. # Rename reading 4.SET_TEMPERATURE as desired-temp<br/>
  726. attr mydev ccureadingname 0.(LOWBAT|LOW_BAT):+battery;1.SET_TEMPERATURE:desired-temp<br/>
  727. # Store values of readings n.PRESS_SHORT in new reading pressed.<br/>
  728. # Value of pressed is 1/true if any button is pressed<br/>
  729. attr mydev ccureadingname [1-4].PRESSED_SHORT:+pressed
  730. </code>
  731. </li><br/>
  732. <li><b>ccuscaleval &lt;datapoint&gt;:&lt;factor&gt;[,...]</b><br/>
  733. <b>ccuscaleval &lt;[!]datapoint&gt;:&lt;min&gt;:&lt;max&gt;:&lt;minn&gt;:&lt;maxn&gt;[,...]
  734. </b><br/>
  735. Scale, spread, shift and optionally reverse values before executing set datapoint commands
  736. or after executing get datapoint commands / before storing values in readings.<br/>
  737. If first syntax is used during get the value read from CCU is devided by <i>factor</i>.
  738. During set the value is multiplied by factor.<br/>
  739. With second syntax one must specify the interval in CCU (<i>min,max</i>) and the interval
  740. in FHEM (<i>minn, maxn</i>). The scaling factor is calculated automatically. If parameter
  741. <i>datapoint</i> starts with a '!' the resulting value is reversed.
  742. <br/><br/>
  743. Example: Scale values of datapoint LEVEL for blind actor and reverse values<br/>
  744. <code>
  745. attr myblind ccuscale !LEVEL:0:1:0:100
  746. </code>
  747. </li><br/>
  748. <li><b>ccuverify {<u>0</u> | 1 | 2}</b><br/>
  749. If set to 1 a datapoint is read for verification after set operation. If set to 2 the
  750. corresponding reading will be set to the new value directly after setting a datapoint
  751. in CCU without any verification.
  752. </li><br/>
  753. <li><b>controldatapoint &lt;datapoint&gt;</b><br/>
  754. Set datapoint for device control. Can be use to realize user defined control elements for
  755. setting control datapoint. For example if datapoint of thermostat control is
  756. SET_TEMPERATURE one can define a slider for setting the destination temperature with
  757. following attributes:<br/><br/>
  758. attr mydev controldatapoint SET_TEMPERATURE<br/>
  759. attr mydev webCmd control<br/>
  760. attr mydev widgetOverride control:slider,10,1,25
  761. </li><br/>
  762. <li><b>disable {<u>0</u> | 1}</b><br/>
  763. Disable client device.
  764. </li><br/>
  765. <li><b>hmstatevals &lt;subst-rule&gt;[;...]</b><br/>
  766. Define building rules and substitutions for reading hmstate. Syntax of <i>subst-rule</i>
  767. is<br/>
  768. [=&lt;reading&gt;;]&lt;datapoint-expr&gt;!&lt;{#n1-m1|regexp}&gt;:&lt;text&gt;[,...]
  769. <br/><br/>
  770. The syntax is almost the same as of attribute 'substitute', except there's no channel
  771. specification possible for datapoint and parameter <i>datapoint-expr</i> is a regular
  772. expression.<br/>
  773. The value of the I/O device attribute 'ccudef-hmstatevals' is appended to the value of
  774. this attribute. The default value of 'ccudef-hmstatevals' is
  775. '^UNREACH!(1|true):unreachable;LOW_?BAT!(1|true):warn_battery'.
  776. Normally one should not specify a substitution rule for the "good" value of an error
  777. datapoint (i.e. 0 for UNREACH). If none of the rules is matching, reading 'hmstate' is set
  778. to value of reading 'state'.<br/>
  779. Parameter <i>text</i> can contain variables in format ${<i>varname</i>}. The variable
  780. $value is substituted by the original datapoint value. All other variables must match
  781. with a valid datapoint name or a combination of channel number and datapoint name
  782. seperated by a '.'.<br/>
  783. Optionally the name of the HomeMatic state reading can be specified at the beginning of
  784. the attribute in format =&lt;reading&gt;;. The default reading name is 'hmstate'.
  785. </li><br/>
  786. <li><b>peer &lt;datapoints&gt;:&lt;condition&gt;:
  787. {ccu:&lt;object&gt;=&lt;value&gt;|hmccu:&lt;object&gt;=&lt;value&gt;|
  788. fhem:&lt;command&gt;}</b><br/>
  789. Logically peer datapoints of a HMCCUCHN or HMCCUDEV device with another device or any
  790. FHEM command.<br/>
  791. Parameter <i>datapoints</i> is a comma separated list of datapoints in format
  792. <i>channelno.datapoint</i> which can trigger the action.<br/>
  793. Parameter <i>condition</i> is a valid Perl expression which can contain
  794. <i>channelno.datapoint</i> names as variables. Variables must start with a '$' or a '%'.
  795. If a variable is preceded by a '$' the variable is substituted by the converted datapoint
  796. value (i.e. "on" instead of "true"). If variable is preceded by a '%' the raw value
  797. (i.e. "true") is used. If '$' or '%' is doubled the previous values will be used.<br/>
  798. If the result of this operation is true, the action specified after the second colon
  799. is executed. Three types of actions are supported:<br/>
  800. <b>hmccu</b>: Parameter <i>object</i> refers to a FHEM device/datapoint in format
  801. &lt;device&gt;:&lt;channelno&gt;.&lt;datapoint&gt;<br/>
  802. <b>ccu</b>: Parameter <i>object</i> refers to a CCU channel/datapoint in format
  803. &lt;channel&gt;.&lt;datapoint&gt;. <i>channel</i> can be a channel name or address.<br/>
  804. <b>fhem</b>: The specified <i>command</i> will be executed<br/>
  805. If action contains the string $value it is substituted by the current value of the
  806. datapoint which triggered the action. The attribute supports multiple peering rules
  807. separated by semicolons and optionally by newline characters.<br/><br/>
  808. Examples:<br/>
  809. # Set FHEM device mydummy to value if formatted value of 1.STATE is 'on'<br/>
  810. <code>attr mydev peer 1.STATE:'$1.STATE' eq 'on':fhem:set mydummy $value</code><br/>
  811. # Set 2.LEVEL of device myBlind to 100 if raw value of 1.STATE is 1<br/>
  812. <code>attr mydev peer 1.STATE:'%1.STATE' eq '1':hmccu:myBlind:2.LEVEL=100</code><br/>
  813. # Set 1.STATE of device LEQ1234567 to true if 1.LEVEL < 100<br/>
  814. <code>attr mydev peer 1.LEVEL:$1.LEVEL < 100:ccu:LEQ1234567:1.STATE=true</code><br/>
  815. # Set 1.STATE of device LEQ1234567 to true if current level is different from old level<br/>
  816. <code>attr mydev peer 1.LEVEL:$1.LEVEL != $$1.LEVEL:ccu:LEQ1234567:1.STATE=true</code><br/>
  817. </li><br/>
  818. <li><b>statedatapoint &lt;datapoint&gt;</b><br/>
  819. Set state datapoint used by some commands like 'set devstate'.
  820. </li><br/>
  821. <li><b>statevals &lt;text&gt;:&lt;text&gt;[,...]</b><br/>
  822. Define substitution for values of set commands. The parameters <i>text</i> are available
  823. as set commands.
  824. <br/><br/>
  825. Example:<br/>
  826. <code>
  827. attr my_switch statevals on:true,off:false<br/>
  828. set my_switch on
  829. </code>
  830. </li><br/>
  831. <li><b>stripnumber [&lt;datapoint-expr&gt;!]{<u>0</u>|1|2|-n|%fmt}[;...]</b><br/>
  832. Remove trailing digits or zeroes from floating point numbers, round or format
  833. numbers. If attribute is negative (-0 is valid) floating point values are rounded
  834. to the specified number of digits before they are stored in readings. The meaning of
  835. values 0,1,2 is:<br/>
  836. 0 = Floating point numbers are stored as read from CCU (i.e. with trailing zeros)<br/>
  837. 1 = Trailing zeros are stripped from floating point numbers except one digit.<br/>
  838. 2 = All trailing zeros are stripped from floating point numbers.<br/>
  839. With %fmt one can specify any valid sprintf() format string.<br/>
  840. If <i>datapoint-expr</i> is specified the formatting applies only to datapoints
  841. matching the regular expression.<br/>
  842. Example:<br>
  843. <code>
  844. attr myDev stripnumber TEMPERATURE!%.2f degree
  845. </code>
  846. </li><br/>
  847. <li><b>substexcl &lt;reading-expr&gt;</b><br/>
  848. Exclude values of readings matching <i>reading-expr</i> from substitution. This is helpful
  849. for reading 'control' if the reading is used for a slider widget and the corresponding
  850. datapoint is assigned to attribute statedatapoint and controldatapoint.
  851. </li><br/>
  852. <li><b>substitute &lt;subst-rule&gt;[;...]</b><br/>
  853. Define substitutions for datapoint/reading values. Syntax of <i>subst-rule</i> is<br/><br/>
  854. [[&lt;channelno&gt;.]&lt;datapoint&gt;[,...]!]&lt;{#n1-m1|regexp}&gt;:&lt;text&gt;[,...]
  855. <br/><br/>
  856. Parameter <i>text</i> can contain variables in format ${<i>varname</i>}. The variable
  857. ${value} is
  858. substituted by the original datapoint value. All other variables must match with a valid
  859. datapoint name or a combination of channel number and datapoint name seperated by a '.'.
  860. <br/><br/>
  861. Example: Substitute the value of datapoint TEMPERATURE by the string
  862. 'T=<i>val</i> deg' and append current value of datapoint 1.HUMIDITY<br/>
  863. <code>
  864. attr my_weather substitute TEMPERATURE!.+:T=${value} deg H=${1.HUMIDITY}%
  865. </code><br/><br/>
  866. If rule expression starts with a hash sign a numeric datapoint value is substituted if
  867. it fits in the number range n &lt;= value &lt;= m.
  868. <br/><br/>
  869. Example: Interpret LEVEL values 100 and 0 of dimmer as "on" and "off"<br/>
  870. <code>
  871. attr my_dim substitute LEVEL!#0-0:off,#1-100:on
  872. </code>
  873. </li>
  874. </ul>
  875. </ul>
  876. =end html
  877. =cut