Setting light themes in rules

Hi All,

I have been playing with openhab now for a couple of weeks and after a couple of issues caused by not reading instructions properly I have got a decent setup running connected to a variety of devices around the house but on my recent mini project I am not convinced I am going in the correct direction and cannot find any help topics or forum posts that cover what I am trying to achieve.

I have created the template below (Still rough just for testing) and it functions exactly as I want, one theme selected goes active and others go inactive. (Ignore the Office OFF statuses, they are just a placeholder)

Capture

The way that I am achieving this though is what concerns me, I am taking the approach of storing the themes as items

Switch 	Theme_WatchTV
Switch 	Theme_LivingRoom_Bright
Switch 	Theme_LivingRoom_Relax
Switch 	Theme_LivingRoom_Nightlife

then setting the states of these switches (and accompanying bulbs) via rules

val logName = "lighttheme"

rule "Set Watch TV"
when
	Item Theme_WatchTV changed to ON
then 
	logInfo(logName,"Theme: Watch TV selected")
  
	Theme_LivingRoom_Bright.sendCommand("OFF")
	Theme_LivingRoom_Relax.sendCommand("OFF")
	Theme_LivingRoom_Nightlife.sendCommand("OFF")
	
    LivingRoom_1_1_Dimmer.sendCommand("69")
    LivingRoom_1_1_Colour.sendCommand("82,55,69")
    LivingRoom_1_1_ColourTemp.sendCommand("61")
	
    LivingRoom_1_2_Dimmer.sendCommand("69")
    LivingRoom_1_2_Colour.sendCommand("82,55,69")
    LivingRoom_1_2_ColourTemp.sendCommand("61")
	
    LivingRoom_2_1_Dimmer.sendCommand("29")
    LivingRoom_2_1_Colour.sendCommand("82,55,29")
    LivingRoom_2_1_ColourTemp.sendCommand("61")
	
    LivingRoom_2_2_Dimmer.sendCommand("29")
    LivingRoom_2_2_Colour.sendCommand("82,55,29")
    LivingRoom_2_2_ColourTemp.sendCommand("61")
	
    LivingRoom_3_1_Dimmer.sendCommand("1")
    LivingRoom_3_1_Colour.sendCommand("82,55,1")
    LivingRoom_3_1_ColourTemp.sendCommand("61")
	
    LivingRoom_3_2_Dimmer.sendCommand("1")
    LivingRoom_3_2_Colour.sendCommand("82,55,1")
    LivingRoom_3_2_ColourTemp.sendCommand("61")
  
end


rule "Set Living Room Bright"
when
	Item Theme_LivingRoom_Bright changed to ON
then 
	logInfo(logName,"Theme: Living Room Bright")
  
	Theme_WatchTV.sendCommand("OFF")
	Theme_LivingRoom_Relax.sendCommand("OFF")
	Theme_LivingRoom_Nightlife.sendCommand("OFF")
  
    LivingRoom_1_1_Dimmer.sendCommand("100")
    LivingRoom_1_1_Colour.sendCommand("82,55,100")
    LivingRoom_1_1_ColourTemp.sendCommand("61")
	
    LivingRoom_1_2_Dimmer.sendCommand("100")
    LivingRoom_1_2_Colour.sendCommand("82,55,100")
    LivingRoom_1_2_ColourTemp.sendCommand("61")
	
    LivingRoom_2_1_Dimmer.sendCommand("100")
    LivingRoom_2_1_Colour.sendCommand("82,55,100")
    LivingRoom_2_1_ColourTemp.sendCommand("61")
	
    LivingRoom_2_2_Dimmer.sendCommand("100")
    LivingRoom_2_2_Colour.sendCommand("82,55,100")
    LivingRoom_2_2_ColourTemp.sendCommand("61")
	
    LivingRoom_3_1_Dimmer.sendCommand("100")
    LivingRoom_3_1_Colour.sendCommand("82,55,100")
    LivingRoom_3_1_ColourTemp.sendCommand("61")
	
    LivingRoom_3_2_Dimmer.sendCommand("100")
    LivingRoom_3_2_Colour.sendCommand("82,55,100")
    LivingRoom_3_2_ColourTemp.sendCommand("61")
  
end


rule "Set Living Room Relax"
when
	Item Theme_LivingRoom_Relax changed to ON
then 
	logInfo(logName,"Theme: Living Room Relax")
  
	Theme_WatchTV.sendCommand("OFF")
	Theme_LivingRoom_Bright.sendCommand("OFF")
	Theme_LivingRoom_Nightlife.sendCommand("OFF")
  
    LivingRoom_1_1_Dimmer.sendCommand("56")
    LivingRoom_1_1_Colour.sendCommand("74,78,56")
    LivingRoom_1_1_ColourTemp.sendCommand("84")
	
    LivingRoom_1_2_Dimmer.sendCommand("56")
    LivingRoom_1_2_Colour.sendCommand("74,78,56")
    LivingRoom_1_2_ColourTemp.sendCommand("84")
	
    LivingRoom_2_1_Dimmer.sendCommand("56")
    LivingRoom_2_1_Colour.sendCommand("74,78,56")
    LivingRoom_2_1_ColourTemp.sendCommand("84")
	
    LivingRoom_2_2_Dimmer.sendCommand("56")
    LivingRoom_2_2_Colour.sendCommand("74,78,56")
    LivingRoom_2_2_ColourTemp.sendCommand("84")
	
    LivingRoom_3_1_Dimmer.sendCommand("56")
    LivingRoom_3_1_Colour.sendCommand("74,78,56")
    LivingRoom_3_1_ColourTemp.sendCommand("84")
	
    LivingRoom_3_2_Dimmer.sendCommand("56")
    LivingRoom_3_2_Colour.sendCommand("74,78,56")
    LivingRoom_3_2_ColourTemp.sendCommand("84")
  
end


rule "Set Living Room Nightlife"
when
	Item Theme_LivingRoom_Nightlife changed to ON
then 
	logInfo(logName,"Theme: Living Room Nightlife")
  
	Theme_WatchTV.sendCommand("OFF")
	Theme_LivingRoom_Bright.sendCommand("OFF")
	Theme_LivingRoom_Relax.sendCommand("OFF")
  
    LivingRoom_1_1_Dimmer.sendCommand("1")
    LivingRoom_1_1_Colour.sendCommand("59,98,1")
    LivingRoom_1_1_ColourTemp.sendCommand("100")
	
    LivingRoom_1_2_Dimmer.sendCommand("1")
    LivingRoom_1_2_Colour.sendCommand("59,98,1")
    LivingRoom_1_2_ColourTemp.sendCommand("100")
	
    LivingRoom_2_1_Dimmer.sendCommand("1")
    LivingRoom_2_1_Colour.sendCommand("59,98,1")
    LivingRoom_2_1_ColourTemp.sendCommand("100")
	
    LivingRoom_2_2_Dimmer.sendCommand("1")
    LivingRoom_2_2_Colour.sendCommand("59,98,1")
    LivingRoom_2_2_ColourTemp.sendCommand("100")
	
    LivingRoom_3_1_Dimmer.sendCommand("1")
    LivingRoom_3_1_Colour.sendCommand("59,98,1")
    LivingRoom_3_1_ColourTemp.sendCommand("100")
	
    LivingRoom_3_2_Dimmer.sendCommand("1")
    LivingRoom_3_2_Colour.sendCommand("59,98,1")
    LivingRoom_3_2_ColourTemp.sendCommand(100)
  
end

This is feeling awfully verbose way of achieving what I want and despite working I would value your input into my methods.

OK so played a bit more and by adding groups I have made it a little easier on the eyes.

hue.items

// #########################################################
// Group Config
// #########################################################

Group:Switch:OR(ON,OFF) LivingRoomLightSwitch "Living Room Wall Lights"  
Group:Dimmer:AVG LivingRoomLightDimmers "Living Room Wall Dimmers" 
Group:Dimmer:AVG LivingRoomLightColourTemp "Living Room Wall Colour Temp" 

// #########################################################
// Theme Config
// #########################################################
Switch 	Theme_WatchTV
Switch 	Theme_LivingRoom_Bright
Switch 	Theme_LivingRoom_Relax
Switch 	Theme_LivingRoom_Nightlife

// #########################################################
// Item Config
// #########################################################

Switch 	LivingRoom_1_1_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhub:9:color"} 
Dimmer 	LivingRoom_1_1_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhub:9:color"}
Color 	LivingRoom_1_1_Colour 		(LivingRoomLightColour)		{channel="hue:0210:myhub:9:color"}
Dimmer 	LivingRoom_1_1_ColourTemp 								{channel="hue:0210:myhub:9:color_temperature"}


Switch 	LivingRoom_1_2_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhub:11:color"} 
Dimmer 	LivingRoom_1_2_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhub:11:color"}
Color 	LivingRoom_1_2_Colour 		(LivingRoomLightColour)		{channel="hue:0210:myhub:11:color"}
Dimmer 	LivingRoom_1_2_ColourTemp 								{channel="hue:0210:myhub:11:color_temperature"}

Switch 	LivingRoom_2_1_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhub:14:color"} 
Dimmer 	LivingRoom_2_1_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhub:14:color"}
Color 	LivingRoom_2_1_Colour 									{channel="hue:0210:myhub:14:color"}
Dimmer 	LivingRoom_2_1_ColourTemp 								{channel="hue:0210:myhub:14:color_temperature"}


Switch 	LivingRoom_2_2_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhub:10:color"} 
Dimmer 	LivingRoom_2_2_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhub:10:color"}
Color 	LivingRoom_2_2_Colour 									{channel="hue:0210:myhub:10:color"}
Dimmer 	LivingRoom_2_2_ColourTemp 								{channel="hue:0210:myhub:10:color_temperature"}

Switch 	LivingRoom_3_1_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhub:13:color"} 
Dimmer 	LivingRoom_3_1_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhub:13:color"}
Color 	LivingRoom_3_1_Colour 									{channel="hue:0210:myhub:13:color"}
Dimmer 	LivingRoom_3_1_ColourTemp 								{channel="hue:0210:myhub:13:color_temperature"}


Switch 	LivingRoom_3_2_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhub:12:color"} 
Dimmer 	LivingRoom_3_2_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhub:12:color"}
Color 	LivingRoom_3_2_Colour 									{channel="hue:0210:myhub:12:color"}
Dimmer 	LivingRoom_3_2_ColourTemp 								{channel="hue:0210:myhub:12:color_temperature"}


lighttheme.rules

val logName = "lighttheme"

rule "Set Watch TV"
when
	Item Theme_WatchTV changed to ON
then 
	logInfo(logName,"Theme: Watch TV selected")
	
	Theme_LivingRoom_Bright.sendCommand("OFF")
	Theme_LivingRoom_Relax.sendCommand("OFF")
	Theme_LivingRoom_Nightlife.sendCommand("OFF")
	
	LivingRoomLightColourTemp.sendCommand("61")
	
    LivingRoom_1_1_Colour.sendCommand("82,55,69")
    LivingRoom_1_2_Colour.sendCommand("82,55,69")
    LivingRoom_2_1_Colour.sendCommand("82,55,29")
    LivingRoom_2_2_Colour.sendCommand("82,55,29")
    LivingRoom_3_1_Colour.sendCommand("82,55,1")
    LivingRoom_3_2_Colour.sendCommand("82,55,1")
  
end


rule "Set Living Room Bright"
when
	Item Theme_LivingRoom_Bright changed to ON
then 
	logInfo(logName,"Theme: Living Room Bright")
  
	Theme_WatchTV.sendCommand("OFF")
	Theme_LivingRoom_Relax.sendCommand("OFF")
	Theme_LivingRoom_Nightlife.sendCommand("OFF")
  
	LivingRoomLightColourTemp.sendCommand("61")
	
    LivingRoom_1_1_Colour.sendCommand("82,55,100")
    LivingRoom_1_2_Colour.sendCommand("82,55,100")
    LivingRoom_2_1_Colour.sendCommand("82,55,100")
    LivingRoom_2_2_Colour.sendCommand("82,55,100")
    LivingRoom_3_1_Colour.sendCommand("82,55,100")
    LivingRoom_3_2_Colour.sendCommand("82,55,100")
  
end


rule "Set Living Room Relax"
when
	Item Theme_LivingRoom_Relax changed to ON
then 
	logInfo(logName,"Theme: Living Room Relax")
  
	Theme_WatchTV.sendCommand("OFF")
	Theme_LivingRoom_Bright.sendCommand("OFF")
	Theme_LivingRoom_Nightlife.sendCommand("OFF")
  
	LivingRoomLightColourTemp.sendCommand("84")
	
    LivingRoom_1_1_Colour.sendCommand("74,78,56")
    LivingRoom_1_2_Colour.sendCommand("74,78,56")
    LivingRoom_2_1_Colour.sendCommand("74,78,56")
    LivingRoom_2_2_Colour.sendCommand("74,78,56")
    LivingRoom_3_1_Colour.sendCommand("74,78,56")
    LivingRoom_3_2_Colour.sendCommand("74,78,56")
  
end


rule "Set Living Room Nightlife"
when
	Item Theme_LivingRoom_Nightlife changed to ON
then 
	logInfo(logName,"Theme: Living Room Nightlife")
  
	Theme_WatchTV.sendCommand("OFF")
	Theme_LivingRoom_Bright.sendCommand("OFF")
	Theme_LivingRoom_Relax.sendCommand("OFF")
  
	LivingRoomLightColourTemp.sendCommand("100")
	
    LivingRoom_1_1_Colour.sendCommand("59,98,1")
    LivingRoom_1_2_Colour.sendCommand("59,98,1")
    LivingRoom_2_1_Colour.sendCommand("59,98,1")
    LivingRoom_2_2_Colour.sendCommand("59,98,1")
    LivingRoom_3_1_Colour.sendCommand("59,98,1")
	LivingRoom_3_2_Colour.sendCommand("59,98,1")
  
end

Still second guessing myself though in terms of if this is the best approach or not?

Setting up scenes like this is one of the weaker areas of OH unfortunately. As with any programming environment, all things are possible, but not all things are easy.

I’m glad you found Groups because that is one of the better ways to manage this sort of setup in Rules.

A lot of people will use a single String or Number Item and a selector to set the Theme from your sitemap or HABPanel using a selection. This really isn’t functionally any different from what you are doing and I would call it a personal preference choice.

You might find some inspiration from Design Pattern: Associated Items, Design Pattern: Encoding and Accessing Values in Rules, and Design Pattern: Working with Groups in Rules. For example, you can store the state of the lights in Items with associated item names. This would add flexibility for you to adjust the settings for each light individually for each scene from your HABPanel and let you reduce your rules down to one generic rule. However it comes at the cost of greatly increasing the complexity of your Items.

For a simple example of what I mean, here are my lighting rules. I control my lights based on Design Pattern: Time Of Day. Each ToD (equivalent to your themes) has two Groups, an ON Group and an OFF Group. All members of the ON Group get turned ON at the start of that ToD and all members of the OFF Group get turned OFF at the start of that ToD.

Group:Switch:OR(ON,OFF) gLights_ALL "All Lights"
	<light>

Group:Switch:OR(ON, OFF) gLights_ON
Group:Switch:OR(ON, OFF) gLights_OFF
Group:Switch:OR(ON, OFF) gLights_ON_MORNING    (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_MORNING   (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_DAY        (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_DAY       (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_AFTERNOON  (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_AFTERNOON (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_EVENING    (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_EVENING   (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_NIGHT      (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_NIGHT     (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_BED        (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_BED       (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_WEATHER    
Group:Switch:OR(ON, OFF) gLights_WEATHER_OVERRIDE

Switch aFrontLamp "Front Room Lamp" 
  (gLights_ALL, gLights_ON_MORNING, gLights_OFF_DAY, gLights_ON_AFTERNOON, gLights_ON_EVENING, gLights_OFF_NIGHT, gLights_OFF_BED, gLights_ON_WEATHER)
  { channel="zwave:device:dongle:node26:switch_binary" }
  
Switch aFamilyLamp "Family Room Lamp"
  (gLights_ALL, gLights_ON_MORNING, gLights_OFF_DAY, gLights_ON_AFTERNOON, gLights_ON_EVENING, gLights_OFF_NIGHT, gLights_OFF_BED, gLights_ON_WEATHER)
  { channel="zwave:device:dongle:node25:switch_binary" }
    
Switch aPorchLight "Front Porch"
  (gLights_ALL, gLights_OFF_MORNING, gLights_OFF_DAY, gLights_ON_AFTERNOON, gLights_ON_EVENING, gLights_OFF_NIGHT, gLights_OFF_BED)
  { channel="zwave:device:dongle:node27:switch_binary" }
val logName = "lights"

rule "Set lights based on Time of Day"
when
  Item vTimeOfDay changed
then
  // reset overrides
  gLights_WEATHER_OVERRIDE.postUpdate(OFF)

  val offGroupName = "gLights_OFF_"+vTimeOfDay.state.toString
  val onGroupName = "gLights_ON_"+vTimeOfDay.state.toString

  logInfo(logName, "Turning off lights in " + offGroupName)
  val GroupItem offItems = gLights_OFF.members.filter[g|g.name == offGroupName].head as GroupItem
      offItems.members.filter[l|l.state != OFF].forEach[l | l.sendCommand(OFF)
  ]

  logInfo(logName, "Turning on lights for " + onGroupName)
  val GroupItem onItems = gLights_ON.members.filter[g|g.name == onGroupName].head as GroupItem
      onItems.members.filter[l|l.state != ON].forEach[l | l.sendCommand(ON)
  ]
  
end

This will get you halfway there. The next step would be to add Items for each theme and each light. Something like:

Group:Color ThemeValues
Group:Color LivingRoomLights

Color LivingRoom_1_1_Colour (LivingRoomLights) {channel="hue:0210:myhub:9:color"}
Color LivingRoom_1_1_Colour_WatchTV (ThemeValues)
Color LivingRoom_1_1_Colour_LivingRoom_Bright (ThemeValues)
...

Then your Rules would look something like:

// If using persistence with restoreOnStartup you can remove this rule after all your Items have a value
rule "Populate the initial value for the theme items"
when
    System started
then
    LivingRoom_1_1_Colour_WatchTV.postUpdate("82,55,69")
    LivingRoom_1_2_Colour_LivingRoom_Bright.postUpdate("82,55,100")
    ...
end

rule "Set Watch TV"
when
    Item Theme_WatchTV changed to ON
then
    Theme_LivingRoom_Bright.sendCommand("OFF")
    Theme_LivingRoom_Relax.sendCommand("OFF")
    Theme_LivingRoom_Nightlife.sendCommand("OFF")

    LivingRoomLights.members.forEach[light | 
        light.sendCommand(ThemeValues.members.findFirst[value | value.name == light.name+"_WatchTV"].state)
    ]
end

So, as you can see, vastly simplified Rule but a proliferation of Items. Personally, I’d rather move complexity to my Items than my Rules but that is a personal preference.

1 Like

Yep, like it :slight_smile:

I’ll be having a bit of a play later on but your approach does seem simpler in the long run.

I’ll also look at the dynamic switching off of other themes by group to avoid duplication of the following for each theme

    Theme_LivingRoom_Bright.sendCommand("OFF")
    Theme_LivingRoom_Relax.sendCommand("OFF")
    Theme_LivingRoom_Nightlife.sendCommand("OFF")

OK so stumbling block one.

I cannot set the HSB values of the bulb via a group which is something I had suffered from before but thought your suggestion to address each bulb in a loop may resolve but sadly not.

items

Group:Color LivingRoomLightColour

Switch 	LivingRoom_1_1_Switch 		(LivingRoomLightSwitch) 	{channel="hue:0210:myhue:9:color"} 
Dimmer 	LivingRoom_1_1_Dimmer 		(LivingRoomLightDimmers)	{channel="hue:0210:myhue:9:color"}
Color 	LivingRoom_1_1_Colour 		(LivingRoomLightColour)		{channel="hue:0210:myhue:9:color"}
Dimmer 	LivingRoom_1_1_ColourTemp 	(LivingRoomLightColourTemp)	{channel="hue:0210:myhue:9:color_temperature"}

rules

val logName = "lighttheme"
val ThemeLivingRoomBright = "82,55,100"

rule "Set Living Room Bright"
when
	Item Theme_LivingRoom_Bright changed to ON
then 
	logInfo(logName,"Theme: Living Room Bright")

    LivingRoomLightColour.members.forEach[light | 
	logInfo(logName,"Theme: Living Room Bright - " + light.name + " set to " + ThemeLivingRoomBright)	
    ]
end

openhab.log


2017-12-02 18:29:33.503 [INFO ] [se.smarthome.model.script.lighttheme] - Theme: Living Room Bright


events.log

2017-12-02 18:29:33.421 [ItemCommandEvent          ] - Item 'Theme_LivingRoom_Bright' received command ON
2017-12-02 18:29:33.429 [ItemStateChangedEvent     ] - Theme_LivingRoom_Bright changed from OFF to ON

Then nothing, the rule throws no errors on load but there is either no members for LivingRoomLightColour or its discreetly bombing somewhere.

I have tried a simple Group “Group xxx”

But get the following error on load.

2017-12-02 18:26:06.966 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'lighttheme.rules'
2017-12-02 18:26:16.483 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'lighttheme.rules', using it anyway:
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.

I know this is not exactly as per the answer you provided previously but I’m baby stepping things so I fully understand whats going on.

Depending on the version of oH there is a bug that forces you to restart OH for changes in Group membership being picked up.

Yeah, had fun with group changes not taking effect but a simple workaround seems to be to use new names.

Tested the previous code by looping over the switch group and all is good there so it’s just the colour it is having issues with.

Did try restarting as well … no change

Going to pick this up again in a few days and see if I can get to the bottom of it.

Thanks for your feedback

Hi guys,

your absolutely right.

Finally after some time of fiddling with different approaches I think I found a way that is quite easy and needs nothing but a query-able persistence, 2 quite simple rules and of course some items. And you can even save the scene states from any gui if you want to change the state of lights in a scene.

So I’m happy to share this with you and looking forward to your feedback.

Here we go:

.items

// Groups
Group gLiving         "LivingRoom"
Group gWzScene        "Scene LivingRoom"                  (gLiving)
Group pSave           "Persistence Save"                  // mapdb -> everyChange, restoreOnStartup
Group pGraph          "Persistence Graph"                 // influxdb -> everyChange                                    

// LivingRoom Lights
Dimmer aWzDimmer      "Dimmable Light"                    (gLiving, pSave, pGraph)  { channel="<whatever you use>" }
Color aWzRgb          "RGB Light"                         (gLiving, pSave, pGraph)  { channel="<whatever you use>" }
Switch aWzSwitch      "Switchable Light"                  (gLiving, pSave, pGraph)  { channel="<whatever you use>" }

// Scene items
Number vWzScene       "Scene LivingRoom [%d]"             (gLiving, pSave)
Switch vWzScene_Save  "Scene LivingRoom save"             (gWzScene)
DateTime vWzScene_0   "Time 0 [%1$td.%1$tm.%1$tY %1$tT]"  (gWzScene, pSave)
DateTime vWzScene_1   "Time 1 [%1$td.%1$tm.%1$tY %1$tT]"  (gWzScene, pSave)
DateTime vWzScene_2   "Time 2 [%1$td.%1$tm.%1$tY %1$tT]"  (gWzScene, pSave)  // add as many scenes as want to have

.rules

rule "WzSceneSave"
when
	Item vWzScene_Save received command ON
then
	val sceneItem = gWzScene.members.filter[i|i.name == "vWzScene_"+vWzScene.state].head as DateTimeItem
	sceneItem.sendCommand(new DateTimeType(now.toString()))
	vWzScene_Save.postUpdate(OFF)
end

rule "WzSzeneLoad"
when
	Item vWzScene received command
then
	val timestamp = (gWzScene.members.filter[i|i.name == "vWzScene_"+vWzScene.state].head as DateTimeItem).state.toString
	aWzDimmer.sendCommand(aWzDimmer.historicState(parse(timestamp),"influxdb").state as PercentType)
	aWzRgb.sendCommand(aWzRgb.historicState(parse(timestamp),"influxdb").state as HSBType)
	aWzSwitch.sendCommand(aWzSwitch.historicState(parse(timestamp),"influxdb").state as OnOffType)
	vWzScene.postUpdate(OFF)
end

How it works

  • All relevant items for the scene are persisted with influxdb on every change
  • Number item vWzScene carries the scene number
  • If scene number is changed the scene is loaded by triggering the second rule
  • To do so the items are set to their historicState from influxdb according to a timestamp -> items vWzScene_X
  • If you want to change the scene you now can modify the single items
  • By clicking the button for vWzScene_Save the first rules is triggered
  • This rules writes the current date/time to the respective DateTime item and so updates the timestamp
  • Of course all the timestamps also have to be persisted and restored on startup

Additional hint: If your persistence strategy deletes or aggregates old data (for example with influxdb retention policy) you have to ensure that all data for your timestamps are still valid. E.g. you can update the timestamp every time a scene is loaded (not tested, my database is not aggregated at the moment)

Greetings
Sebastian

2 Likes

Would you be willing to post this as a separate post in the Examples and Tutorials section? It is an excellent demonstration of one of the ways one can use Persistence to make rules like this easier. I’ve done something similar to do presence simulation where everything gets turned on and off based on their state a week ago to make it look like you are home, but it never occurred to me to implement Scenes like this using Persistence.

As a separate posting, it will be a lot easier for people to find.

Of course. Done.

Yep, same here.

1 Like