Rules for latching relays group

He’s using a Contact type because it works here. His Items do not represent a controllable light switch on their own. It’s part of a pulsed relay system via GPIO ; for each light, there is a Switch Item simulating a pushbutton, and a Contact Item showing the status of the light circuit. You can’t send commands to the “status” Item, you can’t use the “pulse” Item state to indicate light state, you have to use them as an interlinked pair.

It’s not really related to the rules in question - whether he’s looking for ON or CLOSED makes no fifference there.

@julesx81 is stuck with Contact type to represent light on/off I believe - because the GPIO v1.x binding he has in use limits incoming binary channels to Contact types.

could you correct this for me?

    gLight.members.filter[a|a.state==OPEN].forEach[s|
	var nameOfLight = s.name 
	var nameofPulse = nameOfLight.substring(s.lenghth() - 5,s.length()).concat("Pulse")
	sendCommand(nameofPulse, OFF)
	Thread::sleep(100)
	]

It’s not s that you are interested in the length of - that’s the whole Item

Assuming GF_Entryway1_Light

var nameOfLight = s.name.split("_")
var nameofPulse = nameOfLight.get(0) + "_" + nameOfLight.get(1) + "_Pulse"

Doesn’t recognize like array?

2019-12-18 12:14:42.603 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'all pulse off': The name 'nameOfLight' cannot be resolved to an item or type; line 53, column 21, length 14

gLight.members.filter[a|a.state==OPEN].forEach[s|
    logInfo("pulseAll","Processing Item {} ({})",s.name,s.state,s.name)
	nameOfLight = s.name.split("_")
	nameofPulse = nameOfLight[0] + "_" + nameOfLight[1] + "_Pulse"
	sendCommand(nameofPulse, OFF)
	/* gPulse.members.filter[i|
        i.name.split("_").get(0) == s.name.split("_").get(0)
    ].head.sendCommand(OFF)*/
    Thread::sleep(300) 
]

Yes I just corrected my post to use stringparts.get(0) instead of stringparts[0]

Come on, you’ve been doing this long enough to find and fix silly mistakes yourself :wink:

Note that for some reason you have removed the var declarations. Try to change only one thing at a time.

I have basic experience on programming , and not on java. Be patient.

Returning at issue
Code

rule "all pulse off"
when
    Item all_lights_off received command ON
then
    logInfo("pulseAll","Rule started.")
    gLight.members.filter[a|a.state==OPEN].forEach[s|
        logInfo("pulseAll","Processing Item {} ({})",s.name,s.state,s.name)
		var nameOfLight = s.name.split("_")
		var nameofPulse = nameOfLight.get(0) + "_" + nameOfLight.get(1) + "_Pulse"
		sendCommand(nameofPulse, OFF)
        Thread::sleep(300) 
    ]
    logInfo("pulseAll","Rule ends.")
	sendCommand(all_lights_off, OFF)
end

log

2019-12-18 12:25:21.527 [INFO ] [ipse.smarthome.model.script.pulseAll] - Rule started.

==> /var/log/openhab2/events.log <==

2019-12-18 12:25:21.529 [vent.ItemStateChangedEvent] - all_lights_off changed from OFF to ON

==> /var/log/openhab2/openhab.log <==

2019-12-18 12:25:21.541 [INFO ] [ipse.smarthome.model.script.pulseAll] - Processing Item GF_ToiletMirror_Light (OPEN)

2019-12-18 12:25:21.550 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'all pulse off': Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(java.lang.String,java.lang.String) on instance: null

OFF is not a string. “OFF” is a string. The error message does offer clues what to look at and think about.

SOLVED!!!

The code below works fine. Many Many thanks to @rossko57 and @Udo_Hartmann.

i don’t understand the differences between sendcommand functions… First need two string as parameters , instead the second one item object as first , and second param? What? Not a string?

rule "all pulse off"
when
    Item all_lights_off received command ON
then
    logInfo("pulseAll","Rule started.")
    gLight.members.filter[a|a.state==OPEN].forEach[s|
        logInfo("pulseAll","Processing Item {} ({})",s.name,s.state)
		var nameOfLight = s.name.split("_")
		var nameofPulse = nameOfLight.get(0).toString + "_" + nameOfLight.get(1).toString + "_Pulse"
		sendCommand(nameofPulse, "OFF")
        Thread::sleep(300) 
    ]
    logInfo("pulseAll","Rule ends.")
	sendCommand(all_lights_off, OFF)
end

REGARDS
Lorenzo

someItem.sendCommand(OFF)
is a method of your Item. That’s to say, it’s part of the Item object and expects a real command suitable for itself. e.g. mySwitch.sendCommand(UP) is going to fail because UP isn’t suitable for a Switch type Item.

sendCommand("myItemname", "somevalue")
is an action in rules language. It’s deliberately written to be as generalized as possible. It has no idea what kind of Item is involved until it looks it up by name, it may not even exist. So it has no idea what kind of commands might be allowed.

It does try its best to deal with whatever you might give it instead of two strings, though it doesn’t always pick the right one because it is guessing then.
Don’t make it guess, give it two strings like it says in the documentation…

There is an extra s.name here, but the DSL won’t complain about it.

modedd on relative post.
Thanks.

Sorry Guys,
i try to filter a subgroup of glight,

these are groups:

Group Home “Our Home”

Group GF “Piano Terra” (Home)
Group FF “Primo Piano” (Home)

How can i filter gLights on a Group GF?

Regards

There is nothing called gLights in what you have shown us.

Filter for what purpose? Using what criteria? In a rule, for display, leave out any members with FRED in their names, turn on only members updated in the last week?

Sorry i added a “s” too, gLight is the correct name of main group.

i would switch off the lamps filtered on floor, like rules above but based on floor.

Hi

groups:

Group Home “Our Home”
Group GF “Piano Terra” (Home)
Group FF “Primo Piano” (Home)

Group GF_Dining “Sala da Pranzo” <eating_room> (Home, GF)
Group GF_Entryway “Ingresso” (Home, GF)

Group FF_Bedroom “Camera da Letto” (Home, FF)
Group FF_KidsRoom "Camera " <baby_1> (Home, FF)

Contact GF_Dining_Light “Luce Elisse” (GF_Dining, gLight) [“Lightning”] {channel=“mcp23017:mcp23017:chip20:input#B4”}
Switch GF_Dining_Pulse “pulsante Luce Elisse” (GF_Dining, gPulse) {channel=“mcp23017:mcp23017:chip20:output#A4”}

Contact GF_Entryway1_Light “Luce Est. Portoncino” (GF_Entryway, gLight) [“Lightning”] {channel=“mcp23017:mcp23017:chip21:input#B4”}
Switch GF_Entryway1_Pulse “puls Luce Esterna Portoncino” (GF_Entryway, gPulse) {channel=“mcp23017:mcp23017:chip21:output#A1”}

I would change your structure from this

To something like

Contact GF_Dining_Light "Luce Elisse" (GF_Dining, gLight) ...
Switch GF_Dining_Pulse "pulsante Luce Elisse" (gPulse) ...

You’re not really interested in what room the “pulse” Items belong to, only in the light they belong to.

If you do that, then all Items in a group like GF_Dining are going to be lights, and you can run your rule exactly the same as you do for gLight

Nope, after your mod i can’t control single pulse.

Can i simple check the first and second char of light’s name ?

rule " GF all light off"
when
    Item GF_lights_off received command ON
then
    logInfo("GF_lights_off","Rule started.")
    gLight?.members.filter[a|a.state==OPEN].forEach[s|
        logInfo("GF_pulse","Processing Item {} ({})",s.name,s.state)
		var nameOfLight = s.name.split("_")
		var nameofPulse = nameOfLight.get(0) + "_" + nameOfLight.get(1) + "_Pulse"
                   if (nameofPulse.substring(0,2) = "GF"){
		           sendCommand(nameofPulse, "OFF") } else {}

        Thread::sleep(300) 
    ]
    logInfo("GF_pulse","Rule ends.")
	sendCommand(GF_lights_off, OFF)
end

Don’t know what that means, cannot see what you are doing.

I thought you wanted to control members of group like GF_Dining ?
Why would you not use GF_Dining?.members.filter[...

GF_Dining is only a room, i would fiter all lights on floor GF , i tried with GF?.members.filter , but members are only the rooms.

image

Ah right, nested groups.
GF?.allMembers.filter...
will reach through the layers.

I solved simple with string compare

rule "GF lights off"
when
    Item GF_lights_off received command ON
then
    logInfo("GF lights off","Rule started.")
    gLight?.members.filter[a|a.state==OPEN].forEach[s|
        logInfo("GF_pulse","Processing Item {} ({})",s.name,s.state)
		var nameOfLight = s.name.split("_")
		var nameofPulse = nameOfLight.get(0) + "_" + nameOfLight.get(1) + "_Pulse"
		            if ( nameOfLight.get(0) == "GF") {
		           sendCommand(nameofPulse, "OFF") } else {}

        Thread::sleep(300) 
    ]
    logInfo("GF lights off","Rule ends.")
	sendCommand(GF_lights_off, OFF)
end