Magical light scenes

Introduction

This is the lighting tutorial (DESIGN PATTERN) which is a part of my tutorial list, I keep coming back to them, improving them add functionality to them etc, so if you like it then hit “like” it and you will get notified when changes occurs. I would like to thanks @rlkoshak for the help with this one.

Please see Design Pattern: What is a Design Pattern and How Do I Use Them for details on what a DP is and how to use them.

So for those who are used to phillips hue, IKEA, ewelink and so on should know that OH does not work in the same easy way. So if you buy a hue light bulb, you will plug it in, open the hue app, find the lamp bulb then give it a name, assign it to a room. Then you have a fully working lamp which you have dimmer widget for, a color change widget and a simple on off switch as well as it works with alexa.

So its unfortunately not so simple in Oh and hence this tutorial will help you to make the same functionality as the hue app, unfortunately you need to create the widget urself, but the logic behind the widget I have made for you.

Change Log

Please keep in mind that the tutorial is not quite finished and a few details might be missing. I decided to post it rather sooner than later. Comments are welcome!

!Update 22.11.2019
Updated the code for light switches

!Update 08.11.2019
Added some more background info about group files for dimmers, scenes

!Update 07.10.2019
Added some more background info as well as a default map file

!Update 20.07.2019
Fixed a bug in coloritem change

!Update 24.04.2019
Added the new rule that useses triggeringItem, this became available in OH2.3 and makes the rules way simpler

!Update 23.04.2019
Added Screenshot of current layout in Basic UI

!Update 22.02.2019
Initial Commit

Implementation in openhab

In this tutorial I would like to share my generic approach for lighting that might also be useful for others, its quite long so lets just jump into it.

We will discuss:

  • Layout of room
  • Types of lights
  • Layout of light
  • Light controllers
  • Rules
  • Light hardware

Layout of room

I have 6 rooms:

  1. Bathroom
  2. Bedroom
  3. MasterBedroom
  4. Livingroom
  5. Hallway
  6. Balcony

My layout can been seen below

Your layout will be different, but the important thing is not to call two rooms the same and have a naming pattern that is easy to understand! Also remember that everything is case sensitive so be consequent with the names!

User interface

So what we figured out over the years, is to keep the UI as simple as possible, how do we know? Well feedback from some over 60 differnt AirBnb people. So this is how our display looks like for every room:

However when implementing this into Openhab a great tip is to make an admin sitemap where you can test out different functionality that is not included WAF(Wife acceptance factor). So before you keep on reading make sure that each individual light work! Add the correct binding and test it out well before starting with this tutorial. So when your lights are working individually lets move on and do some magic and get them to work together!

Groups

So now you need to create a group for each room with your naming convection. The naming convetion is really important, pick one and stick to it. Its case sensitive so keep that in mind. I know its common to use gLivingRoom however with feedback from @rlkoshak I prefer to use Group_xxx so that it easily can be split later in the rules by “_”. For items, they all start with room name, so if you wnat use this DP, then follow same scheme otherwise you might have to modify rules to fit your naming convention

Group Group_Livingroom
Group Group_MasterBedroom
Group Group_Hallway
Group Group_Bedroom
Group Group_Bathroom
Group Group_Balcony

It is to be noted that you also needs some groups to keep your dimmers,scenes and so in:

Group Group_Scenes
Group Group_Dimmers
Group Group_Moods
Group Group_ColorPickers

Types of lights

In openhab we have 3 types of lights:

  • Switch
  • Dimmer
  • Color

So you need to map your light to one of those types, an RGB light(Phillips hue) will then be mapped to a Color Item, a normal on off lamp will be mapped to Switch(SonOff MQTT) and a dimmable light will be dimmer(Zwave)

You can name your light items and map whatever binding to them as you like, my generic rule will handle them all. The important thing is that you add the room group and room scene(more on this later) it should belong to.

Layout of lights

When you build your own Taj Mahal you should think about how you should light it, and how you would use your place. A good light setting will make your home more welcome and relax and is something that is easy to forget when planning the home and is it hard to fix afterwards in a clean way.

So in my case I was not quite sure of how I would arrange furniture when I started the building progress so I ended up with a grid pattern of 120cm of the downlights(If I would start over again, I would probably change this slightly).

So now when you have the light plan ready, you should decide which light modes(Scenes) you would like. Here come the trick, you need to create a group for each light mode you would like EXCEPT OF: Every room needs to have at least ON/OFF of lights,( I personally also like to have NIGHT mode ). So go ahead and create light modes( such as reading, dinner, relax…) and decide which lights that should be activated in that mode,. When you have decided on these modes we need to create these groups :

Group Group_Livingroom_Lights_Night
Group Group_Livingroom_Lights_Dinner
Group Group_Livingroom_Lights_Wall
Group Group_Livingroom_Lights_FirePlace
Group Group_Livingroom_Lights_Kitchen
Group Group_Livingroom_Lights_TV
Group Group_Livingroom_Lights_Cooking
Group Group_Livingroom_Lights_Reading
Group Group_Livingroom_Lights_Lounge 

and go back to your items(your lights) and add those groups to the item definition.

Color LL27 "LL27"(.....Group_LivingRoom,Group_LivingRoom_FirePlace,Group_LivingRoom_TV) {dmx="CHANNEL[55,56,57:100000]"}

You also need to make a map file and set it up in your sitemap, more about this later.

Light controllers

So I assume that you would like to control your light, there are several way to do so:

  • Computer(Laptop,PC,Tablet)
  • Physical device(Light switches, motion detectors,dimmers etc)
  • Voice(Alexa, google,siri…)

Now comes the nice part(At least I think so…) For each room I have defined a scene selector(Even if the hallway only have one light(Simple switch)…)

So as mentioned above we created some groups representing the modes we liked to have in our home, so now is the time to implement this:

SCENES

So to actually turn on and off the lights in a ROOM we do not use a switch item but rather a number item which again will be set by selection item, physically press of a switch or voice command.

So in the lights.items files you need to create number item for each room and also this needs to belong to the Group Group_Scenes which will be used later in our generic rule:

	Number Livingroom_Scene "Scene Selector"(Group_Scenes)
	Number MasterBedroom_Scene "Scene Selector"(Group_Scenes)
	Number Bathroom_Scene "Scene Selector"(Group_Scenes)
	Number GuestBedroom_Scene "Scene Selector"(Group_Scenes)
	Number Hallway_Scene "Scene Selector"(Group_Scenes)
	Number Balcony_Scene "Scene Selector"(Group_Scenes)

these scene always have the same start mapping:

  • 0=OFF
  • 1=ON
  • 2=NIGHT
  • 3=…
  • 4=…

so you need to manually fill in the names of your modes starting from 2, remember that for some rooms maybe just ON/OFF is OK, then you just add those. So in the sitemap the file would like this:

Selection item=Scene_Livingroom label="Scene Selector" mappings=[0="OFF", 1="ON", 2="AWAY, 3="DINNER", 4="READING",5="FIREPLACE", 6="BAR", 7="PARTY", 8="TV",9="COOKING", 10="WALL", 11="KITCHEN", 12="LOUNGE"] 

For the physical devices such a single push button it might be hard to cycle through different scene, and these might therefore be better off just using as controlling all lights on/off in the given room. In my setup I did run 4 wires to each button locations so in theory I could swap single button to double or triple button, where button presses can be used as scene selector and/or dimming function. But for now I leave this as an optional feature for others to implement.

So for the physical devices add them to the room(Group) they should control as well as make a group for all light switches:

Group Group_LightSwitches

Each of these has at least one switch defined:

    	Contact Contact_BathroomL (Group_LightSwitches,Group_BathRoom)  {gpio="pin:24 debounce:0 activelow:yes"}//SW3
    	Contact Contact_BathroomR (Group_LightSwitches,Group_BathRoom)  {gpio="pin:25 debounce:0 activelow:yes"}//SW4

Presence sensor such as PIR motion sensor can be set up in the same way to control the lights.

I am only discussing alexa here, since that the system I am familiar with. Voice commands are in Openhab supported through the hue emulator or the skill. This means we need to create dummy items for each light mode, I have made an excel tool which can create all these items and corresponding rules for you or you can create them like this:

Switch Alexa_Livingroom_Reading "Reading" (Group_AlexaEmulator) [ "Lighting" ]
Switch Alexa_Livingroom_Dinner "Dinner" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_Tv "TV" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_Lounge "Relax" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_FirePlace "Fireplace" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_Cooking "Cooking" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_Kitchen "Kitchen" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_Party "Party" (Group_AlexaEmulator)  [ "Lighting" ]
Switch Alexa_Livingroom_OnOff "Living Room"  (Group_AlexaEmulator) [ "Lighting" ]

Note: Since the release of Alexa skill V3 we are supposed to be able to skip the virtual items and tag the groups directly instead, can someone please confirm this? If so we could make a rule and get the triggering item and then make a simple rule for voice command as well

Rules

Now the fun begins, we add some logic to our lights! So basically the idea is that you can add lights, change light modes and so on, but the rules always stay the same and does not need to be touched to get the system to work.

We will have 3 seperate rule files:

  1. LightControl.rules
  2. LightSwitches.rules
  3. AlexaEmulator.rules

LIGHT RULE

So we start out with the simple rule that that sends it ON/OFF then later we add the rule for dimming and changing colors(Only needed for those who has RGB lights, dimmable or those with wharm/cold white lights)

SCENE CHANGER

import org.eclipse.smarthome.model.script.ScriptServiceUtil
rule "Update lights"
when
    Member of Group_Scenes changed 
then
    logInfo("Notification", "Scene changed: " + triggeringItem.name.split("_").get(0))
    val roomName= triggeringItem.name.split("_").get(0) as String
    val group =ScriptServiceUtil.getItemRegistry.getItem("Group_"+roomName +"_Lights") as GroupItem
    val dimmer=ScriptServiceUtil.getItemRegistry.getItem(roomName +"_Dimmer") as DimmerItem

    if(group === null) {
        logError("admin", "Cannot find Item " + "Group_"+roomName +"_Lights")
        return;
    }

    
    if (triggeringItem.state ==0) {
        logInfo("Notification", "Group to set OFF: " + group.name)
        group.members.forEach[ i | i.sendCommand(OFF) ]
        if(dimmer !== null) {
            dimmer.postUpdate(OFF)
        }
    }
    else if (triggeringItem.state ==1) {
        logInfo("Notification", "Group to set ON: " + group.name)
        group.members.forEach[ i | i.sendCommand(ON) ]
        if(dimmer !== null) {
            dimmer.postUpdate(ON)
        }
    }
    else{
        val sceneGroup = ScriptServiceUtil.getItemRegistry.getItem( "Group_"+roomName +"_Lights_" +transform("MAP", roomName +".map", ""+triggeringItem.state) ) as GroupItem
        logInfo("Notification", "Scene to set: " + sceneGroup.name)
        if(sceneGroup === null) {
            logError("admin", "Cannot find Item " + "Group_"+roomName +"_Lights_" +transform("MAP", roomName +".map", ""+triggeringItem.state))
            return;
        }

        group.members.forEach[ i |
            if (i.getGroupNames.contains(sceneGroup.name)){
                i.sendCommand(ON)
            }
            else{
                i.sendCommand(OFF)
            }
        ]
    }
end

DIMMER CHANGE

Then we have the case for those who has dimmable lights which might want to like to dimm the lights:

rule "Update dimmers"
when
	Member of Group_Dimmers changed 
then
	logInfo("Notification", "Dimmer changed: " + triggeringItem.name.split("_").get(0))
	val roomName= triggeringItem.name.split("_").get(0) as String
	val group =ScriptServiceUtil.getItemRegistry.getItem("Group_"+roomName +"_Lights") as GroupItem
	val dimmer=ScriptServiceUtil.getItemRegistry.getItem(roomName +"_Dimmer") as DimmerItem

	if(group === null || dimmer === null) {
        logError("admin", "Cannot find Item " +roomName +"_Dimmer or Group_"+roomName +"_Lights")
        return;
    }

	group.members.forEach[ i | 
		// We need to grab active scene, transform it to group
		val scene =ScriptServiceUtil.getItemRegistry.getItem(roomName +"_Scene") as NumberItem 
		//Just a nifty touch to update UI
		//if (scene.state==0 ){
			//scene.postUpdate(1)
		//}
		val sceneGroup = ScriptServiceUtil.getItemRegistry.getItem( "Group_"+roomName +"_Lights" +transform("MAP", roomName+ ".map", ""+scene.state) ) as GroupItem
		// only dim lights if its a member of the selected group
		if (i.getGroupNames.contains(sceneGroup.name)){
			//Coloritems and dimmer items
			if(i instanceof ColorItem || i instanceof DimmerItem) {
				logInfo("Notification", "Icolor/dimmeritem: " + i.name)
				i.sendCommand(dimmer.state)	
			}
			//Switch item
			else if(i instanceof SwitchItem) {
				logInfo("Notification", "Iswitchitem: " + i.name)
				// So normal lights get switched off when dim value passes 50%
				if (dimmer.state<50){
					i.sendCommand(OFF)
				}
				//it could have been dimmed below 50% and then dimmed back up again
				else{
					i.sendCommand(ON)
				}
			}
			//In case someone added light group to non light item
			else{
				logError("admin", "item in wrong group " +i.name)
			}	
		}		
	]
end 

Color change

And finally we have those who would like to change colors of their lights depending on the mood, time of day etc…
Here its two method, one using a colorpicker other to use preselected colors. I am tempted to get away from the colorpicking, because I rarly use it. Also the preselected colors could be added to the scenes…

Color Picker

rule "Update color pickers"
when
	Member of Group_ColorPickers changed 
then
	logInfo("Notification", "Color changed: " + triggeringItem.name.split("_").get(0))
	val roomName= triggeringItem.name.split("_").get(0) as String
	val group =ScriptServiceUtil.getItemRegistry.getItem("Group_"+roomName +"_Lights") as GroupItem
	
	if(group === null ) {
        logError("admin", "Cannot find Item Group_"+roomName +"_Lights")
        return;
    }

	group.members.forEach[ i | 
		// We need to grab active scene, transform it to group
		val scene =ScriptServiceUtil.getItemRegistry.getItem(roomName +"_Scene") as NumberItem 
		//Just a nifty touch to update UI
		//if (scene.state==0 ){
			//scene.postUpdate(1)
		//}
		val sceneGroup = ScriptServiceUtil.getItemRegistry.getItem( "Group_"+roomName +"_Lights" +transform("MAP", roomName+ ".map", ""+scene.state) ) as GroupItem
		// only dim lights if its a member of the selected group
		if (i.getGroupNames.contains(sceneGroup.name)){
			//Coloritems
			if(i instanceof ColorItem) {
				logInfo("Notification", "Icolor/dimmeritem: " + i.name)
				i.sendCommand(triggeringItem.state.toString)	
			}
		}		
	]
end 

Mood Selector

rule "Update mood"
when
	Member of Group_Moods changed 
then
	logInfo("Notification", "Color changed: " + triggeringItem.name.split("_").get(0))
	val roomName= triggeringItem.name.split("_").get(0) as String
	val group =ScriptServiceUtil.getItemRegistry.getItem("Group_"+roomName +"_Lights") as GroupItem
	
	if(group === null ) {
        logError("admin", "Cannot find Item Group_"+roomName +"_Lights")
        return;
    }

	group.members.forEach[ i | 
		// We need to grab active scene, transform it to group
		val scene =ScriptServiceUtil.getItemRegistry.getItem(roomName +"_Scene") as NumberItem 
		//Just a nifty touch to update UI
		//if (scene.state==0 ){
			//scene.postUpdate(1)
		//}
		val sceneGroup = ScriptServiceUtil.getItemRegistry.getItem( "Group_"+roomName +"_Lights" +transform("MAP", roomName+ ".map", ""+scene.state) ) as GroupItem
		// only dim lights if its a member of the selected group
		if (i.getGroupNames.contains(sceneGroup.name)){
			//Coloritems
			if(i instanceof ColorItem) {
				logInfo("Notification", "Colortem: " + transform("MAP", "Moods.map", ""+triggeringItem.state))
				i.sendCommand(transform("MAP", "Moods.map", ""+triggeringItem.state))	
			}
		}		
	]
end 

Rules for physically devices

So lets move on to the lightSwitch(Add motion sensor as same as physically switch) … Note that I have commented out the option to have special scene called night being triggered when you press the switched if the time of day is night.

rule "Switch pressed"
when
    Member of Group_LightSwitches changed from OPEN to CLOSED 
then
	var roomName = triggeringItem.name.split("_").get(0) 
	logInfo("Light switch", "room is now " + roomName)

        // Well we need to be home if someone pressed a physical device
	//Presence_Home.sendCommand(ON)
	
	var sceneItem =ScriptServiceUtil.getItemRegistry.getItem(roomName +"_Scene") as NumberItem
	
	logInfo("Light switch", "Scene is now " + sceneItem.name)
	
if (sceneItem!==null){
        if(sceneItem.state == 0){
		    //if (vTimeOfDay.state.toString.contains("NIGHT")){
			   //sceneItem.sendCommand(2)
		    //}
		   	//else{
				sceneItem.sendCommand(1)
		   	//}
	    }
	    else {
			sceneItem.sendCommand(0)
	    }
	}
end

VOICE COMMANDS
And finally the voice command

rule "Switch pressed"
when
    Item Group_AlexaEmulator received command
then 
    Thread::sleep(5)
    Presence_Home.sendCommand(ON)
    val changedSwitch = Group_AlexaEmulator.members.filter[alexaItem | alexaItem.lastUpdate != null].sortBy[lastUpdate].last
    if(alexaItem == null) logWarn("FILE", "Something is amiss, no Item has a valid lastUpdate!")

    val sceneItemTemp = changedSwitch.name.toUpperCase().replace("ALEXA","SCENE") as String
    val sceneItem = Group_RoomScenes.members.findFirst[roomName | sceneItemTemp.contains(roomName.name.toUpperCase())] as NumberItem
    
// Extract the SceneMode from SceneItemTemp
val sceneMode = 
    logInfo("Light switch", "Scene is now " + sceneItem)
    if (sceneItem!=null){
        if(sceneItem.state == 0){
            if (vTimeOfDay.state.toString.contains("NIGHT")){
               sceneItem.sendCommand(2)
            }
            else{
                sceneItem.sendCommand(1)
            }
        }
        else {
            sceneItem.sendCommand(0)
        }
    }
end

Requirements

  • You need to have the Map transformation to get this to work
  • You need to install the Alexa skill to get voice command to work
  • Optionally have time of day rule

Summary

  1. Install your lights
  2. Create groups, Each room and each scene beyond default
  3. Create a default map.file and scene.map file if needed
  4. Copy SceneChanger.rule
  5. Copy Switch/MotionSensor.rule
  6. If dimmeable light, copy Dimmer.rule
  7. If RGB led, copy Color.rule and Mood.rule
  8. If voice command copy Alexa.rule
  9. If more fancy actions copy timeOfDay.rules

Common bugs

  1. UI does not get updated to ON if scene is OFF and you select dimmer to dimm lights to ON
  2. Changing colors does not set Dimmer value in UI
  3. No error checking if map files exist, plan to implement a default one if non exist
  4. Can not define mood colors for scene preset, would like to do this in map file somehow
  5. Openhab can not use map file in sitemaps
  6. Autogeneration of selection item for sitemap and virtual items for voice assistance based on javascript from map files does not exist

Further readings

You are always welcome to my github for a more in depth explanation and easier cloning of files:
https://github.com/skatun/LittleChina/wiki or more specific:

Related Design Patterns(Link to Rich’s DP for now)

Design Pattern How Used
Design Pattern: How to Structure a Rule Overall structure of the first complex rule follows this DP
Assocaited Items Gets the Alerted Item based on the Online Item’s name
Working with Groups in Rules Get the Items around the time the rule was triggered, loop through those Items
Time of Day Time of the day to alter lights
Heating How to control the temperature in your Taj Mahal
44 Likes

Another great posting! Keep them coming.

Great post.

Hi,

i really need some help here. I dont get the dependencies between the Groups. Where is the Link between a Scene_ Room, Type Number, which you use at the Panel and the rest?

Best Regards, Hasturo

The scene item is an instance of the Number type. Same as simple on/off lamp is an instance of a switch type and so on…

So Number Scene_BathRoom can be set to any integer number 0,1,2,3…15
Predefined is 0 which is off 1 is on… rest is custom…like if you want only group of ur lights to be on you can set that to 3, or if you want to dim ur lights to 50% that can be scene 4 and so on…
Or what do you mean?

Ok, but how is the relation to the Room and Scene Groups i created? I have a Room Group(Group_Livingroom). A Scene Group(Group_Livingroom_Night), a Item of Type Number with the Name Scene_Livingroom but no other Content?

Ive created a Panel Selector for the Scene Livingroom Item with the Selection 0=OFF, 1=ON,2=Night

I created the LightControl.rules File from the Example and modified to rgbLights.Apply(Group_Livingroom,Group_Livingroom_Night). Also i have to add “Item” to the when clause.

I dont understand how “Scene_Livingroom” is related to the “Group_Scene” clause in the Rule File.

Hi @Hasturo,
The tutorial were written for OH2.1 and before @rlkoshak recomended me to change to roomname_ whatever syntax. So these days I am rewriting it. Main thing is that now we can use Member of Group as rule trigger and use triggeringitem, as well as use split((triggeringItem,"_").get(0) to get the associated item: Design Pattern: Associated Items

However it should work as intended as listed above,

The idea is that you put your lights into groups, all lights in livingroom belongs to that group, however you might have a group called livingroom_relax which then is a subset of your lamps in the livingroom.

The scene item is just for the sitemap which then lets you select the correct scene, the idea is that to make it as generic as possible 0,1,2 is predefined, above you add ur relax scene and so on…

The lambda function(where all the magic happens) takes the room group, and the scene group. The third parameter is hsbValue, maybe @rlkoshak can come with some input here. The idea is that in many cases(like your relax mode) you would like to dim your light to 50% and turn the light more yellow. hsbType can store both these information with a single item, hence the third parameter. I am unsure if I can make it optional somehow, to simplify it for lights with just ON/OFF.

I expect to update this tutorial by easter! But feel free to use it as it is for now.

As far as I know lambdas do not support optional arguments. But even if it did, an optional parameter really means that some default value is used instead of one passed into the lambda. Given that’s the case, just pass in a default value for those places where one would not otherwise pass in the HSBType.

Great tutorial! Thank you!
I managed to get this working with limited OpenHab knowledge.

There are however some points that weren’t clear, would be nice if it was updated in the tutorial:

  1. I’ve spent alot of time to get the transform/map working. In the end I found that I had to install the transform/map binding.
  2. It wasn’t clear from the tutorial that I had to create a roomname.map file for each room. I also didn’t know how to do it.
  3. I’ve changed this in the code:
//val sceneGroup = ScriptServiceUtil.getItemRegistry.getItem( "Group_"+roomName +"_Lights_" +transform("MAP", "Livingroom.map", ""+triggeringItem.state) ) as GroupItem
val sceneGroup = ScriptServiceUtil.getItemRegistry.getItem( "Group_"+roomName +"_Lights_" +transform("MAP", roomName+".map", ""+triggeringItem.state) ) as GroupItem

transform(“MAP”, “Livingroom.map”, “”+triggeringItem.state) ==> transform(“MAP”, roomName+".map", “”+triggeringItem.state)

Hope this will help other people.

Thanks for the feedback, I am currently updating the tutorial from OH2.1 to OH2.5 and the only thing left to explain better is the map files, switches and voice commands. I hope to get to it this week. Let me know if you need any further assistance @RobbeM

Thanks for the tutorial! I’m currently trying to understand the concept and the rules. Hope I can adapt this to my small setup.
Could you please answer a few questions? Some things are not clear to me…

  • Do I have to create e.g. a GROUP_DIMMER group and add all Dimmer items to this group?
  • How do I assign different brightness levels to the lights included in a scene? Or different colors?
  • Did you finish the update for OH2.5? :slight_smile:

Regards,
Mirko

@mck Thanks for pointing out the missing info, tutorial is now updated. Yes you need to create those groups:) It should work without any problems at OH2.5

I would like to implement this in the map file, maybe @rlkoshak has an idea how this can best be implemented.

I can’t say I understand how the code above works. The best I can offer is Design Pattern: Associated Items or A simple scene management: finally a good use of scripts. If it were Scripted Automation you could use .Design Pattern: Using Item Metadata as an Alternative to Several DPs.

@skatun Thank you for the update! I’ll try to finish my setup in a few days…
@rlkoshak I think the second link sounds like a good approach for scenes, thank you. But first I have to understand the code in this design pattern :wink:

If you go with scripted automation, check out…

I have updated the info:

So for those who are used to phillips hue, IKEA, ewelink and so on should know that OH does not work in the same easy way. So if you buy a hue light bulb, you will plug it in, open the hue app, find the lamp bulb then give it a name, assign it to a room. Then you have a fully working lamp which you have dimmer widget for, a color change widget and a simple on off switch as well as it works with alexa.

So its unfortunately not so simple in Oh and hence this tutorial will help you to make the same functionality as the hue app, unfortunately you need to create the widget urself, but the logic behind the widget I have made for you.

It uses Associated items to grab the correct widget when you know which room you are in i.e to grab the dimmer item, scene item, color item when you know that the group is livingroom.

The code can probably be ported to scripts, but i haven’t looked into that since its been stable and does it jobs with rule DSL. However if someone wants to port and need some help please let me know:)

Hi,

I really like your concepts and start playing with your code. So first off all thank you for sharing your work.
Until now i managed to make the groups and scene changer code to work.
But I am stuck with the rules for physically devices. In that rule “Group_RoomScenes” is used but i dont see where this group is created or populated. If I understand it correctly this must be the “Group_Scenes” ? But even if I change that in the code the logs always show “[INFO ] [.smarthome.model.script.Light switch] - Scene is now null”
Does anybody has an example on how the goups are populated to make this work ?

Regards,
Nico

Updated the tutorial now, just add the room group and the lightswitch group to your item and it should work

Contact Contact_BathroomL (Group_LightSwitches,Group_BathRoom)  {gpio="pin:24 debounce:0 activelow:yes"}//SW3

I stole this from someone or a combination of ideas in these forums. But here’s my approach to different dim levels per scene.

I have 1 map file per scene: day, night, party, sleep…
example party.map:

kitchen=100
foyer=25
uphall=ON
// note you can mix switch ON/OFF values with dimmer numeric values
hallway=sun
// sun is a special case that I code for, described below

BUT, I sometimes prefer to access this list as a hashmap in the rules DSL, so I read the flat file into a hashmap array (on a windows computer) (search elsewhere in the forums for a linux example using cat instead of type)

val Map<String, String> party_dim = newHashMap
party_dim.clear
var lines = executeCommandLine("cmd.exe /c type C:\\openhab\\conf\\transform\\party.map",1000).split("\n")
lines.forEach[ line |
    if ( line.contains("=") && !line.contains("//") ){
	party_dim.put(line.split("=").get(0).trim,line.split("=").get(1).trim)
    }
]

My “night” scene is actually just all my outside lights that come on at dark and turn off when I go to bed.
So for that, it’s easy, when the sun sets:

nite_dim.forEach[sItem,sDim | sendCommand(sItem,sDim)]

or, when I go to bed or at a specific time like midnight, and I want to turn OFF the same lights:

nite_dim.forEach[sItem,sDim | sendCommand(sItem,"OFF")]

For the “day” scene, I include every light in the house in one scene/map (example day.map), but use groups to know which lights to turn on, like your example above. Once I have the name of a light I want to turn on, instead of just setting the light value to on, I look up the dim value from the appropriate map (depending on time of day / scene / trigger).

group.members.forEach[ i | 
    i.sendCommand(day_dim.get(i.name))   // using hashmap
//    i.sendCommand(transform("MAP", "day.map", i.name))	 // alternate form using map file
]

for added complexity, I have some lights that I change dim level based up how high the sun is in the sky (I like them brighter to match brighter outside, dimmer when darker outside). You can add your own formula, but mine looks like this:

val Number nMax=99
val Number nMin=55 // or use a MAP file that sets min/max per light
var String dimVal = day_dim.get(i.name)
val Number fmNoon = Math::abs((Noon.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli - now.millis  ) /1000/60 // minutes till/since noon 
val Number dayMins = (daylight.state as Number) / 2 // divide by 2 to get daylight minutes split between the morning or afternoon
var int sundim = (nMax - (fmNoon / dayMins) * (nMax-nMin)).intValue
if ( sundim < nMin ) { sundim = nMin }
if (dimVal == "sun") { dimVal = sundim.toString }
i.sendCommand(dimVal)