Simple Sync Rule please

Hi,
I’m looking to sync the conditions of two smart lights.
When Light 1 goes On, Turn On light 2
When Light 2 goes On, Turn On light 1
When Light 1 goes OFF, Turn OFF light 2
When Light 2 goes OFF, Turn OFF light 1

Can someone please help me with a rule. I have tried lots and lots and cant nail it.
Cheers

Does this give you any pointers? I’m using a virtual switch.

rule "Ceiling Lights"
when

	Item Living_Room_Ceiling_Lights_Switch changed
then
	if(Living_Room_Ceiling_Lights_Switch.state == ON) {
		Living_Room_Ceiling_Light1_Switch.sendCommand(ON)
		Living_Room_Ceiling_Light2_Switch.sendCommand(ON)
	} else {
		Living_Room_Ceiling_Light1_Switch.sendCommand(OFF)
		Living_Room_Ceiling_Light2_Switch.sendCommand(OFF)
	}
end

I’m not using a virtual switch so i’m not sure how to do it.

Hello James,

please take a look into this:
https://community.openhab.org/t/features-for-rules-that-work-with-groups/40460

Greetings
Michael

Hello James,

I just had some minutes. Please give that a try:

rules "sync lights"
when
Item light1 changed or
Item light2 changed
then
if (triggeringItem.name == "light1") {
 light2.postUpdate(light1.status.toString)
} else {
 light1.postUpdate(light2.status.toString)
}
end

I currently have no chance to test it … but it should work. :sunglasses:

Greetings
Michael

1 Like

I have been reading and asking questions for 4 weeks now and can never get a straight answer. I have asked this question 3 different ways and have never got an actual solution. Just people saying read this or modify that.
Is there a secret community rule that says offer vague help but don’t supply actual answers.
I have no clue how to write code so I need a simple answer. IE put this code in your rules file.
Cheers

Hi,

there are hundrets of solutions. To get a straight solution, just give us more detaisl, names of the items for the switch, whcih turns on/off the light1/2 and the names of the lights itself. Please use the code block for better formatting of your item file.

One is called Light_1, the other is Light_2. They are tp-link lb100 bulbs. The switch for the lights are not important as they are a physical switch and always on(supplying power to the bulb). i can turn the globes on from the habpanel or from google home. But I want them to work in sync as per
When Light 1 goes On, Turn On light 2
When Light 2 goes On, Turn On light 1
When Light 1 goes OFF, Turn OFF light 2
When Light 2 goes OFF, Turn OFF light 1

Hi James,

Reading this thread you’ve expressed that your not a coder, neither am I for that matter. So what this means is that like me you’ll have to either learn by reviewing other peoples code or try an alternative platform for your home automation. I’ve been learning for the past 12 months and still need help.

The great thing about openHAB is that you can achieve most things because it is so flexible, but you have to understand what your trying to achieve first. Not everything in home automation has to be complicated, but some things need an alternative method to achieve the end result. A few phrases come to mind; “Thinking outside the box” or “Sky blue thinking”. openHAB is what’s known an enabler.

In your first reply to me you have said your not using a virtual switch. However if your using HABpanel to switch the lights on then you are using a virtual switch already, even if you don’t realise it. I suspect what you’ve done is simply defined a switch that directly mirrors what tp-link provides you. If that’s the case then I don’t understand why your would put openHAB in the middle. So here’s an approach I think you should take a look at.

As I originally showed you, create a separate virtual switch that you will use to switch on both of your lights at the same time. As per the rule I provided further up the thread. If you want to be able to control the lights individually then you will need to create separate virtual switches for each light. You’ll then have three light switches available to you, one that controls both lights at the same time and two other for the individual lights. Now say you want openHAB to switch on the alternative light to the one you manually switch on, this is where you need to work on your coding skills. Essentially you need to create a couple of “IF” statements.

Lights ON
IF Light One == ON
THEN Switch ON Light Two
ELSE 
         IF Light Two == ON
         THEN Switch ON Light One
Lights OFF
IF Light One == OFF
THEN Switch OFF Light Two
ELSE 
         IF Light Two == OFF
         THEN Switch OFF Light One

That is the most basic way, there are far more complex ways but I would avoid those for the time being.

1 Like

Because there is no straight answer without context. And you don’t provide nearly enough context. So all we can do is offer general answers. And there are probably a dozen different ways to solve your problem, each more or less suited to given situations.

If that is the answer you are after you will not get it. We will help you with problems with your Rules. We will even help you rewrite your Rules. But we will not write your Rules for you. That ends up taking up huge amounts of time from the community and the recipient of the effort is rarely grateful and because they didn’t learn anything they keep coming back over and over again to write more and more of their Rules. We don’t have the bandwidth for that.

We will bend over backwards to teach you to fish, but you have to go catch your own fish.

So take one of the suggestions, try to write a Rule that does what you want. When/if it doesn’t work come back, post your Rule, and we will go out of our way to help you not only fix the Rule but understand why it didn’t work before and how to avoid that problem in the future.

5 Likes

Thanks Maximo, I need to avoid using a virtual switch for the rules so I can then apply the same code to other items I wish to sync such as a pair of Sonoff T1 light switches. At the moment I have the lights in a group and 3 virtual switches in habpanel which allows me to turn on/off each light or the group, however, if one light is turned on outside of the habpanel the other light is not turned on.

In the case of the T1’s, they are a smart switch with a relay built in that activates either by software such as openhab or by the touch button, so the when part needs to be one of the two items and not a virtual switch. I will see what I can do with your if statements.
Cheers

vzorglub Vincent Regaud got me going. This works on my tp-link lights and my Sonoff T1’s

rule “update lamp B”
when
Item lamp_A changed
then
lamp_B.sendCommand(lamp_A.state.toString)
end

rule “update lamp A”
when
Item lamp_B changed
then
lamp_A.sendCommand(lamp_B.state.toString)
end

Hi James,

Good to see your making progress. Now you have the basics in place there is room to refine this rule further, this is where I struggle and @rlkoshak has helped me out a good few times in the past.

I’m sure there is a way to bring these two rules together into a single rule. But you need some logic to make it work. Let me help start you off with a bit of consolidation below.

rule “Lights”
when
Item lamp_A changed or
Item lamp_B changed
then
if(lamp_A.state != lamp_B.state) {
lamp_A.sendCommand(lamp_B.state.toString)
} else if(lamp_B.state != lamp_A.state) {
lamp_B.sendCommand(lamp_A.state.toString)
end

Hi James, Hi Garry

The comparisons after the if-statement and after the else-statement are identical, aren’t they?

I would do it that way:

rule "sync lights"
// rule gets activated when one of the following items change
when Item lamp_A changed or
Item lamp_B changed
then
// triggeringItem is the item that changed
if (triggeringItem.name == "lamp_A") {
// you have to decide whether postUpdate or sendCommand should be used
lamp_B.sendCommand(lamp_A.state.toString)
//lamp_B.postUpdate(lamp_A.state.toString)
} else { 
lamp_A.sendCommand(lamp_B.state.toString)
//lamp_A.postUpdate(lamp_B.state.toString)
}
end

Greetings
Michael

OK first things you need to learn about the forum:

Use the code fences:

When mentioning another user use @ like @JDLambert

You need to mark the posts that are a solution to your problem so that the post will appear as solved and another future user may find the solution there

hc_292

Any other post that you see that you like for any reason, helpful, funny… Please like by clicking the little heart.

It’s a community and we help each other. It starts by following the rules.

1 Like

Unfortunately, this code won’t work. Let’s say that lamp_A changed, then the first if runs and we send lamp_B a command. So far so good. Now let’s say that lamp_B changed. lamp_A.state != lamp_B.state so the if runs and lamp_B gets the command. The else never exeutes and when lamp_B changes, lamp_A never gets that synchronization command.

I don’t have too much of a problem with having these in separate Rules. Especially for a new user having the two separate Rules is simple and easy to understand.

Michael’s solution looks correct, but @Maximo and @JDLambert, take heed of the comment “you have to decide whether postUpdate or sendCommand should be used.” This is important because sendCommand will go out to the device linked to/bound to the Item whereas a postUpdate will only change the Item’s state inside OH.

When synchronizing Items like this, most of the time postUpdate is the correct answer. In this case however I believe the intended behavior is to actually change a light so sendCommand is probably the right answer.

Another thing to watch out for is infinite loops at worse, or extra executions of your Rule at best. In this case, using Michael’s Rule, consider the following:

  1. both switches are OFF
  2. A changes to ON
  3. sync lights runs
  4. B gets command ON
  5. B changes
  6. sync light runs again
  7. A gets commanded to ON
  8. A is already ON so there is no change and the Rule doesn’t trigger again.

In this case the fact that the Rule triggers twice is benign. Nothing results from it. But in many cases the Rule may do something and you don’t want it to do it twice. Also, if one changed the Rule trigger from changed to received command or received update there would be an infinite loop because the Rule would trigger on the command whether or not the command resulted in a change in the Item.

And just to provide another alternative for combining the Rules, I would do it as follows:

rule "sync lights"
when
    Item lamp_A changed or
    Item lamp_B changed
then
    val newState = triggeringItem.state

    if(lamp_A.state != newState) lamp_A.sendCommand(newState)
    if(lamp_B.state != newState) lamp_B.sendCommand(newState)
end

The advantage of this Rule, besides being simpler and shorter, is that if one were to change the Rule trigger to received command or received update then the Rule would not go into an infinite loop because we wouldn’t even issue the sendCommand if the states are already the same. It will still trigger twice though for each individual change to one of the switches.

If the lamps were in a Group the Rule could be further reduced down to

rule "sync lights"
when
    Member of Lamps changed
then
    val newState = triggeringItem.state

    Lamps.members.forEach[ lamp | if(lamp.state != newState) lamp.sendCommand(newState) ]
end

Personally, I’d put the lamps in a Group and only put the Group on your UI (sitemap/habpanel). Any command sent to the Group gets forwarded to all its members so it would let you control both lamps with on switch without any rules at all.

4 Likes

Thank you this also worked well.
I very much appreciate the help.
James

Just stumbled upon this (it’s the first google hit for “openhab sync two items”) and found that it’s not working in OH3 any more.

In OH3 triggeringItem is gone, but newState is available directly (see Rules | openHAB). For the “Member of” rule, triggeringItem is still available, so no need to change there.

I also needed to append “toString” to newState, otherwise I got the error message Script execution of rule with UID '...' failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.actions.BusEvent.sendCommand(org.openhab.core.items.Item,java.lang.String) on instance: null in ...

So the new version (for me at least) is:

rule "sync lights"
when
    Item lamp_A changed or
    Item lamp_B changed
then
    if(lamp_A.state != newState) lamp_A.sendCommand(newState.toString)
    if(lamp_B.state != newState) lamp_B.sendCommand(newState.toString)
end

It’s there but only for Items triggered by a Member of rule trigger. For other Item triggered rules there is now a triggeringItemName implicit variable.

And yes, in the three years since that code above was posted there have been a lot of other changes as well, such as the addition of the newState implicit variable.

And the Follow Profile (Profiles didn’t even exist when this thread was written) might also work in some cases.