Script that runs one a day

Hello, just starting with openhab2 and have one question about scripts. I need once a day make cleaning with robovac I see that rule something like this: openhab see that I’m not at home for 30 mins, openhab starts cleaning, vac cleans apt and after it stops monitoring my presence and goes to sleep till 02:00. it should be only once a day and after 02:00(midnight) start monitoring again, because now when I leave apt for the second time it starts cleaning again.

I suggest you start with reading the documentation.
After that, you should be able to start with developing your rule, however do that step by step. You can’t come up with a rule that will solve all your requirements up front.
So:

  1. Create a rule that starts the robovac
  2. Monitor your presence
  3. Create a rule that triggers x minutes after leaving the house.

Having solved all the single steps, you can start to put them together.

BTW: I don’t do your homework!

I read from that that they’re stuck on the last step, making it trigger only once a day.

@None_No you need to have a variable that’s shared between them, set it to true after your robot has started cleaning. Set it to false in another rule that triggers at a certain time:

Then, edit your cleaning rule so that it only cleans if that variable is false!

var hasCleaned = false

rule cleaning
when Item presence changed from ON to OFF
then
  if (hasCleaned == false) {
     // cleaning stuff
     hasCleaned = true
  }
end

rule resetClean
when Cron "0 0 2 1/1 * ? *"
then
  hasCleaned = false
end

The above is completely untested and I have not checked it’s syntax, but should put you in the right direction.

Another approach that would eliminate the need for the second rule is to use a timestamp.

var lastCleaned = now.minusDays(1)

rule "Cleaning"
when
    Item presence changed from ON to OFF
then
    if(lastCleaned.isBefore(now.minusDays(1)){
        // robo clean
        lastCleaned = now
    }
end
1 Like

Sorry, but I have an argument against that approach.
Consider two consecutive days, day one the user leaves home late, hence the job is done late. Day two he leaves early, the trigger starts but the time-diff is not over 24 hours, no cleaning. You would need to trigger more often in order to do the cleaning.

OK, then use

if(lastCleaned.isBefore(now.withTimeAtStartOfDay))

which only tests whether the last run was before midnight today.

2 Likes

I was expecting an answer, but not THAT fast.:+1:

The hard part is thinking of all the edge cases. Once you know them they often are easy enough to deal with. :smiley:

Thanks for answers, it really helps a lot. Have one more question: now after presence detection it should wait for 25 mins after it check presence one more time and it’s still nobody home starts cleaning. I haven’t found anything like labels with goto or loops, hope u can show me where i can read about it or what code should be. Thanks

VB programmer? You will rarely find labels and gotos in any programming language invented in the past 20 years.

https://docs.openhab.org/configuration/rules-dsl.html

A simple Timer is all you need.

var lastCleaned = now.minusDays(1)
var Timer timer = null

rule "Cleaning"
when
    Item presence changed from ON to OFF
then
    // we haven't cleaned yet today
    if(lastCleaned.isBefore(now.minusDays(1)){

        // schedule cleaning for 25 minutes from now
        timer = createTimer(now.plusMinutes(25), [|
            // robo clean
            lastCleaned = now
            timer = null
        ])
    }
end

rule "Cleaning"
when
    Item presence changed to ON
then
    // cancel the timer if it exists to prevent cleaning now someone is home
    timer?.cancel
    timer = null
end
1 Like

I have a question to the rule here

var lastCleaned = now.minusDays(1)

lastCleaned is outside of a cron job just on top of a rule file. Did this variable update only on startup?

Or at other triggers?
If this will be the case, which triggers? Becasue I have to change a lot of rules if this is not a fix value initial set on startup and will changed on triggers too.

It is a global variable. It gets created and initialized to now.minusDays(1) at startup and then updated when ever a rule has it to the left of an =. In this case we set it to yesterday so the next time the rule runs it will clean. When ever we clean we set it to now so it won’t clean until tomorrow.

Global variables are intended to store fixed values used in your rules (in which case use val instead of var), or to store a value g that sticks around from run to run if a rule.

@rlkoshak

Ah, I overseen this line here.

lastCleaned = now

Is is clear now.

now i get this(
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Cleaning’: cannot invoke method public abstract boolean org.eclipse.smarthome.model.script.actions.Timer.cancel() on null

var lastCleaned = now.minusDays(1)
var Timer apt_timer = null

rule "Cleaning"
when
    Thing 'bluetooth:ble:EBAC72F4839A' changed from ONLINE to OFFLINE
then
    // we haven't cleaned yet today
    if (lastCleaned.isBefore(now.minusDays(1))){
        logInfo("lamp.rules", "BLUETOOTH not in range will wait 25 min")
        // schedule cleaning for 25 minutes from now
        apt_timer = createTimer(now.plusMinutes(25), [|
            sendCommand(XiaomiPhilipsLEDCeilingLamp_PowerOnOff,ON)
            lastCleaned = now
            apt_timer = null
        ])
    }
end

rule "Cleaning"
when
    Thing 'bluetooth:ble:EBAC72F4839A' changed from OFFLINE to ONLINE
then
    // cancel the timer if it exists to prevent cleaning now someone is home
    apt_timer.cancel
    apt_timer = null
end

Got soultion, forget about ? in apt_timer.cancel
it should be apt_timer?.cancel

Another note, your rules have the same name! That can cause havok! If I’m not mistaken there is already an issue filed in order to have that noted in the docs.

Thanks, i’ll make changes

Hi All

I’m trying to do something similiar.

I want this scene to run once and only once every 12 hours, if the conditions are true.

This switches on some lights when the occupant comes home, but what happens is due to the presence being problematic, it may switch on during the night when the phone goes into and out of deep sleep.

Is this the correct method to achieve this?


var lastIlluminated = now.minusHours(12)

rule "Turn on arrival lights when guests arrive home after being out for 60minutes"
when
        Item gPresenceSensors changed to ON
then
       if (lastIlluminated.isBefore(now.minusHours(12))){
        if (Presence_Proxy.state == OFF) {
         if (vTimeOfDay.state == "EVENING" || vTimeOfDay.state == "NIGHT" || vTimeOfDay.state == "EVENING") {
         Bird_Light.sendCommand(ON)
         WallPendant_Light.sendCommand(ON)
         FrontDoor_Light.sendCommand(ON)
         Stairs_Light.sendCommand(ON)
         lastIlluminated = now
        }
    }
}
end

Time Based Trigger…

I cannot use time based triggers as I’m using a presence trigger

Ok … than use the Expire Binding …

Switch XYZ “XYZ” { expire=“12h,command=OFF” }