[SOLVED] Making this rule generic

It seems to be fine with the OR.

Ive added the extra statements for the rule:


rule "Motion activated Lights using CCTV Cameras"
when
        Member of gMotionSensors received command ON
then
        logInfo("Motion.rules", triggeringItem.name + " detected motion.")
   if (vTimeOfDay.state == "EVENING" || vTimeOfDay.state == "NIGHT" || vTimeOfDay.state == "DAY") {
    val source = triggeringItem.name.split("_").get(0)
    val _Armed = gMotionSensors.members.findFirst[ armed | armed.name == source +"_Armed" ]
    logInfo("Motion.rules", _Armed + " Sensor")
    val _Light = gAllLights.members.findFirst[ light | light.name == source +"_Light" ]
    logInfo("Motion.rules", _Light + " Light")
     }
end

Fixed the Motion sensors, and now I see the state

:47:37.894 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'NorthWestDrive_Motion' received command ON
15:47:37.894 [INFO ] [e.smarthome.model.script.Motion.rules] - NorthWestDrive_Motion detected motion.
15:47:37.917 [INFO ] [e.smarthome.model.script.Motion.rules] - NorthWestDrive_Armed (Type=SwitchItem, State=ON, Label=, Category=null, Groups=[gMotionSensors]) Sensor
15:47:37.919 [INFO ] [e.smarthome.model.script.Motion.rules] - NorthWestDrive_Light (Type=SwitchItem, State=OFF, Label=North West Exterior, Category=null, Groups=[gLights_Random, gAllLights, gInsideLights]) Light

still looks like you we’re missing the turn on the light and after 60 seconds timer fires to turn it off

Yes, I havent added that, I first wanted to ensure all the variables are right and logging before I add in the logic to actually do something :slight_smile:

Just fixing up names and descriptions before I get onto that.

sendCommand(_Light,ON)
	createTimer(now.plusSeconds(60)) [ | {sendCommand(_Light,OFF)}]

Sorry being blind is a real problem with this UI.

hopefully I got it right this time

1 Like

Thanks Paul,

I need to check that the sensor is armed first, so I would imagine this is my rule then but it doesnt like
the state check for _Armed


16:01:20.775 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Motion activated Lights using CCTV Cameras': The name '_armed' cannot be resolved to an item or type; line 13, column 9, length 6


rule "Motion activated Lights using CCTV Cameras"
when
        Member of gMotionSensors received command ON
then
        logInfo("Motion.rules", triggeringItem.name + " detected motion.")
   if (vTimeOfDay.state == "EVENING" || vTimeOfDay.state == "NIGHT" || vTimeOfDay.state == "DAY") {
    val source = triggeringItem.name.split("_").get(0)
    val _Armed = gMotionSensors.members.findFirst[ armed | armed.name == source +"_Armed" ]
    logInfo("Motion.rules", _Armed + " Sensor")
    val _Light = gAllLights.members.findFirst[ light | light.name == source +"_Light" ]
    logInfo("Motion.rules", _Light + " Light")
    }
    if (_Armed.state == ON){
    sendCommand(_Light,ON)
        createTimer(now.plusSeconds(60)) [ | {sendCommand(_Light,OFF)}]
}
end


remove the wrapper if (_Armed.state == ON){ and the }.

1 Like

same issue without the {}

remove the whole if line not just the curly braces

But I want to check if the camera is Armed, before I switch the lights on

perhaps I misunderstand, is the motion sensor that when switched ON that fires the rule not the same as the camera being armed?

Wait brain engage, got the armed idea now

1 Like

The Motion sensor files the rule. The _Armed, switch item allows me to turn the rule on/off by arming/disarming the camera motion sensor :slight_smile: Otherwise the lights will go on/off constantly when motion is detected.

If we are home, we will disengage the Arming, and that will not trigger the lights

Sorry if that doesnt make sense

So I need the Armed item to check its state before I send the command on for the light

Fixed the check, had to have it inside the {}

16:21:30.935 [INFO ] [del.core.internal.ModelRepositoryImpl] - Refreshing model 'motion.rules'
16:21:33.265 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'NorthWestDrive_Motion' received command ON
16:21:33.307 [INFO ] [e.smarthome.model.script.Motion.rules] - NorthWestDrive_Motion detected motion.
16:21:33.310 [INFO ] [e.smarthome.model.script.Motion.rules] - NorthWestDrive_Armed (Type=SwitchItem, State=ON, Label=, Category=null, Groups=[gMotionSensors]) Sensor
16:21:33.311 [INFO ] [e.smarthome.model.script.Motion.rules] - NorthWestDrive_Light (Type=SwitchItem, State=OFF, Label=North West Exterior, Category=null, Groups=[gLights_Random, gAllLights, gInsideLights]) Light
16:21:33.313 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'NorthWestDrive_Light' received command ON
16:21:33.314 [INFO ] [arthome.event.ItemStatePredictedEvent] - NorthWestDrive_Light predicted to become ON
16:21:33.325 [INFO ] [smarthome.event.ItemStateChangedEvent] - NorthWestDrive_Light changed from OFF to ON
16:21:33.330 [INFO ] [home.event.GroupItemStateChangedEvent] - gAllLights changed from OFF to ON through NorthWestDrive_Light
16:21:33.331 [INFO ] [home.event.GroupItemStateChangedEvent] - gInsideLights changed from OFF to ON through NorthWestDrive_Light

Are you wanting an Armed item for each light//camera install or it one for the whole house?

I have an Armed for every single camera. But I can send an ON/OFF to the gMotionSensors to turn them all on or off

yep that makes sense, like zoning and a single ‘gone out’ switch.
so do you have it all functioning now?

Mostly! Just a bit more tweaking I think :slight_smile: Thanks so much @idkpmiller & @pacive

For anyone wanting this rule:

Here it is:


rule "Motion activated Lights using CCTV Cameras"
when
        Member of gMotionSensors received command ON
then
        logInfo("Motion.rules", triggeringItem.name + " detected motion.")
   if (vTimeOfDay.state == "EVENING" || vTimeOfDay.state == "NIGHT") {
    val source = triggeringItem.name.split("_").get(0)
    val _Armed = gMotionSensors.members.findFirst[ armed | armed.name == source +"_Armed" ]
    logInfo("Motion.rules", _Armed + " Sensor")
    val _Light = gAllLights.members.findFirst[ light | light.name == source +"_Light" ]
    logInfo("Motion.rules", _Light + " Light")
   if (_Armed.state == ON && gPresenceSensors.state == OFF)
    sendCommand(_Light,ON)
        createTimer(now.plusSeconds(60)) [ | {sendCommand(_Light,OFF)}]
}
end


I don’t think this got covered.
We’re exploiting the methods (functions) of an openHAB group Item here.

gMotionSensors.members
Groups have a bunch of methods to operate on group members.
That’s a bit vague, we need a specific operation.

gMotionSensors.members.findFirst[ ... ]
This is a more specific - find me the first member Item of this group.
Of course, “first” itself is vague - alphabetic? age? value?
findFirst wants you to provide some sorting criterion in the square brackets [] and will give you back the first thing that matches.

gMotionSensors.members.findFirst[ cam | ... ]
This is non-obvious.
We’re asking it to look through group members, which are Items. But we don’t know what these Items are called.
The cam bit in this example is a placeholder, referring to each Item in turn as we examine them. Call it what you like, this_one say.

gMotionSensors.members.findFirst[ cam | cam.name == xxx]
We need to do more than just refer to each Item, we are trying to do some kind of matching for the findFirst part.
The part after the | is our criterion. If our placeholder Item’s name matches some variable xxx - that’s the test.
item.name is a string, so our target xxx would need to be a string too.
We could do a similar search on item.state, for an example.

val _Sensor = gMotionSensors.members.findFirst[ cam | cam.name == Source + "_Camera" ]

The name matching part here is using a string made up from the contents of a variable Source with a bit added on, the string "_Camera".

If we find anything that matches, we return it into a variable we’ve just created named _Sensor
Not that this _Sensor is an existing Item, one we’ve selected from a group. We can do anything with this that we can do with the “real” Item, like sendCommand.

Overall, the purpose here is to get hold of a real Item when we only have it’s name as a string.

2 Likes

This should be in a wiki! Thank you , ill save the post.