20_X10.pm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. ################################################################
  2. #
  3. # Copyright notice
  4. #
  5. # (c) 2008 Dr. Boris Neubert (omega@online.de)
  6. #
  7. # This script is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # The GNU General Public License can be found at
  13. # http://www.gnu.org/copyleft/gpl.html.
  14. # A copy is found in the textfile GPL.txt and important notices to the license
  15. # from the author is found in LICENSE.txt distributed with these scripts.
  16. #
  17. # This script is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. # This copyright notice MUST APPEAR in all copies of the script!
  23. #
  24. ################################################################
  25. # $Id: 20_X10.pm 17421 2018-09-28 19:18:37Z neubert $
  26. #
  27. # Internals introduced in this module:
  28. # MODEL distinguish between different X10 device types
  29. # BRIGHT brightness level of dimmer devices in units of microdims (0..210)
  30. #
  31. # Readings introduced in this module:
  32. # state function and argument of last command
  33. # onoff inherited from switch interface (0= on, 1= off)
  34. # dimmer inherited from dimmer interface (0= dark, 100= bright)
  35. #
  36. # Setters introduced in this module:
  37. # on inherited from switch interface
  38. # off inherited from switch interface
  39. # dimmer inherited from dimmer interface (0= dark, 100= bright)
  40. # dimdown inherited from dimmer interface
  41. # dimup inherited from dimmer interface
  42. #
  43. package main;
  44. use strict;
  45. use warnings;
  46. my %functions = ( ALL_UNITS_OFF => "all_units_off",
  47. ALL_LIGHTS_ON => "all_lights_on",
  48. ON => "on",
  49. OFF => "off",
  50. DIM => "dimdown",
  51. BRIGHT => "dimup",
  52. ALL_LIGHTS_OFF => "all_lights_off",
  53. EXTENDED_CODE => "",
  54. HAIL_REQUEST => "",
  55. HAIL_ACK => "",
  56. PRESET_DIM1 => "",
  57. PRESET_DIM2 => "",
  58. EXTENDED_DATA_TRANSFER => "",
  59. STATUS_ON => "",
  60. STATUS_OFF => "",
  61. STATUS_REQUEST => "",
  62. );
  63. my %snoitcnuf; # the reverse of the above
  64. my %functions_rewrite = ( "all_units_off" => "off",
  65. "all_lights_on" => "on",
  66. "all_lights_off" => "off",
  67. );
  68. my %functions_snd = qw( ON 0010
  69. OFF 0011
  70. DIM 0100
  71. BRIGHT 0101 );
  72. my %housecodes_snd = qw(A 0110 B 1110 C 0010 D 1010
  73. E 0001 F 1001 G 0101 H 1101
  74. I 0111 J 1111 K 0011 L 1011
  75. M 0000 N 1000 O 0100 P 1100);
  76. my %unitcodes_snd = qw( 1 0110 2 1110 3 0010 4 1010
  77. 5 0001 6 1001 7 0101 8 1101
  78. 9 0111 10 1111 11 0011 12 1011
  79. 13 0000 14 1000 15 0100 16 1100);
  80. my %functions_set = ( "on" => 0,
  81. "off" => 0,
  82. "dimup" => 1,
  83. "dimdown" => 1,
  84. "dimto" => 1,
  85. "on-till" => 1,
  86. "on-for-timer" => 1,
  87. "all_units_off" => 0,
  88. "all_units_on" => 0,
  89. "all_lights_off" => 0,
  90. "all_lights_on" => 0,
  91. );
  92. my %models = (
  93. lm12 => 'dimmer',
  94. lm15 => 'switch',
  95. am12 => 'switch',
  96. tm13 => 'switch',
  97. );
  98. my %interfaces = (
  99. lm12 => 'dimmer',
  100. lm15 => 'switch_passive',
  101. am12 => 'switch_passive',
  102. tm13 => 'switch_passive',
  103. );
  104. my @lampmodules = ('lm12','lm15'); # lamp modules
  105. sub
  106. X10_Initialize($)
  107. {
  108. my ($hash) = @_;
  109. foreach my $k (keys %functions) {
  110. $snoitcnuf{$functions{$k}}= $k;
  111. }
  112. $hash->{Match} = "^X10:[A-P];";
  113. $hash->{SetFn} = "X10_Set";
  114. $hash->{StateFn} = "X10_SetState";
  115. $hash->{DefFn} = "X10_Define";
  116. $hash->{UndefFn} = "X10_Undef";
  117. $hash->{ParseFn} = "X10_Parse";
  118. $hash->{AttrList} = "IODev do_not_notify:1,0 " .
  119. "dummy:1,0 showtime:1,0 model:lm12,lm15,am12,tm13";
  120. }
  121. #####################################
  122. sub
  123. X10_SetState($$$$)
  124. {
  125. my ($hash, $tim, $vt, $val) = @_;
  126. return undef;
  127. }
  128. #############################
  129. sub
  130. X10_StateMachine($$$$)
  131. {
  132. my($hash, $time, $function, $argument)= @_;
  133. # the following changes between (onoff,bright) states were
  134. # experimentally observed for a Busch Timac Ferndimmer 2265
  135. # bright and argument are measured in brightness steps
  136. # from 0 (0%) to 210 (100%).
  137. # for convenience, we connect the off state with a 210 bright state
  138. #
  139. # initial on off dimup d dimdown d
  140. # -------------------------------------------------------------------------
  141. # (on,x) -> (on,x) (off,210) (on,x+d) (on,x-d)
  142. # (off,210) -> (on,210) (off,210) (on,210) (on,210-d)
  143. my $onoff;
  144. my $bright;
  145. if(defined($hash->{ONOFF})) {
  146. $onoff= $hash->{ONOFF};
  147. } else {
  148. $onoff= 0; }
  149. if(defined($hash->{BRIGHT})) {
  150. $bright= $hash->{BRIGHT};
  151. } else {
  152. $bright= 0; }
  153. #Log3 $hash, 1, $hash->{NAME} . " initial state ($onoff,$bright)";
  154. if($onoff) {
  155. # initial state (on,bright)
  156. if($function eq "on") {
  157. } elsif($function eq "off") {
  158. $onoff= 0; $bright= 210;
  159. } elsif($function eq "dimup") {
  160. $bright+= $argument;
  161. if($bright> 210) { $bright= 210 };
  162. } elsif($function eq "dimdown") {
  163. $bright-= $argument;
  164. if($bright< 0) { $bright= 0 };
  165. }
  166. } else {
  167. # initial state (off,bright)
  168. if($function eq "on") {
  169. $onoff= 1; $bright= 210;
  170. } elsif($function eq "off") {
  171. $onoff= 0; $bright= 210;
  172. } elsif($function eq "dimup") {
  173. $onoff= 1; $bright= 210;
  174. } elsif($function eq "dimdown") {
  175. $onoff= 1;
  176. $bright= 210-$argument;
  177. if($bright< 0) { $bright= 0 };
  178. }
  179. }
  180. #Log3 $hash, 1, $hash->{NAME} . " final state ($onoff,$bright)";
  181. $hash->{ONOFF}= $onoff;
  182. $hash->{BRIGHT}= $bright;
  183. $hash->{READINGS}{onoff}{TIME}= $time;
  184. $hash->{READINGS}{onoff}{VAL}= $onoff;
  185. $hash->{READINGS}{dimmer}{TIME}= $time;
  186. $hash->{READINGS}{dimmer}{VAL}= int(1000.0*$bright/210.0+0.5)/10.0;
  187. }
  188. #############################
  189. sub
  190. X10_LevelToDims($)
  191. {
  192. # 22= 100%
  193. my ($level)= @_;
  194. my $dim= int(22*$level/100.0+0.5);
  195. return $dim;
  196. }
  197. #############################
  198. sub
  199. X10_Do_On_Till($@)
  200. {
  201. my ($hash, @a) = @_;
  202. return "Timespec (HH:MM[:SS]) needed for the on-till command" if(@a != 3);
  203. my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($a[2]);
  204. return $err if($err);
  205. my @lt = localtime;
  206. my $hms_till = sprintf("%02d:%02d:%02d", $hr, $min, $sec);
  207. my $hms_now = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]);
  208. if($hms_now ge $hms_till) {
  209. Log3 $hash, 4, "on-till: won't switch as now ($hms_now) is later than $hms_till";
  210. return "";
  211. }
  212. if($modules{X10}{ldata}{$a[0]}) {
  213. CommandDelete(undef, $a[0] . "_timer");
  214. delete $modules{FS20}{ldata}{$a[0]};
  215. }
  216. $modules{X10}{ldata}{$a[0]} = "$hms_till";
  217. my @b = ($a[0], "on");
  218. X10_Set($hash, @b);
  219. CommandDefine(undef, $hash->{NAME} . "_timer at $hms_till set $a[0] off");
  220. }
  221. #############################
  222. sub
  223. X10_Do_On_For_Timer($@)
  224. {
  225. my ($hash, @a) = @_;
  226. return "Timespec (HH:MM[:SS]) needed for the on-for-timer command" if(@a != 3);
  227. my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($a[2]);
  228. return $err if($err);
  229. my $hms_for_timer = sprintf("+%02d:%02d:%02d", $hr, $min, $sec);
  230. if($modules{X10}{ldata}{$a[0]}) {
  231. CommandDelete(undef, $a[0] . "_timer");
  232. delete $modules{FS20}{ldata}{$a[0]};
  233. }
  234. $modules{X10}{ldata}{$a[0]} = "$hms_for_timer";
  235. my @b = ($a[0], "on");
  236. X10_Set($hash, @b);
  237. CommandDefine(undef, $hash->{NAME} . "_timer at $hms_for_timer set $a[0] off");
  238. }
  239. ###################################
  240. sub
  241. X11_Write($$$)
  242. {
  243. my ($hash, $function, $dim)= @_;
  244. my $name = $hash->{NAME};
  245. my $housecode= $hash->{HOUSE};
  246. my $unitcode = $hash->{UNIT};
  247. my $x10func = $snoitcnuf{$function};
  248. undef $function; # do not use after this point
  249. my $prefix= "X10 device $name:";
  250. Log3 $name, 5, "$prefix sending X10:$housecode;$unitcode;$x10func $dim";
  251. my ($hc_b, $hu_b, $hf_b);
  252. my ($hc, $hu, $hf);
  253. # Header:Code, Address
  254. $hc_b = "00000100"; # 0x04
  255. $hc = pack("B8", $hc_b);
  256. $hu_b = $housecodes_snd{$housecode} . $unitcodes_snd{$unitcode};
  257. $hu = pack("B8", $hu_b);
  258. IOWrite($hash, $hc, $hu);
  259. # Header:Code, Function
  260. $hc_b = substr(unpack('B8', pack('C', $dim)), 3) . # dim, 0..22
  261. "110"; # always 110
  262. $hc = pack("B8", $hc_b);
  263. $hf_b = $housecodes_snd{$housecode} . $functions_snd{$x10func};
  264. $hf = pack("B8", $hf_b);
  265. IOWrite($hash, $hc, $hf);
  266. }
  267. ###################################
  268. sub
  269. X10_Set($@)
  270. {
  271. my ($hash, @a) = @_;
  272. my $ret = undef;
  273. my $na = int(@a);
  274. # initialization and sanity checks
  275. return "no set value specified" if($na < 2);
  276. my $name= $hash->{NAME};
  277. my $function= $a[1];
  278. my $nrparams= $functions_set{$function};
  279. return "Unknown argument $function, choose one of " .
  280. join(" ", sort keys %functions_set) if(!defined($nrparams));
  281. return "Wrong number of parameters" if($na != 2+$nrparams);
  282. # special for on-till
  283. return X10_Do_On_Till($hash, @a) if($function eq "on-till");
  284. # special for on-for-timer
  285. return X10_Do_On_For_Timer($hash, @a) if($function eq "on-for-timer");
  286. # argument evaluation
  287. my $model= $hash->{MODEL};
  288. my $dim= 0;
  289. if($function =~ m/^dim/) {
  290. return "Cannot dim $name (model $model)" if($models{$model} ne "dimmer");
  291. my $arg= $a[2];
  292. return "Wrong argument $arg, use 0..100" if($arg !~ m/^[0-9]{1,3}$/);
  293. return "Wrong argument $arg, use 0..100" if($arg>100);
  294. if($function eq "dimto") {
  295. # translate dimmer command to dimup/dimdown command
  296. my $bright= 210;
  297. if(defined($hash->{BRIGHT})) { $bright= $hash->{BRIGHT} };
  298. $arg= $arg-100.0*$bright/210.0;
  299. if($arg> 0) {
  300. $function= "dimup";
  301. $dim= X10_LevelToDims($arg);
  302. } else {
  303. $function= "dimdown";
  304. $dim= X10_LevelToDims(-$arg);
  305. }
  306. } else {
  307. $dim= X10_LevelToDims($arg);
  308. }
  309. # the meaning of $dim= 0, 1 is unclear
  310. # if we encounter the need for dimming by such a small amount, we
  311. # ignore it
  312. if($dim< 2) { return "Dim amount too small" };
  313. };
  314. # send command to CM11
  315. X11_Write($hash, $function, $dim) if(!IsDummy($a[0]));
  316. my $v = join(" ", @a);
  317. Log3 $a[0], 2, "X10 set $v";
  318. (undef, $v) = split(" ", $v, 2); # Not interested in the name...
  319. my $tn = TimeNow();
  320. $hash->{CHANGED}[0] = $v;
  321. $hash->{STATE} = $v;
  322. $hash->{READINGS}{state}{TIME} = $tn;
  323. $hash->{READINGS}{state}{VAL} = $v;
  324. X10_StateMachine($hash, $tn, $function, int(210.0*$dim/22.0+0.5));
  325. return undef;
  326. }
  327. #############################
  328. sub
  329. X10_Define($$)
  330. {
  331. my ($hash, $def) = @_;
  332. my @a = split("[ \t][ \t]*", $def);
  333. return "wrong syntax: define <name> X10 model housecode unitcode"
  334. if(int(@a)!= 5);
  335. my $model= $a[2];
  336. return "Define $a[0]: wrong model: specify one of " .
  337. join ",", sort keys %models
  338. if(!grep { $_ eq $model} keys %models);
  339. my $housecode = $a[3];
  340. return "Define $a[0]: wrong housecode format: specify a value ".
  341. "from A to P"
  342. if($housecode !~ m/^[A-P]$/i);
  343. my $unitcode = $a[4];
  344. return "Define $a[0]: wrong unitcode format: specify a value " .
  345. "from 1 to 16"
  346. if( ($unitcode<1) || ($unitcode>16) );
  347. $hash->{MODEL} = $model;
  348. $hash->{HOUSE} = $housecode;
  349. $hash->{UNIT} = $unitcode;
  350. $hash->{internals}{interfaces}= $interfaces{$model};
  351. if(defined($modules{X10}{defptr}{$housecode}{$unitcode})) {
  352. return "Error: duplicate X10 device $housecode $unitcode definition " .
  353. $hash->{NAME} . " (previous: " .
  354. $modules{X10}{defptr}{$housecode}{$unitcode}->{NAME} .")";
  355. }
  356. $modules{X10}{defptr}{$housecode}{$unitcode}= $hash;
  357. AssignIoPort($hash);
  358. }
  359. #############################
  360. sub
  361. X10_Undef($$)
  362. {
  363. my ($hash, $name) = @_;
  364. if( defined($hash->{HOUSE}) && defined($hash->{UNIT}) ) {
  365. delete($modules{X10}{defptr}{$hash->{HOUSE}}{$hash->{UNIT}});
  366. }
  367. return undef;
  368. }
  369. #############################
  370. sub
  371. X10_Parse($$)
  372. {
  373. my ($hash, $msg) = @_;
  374. # message example: X10:N;1 12;OFF
  375. (undef, $msg)= split /:/, $msg, 2; # strip off "X10"
  376. my ($housecode,$unitcodes,$command)= split /;/, $msg, 4;
  377. my @list; # list of selected devices
  378. #
  379. # command evaluation
  380. #
  381. my ($x10func,$arg)= split / /, $command, 2;
  382. my $function= $functions{$x10func}; # translate, eg BRIGHT -> dimup
  383. undef $x10func; # do not use after this point
  384. # the following code sequence converts an all on/off command into
  385. # a sequence of simple on/off commands for all defined devices
  386. my $all_lights= ($function=~ m/^all_lights_/);
  387. my $all_units= ($function=~ m/^all_units_/);
  388. if($all_lights || $all_units) {
  389. $function= $functions_rewrite{$function}; # translate, all_lights_on -> on
  390. $unitcodes= "";
  391. foreach my $unitcode (keys %{ $modules{X10}{defptr}{$housecode} } ) {
  392. my $h= $modules{X10}{defptr}{$housecode}{$unitcode};
  393. my $islampmodule= grep { $_ eq $h->{MODEL} } @lampmodules;
  394. if($all_units || $islampmodule ) {
  395. $unitcodes.= " " if($unitcodes ne "");
  396. $unitcodes.= $h->{UNIT};
  397. }
  398. }
  399. # no units for that housecode
  400. if($unitcodes eq "") {
  401. Log3 $hash, 3, "X10 No units with housecode $housecode, command $command, " .
  402. "please define one";
  403. push(@list,
  404. "UNDEFINED X10_$housecode X10 lm15 $housecode ?");
  405. return @list;
  406. }
  407. }
  408. # apply to each unit in turn
  409. my @unitcodes= split / /, $unitcodes;
  410. if(!int(@unitcodes)) {
  411. # command without unitcodes, this happens when a single on/off is sent
  412. # but no unit was previously selected
  413. Log3 $hash, 3, "X10 No unit selected for housecode $housecode, command $command";
  414. push(@list,
  415. "UNDEFINED X10_$housecode X10 lm15 $housecode ?");
  416. return @list;
  417. }
  418. # function rewriting
  419. my $value= $function;
  420. return @list if($value eq ""); # function not evaluated
  421. # function determined, add argument
  422. if( defined($arg) ) {
  423. # received dims from 0..210
  424. my $dim= $arg;
  425. $value = "$value $dim" ;
  426. }
  427. my $unknown_unitcodes= '';
  428. my $tn= TimeNow();
  429. foreach my $unitcode (@unitcodes) {
  430. my $h= $modules{X10}{defptr}{$housecode}{$unitcode};
  431. if($h) {
  432. my $name= $h->{NAME};
  433. $h->{CHANGED}[0] = $value;
  434. $h->{STATE} = $value;
  435. $h->{READINGS}{state}{TIME} = $tn;
  436. $h->{READINGS}{state}{VAL} = $value;
  437. X10_StateMachine($h, $tn, $function, $arg);
  438. Log3 $hash, 2, "X10 $name $value";
  439. push(@list, $name);
  440. } else {
  441. Log3 $hash, 3, "X10 Unknown device $housecode $unitcode, command $command, " .
  442. "please define it";
  443. push(@list,
  444. "UNDEFINED X10_$housecode X10 lm15 $housecode $unitcode");
  445. }
  446. }
  447. return @list;
  448. }
  449. 1;
  450. =pod
  451. =item summary devices communicating via the X10 protocol
  452. =item summary_DE Anbindung von X10-Ger&auml;ten
  453. =begin html
  454. <a name="X10"></a>
  455. <h3>X10</h3>
  456. <ul>
  457. <a name="X10define"></a>
  458. <b>Define</b>
  459. <ul>
  460. <code>define &lt;name&gt; X10 &lt;model&gt; &lt;housecode&gt;
  461. &lt;unitcode&gt;</code>
  462. <br><br>
  463. Defines an X10 device via its model, housecode and unitcode.<br><br>
  464. Notes:
  465. <ul>
  466. <li><code>&lt;model&gt;</code> is one of
  467. <ul>
  468. <li><code>lm12</code>: lamp module, dimmable</li>
  469. <li><code>lm15</code>: lamp module, not dimmable</li>
  470. <li><code>am12</code>: appliance module, not dimmable</li>
  471. <li><code>tm12</code>: tranceiver module, not dimmable. Its
  472. unitcode is 1.</li>
  473. </ul>
  474. Model determines whether a dim command is reasonable to be sent
  475. or not.</li>
  476. <li><code>&lt;housecode&gt;</code> ranges from A to P.</li>
  477. <li><code>&lt;unitcode&gt;</code> ranges from 1 to 16.</li>
  478. </ul>
  479. <br>
  480. Examples:
  481. <ul>
  482. <code>define lamp1 X10 lm12 N 10</code><br>
  483. <code>define pump X10 am12 B 7</code><br>
  484. <code>define lamp2 X10 lm15 N 11</code><br>
  485. </ul>
  486. </ul>
  487. <br>
  488. <a name="X10set"></a>
  489. <b>Set </b>
  490. <ul>
  491. <code>set &lt;name&gt; &lt;value&gt; [&lt;argument&gt]</code>
  492. <br><br>
  493. where <code>value</code> is one of:<br>
  494. <pre>
  495. dimdown # requires argument, see the note
  496. dimup # requires argument, see the note
  497. off
  498. on
  499. on-till # Special, see the note
  500. on-for-timer # Special, see the note
  501. </pre>
  502. Examples:
  503. <ul>
  504. <code>set lamp1 dimup 10</code><br>
  505. <code>set lamp1,lamp2 off</code><br>
  506. <code>set pump off</code><br>
  507. <code>set lamp2 on-till 19:59</code><br>
  508. <code>set lamp2 on-for-timer 00:02:30</code><br>
  509. </ul>
  510. <br>
  511. Notes:
  512. <ul>
  513. <li>Only switching and dimming are supported by now.</li>
  514. <li>Dimming is valid only for a dimmable device as specified by
  515. the <code>model</code> argument in its <code>define</code>
  516. statement.</li>
  517. <li>An X10 device has 210 discrete brightness levels. If you use a
  518. X10 sender, e.g. a remote control or a wall switch to dim, a
  519. brightness step is 100%/210.</li>
  520. <li><code>dimdown</code> and <code>dimup</code> take a number in the
  521. range from 0 to 22 as argument. It is assumed that argument 1 is
  522. a 1% brightness change (microdim) and arguments 2 to 22 are
  523. 10%..100% brightness changes. The meaning of argument 0 is
  524. unclear.</li>
  525. <li>This currently leads to some confusion in the logs as the
  526. <code>dimdown</code> and <code>dimup</code> codes are logged with
  527. different meaning of the arguments depending on whether the commands
  528. were sent from the PC or from a remote control or a wall switch.</li>
  529. <li><code>dimdown</code> and <code>dimup</code> from on and off states may
  530. have unexpected results. This seems to be a feature of the X10
  531. devices.</li>
  532. <li><code>on-till</code> requires an absolute time in the "at" format
  533. (HH:MM:SS, HH:MM) or { &lt;perl code&gt; }, where the perl code
  534. returns a time specification).
  535. If the current time is greater than the specified time, then the
  536. command is ignored, else an "on" command is generated, and for the
  537. given "till-time" an off command is scheduleld via the at command.
  538. </li>
  539. <li><code>on-for-timer</code> requires a relative time in the "at" format
  540. (HH:MM:SS, HH:MM) or { &lt;perl code&gt; }, where the perl code
  541. returns a time specification).
  542. </li>
  543. </ul>
  544. </ul>
  545. <br>
  546. <a name="X10get"></a>
  547. <b>Get</b> <ul>N/A</ul><br>
  548. <a name="X10attr"></a>
  549. <b>Attributes</b>
  550. <ul>
  551. <li><a href="#do_not_notify">do_not_notify</a></li>
  552. <li><a href="#attrdummy">dummy</a></li>
  553. <li><a href="#showtime">showtime</a></li>
  554. <li><a href="#model">model</a> (lm12,lm15,am12,tm13)</li>
  555. <li><a href="#IODev">IODev</a></li><br>
  556. <li><a href="#eventMap">eventMap</a></li><br>
  557. </ul>
  558. <br>
  559. </ul>
  560. =end html
  561. =cut