This page last changed on Dec 15, 2013 by orjo.

Hi,

since it is not possible to call macros in a rule, how can i define sleep times in a rule?
I need a sleep of 100ms in a rule.

execute.command("ABC")
sleep(100ms)
execute.command("DEF")

Thank you very much.

It is Java so you can do this:

import java.util.concurrent.TimeUnit;
...
  execute.command("ABC");
  TimeUnit.MILLISECONDS.sleep(100);
  execute.command("DEF");
Posted by aktur at Dec 15, 2013 17:11

Thank you, it works.

Posted by orjo at Dec 15, 2013 20:58

Out of curiosity. Is OR halted during this sleep period or are other rules still running in the background along with the rest of OR say UDP or tcp etc?

Neil.

Posted by nwe at Dec 17, 2013 10:16

The rule engine is stopped and the thread it is running too. Some other parts running in different threads will be running though. Anyway, this solution is suitable for really short delays, like 100ms, I would say up to 1s. If you need more delay in rules, like minutes, hours or even more then a proper approach would be:

1. Make 2 rules and declare a new fact.
2. In the first rule insert the new fact defined previously.
3. In the second rule do the following:

rule "second rule"
timer(int: 1h)
when
  $r: NewFact()
then
  execute.command("delayed command by 1h");
  retract($r);
end
Posted by aktur at Dec 17, 2013 11:18

I did a little testing with using sleep in rules.
The goal to achieve was to run macros to control an AV-Scene. (Turn On AV-Receiver - Turn on TV - Turn on Satellite Receiver - wait 4s to turn on - Send Input HDMI1 to AV-Receiver)

I have the following rule:

rule "WATCH_TV_TV_ON"
when
  $evt : Event(source=="UDPL_HIFI", value=="WATCH_TV_TV_ON")
then
   log("rule: WATCH_TV_TV_ON");
   TimeUnit.MILLISECONDS.sleep(4000);
   log("rule: WATCH_TV_TV_ON starts NOW");
   execute.command("(ON)_IMVC_AV");
   execute.command("(ON)_IMVC_TV");
   execute.command("(ON)_IMVC_SAT");
   execute.command("(OFF)_IMVC_SCREEN");
   execute.command("(OFF)_IMVC_DVD");
   execute.command("(OFF)_IMVC_BEAMER");
   log("rule: WAIT 4s for devices");
   TimeUnit.MILLISECONDS.sleep(4000);
   log("rule: Go On");
   execute.command("(HDMI 3) [AV-Receiver]");
   log("rule: WATCH_TV_TV_ON is ON");
end

Alle the InMemory Virtual Command-Rules look like this:

rule "AV_IMVC_ON"
when
   $evt : Event(source=="(SENSOR)_IMVC_AVPOWER", value=="on")
then
   log("rule: AV_IMVC_ON");
   execute.command("(ON) [AV-Receiver]");
   log("rule: AV_IMVC_ON is ON");
end

There is no sleep in any of them. Every IMVC-Rule writes an Log-Entry before and after executing the "Real" command.
The created Log looks like this:

INFO 2013-12-22 19:29:36,274 : rule: WATCH_TV_TV_ON
INFO 2013-12-22 19:29:40,274 : rule: WATCH_TV_TV_ON starts NOW
INFO 2013-12-22 19:29:40,275 : rule: WAIT 4s for devices
INFO 2013-12-22 19:29:44,275 : rule: Go On
INFO 2013-12-22 19:29:44,432 : rule: WATCH_TV_TV_ON is ON
INFO 2013-12-22 19:29:44,434 : rule: UDPL Hifi Reset
INFO 2013-12-22 19:29:44,934 : rule: SAT_IMVC_ON
INFO 2013-12-22 19:29:45,098 : rule: SAT_IMVC_ON is ON
INFO 2013-12-22 19:29:45,100 : rule: TV_IMVC_ON
INFO 2013-12-22 19:29:45,371 : rule: TV_IMVC_ON is ON
INFO 2013-12-22 19:29:45,373 : rule: AV_IMVC_ON
INFO 2013-12-22 19:29:45,528 : rule: AV_IMVC_ON is ON

THe first Sleep is OK but why are the IMVC-Rules called after the Sleep-Time of 4seconds? In the Main-Rule it is called after sending all the IMVC-Rules.

Any Ideas?

@Michal Rutka: Could you post a complete Code-Sample of the two Rules for non Programmers (like me)

Thank you in advance.

Posted by orjo at Dec 22, 2013 18:47

This is expected behavior. A single rule execution blocks other rules and the whole sensor thread. To add delays without blocking you need to do the following: (not tested so beware of typos)

declare DelayEvent
  @role(event)
  source: String
  value: String
end

rule "Rule 1"
when
  Event($s: source, $v: value, source=="UDPL_HIFI", value=="WATCH_TV_TV_ON")
then
  insert(new DelayEvent($s.toString(), $v.toString()));
  // do rest here without delay
end

rule "Rule 2"
  timer (int: 4s)
when
  DelayEvent(source=="UDPL_HIFI", value=="WATCH_TV_TV_ON")
then
  // do something after 1st delay of 4s
end

rule "Rule 3"
  timer (int: 8s)
when
  $de : DelayEvent(source=="UDPL_HIFI", value=="WATCH_TV_TV_ON")
then
  // do something after 2nd delay of 8s
  retract($de); // retract delay when all done
end
Posted by aktur at Dec 23, 2013 09:50

Thank you Michael, that works perfect.
I will try to adopt this to my other scenes.

Posted by orjo at Dec 26, 2013 08:40
Document generated by Confluence on Jun 05, 2016 09:39