Design Pattern: Proxy Item

Ok, are you suggesting that Deadmans switch isnt sufficient. So i do need to implement the sw_BedRoomLight_manual switch.

I guess in that case the timeoftheday rule i have set solves the same way?

if (now.getHourOfDay() >7 && now.getHourOfDay() <22){  //07:00:00 to 21:59:59  only enable sensor during the day

The DeadMansSwitch is sufficient for detecting when a light was switched manually. That is all the Design Pattern does. What you do with that knowledge is left up to you. In this case, you want to set/check an override flag and avoid turning on/off the light when the override flag is set.

The timers are tricky to follow. Can you explain in words what the two timers are supposed to do?

See

KLTimer_5m_OFF is an Item configured with the Expire binding to receive an OFF command five minutes after it received the last ON command.

KLTimer_10s_OFF is an Item configured with the Expire binding to receive an OFF command five minutes after it received the last ON command.

There is a rule that gets triggered when either of these Timer Item changes to OFF (I would have used received command OFF instead of changed to OFF so that the rules do not trigger when the Timer is canceled but Bob is really deliberate in his Rules so expect there is a reason he wants the rule to fire even when the Timer is cancelled with an update).

When the 5m timer goes to OFF, the 10s timer gets set to ON. When the 10s timer goes OFF, the kitchen motion sensor is checked. If it is ON then the 10s timer is reset to fire in another 10 seconds. If not then the light is turned OFF.

The Rule that uses the Timers gets fires when the motion sensor changes from ON to OFF. If I remember correctly, his motion sensors remain ON for a period of time after detecting motion so this rule gets triggered some minutes after the last motion detected. If the light was ON when the motion sensor went OFF then if the 5m timer is still running then it gets turned OFF. In either case the 10s timer get set to turn off the Light in 10 seconds (assuming there isn’t another motion event).

If the light is OFF then the timers are canceled with a postUpdate(OFF).

So, at a high level, he has a 5-minute timer that gets set somewhere (probably his lights proxy rule). When that timer expires he sets a 10-second timer that when it expires turns off the lights.

3 Likes

Correct explanation of the intent. In reality the 5m_OFF timer is a kind of safety valve. My particular motion sensors re-evaluate motion status after 4 minutes (+/- a few seconds). So if the motion sensor shifts to OFF/CLOSED at 4 minutes (+/- a few sec) , the 5m_OFF timer gets cancelled and the 10s_OFF timer goes into a tight re-evaluation loop. As long as the motion sensor stays OFF/CLOSED, (in most likely case 10s), the PROXY will be switched off after 10s. If by chance, someone reactivates the motion sensor in that time, the 10s timer will get reset and continue doing so as long as the motion sensor is in ON/OPEN state. A reactivation of the sensor also re-establishes the 5m_OFF safety valve timer.

Agree with @rlkoshak on received command — I actually implemented that after my original post.

BTW there is redundancy in the outer ELSE clause of the MO_2 rule–leftover from some debugging. I think I edited the original post to remove it, but just FYI.

I really like the expire binding – it simplifies timers a lot — you have to have more rules but they are simpler in context. And (another big plus) the expire-binding timers are commonly accessible across rule sets (I have 8 or so). Does make it somewhat easier to shoot yourself in the foot, but being able to segment rule sets into different files is worth it.

1 Like

Hello, I have been struggling with correct settings of my new setup and this design pattern (Proxy / Virtual item) is exactly what I needed. It took me a while until I fully understood it to apply to my case and finally have it working. I have improved it with what I have learnt from @rlkoshak in another topic about PIR alarm, by using a group of items and triggeringItem and would like to share it for anyone else who would be searching for such solution.

My setup:
I have a relay (actually 2 x 8 relays modules = 16 relays) which are connected to Arduino MEGA and those relays are connected to my room(s) lights. I have also wall switches, also connected to MEGA.

The MEGA is then communicatig via serial with ESP8266 which is then publishing and subscribing to MQTT topics managed by a mosquitto broker on my RPI3 where also Openhabian is running.

My approach was to keep things running even if Openhab would be offline for any reason so Wall switches are toggling states of relays directly on MEGA. So the MEGA is the only point of failure which could be easily replaced by another one which (will be :slight_smile: ) ready for that.

To be able to add Openhab in, I had to connect MEGA to the wifi. I decided to use ESP8266 which is forwarding commands to relays (from Openhab etc.) and states of relays (to Openhab). I am exchanging these between MEGA and ESP via EasyTransfer library for Arduino which is basically serial communication where I am exchanging only Pin ID and Pin Value (e.g. Pin ID = 22 and Pin Value = 1 means relay connected to pin D22 will switch OFF (this would actually switch the relay ON due to inverted logic on relays but that is not important here).

So whenever my wall switch toggles the relay (living room light) state, I am sending this information from MEGA to ESP and publishing this change of relay’s state to a relevant topic (e.g. house/livingroom/lightState)

The rule then updates my virtual switch item in openhab to the new state.

And vice versa, when my virtual item switch (or a rule or a mobile app) wants to toggle the relay/light, the rule (which could make some additional checks) forwards this command via MQTT topic (e.g. house/livingroom/lightCommand) to ESP which then forwards it to MEGA which finally toggles the relay to desired state and replies back with the new state to confirm command received.

I decided to use two separated MQTT topics to avoid loops which was my issue when I tried to use a simpler way of having only one switch item subscribed and publishing it’s state to one same topic, not even using a virtual item.

So you could easily use a one rule for a one set of relay/switch, but in my case this would be about 12+ sets so 12+ x rules. Very inefficient, hard to maintain etc. So I used the group way that I learnt from Rich (thanks again) and improved that for me.

So my items (simplified and generalized) are:

//Lights
Group:Switch:OR(ON, OFF) gCommands "All relays [(%d)]"
Group:Switch:OR(ON, OFF) gVirtualSwitches "All virtual switches [(%d)]"

Switch LRLights_State		    "Living room lights state"        <switch> 	                {mqtt="<[mosquitto:house/livingroom/lightState:state:default]"}
Switch LRLights_Command		    "Living room lights command"      <switch>    (gCommands)     {mqtt=">[mosquitto:house/livingroom/lightCommand:command:*:default]"}
Switch LRLights_VirtualSwitch    "Living room lights virtual switch"      <light>     (gVirtualSwitches)

And my rules are:

rule "VirtualSwitch received command" //so I want to toggle relay via openhab/mobile app, rule etc.
when
    Item LRLights_VirtualSwitch received command// or
    //Item LRLights2_VirtualSwitch received command 
    //...
    
then
        //logInfo("light.rules switch received command", "STARTED")
     // getting here the command Item object related to the same lights virtual switch which triggered this rule    
     val relCommand = gCommands.members.findFirst[c| c.name == triggeringItem.name.split("_").get(0) + "_Command"]
        //logInfo("light.rules switch received command", "triggeringItem.name=[{}]",triggeringItem.name)
        //logInfo("light.rules switch received command", "virtSwitch.name=[{}]",triggeringItem.name)
    
    switch(triggeringItem.name){
        case "LRLights_VirtualSwitch": {
                //logInfo("light.rules switch received command", "case: LRLights_VirtualSwitch")
            if(receivedCommand == ON) {
                // additional ON logic, e.g. check presence, time of day, motion detectors, set/unset a flag, etc.
                relCommand.sendCommand(ON) // forward the command
                    //logInfo("light.rules switch received command", "send command: ON to:[{}]",relCommand.name)
            }
            else {
                // additional OFF logic, e.g. check presence, time of day, motion detectors, set/unset a flag, etc.
                relCommand.sendCommand(OFF) // forward the command
                    //logInfo("light.rules switch received command", "send command: OFF to:[{}]",relCommand.name)
            }
        }
        //case "LRLights2_VirtualSwitch": {}
        //....   
 }
end

rule "State item received update"// so the relay state has changed, via virtual switch above or via wall switch, so ESP is informing (confirming) openhab about it's new state
when
    Item LRLights_State received update //or
    //Item LRLights2_State received update or
    //...
then
    //getting here the virtual switch item object which is related to the relay/light that changed it's state so I can update the new state to the virtual switch    
    val virtSwitch = gVirtualSwitches.members.findFirst[c| c.name == triggeringItem.name.split("_").get(0) + "_VirtualSwitch"]
        logInfo("light.rules state received update", "triggeringItem.name=[{}]",triggeringItem.name)
    
    switch(triggeringItem.name){
        case "LRLights_State": {
            if(triggeringItem.state == ON) {
                // additional ON logic, e.g. check presence, time of day, motion detectors, set/unset a flag, etc.
                virtSwitch.postUpdate(ON) // forward the command
            }
            else {
                // additional OFF logic, e.g. check presence, time of day, motion detectors, set/unset a flag, etc.
                virtSwitch.postUpdate(OFF) // forward the command
            }
        }
        //case "LRLights2_State": {}
        //...    
}
end
3 Likes

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?