Motion Detector Lights

Motion Detectors and Lighting

I have a fairly complex lighting setup, and this is one element of that. It is probably not perfect but it is working.
Maybe someone will find this useful for themselves, or suggest improvements.

Other components of my lighting setup can be seen here-

And here is my rules file controlling all of my motion detector lights:

var Timer timer_backhall = null
var Timer timer_hall = null
var Timer timer_kEndboard = null
var Timer timer_kSink = null

rule "Motion Light - Back Hall custom timer"
when
    Item BackHall_MotionLightSensor_Motion received update ON 
then
    val bright = BackHall_Ceiling_Light_Brightness
    val sceneB = BackHall_Ceiling_Light_SceneBrightness
    val ctemp = BackHall_Ceiling_Light_ColorTemperature
    val illum = BackHall_MotionLightSensor_Illuminance
    val illumt = BackHall_Ceiling_Light_IlluminanceThreshold
    val timerItem = BackHall_MotionLightSensor_Timer
    val onOff = BackHall_MotionLightSensor_OnOff

    if (onOff.state == ON) {    
        if (timer_backhall === null) {
            logInfo("Motion Lights - " + getLocation(bright).label, "Motion detected") 

            if ((illum.state as Number) <= (illumt.state as Number)) {
                logInfo("Motion Lights - " + getLocation(bright).label, "Illuminance (" + illum.state + ") is below Threshold (" + illumt.state + "). Turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
                ctemp.sendCommand(Calculated_ColorTemperature.state.toString)
                if (bright.state != sceneB.state) {
                    bright.sendCommand(sceneB.state.toString)
                }

                timer_backhall = createTimer(now.plusMinutes(Integer::parseInt(timerItem.state.toString)), [ | 
                    bright.sendCommand(OFF)
                    timer_backhall.cancel()
                    timer_backhall = null
                    logInfo("Motion Lights - " + getLocation(bright).label, "Timer elapsed. " + getLocation(bright).label + " " + getEquipment(bright).label + " turned OFF")
                ])
                logInfo("Motion Lights - " + getLocation(bright).label, timerItem.state + " min Timer started")

            } else {
                logInfo("Motion Lights - " + getLocation(bright).label, "Illuminance (" + illum.state + ") is above Threshold (" + illumt.state + "). Not turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
            }

        } else if (timer_backhall !== null) {
            timer_backhall.reschedule(now.plusMinutes(Integer::parseInt(timerItem.state.toString)))
            logInfo("Motion Lights - " + getLocation(bright).label, timerItem.state + " min Timer rescheduled")
        } 

        Kitchen_Endboard_MotionLightSensor_Motion.sendCommand(ON)
        Kitchen_Endboard_MotionLightSensor_Motion.sendCommand(OFF)

    }
end

rule "Lights, Back Hall - 'On Time' turns OFF 'Motion Detection'"
when
    Item BackHall_Ceiling_Light_OnTime changed
then
    if (newState > 0 && BackHall_MotionLightSensor_OnOff.state == ON) {
        BackHall_MotionLightSensor_OnOff.sendCommand(OFF)
        logInfo("Lights - Back Hall", "'On Time' turned ON, so Motion Detection is turning OFF")
    }
end

rule "Lights, Back Hall - 'Motion Detection' turns OFF 'On Time'"
when
    Item BackHall_MotionLightSensor_OnOff changed to ON
then
    if (BackHall_Ceiling_Light_OnTime.state > 0) {
        BackHall_Ceiling_Light_OnTime.sendCommand(0)
        logInfo("Lights - Back Hall", "'Motion Detection' turned ON, so 'On Time' set to 0 min")
    }
end


rule "Motion Light - Hall custom timer"
when
    Item Hall_MotionLightSensor_Motion received update ON 
then
    val bright = Hall_Ceiling_Light_Brightness
    val sceneB = Hall_Ceiling_Light_SceneBrightness
    val ctemp = Hall_Ceiling_Light_ColorTemperature
    val illum = Hall_MotionLightSensor_Illuminance
    val illumt = Hall_Ceiling_Light_IlluminanceThreshold
    val motion = Hall_MotionLightSensor_Motion
    val timerItem = Hall_MotionLightSensor_Timer
    val onOff = Hall_MotionLightSensor_OnOff
    
    if (onOff.state == ON) {    
        if (timer_hall === null) {
            logInfo("Motion Lights - " + getLocation(bright).label, "Motion detected") 

            if ((illum.state as Number) <= (illumt.state as Number)) {
                logInfo("Motion Lights - " + getLocation(bright).label, "Illuminance (" + illum.state + ") is below Threshold (" + illumt.state + "). Turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
                ctemp.sendCommand(Calculated_ColorTemperature.state.toString)
                if (bright.state != sceneB.state) {
                    bright.sendCommand(sceneB.state.toString)
                }
                

                timer_hall = createTimer(now.plusMinutes(Integer::parseInt(timerItem.state.toString)), [ | 
                    bright.sendCommand(OFF)
                    timer_hall.cancel()
                    timer_hall = null
                    logInfo("Motion Lights - " + getLocation(bright).label, "Timer elapsed. " + getLocation(bright).label + " " + getEquipment(bright).label + " turned OFF")
                    if (motion.state == ON) {
                        motion.sendCommand(OFF)
                    }
                ])
                logInfo("Motion Lights - " + getLocation(bright).label, timerItem.state + " min Timer started")

            } else {
                logInfo("Motion Lights - " + getLocation(bright).label, "Illuminance (" + illum.state + ") is above Threshold (" + illumt.state + "). Not turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
            }

        } else if (timer_hall !== null) {
            timer_hall.reschedule(now.plusMinutes(Integer::parseInt(timerItem.state.toString)))
            logInfo("Motion Lights - " + getLocation(bright).label, timerItem.state + " min Timer rescheduled")
        } 
    }
end

rule "Lights, Hall - 'On Time' turns OFF 'Motion Detection'"
when
    Item Hall_Ceiling_Light_OnTime changed
then
    if (newState > 0 && Hall_MotionLightSensor_OnOff.state == ON) {
        Hall_MotionLightSensor_OnOff.sendCommand(OFF)
        logInfo("Lights - Hall", "'On Time' turned ON, so Motion Detection is turning OFF")
    }
end

rule "Lights, Hall - 'Motion Detection' turns OFF 'On Time'"
when
    Item Hall_MotionLightSensor_OnOff changed to ON
then
    if (Hall_Ceiling_Light_OnTime.state > 0) {
        Hall_Ceiling_Light_OnTime.sendCommand(0)
        logInfo("Lights - Hall", "'Motion Detection' turned ON, so 'On Time' set to 0 min")
    }
end



rule "Motion Light - Kitchen Endboard custom timer"
when
    Item Kitchen_Endboard_MotionLightSensor_Motion received update ON 
then
    val bright = Kitchen_Endboard_Ceiling_Light_Brightness
    val sceneB = Kitchen_Endboard_Ceiling_Light_SceneBrightness
    val ctemp = Kitchen_Endboard_Ceiling_Light_ColorTemperature
    val illum = Kitchen_Endboard_MotionLightSensor_Illuminance
    val illumt = Kitchen_Endboard_Ceiling_Light_IlluminanceThreshold
    val timerItem = Kitchen_Endboard_MotionLightSensor_Timer
    val onOff = Kitchen_Endboard_MotionLightSensor_OnOff

    if (onOff.state == ON) {    
        if (timer_kEndboard === null) {
            logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, "Motion detected") 

            if ((illum.state as Number) <= (illumt.state as Number)) {
                logInfo("Motion Lights - " + getLocation(bright).label + getEquipment(illum).label, "Illuminance (" + illum.state + ") is below Threshold (" + illumt.state + "). Turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
                ctemp.sendCommand(Calculated_ColorTemperature.state.toString)
                if (bright.state != sceneB.state) {
                    bright.sendCommand(sceneB.state.toString)
                }

                timer_kEndboard = createTimer(now.plusMinutes(Integer::parseInt(timerItem.state.toString)), [ | 
                    bright.sendCommand(OFF)
                    timer_kEndboard.cancel()
                    timer_kEndboard = null
                    logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, "Timer elapsed. " + getLocation(bright).label + " " + getEquipment(bright).label + " turned OFF")
                ])
                logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, timerItem.state + " min Timer started")

            } else {
                logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(illum).label, "Illuminance (" + illum.state + ") is above Threshold (" + illumt.state + "). Not turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
            }

        } else if (timer_kEndboard !== null) {
            timer_kEndboard.reschedule(now.plusMinutes(Integer::parseInt(timerItem.state.toString)))
            logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, timerItem.state + " min Timer rescheduled")
        } 
    }
end

rule "Lights, Kitchen Endboard - 'On Time' turns OFF 'Motion Detection'"
when
    Item Kitchen_Endboard_Ceiling_Light_OnTime changed
then
    if (newState > 0 && Kitchen_Endboard_MotionLightSensor_OnOff.state == ON) {
        Kitchen_Endboard_MotionLightSensor_OnOff.sendCommand(OFF)
        logInfo("Lights - Kitchen Endboard", "'On Time' turned ON, so Motion Detection is turning OFF")
    }
end

rule "Lights, Kitchen Endboard - 'Motion Detection' turns OFF 'On Time'"
when
    Item Kitchen_Endboard_MotionLightSensor_OnOff changed to ON
then
    if (Kitchen_Endboard_Ceiling_Light_OnTime.state > 0) {
        Kitchen_Endboard_Ceiling_Light_OnTime.sendCommand(0)
        logInfo("Lights - Kitchen Endboard", "'Motion Detection' turned ON, so 'On Time' set to 0 min")
    }
end


rule "Motion Light - Kitchen Sink custom timer"
when
    Item Kitchen_Sink_MotionLightSensor_Motion received update ON 
then
    val bright = Kitchen_Sink_Ceiling_Light_Brightness
    val sceneB = Kitchen_Sink_Ceiling_Light_SceneBrightness
    val ctemp = Kitchen_Sink_Ceiling_Light_ColorTemperature
    val illum = Kitchen_Sink_MotionLightSensor_Illuminance
    val illumt = Kitchen_Sink_Ceiling_Light_IlluminanceThreshold
    val timerItem = Kitchen_Sink_MotionLightSensor_Timer
    val onOff = Kitchen_Sink_MotionLightSensor_OnOff

    if (onOff.state == ON) {    
        if (timer_kSink === null) {
            logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, "Motion detected") 

            if ((illum.state as Number) <= (illumt.state as Number)) {
                logInfo("Motion Lights - " + getLocation(bright).label + getEquipment(illum).label, "Illuminance (" + illum.state + ") is below Threshold (" + illumt.state + "). Turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
                ctemp.sendCommand(Calculated_ColorTemperature.state.toString)
                if (bright.state != sceneB.state) {
                    bright.sendCommand(sceneB.state.toString)
                }

                timer_kSink = createTimer(now.plusMinutes(Integer::parseInt(timerItem.state.toString)), [ | 
                    bright.sendCommand(OFF)
                    timer_kSink.cancel()
                    timer_kSink = null
                    logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, "Timer elapsed. " + getLocation(bright).label + " " + getEquipment(bright).label + " turned OFF")
                ])
                logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, timerItem.state + " min Timer started")

            } else {
                logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, "Illuminance (" + illum.state + ") is above Threshold (" + illumt.state + "). Not turning " + getLocation(bright).label + " " + getEquipment(bright).label + " ON")
            }

        } else if (timer_kSink !== null) {
            timer_kSink.reschedule(now.plusMinutes(Integer::parseInt(timerItem.state.toString)))
            logInfo("Motion Lights - " + getLocation(bright).label + " " + getEquipment(bright).label, timerItem.state + " min Timer rescheduled")
        }
    } 
end

rule "Lights, Kitchen Sink - 'On Time' turns OFF 'Motion Detection'"
when
    Item Kitchen_Sink_Ceiling_Light_OnTime changed
then
    if (newState > 0 && Kitchen_Sink_MotionLightSensor_OnOff.state == ON) {
        Kitchen_Sink_MotionLightSensor_OnOff.sendCommand(OFF)
        logInfo("Lights - Kitchen Sink", "'On Time' turned ON, so Motion Detection is turning OFF")
    }
end

rule "Lights, Kitchen Sink - 'Motion Detection' turns OFF 'On Time'"
when
    Item Kitchen_Sink_MotionLightSensor_OnOff changed to ON
then
    if (Kitchen_Sink_Ceiling_Light_OnTime.state > 0) {
        Kitchen_Sink_Ceiling_Light_OnTime.sendCommand(0)
        logInfo("Lights - Kitchen Sink", "'Motion Detection' turned ON, so 'On Time' set to 0 min")
    }
end


rule "Lights, Understairs - 'On Time' turns OFF 'Motion Detection'"
when
    Item Hall_Understairs_Lamp_OnTime changed
then
    if (newState > 0 && Understairs_MotionLightSensor_OnOff.state == ON) {
        Understairs_MotionLightSensor_OnOff.sendCommand(OFF)
        logInfo("Lights - Understairs", "'On Time' turned ON, so Motion Detection is turning OFF")
    }
end

rule "Lights, Understairs - 'Motion Detection' turns OFF 'On Time'"
when
    Item Understairs_MotionLightSensor_OnOff changed to ON
then
    if (Hall_Understairs_Lamp_OnTime.state > 0) {
        Hall_Understairs_Lamp_OnTime.sendCommand(0)
        logInfo("Lights - Understairs", "'Motion Detection' turned ON, so 'On Time' set to 0 min")
    }
end
2 Likes