3 different methods to use scenes with Google Home & openHAB

It occurred to me that you could make the scene Rule generic using Design Pattern: Associated Items.

It is a little complex but I’ve implemented stuff like this before so know it will work:

  • create your proxy items as you have
  • also create a Group for each scene and add all the Items that are controlled by scene to that Group
  • create another Group to hold the Items that store the states for those controlled Items
  • put those Groups in a parent Group
  • all the Items and Groups are named such that we can generate their names based on another Items’ name, in this case the Groups are named such that we can generate their name from the Proxy Item and the scene value Items are named such that we can generate their name from the Proxy Item and the Item being controlled
// Put the Scene Groups in Scene_Items
Group Scenes_Items
// Put all the Items that hold the state for a scene in Scene_States
Group Scenes_States

Switch Evening // Proxy Item
Group Evening_Items (Scene_Items) // Group to hold the Items controlled in these scene

Switch Morning
Group Morning_Items (Scene_Items)

...

Switch LEDStrip_Group2_Power (Evening_Items,Morning_Items) ...
Switch Evening_LEDStrip_Group2_Power (Scene_States)
Switch Morning_LEDStrip_Group2_Power (Scene_States)
...

Color LEDStrip_Group2_Color (Evening_Items,Morning_Items)...
Color Evening_LEDStrip_Group2_Color (Scene_States)
Color Morning_LEDStrip_Group2_Color (Scene_States)

...
rule "Lighting Scene"
when
    Item Evening received command ON or
    Item Morning received command ON or
    ...
then
    // Get the Group if Items that are controlled during this scene
    val items = Scene_Items.members.findFirst[ grp | grp.name == triggeringItem.name+"_Items" ] as GroupItem

    // Loop through all the Items controlled by this scene
    items.members.forEach[ GenericItem i |

        // Get the state for this Item and Scene
        val sceneState = Scene_States.members.findFirst[ GenericItem st | st.name == triggeringItem.name+"_"+i.name ]

        // sendCommand the Scene state
        i.sendCommand(sceneState.state)
    ]
end

Everything is controlled by Group membership.

To add a scene:

  • add proxy Item
  • add trigger to the rule above
  • add a Group for the scene named the same as the proxy item with “_Items” appended to the name
  • add the Items controlled by the scene to the Group
  • add new Items named the same as the proxy item + “_” + Item name to hold the value that the device should be set to during this state and add these Items to Scene_States

To add/remove Items to an existing scene simply add/remove them from the Items Group.

You never have to touch the rules beyond adding the trigger (see below) which is nice and it saves having a lot of rules for each and every scene.

And once 2.3 is released (or for those on a recent snapshot) you can add all the scene proxy items to a Group and change the trigger to

Member of SceneProxies received command ON

and you won’t even have to add/remove the Rule trigger in when adding/removing a new scene.

On reflection, you could probably eliminate Scene_Items and just put everything into Scene_States but keeping the Groups separate from the new state Items makes the code a little clearer I think.

I just typed in the above, There is almost certainly some typos. Also, you will want to add some error checking and logging to use it in production.

Edit: It occurred to me after watching the video that you could also dynamicaly add/remove Items to a scene Group. There are ways to change group membership from within rules, but I don’t know how easy it is to persist the membership across OH restarts. You may need to store the names of the members of the Group to a String Item that is persisted and have a System started rule restore the membership settings. I’ll leave that as an exercise to the student. :slight_smile:

4 Likes