Light Sensor Rule

I have a photoresistor light sensor hooked up to an Arduino Uno to check the light levels in the living room. The sensor is in the living room attached to the Raspberry Pi running OpenHAB. OpenHAB pulls in the light level and whether it is daytime according to Astro. It switches on the lights if the light level falls below a set point and Astro says it is daytime. The idea is to turn on the lights if it gets dark during a thunderstorm.

This works fine turning on the lights when it gets dark. The problem is that I don’t know how to get the lights to switch off if it is not dark out anymore. I had reconfigured the rules set up to pull in light intensity from Weather Underground instead of the light sensor. This isn’t ideal, but the weather station is 3-4 blocks away so it does work okay. Another problem is that the free API is going away soon, so I need to migrate it away from that.

What can I do to check when the lights should switch off? Is there another data source to poll? It will be a little difficult to move the sensor to another place since the Arduino doesn’t have networking.

Here are the configuration files:

lightsensor.rules

rule "Light Sensor String Conversion"

when
        Item light changed
then
        LRLightLevel.sendCommand(Float::parseFloat(String::format("%s",light.state).replace(' ','')))
        logInfo("rule", "light State is " + light.state)
        logInfo("rule", "LRLightLevel State is " + LRLightLevel.state)
end

rule "LR Lights Sensor"

when
        Item LRLightLevel changed
then
        if (lightsensorenable == ON) { //check if light sensor switch item is enabled
                if (Daylight.state == ON && LRLightLevel.state <= 1.0) { //only run if it is daytime
                        logInfo("events", "Light Sensor changed to LOWER than threshold")
                        logInfo("events", "Turning on Livingroom Lights")
                        sendCommand(LRLamp, ON)
                        postUpdate(LRLightSensor, ON) //set a flag that the lights were turned on by sensor
                        }
                }
        if (LRLightSensor.state == ON && LRLightLevel.state > 25.0) {
                if (Daylight.state == ON) {  //only run if it is daytime
                        logInfo("events", "Light Sensor changed to HIGHER than threshold")
                        logInfo("events", "Turning off Livingroom Lights")
                        sendCommand(LRLamp, OFF)
                        postUpdate(LRLightSensor, OFF) //clear the flag that the lights were turned on by sensor
                        }
                }
end

dayflags.rules

rule "Set Daylight"
when
        Channel 'astro:sun:home:rise#event' triggered START
then
        logInfo(events, "Day flag set")
        postUpdate(Daylight, ON)
end

rule "Set night"
when
        Channel 'astro:sun:home:set#start' triggered START
then
        logInfo(events, "Night flag set")
        postUpdate(Daylight, OFF)
end

lightsensor.items

String  light   "[%s]"  {channel="exec:command:poll_light:output"}
Switch  LRLightSensor
Number  LRLightLevel    "LR Light level [%.1f]" (lightsensors)
Number  LRLight_Levels  "Light Sensor History"
Group   lightsensors    "Light Level"
Switch  lightsensorenable
Switch  Daylight        "Daylight"

Light Sensor Schematic

“LR Lights Sensor” rule looks sensible. What doesn’t work about it, do you see the light level Item changing to >25 in the events.log ?

The rule code seems fine as @rossko57 mentionned
You should add the trigger of Item Daylight changed in the light sensor rule

I would also recommend that you use the .sendCommand() and .postUpdate() methods instead of the action:https://www.openhab.org/docs/configuration/rules-dsl.html#myitem-sendcommand-new-state-versus-sendcommand-myitem-new-state

Last but not least, you are inconsistent with your item naming: light, lightsensorenable, Daylight
Should be Light, LightSensorEnable and DayLight

rule "Light Sensor String Conversion"
when
    Item light changed
then
    // [CHANGED] LRLightLevel.sendCommand(Float::parseFloat(String::format("%s",light.state).replace(' ','')))
    LRLightLevel.sendCommand(Float::parseFloat(light.state.toString.replace(" ",",")))
    logInfo("rule", "light State is " + light.state)
    logInfo("rule", "LRLightLevel State is " + LRLightLevel.state)
end

rule "LR Lights Sensor"
when
    Item LRLightLevel changed or
    Item Daylight changed
then
    if (lightsensorenable == ON) { //check if light sensor switch item is enabled
        if (Daylight.state == ON && LRLightLevel.state <= 1.0) { //only run if it is daytime
            logInfo("events", "Light Sensor changed to LOWER than threshold")
            logInfo("events", "Turning on Livingroom Lights")
            LRLamp.sendCommand(ON)
            LRLightSensor.postUpdate(ON) //set a flag that the lights were turned on by sensor
        }
    }
    if (LRLightSensor.state == ON && LRLightLevel.state > 25.0) {
        if (Daylight.state == ON) {  //only run if it is daytime
            logInfo("events", "Light Sensor changed to HIGHER than threshold")
            logInfo("events", "Turning off Livingroom Lights")
            LRLamp.sendCommand(OFF)
            LRLightSensor.postUpdate(OFF) //clear the flag that the lights were turned on by sensor
        }
    }
end

rule "Set Daylight"
when
    Channel 'astro:sun:home:rise#event' triggered START
then
    logInfo(events, "Day flag set")
    Daylight.postUpdate(ON)
end

rule "Set night"
when
        Channel 'astro:sun:home:set#start' triggered START
then
        logInfo(events, "Night flag set")
        Daylight.postUpdate(OFF)
end

I think the only solution will be to place the sensor outside away from lights so it can report the ambient light from the sun. That way the light from any lamps will not override it.

If the nearest weather station that is 3-4 blocks away isn’t close enough to be accurate, you really are stuck with using your own sensor. And as you are seeing, if the sensor can also pick up the light from the lamps that turn on when it gets cloudy, there is no way to know when to turn the lights back off when the sun returns.

You might be able to get clever if you gather a bunch of data and see if you can see a spike in the measured reading when the sun comes back. But there are so many variables I don’t think it will be feasible.