As soon as you have color lights, you want to start doing fancy things with them. Two problems you run into:
- Switched lights are in the way when you want to light the room with fancy colors
- Switched lights stick out like a sore thumb when you want to dim the brightness
So I created rules to adjust switched lights to whatever is going on in the room. The idea was to give them a dummy color channel, so that they could receive the same commands as all the other lights, and then adjust their on/off state accordingly. I also wanted this to work vice-versa, so that their current status would be reflected in the color channel as well, so that for automation’s sake, they could be treated as color lights alltogether, no need to make different logic for different lights.
NOTE 14/11/2018: There is updated code in post #6!
Here’s a dummy color channel, as an example:
Color WandschalterSchlafzimmer_Deckenlicht_Color "Deckenlicht" (gSDeckenlicht, gSwitchToColor, gColorSZ) ["Lighting"]
As one can see, I have tagged this with “Lighting”, so that Alexa will control the light through this dummy channel and not the actual (Zigbee binding) channel. The name of the actual switch channel has to end with “_SwitchOnoff”. It also should be in the group gSwitchtoColor.
And here’s the rules, one for switching according to the color commands, and one for reflecting the switch states back to the color channel:
var onLock = false
var offLock = false
var Timer lockTimer = null
rule "Color to Switch translator"
//Allow Switched lamps to be switched along a color command to other lights
when
Item SchranklichtSchlafzimmer_Color changed or
Item WandschalterSchlafzimmer_Deckenlicht_Color changed
then
//construct corresponding switch item
var itemName = triggeringItem.getName().replace("_Color", "_SwitchOnoff")
var lampSwitch = gSwitchToColor.members.filter[lamp|lamp.name == itemName].head
if ( lampSwitch !== null) {
//convert Color to switch command (low brightness or solid color switches off)
if ((( (triggeringItem.state as HSBType).getBrightness().intValue() < 50 ) ||
( (triggeringItem.state as HSBType).getSaturation().intValue() > 50 ) ) &&
(lampSwitch.state == ON ) ){
if (!offLock) {
onLock = true //prevent rule from bouncing on itself
sendCommand( lampSwitch, OFF )
logInfo( itemName, "OFF")
lockTimer = createTimer(now.plusMillis(500) , [ | onLock = false])
}
}
else if ((( (triggeringItem.state as HSBType).getBrightness().intValue() >= 50 ) &&
( (triggeringItem.state as HSBType).getSaturation().intValue() <= 50 ) ) &&
(lampSwitch.state == OFF ) ){
if (!onLock) {
offLock = true //prevent rule from bouncing on itself
sendCommand( lampSwitch, ON )
logInfo( itemName, "ON")
lockTimer = createTimer(now.plusMillis(500) , [ | offLock = false])
}
}
}
else {
logWarn("SwitchtoColor", "The switch item to adjust color state " + itemName + " could not be found")
}
end
rule "Switch to Color translator"
//Reflect switched lamps state in their dummy color channel
when
Item SchranklichtSchlafzimmer_SwitchOnoff changed or
Item WandschalterSchlafzimmer_Deckenlicht_SwitchOnoff changed
then
//construct corresponding color item
var itemName = triggeringItem.getName().replace("_SwitchOnoff", "_Color")
var lampColor = gSwitchToColor.members.filter[lamp|lamp.name == itemName].head
if ( lampColor !== null) {
//convert Color to switch command (low brightness or solid color switches off)
logInfo(itemName,"Switch command converted to color value")
if ((triggeringItem.state == ON) ) {
sendCommand( lampColor, "45,40,99" )
}
else if ((triggeringItem.state == OFF) ) {
sendCommand( lampColor, "45,40,1" )
}
}
else {
logWarn("SwitchtoColor", "The color item to adjust switch state " + itemName + " could not be found")
}
end
Notes:
- I think with OH 2.4 it should become possible to get a single item “triggeringItem” even when the rule trigger is defined as a group. It will then be possible that in stead of defining the individual lamp items, you can just define a single group as the trigger for a rule (and still get the correct triggeringItem later on).
- Without reflecting back the status into the color channel (the second rule), the switching should still work, and you wouldn’t necessarily need the locks to preventing both rules to keep on triggering each other. However, the locks are also useful to prevent possible bouncing between this and other rules (example below).
- The reflected HSB values are such because I always try to keep lights in a warm white hue, and I am not using 0 and 100 so that I can see that the values were set by this rule.
- These rules do not yet cater for white dimmable lights, but it should be close enough for people to figure it out for themselves.
As an example of another rule that uses the locks to not to create a mess, a little bonus rule below. I have one light that is directly switched by a Ubisys S2 component (according to a conventional wall switch), and switch all other lights according to that light.
rule "Bedroom lights on according wall switch"
//Switch lights according to ceiling light
when
Item WandschalterSchlafzimmer_Deckenlicht_Color changed
then
if (!onLock && !offLock) { //make sure the change was not triggered by a color command
if ((WandschalterSchlafzimmer_Deckenlicht_Color.state as HSBType).getBrightness().intValue() >= 99) {
logInfo("Deckenlicht","Deckenlicht an mit Schalter")
if (Sun_Daylight == ON) {
gColorSZ.sendCommand("45,10,100")
}
else{
gColorSZ.sendCommand("45,40,50")
}
}
else if ((WandschalterSchlafzimmer_Deckenlicht_Color.state as HSBType).getBrightness().intValue() <= 1) {
logInfo("Deckenlicht","Deckenlicht aus")
gColorSZ.sendCommand("45,40,0")
}
}
end
Sun_Daylight is a dummy switch which is managed by a rule using the Astro binding to reflect whether there is daylight.