Design Pattern: Proxy Item

What would be the best approach if some of the bound items would overlap between two proxy items ?
The use case:

  • 3 bound outdoor light items: frontgate, entry, carport
  • Different bound and virtual trigger items: darkness, manual, gate contacts
  • 2 proxy items:
    • fromFrontgate: handles frontgate and entry when front gate opens in darkness
    • fromCarport: handles carport and entry when carport gate opens in darkness

I currently have a wild combination of the virtual and proxy approach, which finally works somehow but the code is ugly and it takes me every time half an hour to re-understand it.

I would create a Group for each trigger and send command to the group. Items can be members of multiple groups and a command sent to a group gets forwarded to all it’s members.

You run into trouble when you start to need scenes (e.g you have a mix of dimmers, switches and color and each needs a custom value) in which case you need to use proxy items and rules.

Tried that but that led to the following conflict:
Lets say we have two groups A and B. Members of A are x and y, member of B are y and z.
Assume both groups are ON. Then the timer for group A expires, the timer for group B has still some time left. Switching off group A would switch off y which is not intended in this situation. As far as I concern there is no possibility to define an XOR
Group which would solve this situation.

That want clear from your posting. You can still use groups but you need to use a proxy item to trigger the on and off.

On the rule you can do something like:

GroupA.members.filter[light | !light.groups.contains("B")].forEach[light| light.sendCommand(OFF)]

Of course the logic will be a bit more complex because you don’t need to send off if the light is already off and you only want to exclude B members sometimes, but this should address the problem somewhat.

Smart. There is so much you can do with the rules DSL and so little documentation. Even the Xtend / Xtext docs I found only cover the definition and implementation of a DSL, not its usage - do you have some hints where to look on the usage of an already defined DSL ?

I learned a lot from the Xtend movie demo.
https://www.eclipse.org/xtend/documentation/102_moviesexample.html

Beyond that look at the Design Patterns. In particular almost everything you can do with Groups is in Design Pattern: Working with Groups in Rules.

2 Likes

How do I create the proxy switch to begin with? I have a zigbee switch that is reporting exactly opposite it’s setting (saying off when on and vice versa) and want to make a proxy switch to reverse it but unsure how to do so. I follow the logic of the rule and can see how to modify but don’t know how to make the unbound switch in the first place.

Simpy create it, either through an *.items file or through Paper UI. Don’t use curly brackets in the items definition (in items file the channel link), don’t link the item to a channel.

*.items:

Switch myZigbeeSwitch "zigbee switch [%s]" { channel="zigbee:..." }
Switch myProxySwitch "opposite switch [%s]"

*.rules (simple, but incomplete):

rule "opposite switch"
when
    Item myZigbeeSwitch changed
then
    myProxySwitch.postUpdate(if(myZigbeeSwitch.state != ON) ON else OFF)
end

*.rules (complete):

rule "opposite switch"
when
    Item myZigbeeSwitch changed
then
    myProxySwitch.postUpdate(
        switch (myZigbeeSwitch.state) {
            case ON  : OFF
            case OFF : ON
            default  : NULL
        }
    )
end

*.rules (easy to read):

rule "opposite switch"
when
    Item myZigbeeSwitch changed
then
    var mySwitch
    switch (myZigbeeSwitch.state) {
        case ON  : mySwitch = OFF
        case OFF : mySwitch = ON
        default  : mySwitch = NULL
    }
    myProxySwitch.postUpdate(mySwitch)
end
2 Likes

Apologies if this isn’t quite the correct place to post but I’m after some thoughts on the flow of my DP


I’ve got a few proxy and unbound items working fine:

vPresence ON / OFF - Someone is home or not
vEndOfDay - Essentially a ON / OFF to determine if we are in bed or not

Now vEndofDay can be triggered to ON / OFF by either an Alexa command, (good night or good morning) or by CRON rules at 00:30 and 6:00, (in case we forget to use the Alexa command).

No problems there, I have a rule that triggers on vEndofDay state changing and via an easy ‘if’, ON runs my nighttime routine, (ie cameras on, tv off, lights to nightlight etc) and OFF turns it OFF, again no problems.

However, I only want this routine to trigger when vPresence = ON as I have another routine working when I’m away to make the house act like someone is there and I don’t want both rules to interfere with each other.

So, the DP question


Should I have the original rules trigger and run based on one sole thing, ie cron or alexa command and then update the DP proxy item, vEndOfDay.

Then the larger rule ‘when Item vEndOfDay changed’ I incorporate an ‘if vPresence = ON’ to make it work


or

Should I only make the original rules update based on cron and vPresence state and then the DP Proxy Item will only update once all conditions are met?

My thought is that a proxy item should only really update based on one trigger and then it has far more options to control within the next rule, or should a DP Proxy item reall yonly be updated after all the multi if cases are met?

What is best depends on what you are using these Items to do. In particular, what Rules or other behaviors occur when the Item changes state? When do you want those things to occur? What else is happening at the same time that might cause interference?

These are questions you need to ask yourself and then code when the proxy Item get’s updated to meet your needs. There is no one correct approach.

Thanks, I had a little light bulb moment and basically used one proxy item change to update a second proxy item change which the rule runs from


So my rules,
if vTimeofDay == BED and vPresence = ON (ie it’s bedtime and I’m home)
then
vEndofDay = ON

The rule then runs on vEndofDay change,
if ON = do some stuff
else = do some other stuff

That way I’m keeping all proxy items as unique single control items but stacking them to make use of them all. :+1:

where in paperUI? it it an item,service,binding or thing?

Well, since this is a design pattern about Proxy Items and Udo says you can create it through *.items file I would have thought it was obvious that we are talking about Items.

If you don’t have an Items entry along the left hand side in PaperUI, that means you have Simple Mode turned ON. You have to turn it OFF (Configuration > Settings) to see the Items option.

1 Like

I have been struggling with getting my lights to work correctly, I am sure I must be using some kind of proxy item to get the result I am looking for.

The problem I have is my lights binding has the ON/OFF on a switch and the Brightness on a Number. so the two Items i have are

Switch Office_Power
Number Office_Brightness

The “Office_Brightness” goes from value 1 to 100
I would really like to have a slider on my sitemap that goes from 0 to 100 where 0 turns the light off.

How do I go about combining the two items into one?

Did you already try to link both channels to one dimmer item?

To use two items and a proxy:

Switch Office_Power
Number Office_Brightness

Dimmer Office_Proxy "Office Light [%d %%]"
rule "office dimmer in"
when
    Item Office_Power changed or
    Item Office_Brightness changed
then
    if(triggeringItem.name == "Office_Power") {
        if(triggeringItem.state == OFF)
            Office_Proxy.postUpdate(OFF)
    } else {
        if(triggeringItem.state instanceof Number)
            Office_Proxy.postUpdate(triggeringItem.state as Number)
    }
end

rule "office dimmer out"
when
    Item Office_Proxy received command
then
    switch (receivedCommand) {
        case ON  : {
            if(Office_Power.state != ON) Office_Power.sendCommand(ON)
            Office_Brightness.sendCommand(100)
        }
        case OFF : {
            if(Office_Power.state != OFF) Office_Power.sendCommand(OFF)
        }
        default  : {
            if(receivedCommand == 0)
                if(Office_Power.state != OFF) Office_Power.sendCommand(OFF)
            else {
                if(Office_Power.state != ON) Office_Power.sendCommand(ON)
                Office_Brightness.sendCommand(receivedCommand)
            }
        }
    }
end

Maybe it’s sufficient to sendCommand the Number to switch ON, maybe it’s sufficient to sendCommand ON to switch to 100% (this is dependent on your dimmer)

1 Like

Thank you for taking the time to help me out. This is one of the last hurdles to overcome to make my system complete.

You have pointed me in the right direction, I have it now working, Modified the code a bit to make it work.
Maybe I am doing something not correctly but it works for now.

The rule I am using now is

rule "office dimmer in"
when
Item Office_Power changed or
Item Office_Brightness changed
then
if(triggeringItem.name == "Office_Power") {
    if(triggeringItem.state == OFF)
        Office_Proxy.postUpdate(0)
} 
else if (triggeringItem.name == "Office_Power") {
    if(triggeringItem.state == ON)
        Office_Proxy.postUpdate(triggeringItem.state as Number)
}
else {
    if(triggeringItem.state instanceof Number)
        Office_Proxy.postUpdate(triggeringItem.state as Number)
}
end

rule "office dimmer out"
when
Item Office_Proxy received command
then
switch (receivedCommand) {
    default  : {
        if(receivedCommand == 0)
            if(Office_Power.state != OFF) Office_Power.sendCommand(OFF)
        if(receivedCommand > 0)
            if(Office_Power.state != ON) Office_Power.sendCommand(ON)
            Office_Brightness.sendCommand(receivedCommand)
    }
}
end

Hope I am now doing it correctly the log shows the following

2019-10-14 16:21:14.015 [ome.event.ItemCommandEvent] - Item 'Office_Brightness' received command 18
2019-10-14 16:21:14.018 [nt.ItemStatePredictedEvent] - Office_Brightness predicted to become 18
2019-10-14 16:21:14.038 [vent.ItemStateChangedEvent] - Office_Brightness changed from 39 to 18
2019-10-14 16:21:17.959 [ome.event.ItemCommandEvent] - Item 'Office_Brightness' received command 97
2019-10-14 16:21:17.964 [nt.ItemStatePredictedEvent] - Office_Brightness predicted to become 97
2019-10-14 16:21:18.009 [vent.ItemStateChangedEvent] - Office_Brightness changed from 18 to 97

Nope, code is not correct.

rule "office dimmer in"
when
Item Office_Power changed or
Item Office_Brightness changed
then
if(triggeringItem.name == "Office_Power") {
    if(triggeringItem.state == OFF)
        Office_Proxy.postUpdate(0)
} 
else if (triggeringItem.name == "Office_Power") { //<--- this part is identical to the first if()
    if(triggeringItem.state == ON)                      // <--- if state is ON it's never a
        Office_Proxy.postUpdate(triggeringItem.state as Number) // <--- Number !
}
else {
    if(triggeringItem.state instanceof Number)
        Office_Proxy.postUpdate(triggeringItem.state as Number)
}
end

This one will take care of the case “Light is switched on, but brightness did not change”:

rule "office dimmer in"
when
    Item Office_Power changed or
    Item Office_Brightness changed
then
    if(triggeringItem.name == "Office_Power") {
        if(triggeringItem.state == OFF)
            Office_Proxy.postUpdate(0)
        else // command is ON or OFF, no other option!
            Office_Proxy.postUpdate(Office_Brightness.state as Number)
    } else {
        if(triggeringItem.state instanceof Number)
            Office_Proxy.postUpdate(triggeringItem.state as Number)
    }
end
rule "office dimmer out"
when
Item Office_Proxy received command
then
switch (receivedCommand) {
    default  : {
        if(receivedCommand == 0)
            if(Office_Power.state != OFF) Office_Power.sendCommand(OFF)
        if(receivedCommand > 0)
            if(Office_Power.state != ON) Office_Power.sendCommand(ON)
            Office_Brightness.sendCommand(receivedCommand)
    }
}
end

If there is no option other than default, why switching at all (and for the record: even if you do not send a command ON or OFF through the UI, it’s possible to use Office_Proxy.sendCommand(ON) or OFF from a rule.
If you don’t want to use this option, the second rule is even shorter:

rule "office dimmer out"
when
    Item Office_Proxy received command
then
    if(receivedCommand instanceof Number) {
        if(receivedCommand == 0)
            if(Office_Power.state != OFF) Office_Power.sendCommand(OFF)
        if(receivedCommand > 0) {
            if(Office_Power.state != ON) Office_Power.sendCommand(ON)
            Office_Brightness.sendCommand(receivedCommand)
        }
    }
end
1 Like

You point me in the right direction, Everything works as it should now. Maybe my code is not written correctly but at least it works as I would like.

rule "Office_ power dimmer in"
when
    Item Office_Power changed
 
then
        if(Office_Power.state == OFF) {
            Office_Proxy.postUpdate(1) 
        }
        else {Office_Proxy.postUpdate(Office_Brightness.state)
    }
end

rule "Office_ brightness dimmer in"
when
    Item Office_Brightness changed
 
then
    if(Office_Brightness.state instanceof Number) {
        Office_Proxy.postUpdate(Office_Brightness.state as Number)
}
end

rule "Office_ dimmer out"
when
    Item Office_Proxy received command
then
    switch (receivedCommand) {
        default  : {
            if(receivedCommand == 1)
                if(Office_Power.state != OFF) Office_Power.sendCommand(OFF)
            if(receivedCommand > 1)
                if(Office_Power.state != ON) Office_Power.sendCommand(ON)
                Office_Brightness.sendCommand(receivedCommand)
        }
    }
end

Really, I doubt that you understand what the code actually does.

You might be correct here. It does the job need for me. I might have to take more time to learn the code to really get the best out of it

Reading the code I think it is correct for my use case.

Maybe you see something that is not the way to do it then enlighten me