88_HMCCUCHN.pm 41 KB

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