Using Semantics in Rules

Recent events had motivated me to take a look at some of my rules. I wanted to rewrite some of them to take advantage of the Location metadata. My first attempt at this was turning the lights off in a room when it is empty. I originally wrote this rule back in OH v2.4 using Rich’s Associated Items DP. Now that I have upgraded to OHv3.2 I thought the below rules would be a good place to start experimenting with the Semantics metadata features.
For this rule I have several groups of lights - _Lights (e.g. LivingRoom_Lights), and switches called _Occupancy_Switch.

My first rule is a room occupancy updater, which works with the second rule that turns the lights off in the appropriate room. Both rules use the getLocation() method…

rule "Room Occupancy Updater"
when
    Member of Adults changed
then
    Thread::sleep(15000)
    gRoomOccupancy.members.forEach[ room |
        var location = getLocation(room)
        if (location.name == Chet.state.toString || location.name == Kathrin.state.toString) {
            room.sendCommand(ON)
        } else {
            room.sendCommand(OFF)
        }
    ]
end 

and the second rule…

rule "Turn lights off when room is empty"
when
    Member of gRoomOccupancy changed to OFF
then
        val LightLocation = getLocation(triggeringItem)
        val LightName = LightLocation.name+"_Lights"
        val Light = ScriptServiceUtil.getItemRegistry.getItem(LightName)
        timer = createTimer(now.plusMinutes(5)) [|. //patiently wait in case someone went to the bathroom.
            if(triggeringItem.state == OFF) Light.sendCommand(OFF)
            logInfo("Room Occupancy Update", triggeringItem.name + " is now empty. Switching off "+ Light.name)
            timer = null
            ]
end

This works, so I wanted to share my success with others who might be looking for this kind of functionality. Be aware, I’m not a professional coder, I put this rule together using various examples I found here in the forum. I’m sure they can be improved. So I welcome feedback/suggestions/etc.

With this success I’m going to modify my Window Open Notification rule. The rule will nag us until we close the window (the nagging feature was a request from my wife.) I will change it to prevent the notification/nagging if the room with the open window is occupied.

4 Likes

I’ve moved this to the Tutorials and Solutions category. It’s a great example of using the model in rules. Thanks for posting!

Looking at the code I see one main area for improvement.

Why such a long sleep? That was a really bad idea back in the old OH 2.x days. It’s not so bad these days but still kind of a long delay. In OH 3, calls to the rule will be queued up and run in sequence. So, for example if three of the members of Adults change within 15 seconds, the rule will run and take 15 seconds for the first one, then 15 seconds for the second one, and finally 15 seconds for the third.

The rule will run three times but it won’t run the last time until 45 seconds after the events occurred. If the members of Adults are flapping for some reason, you could spam this rule and it could be many minutes or longer before it manages to finish processing the events. Given these are controlling the lights, that’s a really long time between the event and the light turning on.

What would be better is to set a Timer for 15 seconds to loop through the locations and send the commands. If the rule is triggered while a Timer is already running, you can either reschedule the Timer or just ignore it.

But it’s not clear to me why there is a timer in the first place. What problem are you trying to solve?

What’s the . doing there? typo when pasting it to the forum or is it in the actual code. If in the code I’m surprised it doesn’t complain about syntax errors.

The Thread::sleep line in the first rule was a remnant of a very early version of the rule in which I wanted the rule to wait and see if the person returned to the room. I have since moved the that function to the second rule with a timer for 5 minutes. I will remove the sleep line and keep an eye on it.

. //patiently wait in case someone went to the bathroom.

That is a cut and paste error. There’s no . in my rule file.

Thanks for this example. How often are your updating gRoomOccupancy.members?

gRoomOccupancy members are updated by a rule that is triggered whenever a member of the Adults group changes (i.e. whenever the wife or I move around the house. Our phones are tracked by the UniFi binding and updates our location within the house.)

1 Like