In this post (and the associated video), I will show you 3 ways to set up scenes in openHAB and connect them with Google Home/Assistant for voice control.
The three methods vary in flexibility (from simple set of on/off commands, to a fully dynamic and customizable scene with setpoint storage), but increase in complexity (from pressing a few buttons in the Google Home app, to creating a set of duplicate items and multiple rules to store the configurable scene settings). Each method should satisfy a need depending on the level of functionality you require.
I’m making an assumption that you already have Google Home and your openHAB connected and items tagged. If not, please read this article and how-to video: Google Home & openHAB connection How-To
I’ve divided the post into three sections, one for each method.
Method 1 - Google Home Routines
This method is very simple, made available by the recently released Google Assistant routines. Simply go to your Google Home app, click on More Settings, Routines, select the routine you want to use, check the “Adjust Lights, plugs, and more” option and click the settings icon next to it. From here, you can select every item you want to change as part of the routine, by selecting “Turn On” or “Turn Off”. Back out of the settings page and hit Save - that’s it!
As you may have guessed, the routines don’t allow fine tuning of light brigthness or changing colors, etc…But, you can get a nice scene set up in minutes!
Method 2 - Use switch item in openHAB with rule to set items
The next method requires a bit more work, but allows fine settings, and any number of actions to happen as part of your scene. Simply create a Scene switch item:
Switch Scene_Wakeup "Wake Up" (LightingScenes) [ "Switchable" ]
The LightingScenes group is not required, but you can add the whole group to your main sitemap, for example, and make all scenes available from that screen. The “Switchable” tag allows you to use the switch in a Google Home routine to select the scene.
You’ll also need a rule to execute when the scene is selected:
rule "Lighting Scene Wakeup"
when
Item Scene_Wakeup received command ON
then
Light_FF_Kitchen_Sink.sendCommand(25)
FF_Kitchen_Island.sendCommand(25)
Light_SF_Landing_Lamp.sendCommand(50)
Scene_Wakeup.postUpdate(OFF)
end
The rule executes when the Scene_Wakeup switch receives an ON command (this can be either via voice to Google Home, or from the UI by turning on the scene switch). In the rule body, I send commands to several lights around the house (notice I’m using dimmer values, something that can’t be done with Method 1), and then turn the Scene switch item OFF again (so it acts as a momentary pushbutton in the UI).
This method allows you to execute any number of actions when the scene is enabled, even those that aren’t currently natively available via Google Home (HVAC, audio control, etc…). But, if you need to change any setting (brightness level, color, etc.), you need to go back into the code and change the rule. If you think this could be a hassle over the long run, go on to method 3.
Method 3 - Full customization with setpoint storage
The third method is the most complex, but allows full dynamic customization of the scene via voice/openHAB UI, and stores the settings to be used for next time the scene is selected!
For this, you’ll need a complete duplicate set of items (basically, a storage item for every item you’re using in the scene). We’ll use rules to copy the setpoints to/from the storage items.
First, we need to define the additional items:
Group gSceneConfig_Evening "Evening Scene Config" (LightingScenes)
Switch Scene_Evening_Store "Evening Scene Store" (gSceneConfig_Evening) ["Switchable"]
Switch Scene_Evening_Kitchen_Strip_Power "Kitchen Strip Power" (gSceneConfig_Evening)
Color Scene_Evening_Kitchen_Strip_Color "Kitchen Strip Color [%d %%]" (gSceneConfig_Evening)
Dimmer Scene_Evening_Light_FF_Kitchen_Recessed "Kitchen Recessed Lights Level [%d %%]" (gSceneConfig_Evening)
Dimmer Scene_Evening_Light_FF_Kitchen_Sink "Kitchen Sink Light Level [%d %%]" (gSceneConfig_Evening)
The gSceneConfig_Evening group allows me to keep the setpoints in one group within the sitemap (and since it’s a part of the LightingScenes group, it’ll show up as a menu option in my LightingScenes selection menu). The “Scene_Evening_Store” switch is the only thing tagged for Google Assistant. I’ve prefixed every storage item with its Scene identifier, so it’s obvious these are the storage items and not the light/color values for the actual things.
Now, we need a rule to copy our setpoints from the storage values to the actual thing values when this scene is executed:
rule "Lighting Scene Evening"
when
Item Scene_Evening received command ON
then
EveningLights.sendCommand(ON)
LEDStrip_Group2_Power.sendCommand(Scene_Evening_Kitchen_Strip_Power.state as OnOffType)
LEDStrip_Group2_Color.sendCommand(Scene_Evening_Kitchen_Strip_Color.state as HSBType)
FF_Kitchen_Recessed.sendCommand(Scene_Evening_Light_FF_Kitchen_Recessed.state as DecimalType)
Light_FF_Kitchen_Sink.sendCommand(Scene_Evening_Light_FF_Kitchen_Sink.state as DecimalType)
Scene_Evening.postUpdate(OFF)
end
You’ll notice that I’m no longer setting hardcoded values for each item. Instead, I’m copying the current state of the setpoint item and setting the actual thing value to its state.
Now, if I make changes to the lights, colors, etc, that I want to store/use the next time this scene is selected, we just need a rule to copy the current thing values into the associated storage items. This rule will fire when the “Scene_Evening_Store” switch is selected:
rule "Lighting Scene Evening Config Store"
when
Item Scene_Evening_Store received command ON
then
Scene_Evening_Kitchen_Strip_Power.sendCommand(LEDStrip_Group2_Power.state as OnOffType)
Scene_Evening_Kitchen_Strip_Color.sendCommand(LEDStrip_Group2_Color.state as HSBType)
Scene_Evening_Light_FF_Kitchen_Recessed.sendCommand(FF_Kitchen_Recessed.state as DecimalType)
Scene_Evening_Light_FF_Kitchen_Sink.sendCommand(Light_FF_Kitchen_Sink.state as DecimalType)
Scene_Evening_Store.postUpdate(OFF)
end
That’s it! This scene is now fully customizable!
Keep in mind, the storage value items need to be added to your persistence, if you want to maintain the scene settings through a power cycle.
Method 3.5 - Generic scene rule (based on @rlkoshak 's suggestions below)
This is a variation of Method 3 above, but uses a generic rule to execute each scene. First, the .items definition changes to group each Scene storage item (just add new “Scene_foo” groups and items to create your own scene)
//Put the Scene Groups in Scene_Items
Group Scene_Items
//Put all the Items that hold the state for a scene in Scene_States
Group Scene_States
/* Scene Proxy Switches (accessible from UI/Google Home)*/
/* Step 1 - Add new Scene switch here */
Switch Scene_Evening "Evening Scene" (LightingScenes) [ "Switchable" ]
Switch Scene_Night "Night Scene" (LightingScenes) [ "Switchable" ]
//Groups to hold all items conrolled by this scene
/* Step 2 - Add new group for scene items */
Group Scene_Evening_Items (Scene_Items)
Group Scene_Night_Items (Scene_Items)
/* Scene Config Proxy Switches (accessible from UI/Google Home)*/
/* Step 3 - Add new proxy switch for storing current state of items into scene state items */
Switch Scene_Evening_Store "Evening Scene Store" (gSceneConfig_Evening) [ "Switchable" ]
Switch Scene_Night_Store "Night Scene Store" (gSceneConfig_Night) [ "Switchable" ]
//Evening Scene Configuration Settings
Group gSceneConfig_Evening "Evening Scene Config" (LightingScenes)
Switch Scene_Evening_LEDStrip_Kitchen_Cabinet_Power "Kitchen Cabinet Power" (gSceneConfig_Evening,Scene_States)
Color Scene_Evening_LEDStrip_Kitchen_Cabinet_Color "Kitchen Cabinet Color [%d %%]" (gSceneConfig_Evening,Scene_States)
Dimmer Scene_Evening_Light_FF_Kitchen_Recessed "Kitchen Recessed Lights Level [%d %%]" (gSceneConfig_Evening,Scene_States)
//Night Scene Configuration Settings
Group gSceneConfig_Night "Night Scene Config" (LightingScenes)
Switch Scene_Night_LEDStrip_Kitchen_Cabinet_Power "Kitchen Cabinet Power" (gSceneConfig_Night,Scene_States)
Color Scene_Night_LEDStrip_Kitchen_Cabinet_Color "Kitchen Cabinet Color [%d %%]" (gSceneConfig_Night,Scene_States)
Dimmer Scene_Night_Light_FF_Kitchen_Recessed "Kitchen Recessed Lights Level [%d %%]" (gSceneConfig_Night,Scene_States)
/* Step 4 - Add set of state items corresponding to items that are to be controlled (ensure anything past Scene_xxx_ matches the actual item name)
/* Step 5 - Add Scene_xxxx_Items as a group identifier to the items you want to control with the scene
Then, you just need a .rules file with the generic “set” rule, and individual “store” rules for each scene:
/* Step 6 - Add "or Item Scene_xxx received command ON" below the last item in the when clause below */
rule "Lighting Scene"
when
//Use this block if you're on OpenHAB 2.2 or below
/*Item Scene_Evening received command ON or
Item Scene_Night received command ON*/
Member of LightingScenes received command ON //Use this line if you're on OpenHAB 2.3 or later
then
// Get the Group of 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 |
//logInfo("Lights", "Lighting Rule getting " + triggeringItem.name+"_"+i.name + " state")
// Get the state for this Item and Scene
val sceneState = Scene_States.members.findFirst[ GenericItem st | st.name == triggeringItem.name+"_"+i.name ]
//logInfo("Lights", triggeringItem.name+"_"+i.name + " state: " + sceneState.state)
//logInfo("Lights", "Item to change: " + i.name)
// sendCommand the Scene state
if(sceneState !== null)
{i.sendCommand(sceneState.state.toString)}
]
triggeringItem.sendCommand(OFF)
end
rule "Lighting Scene Evening Config Store"
when
Item Scene_Evening_Store received command ON
then
Scene_Evening_LEDStrip_Kitchen_Cabinet_Power.sendCommand(LEDStrip_Kitchen_Cabinet_Power.state as OnOffType)
Scene_Evening_LEDStrip_Kitchen_Cabinet_Color.sendCommand(LEDStrip_Kitchen_Cabinet_Color.state as HSBType)
Scene_Evening_Light_FF_Kitchen_Recessed.sendCommand(Light_FF_Kitchen_Recessed.state as DecimalType)
Scene_Evening_Store.postUpdate(OFF)
end
rule "Lighting Scene Night Config Store"
when
Item Scene_Night_Store received command ON
then
Scene_Night_LEDStrip_Kitchen_Cabinet_Power.sendCommand(LEDStrip_Kitchen_Cabinet_Power.state as OnOffType)
Scene_Night_LEDStrip_Kitchen_Cabinet_Color.sendCommand(LEDStrip_Kitchen_Cabinet_Color.state as HSBType)
Scene_Night_Light_FF_Kitchen_Recessed.sendCommand(Light_FF_Kitchen_Recessed.state as DecimalType)
Scene_Night_Store.postUpdate(OFF)
end
/* Step 7 - Add handler rule that will fire whenever Scene_XXX_Store receives ON command (add sendCommand statement for each item to copy the current item into the state item)
It should be possible to make the store rules generic, as well - but I couldn’t find an easy way to group the item/state values for each scene.
To add items to the scene, or add new scenes, follow the commented steps in the code above.
Conclusion
I hope this is useful for some of you - I’ve been using scenes in my setup for a while, and they definitely extend the functionality and improve the SAF (Spousal Acceptance Factor) of my home automation system
Let me know if you have any questions or suggestions below!
-B.K.