Bedroom motion sensor rule

So after a year of climbing the steep hill that is called ´learning how to use OpenHAB´, I finally am confident enough to share a piece of my smarthome with you. Disclaimer; I have/had no prior programming skills whatsoever, so if you have feedback as to how this rule can be improved code-wise that would be greatly appreciated! I tried to give as much info as needed, maybe overkilling it, but for me, info-rich threads really helped me to get the hang of OpenHAB. Hopefully this thread will do the same for other newcommers.

The rule below is used in my bedroom where the light is turned on when someone enters the room under certain conditions. The rule ´knows´ whom is entering, and turns on different lights depending in that person. Furthermore, if you only left the room for a midnight snack or toilet visit, OpenHab won´t turn on the light when you get back. For more side-information, read the Off topic part of this thread.

Off topic:

I live with my parents and am spending a lot of time in my bedroom, studying etc. When I come home, I want OpenHAB to ´know´ it is me that enters the bedroom so it can turn on the mood lighting. However, if my parents enter the room (bringing laundry etc.) and I am not home, they want a good amount of light, hence I turn on different lights depending on the one entering the bedroom.

At nights I put my phone in airplane mode. Via the Network binding, OpenHAB ´thinks´ I left the house which is not true. Thus, when I go to the toilet, OpenHAB turns on the ceiling light when I get back in my room, blinding me. Thanks to the second rule, the system ´knows´ I only left the room for a toilet visit (for example) and won´t turn on the ceiling light when I get back.

On-topic:

So this is the rule I have written with the help of a lot of people here on the forum:

var Timer motionTimer = null
var Number ToiletVisit = 0

rule "Bedroom Motionsensor"
when
    Item MotionSensor changed to ON //Start the rule when motion is detected.
then
    if(Sun.state != OFF) return; //As long as the sun is up, don´t execute.

    if(User_Home.state == ON && Mood_Light.state == OFF) { //If you are home and the mood light is off
        Mood_Light.sendCommand(ON) //Turn on the mood light.
    } else if (User_Home.state == OFF && Mood_Light.state == OFF && Door.state == ON && ToiletVisit == 0) { //if you are from home, mood light is off the door opens and no one is visiting the toilet
            if(motionTimer === null) { //execute al long as the timer is not set or running
                Ceiling_Light.sendCommand(ON) //Turn on the ceiling light
                Ceiling_Light_Bri.sendCommand(75) //Turn the brightness to 75
                logInfo("Motiontimer", "started") //Notify that the timer has started
                motionTimer = createTimer(now.plusSeconds(60), [ | //Create a timer for 60 seconds
                    var Home_Status = User_Home.state.toString //After 60 seconds, copy the state of User_Home to Home_status. If from home, it´s off. If home, it´s on.
                    Ceiling_Light.sendCommand(Home_Status) //Send the Home_status to the ceiling light.
                    motionTimer = null //change the timer to null so the rule can get triggered again if needed.
                    logInfo("Motiontimer", "done") //Notify that the timer is done.
                ])
            } else { //If motion is detected while the timer was running
                motionTimer.reschedule(now.plusSeconds(60)) //Drop the current timer and create a new one for another 60 seconds
                logInfo("Motiontimer", "rescheduled") //notify about te rescheduled timer
            } 
        }

rule "ToiletVisit value switch"
when
    Item Door changed //if the door is opened or closed
then
    if(Sun.state != OFF || MotionSensor.state != ON) return; //if the sun is up and/or there is no motion, don´t execute.

    ToiletVisit = if(Door.state == ON) 1 else 0 // if above is true, change the value of ToiletVisit.
end

Hardware I used:

  • Raspberry Pi 3B+
  • Hue Motion Sensor
  • Hue light bulbs
  • Xiaomi Aqara door switch
  • Bitron Funkstick

Bindings I used:

  • Zigbee binding
  • Network binding
  • Astro binding

Hopefully this rule is something you could use.

Kind regards,
jespiex

Edit: Spelling, removed reference to sleepwalking and improved the rule, according to feedback below.

7 Likes

Totally off-topic, but if she snores or tends to stop breathing t night she may want to consider a sleep test for sleep apnea. CPAP treatment can help with that and, many times, reduces the “sleepwalking”

1 Like

You are totally right, but fortunately for me and my girldfriend, we both never sleepwalk. Like I said in the off topic section, I called the rule ´sleepwalking´ to mock her, she somehow does not like it when I tease her with that. Really nice of you reaching out though! :smile:

2 Likes

Sleep apnea IS serious business though. Many people do not get diagnosed so they suffer needlessly.

2 Likes

You don’t need to cancel motionTimer inside motionTimer’s lambda. The motionTimer has already triggered, there is nothing to cancel. Just don’t do anything and set motionTimer to null at the end.

It helps to treat [ ] as a new context just like { } and indent all the code between them. It really helps one understand what the context is.

Consider failing fast. This can shorten Rules and reduce the number of indents leading to over all simpler Rules. For example, “Motion sensor while sleeping” only does something if the Sun is OFF and MotionSensor is ON. So

when
    if(Sun.state != OFF || MotionSensor.state != ON) return;

    SleepWalk = if(Door.state == ON) 1 else 0 // this is a ternary operator
    logInfo("sleepwalk", "sleepwalk = " + SleepWalk)

end

The above is part of Design Pattern: How to Structure a Rule. The same can be applied to the Motion Sensor Rule to simplify it a little bit as well.

Using Design Pattern: Expire Binding Based Timers could also simplify things a little bit as it will move the Timer body to it’s own Rule.

2 Likes

Thank you @rlkoshak for mentioning the improvements, I edited the rule above accordingly. The rule is a lot smaller and, for me, more logical now. Big thanks! :smile:

1 Like

I understand that the reference to sleepwalking was not a smart move, I removed it from the rule.

1 Like

We just care about the well-being of users here. I was perhaps a little over-zealous.

Sorry for the embarrassment. :cold_sweat:

1 Like

Please feel free to add your version here, for the benefit of later readers.

1 Like