[SOLVED] Cannot Calculate the Milliseconds time difference between two vars

I am creating a rule to keep some lights on for a period of time.

I am trying to compare timeInMillis from two different periods. These are Long Types

But for some reason i cannot substract or even compare two epoch times. The result is:

2018-12-01 12:56:53.934 [INFO ] [rthome.model.script.front_door.rules] - Triggered wakeup
2018-12-01 12:56:53.948 [INFO ] [rthome.model.script.front_door.rules] - Last open is: 1543665310742
2018-12-01 12:56:53.955 [INFO ] [rthome.model.script.front_door.rules] - Time now is:  1543665413940
2018-12-01 12:56:53.961 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Keep Light On': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_minus(int,int) on instance: null

Code is:

rule "Keep Light On"
when
  Item FrontDoor_LightActive changed to ON
then
  var LastOpen = 0
  var i = 15
  var now = 0
  logInfo(log_title, "now is: " + now)
  logInfo(log_title, "Triggered wakeup")
  while (i > 1) {
    now = new DateTimeType().zonedDateTime.toInstant.toEpochMilli
    LastOpen = (FrontDoor_LastOpenTime.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
    logInfo(log_title, "Last open is: " + LastOpen)
    logInfo(log_title, "Time now is:  " + now)
    logInfo(log_title, "Calc: " + (now-LastOpen))
    if((now-LastOpen+5000) < 0) {
        // i = 1
        logInfo(log_title, "Time Reached - While loop updates i to 1")
    }
    logInfo(log_title, "While loop waits for sleep")
    Thread::sleep(2000)

    i = i - 1
    logInfo(log_title, "i Becomes " + i)
  }
  logInfo(log_title, "exit while")
  FrontDoor_LightActive.postUpdate(OFF)
end

What exact behaviour with your lights are you trying to achieve?

While loops in rules are dangerous because you are blocking a thread. There may be more elegant ways to achieve this.

See:

After the main door closes, the Hall Light should stay on for 5 minutes. If door opens’closes this timer should change.

I could do it with a trigger of the rule like the sunset/sunrise shows here. but this is my only rule which require something like this.
If we forget about the while loop
why
(now-LastOpen+5000) < 0)

throws that:
Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_minus(int,int) on instance: null

Ok,

Your need to install the expire binding

Then create an item:

Switch FrontDoor_LightActive_Timer { expire="5m, command=OFF" }

Your rules:

rule "Keep Light On"
when
    Item FrontDoor_LightActive changed to ON
then
    FrontDoor_LightActive_Timer.sendCommand(ON) // Start/Restart Timer
end

rule "Turn Light OFF"
when
    Item FrontDoor_LightActive_Timer received command OFF
then
    FrontDoor_LightActive.sendCommand(OFF)
end

That’s it

This doesn’t solve the case when the door is open for 5 minutes and i want it to start only when door is shut. And if it opens I need to reset this timer.

What is your Door item?

Behaviour?
When the door opens the light goes ON
When the door closes the light stay ON for 5 minutes
If the door opens again the timer reset

Thanks,

I will read more about it. outside the loop issue, on my rule how can I compare Long instead of Integers?
as a lesson for future needs

I have assumed that FrontDoor is your door sensor and FrontDoor_Light is the light item.

rule "Keep Light On"
when
    Item FrontDoor changed //Door is opened or closed
then
    FrontDoor_LightActive_Timer.sendCommand(ON) // Start/Restart Timer
    FrontDoor_Light.sendCommand(ON)
end

rule "Turn Light OFF"
when
    Item FrontDoor_LightActive_Timer received command OFF
then
    if (FrontDoor.state == OPEN) return; // Door stayed opened for 5 minutes do nothing
    FrontDoor_Light.sendCommand(OFF)
end

I think you can’t use the variable name now. Try changing it.

Adding Luminance on your example:

val log_title = "front_door.rules"
rule "Keep Light On"
when
    Item MainDoorSensor_DoorWindowSensor changed
then
    logInfo(log_title, "Door Sensor Change Triggered")
    if(MainDoorMultisensor_SensorLuminance.state < 8) {
      logInfo(log_title, "Door Sensor - Luminance is low enough")
      FrontDoor_LightActive_Timer.sendCommand(ON)
      FrontDoor_Light.sendCommand(ON)
    }
end

rule "Turn Light OFF"
when
    Item FrontDoor_LightActive_Timer received command OFF
then
    if (MainDoorSensor_DoorWindowSensor.state == OPEN) {
      logInfo(log_title, "Door Still Open")
    } else {
      logInfo(log_title, "Door is closed, timer also expired")
      FrontDoor_Light.sendCommand(OFF)
    }
end
1 Like

Nice, well done
The expire binding is very useful this way
You also could have used timers but this is simpler.

Please mark the tread as solved and look at:

It addresses issues with Thread::sleep and while loops in rules.