How to use system time in rules?

I’m wanting my light to turn on if all of these conditions are true:

  1. it is between 7pm and 6am
  2. the PIR sensor is on
  3. the light is off

And turn off if either of these are true:

  1. it is outside 7pm and 6am
  2. the PIR sensor is off

My current rule which isn’t working. I’ve also tried a get.HourOfDay which also doesn’t work.

rule "smart light on"
when
    Time cron "0 0 19-6 1/1 * ? *"
then
    if ((pirDummy == ON) && (YeelightColour.state == OFF))
    {
    YeelightColour.sendCommand(ON)
    }
    else if ((pirDummy == OFF) && (YeelightColour.state == ON)){
    YeelightColour.sendCommand(OFF)}
end

Am I doing something wrong here?

Create a new Switch Item called DayTime

Switch DayTime

Rules:

rule "Daytime ON"
when
    Time cron "0 0 6 ? * * *"
then
    DayTime.postUpdate(ON)
end

rule "Daytime ON"
when
    Time cron "0 0 19 ? * * *"
then
    DayTime.postUpdate(OFF)
end

So now we have a “Flag” for the time
You want to trigger the light depending on the PIR so:

rule "smart light on"
when
    Item pirDummy changed
then
    if ((pirDummy.state == ON) && (YeelightColour.state == OFF) && (DayTime.state == ON)) {
        YeelightColour.sendCommand(ON)
    }
    else if ((pirDummy.state == OFF) && (YeelightColour.state == ON) && (DayTime.state == OFF)) {
        YeelightColour.sendCommand(OFF)
    }
end

Smart thinking, thanks buddy.

See:

I did see this but it seems overkill. Surely there is something simple to just call the current time on the openhab server?

Yes there is, but what seems overkill will come in very handy as your system grows

Yes, now gives you the current time. But giving that time meaning is what the ToD DP is for. It also centralized all of your time calculations in one place.

It may be overkill now if you only care what hour of the day it is in one place. But if you have two or more rules that care about the time of day then it really becomes a problem to have the calculations scattered throughout your rules.

Vincent’s solution is a simplified version of the ToD DP.

But, in reference to your first post, the important thing to realize is that Rules get triggered by events, not states. As written, your rule gets triggered once at 06:00 and every hour until 19:00.

What you need, based on your description, is to trigger the rule at 06:00, at 19:00, when ever the light changes state and when ever the PIR changes state.

Once the rule triggers, you check all the states and take the appropriate action.

Thanks, I may introduce the ToD DP later on, however at the moment the only things I’m able to integrate with openhab are a couple of smart lights, so at this scale there would be less code for me to just directly address local time.

Initially I did have the rule being triggered by the pir sensor changing state and then had the time as one of the conditions, however the rule wasn’t working and I thought how I was addressing time was wrong so I shifted it to how my current rule is written in my OP.

I did try using now, maybe I was writing the code wrong. I had actually tried one of your suggestions to another poster in a thread from about 6 months ago but it didn’t seem to work.

Do you mind sharing how to correctly use now in an if statement?

There are dozens of ways to use now in an if statement. What specifically do you want to compare?

In your case above to see if it is between 07:00 and 19:00 you would user something like

if(now.withTimeAtStartOfDay.plusHours(7).isBefore(now) && now.withTimeAtStartOfDay.plusHours(19).isAfter(now))

Yes that’s what I want to do, compare two set times.

I was expecting there would be a shorter way of addressing the current time.

Is now not accessing the current time on the local machine?

Could you not write something along the lines of if (now >= 1900 && now <= 0600)

Shorter than now? now IS the current time. The withTimeAtStartOfDay gives you midnight today. The plusHours adds that many hours. The isBefore returns true if the passed in time is before the the time you are calling it on

So

now.withTimeAtStartOfDay.plusHours(7).isBefore(now) 

Returns true if it is currently after 07:00 today.

No because now is the time AND date for right now. At it’s base, now is the number of milliseconds since 1970-1-1 00:00:00 (called epoch).

19:00 is meaningless in this context. Computers don’t keep time like a mechanical clock. They steadily count the milliseconds since epoch.

Edit. I had to pay before I was finished.

Anyway, there are other ways to do a test like this. For example

if(now.getHourOfDay > 7 && now.getHourOfDay <19)