[SOLVED] Making this rule generic

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"
        Member of gMotionSensors received command ON
        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)
        createTimer(now.plusSeconds(60)) [ | {sendCommand(_Light,OFF)}]

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

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.


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

I combed the docs and could not find any mention of these group methods. Can anybody point me to them

Here’s the problem. Everyone treats them as out of scope for their docs. OH doesn’t document them because they are not implemented by openHAB. Xtend doesn’t document them because they are not implemented by Xtend/Xtext. They are actually implemented by the underlying Java Stream interface so you have to go to the JavaDocs to find the official docs.

That’s one reason why I wrote Design Pattern: Working with Groups in Rules which provides some documentation for the more common methods we would want to use in an OH context. The Xtend docs actually does refer to these methods, but only in their Movies example.

1 Like

Thank you @rlkoshak because a link to the java docs was what I was trying to find because I thought that was where it would be

Which is why i struggled, there just isnt enough examples/detail around to explain :frowning:

The other side of the coin is there isn’t enough volunteers to rewrite docs and maintain them for stuff that is implemented and documented elsewhere.

1 Like

Absolutely! I’d write if I knew what I was talking about. At least my thread has alots of information and the rule that works now! Hopefully someone can get benefit from that