Dynamische Szenen sind das Highlight smarter Glühbirnen. Wenn sie farbig sind, lassen sich eindrucksvolle Effekte erzeugen. Mit OpenHAB lässt sich dieser Effekt einfach hervorrufen, der sonst nur kompliziert über die Hue App zu starten ist.
Der Grundgedanke: OpenHAB startet eine Schleife, die unter bestimmten Bedingungen läuft und laufend Aktualisierungen an einer Gruppe oder einzelner Lampen vornimmt.
Da manchmal verschiedene Parameter an die Lampe übergeben werden sollen, wird dafür der Lampe ein Interface-Item hinzugefügt, welches im Zweifel notwendige Übersetzungen vornimmt (falls man eben nicht bei Hue bleiben will, Geräte anderer Hersteller hat oder sich mal was ändern sollte) und diese passend für die Lampe sendet, ohne dabei die bestehenden Items für die übrigen Eigenschaften anzusprechen. Letzteres ist notwendig, um die Szenen auch wieder unterbrechen zu können.
Um Szenen sowohl für Gruppen, als auch für einzelne Lampen innerhalb einer Gruppe, welche sich unterschiedlich verhalten sollen, Szenen erstellen zu können, müssen sowohl die Gruppen, als auch die Lampen angelegt werden.
1. Zigbee2MQTT
Verbinde deine Lampen mit zigbee2mqtt. Ich verwende dafür ein bestimmtes Namens-Konzept für die Verwendung von MQTT.
2. OpenHAB Things
Auch dazu habe ich bereits einen Artikel verfasst, welcher generell darauf eingeht, wie Hue mit zigbee2mqtt in OpenHAB eingebunden werden kann.
Dieser Konzept muss noch erweitert werden, sodass das Interface geschaffen werden kann. Außerdem müssen die einzelnen Lampen zumindest ein Interface erhalten. Ein Beispiel in meiner things/mqtt_hue.things :
Bridge mqtt:broker:myMosquitto "Mosquitto" [ host="XXXX", port=1883, secure=false, clientID="XXXX", username="XXXX", password="XXXX" ] {
}
Thing mqtt:topic:myMosquitto:HueBulbOfficeAlex "Büro Alex Licht" (mqtt:broker:myMosquitto) @ "Büro Alex" {
Channels:
Type switch : switch [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", transformationPattern="REGEX:(.*state.*(ON|OFF).*)∩JSONPATH:$.state", transformationPatternOut="JS:switch2zigbee2mqtt.js"]
Type dimmer : brightness [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", min=0, max=100, step=1, transformationPatternOut="JS:openhabDimmer2zigbeebridge.js", transformationPattern="JS:hueWhiteDimmer2openhab.js" ]
Type dimmer : color_temperature [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", min=0, max=100, step=1, transformationPatternOut="JS:openhabColorTemperature2zigbeebridge.js", transformationPattern="JS:hueWhiteAndColorTemperature2openhab.js" ]
Type color : color [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", transformationPatternOut="JS:openhabColor2zigbeebridge.js", transformationPattern="JS:hueWhiteAndColorColor2openhab.js" ]
Type string : interface [ commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", transformationPatternOut="JS:openhabJSON2zigbeebridgeHueInterface.js" ]
}
Thing mqtt:topic:myMosquitto:0x00178801XXXXXXXX "Büro Alex Licht 1" (mqtt:broker:myMosquitto) @ "Büro Alex" {
Channels:
Type string : interface [ commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/Hue/WC/E27/0x0017880XXXXXXXX/set", transformationPatternOut="JS:openhabJSON2zigbeebridgeHueInterface.js" ]
}
Thing mqtt:topic:myMosquitto:0x0017880XXXXXXXX "Büro Alex Licht 2" (mqtt:broker:myMosquitto) @ "Büro Alex" {
Channels:
Type string : interface [ commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/Hue/WC/E27/0x0017880XXXXXXXX/set", transformationPatternOut="JS:openhabJSON2zigbeebridgeHueInterface.js" ]
}
Thing mqtt:topic:myMosquitto:0x0017880XXXXXXXX "Büro Alex Licht 3" (mqtt:broker:myMosquitto) @ "Büro Alex" {
Channels:
Type string : interface [ commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/Hue/WC/E27/0x0017880XXXXXXXX/set", transformationPatternOut="JS:openhabJSON2zigbeebridgeHueInterface.js" ]
}
Hinweis zu OpenHAB 4:
OpenHAB 4 verwendet Java 17 statt Java 11 und die JS-Transformationen sind so nicht mehr verfügbar. Um sie wieder verwenden zu können, muss das Javascript-Binding installiert werden und die nachfolgenden Transformations mit *.script enden statt *.js.
Außerdem verändert sich die Thing-Syntax (nur in der Version 4.0.0, nicht mehr in Version 4.0.3) wie folgt:
Thing mqtt:topic:myMosquitto:HueBulbOfficeAlex "Büro Alex Licht" (mqtt:broker:myMosquitto) @ "Büro Alex" {
Channels:
Type switch : switch [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", transformationPattern="REGEX:(.*state.*(ON|OFF).*)∩JSONPATH:$.state", transformationPatternOut="SCRIPT:js:switch2zigbee2mqtt.script"]
Type dimmer : brightness [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", min=0, max=100, step=1, transformationPatternOut="SCRIPT:js:openhabDimmer2zigbeebridge.script", transformationPattern="SCRIPT:js:hueWhiteDimmer2openhab.script" ]
Type dimmer : color_temperature [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", min=0, max=100, step=1, transformationPatternOut="SCRIPT:js:openhabColorTemperature2zigbeebridge.script", transformationPattern="SCRIPT:js:hueWhiteAndColorTemperature2openhab.script" ]
Type color : color [ stateTopic="+/+/officeAlex/+/lightBulb/group", commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", transformationPatternOut="SCRIPT:js:openhabColor2zigbeebridge.script", transformationPattern="SCRIPT:js:hueWhiteAndColorColor2openhab.script" ]
Type string : interface [ commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/group/set", transformationPatternOut="SCRIPT:js:openhabJSON2zigbeebridgeHueInterface.script" ]
}
Thing mqtt:topic:myMosquitto:0x0017880XXXXXXXX "Büro Alex Licht 1" (mqtt:broker:myMosquitto) @ "Büro Alex" {
Channels:
Type string : interface [ commandTopic="zigbee2mqtt/ug/officeAlex/undef/lightBulb/Hue/WC/E27/0x0017880XXXXXXXX/set", transformationPatternOut="SCRIPT:js:openhabJSON2zigbeebridgeHueInterface.script" ]
}
3. OpenHAB Transformations
Die Transformations verwende ich wie in dem allgemeinen Beispiel beschrieben. Dazu kommt jetzt noch das transform/openhabJSON2zigbeebridgeHueInterface.js.
Das stellt nur sicher, dass bestimmte Konventionen erhalten bleiben und Übersetzungen stattfinden können. Möglicherweise unterstützt das Ziel keinen RGB-Befehl. So können alle Farbbefehle sorglos in einem Format (hier HSB) übergeben werden.
(function(input) {
var json_in = JSON.parse(input);
var json_out = {};
if(json_in.hasOwnProperty('state')){
json_out.state = json_in.state;
}
if(json_in.hasOwnProperty('color')){
if(json_in.color.hasOwnProperty('hsb')){
hsb = json_in.color.hsb.split(",");
json_in.color.h = hsb[0];
json_in.color.s = hsb[1];
json_in.color.b = hsb[2];
}
else if(json_in.color.hasOwnProperty('rgb')){
rgb = json_in.color.rgb.split(",");
json_in.color.r = rgb[0];
json_in.color.g = rgb[1];
json_in.color.b = rgb[2];
}
else if(json_in.color.hasOwnProperty('x') && json_in.color.hasOwnProperty('y')){
}
else if(json_in.color.hasOwnProperty('hex')){
}
else if(json_in.color.hasOwnProperty('hue') && json_in.color.hasOwnProperty('saturation')){
json_in.color.h = json_out.color.hue;
json_in.color.s = json_out.color.saturation;
}
if(json_in.color.hasOwnProperty('h') && json_in.color.hasOwnProperty('s')){
json_out.color = {hue:json_in.color.h,saturation:json_in.color.s};
if(json_in.color.hasOwnProperty('b')){
json_out.color = {
h:json_in.color.h,
s:json_in.color.s
};
json_out.brightness_percent = json_in.color.b;
}
else if(json_in.color.hasOwnProperty('v')){
json_out.color = {
h:json_in.color.h,
s:json_in.color.s,
v:json_in.color.v
};
}
else if(json_in.color.hasOwnProperty('l')){
json_out.color = {
h:json_in.color.h,
s:json_in.color.s,
l:json_in.color.l
};
}
}
else if(json_in.color.hasOwnProperty('r') && json_in.color.hasOwnProperty('g') && json_in.color.hasOwnProperty('b')){
var r = json_in.color.r;
var g = json_in.color.g;
var b = json_in.color.b;
var l = Math.max(r, g, b);
var s = l - Math.min(r, g, b);
var h = s ?
l === r ?
(g - b) / s :
l === g ?
2 + (b - r) / s : 4 + (r - g) / s
: 0;
json_out.color = {};
json_out.color.h = 60 * h < 0 ? 60 * h + 360 : 60 * h;
json_out.color.s = 100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0);
json_out.color.l = (100 * (2 * l - s)) / 2;
}
}
if(json_in.hasOwnProperty('brightness_percent')){
json_out.brightness_percent = json_in.brightness_percent;
}
if(json_in.hasOwnProperty('transition')){
json_out.transition = json_in.transition;
}
if(json_in.hasOwnProperty('color_temp')){
json_out.color_temp = Math.round(json_in.color_temp*3.47+153);
}
if(json_in.hasOwnProperty('effect')){
json_out.effect = json_in.effect;
}
if(json_out.brightness_percent == 0){
return JSON.stringify({state:'OFF'});
}
return JSON.stringify(json_out);
})(input)
4. OpenHAB Items
Für die Items müssen bestimmte Strukturen eingehalten werden, die ich bereits in einem anderen Artikel allgemein empfohlen habe. Alle Items eines Zigbee-Gruppen-Things werden wie folgt definiert und in einer Gruppe mit dem „ig“-Präfix (Item-Group) zusammengefasst. So weiß OpenHAB, welche Eigenschaften zusammengehören. Außerdem werden die Interfaces der Glühbirnen dieser Gruppe hinzugefügt. So weiß OpenHAB, welche Birnen dazugehören, wenn es sie einzeln ansprechen will.
Darüber hinaus gibt es für jede Gruppe einen Speed-Parameter, welcher bei 50% die Szene normal, bei 0% die Szene mit 1/10 Geschwindigkeit und bei 100% 10-fache Geschwindigkeit anwenden soll.
Ein Beispiel aus meiner items/hue.items:
Group igBueroAlexLight "Büro Alex" (sgOfficeAlex)["Lightbulb", "Group"]
Color BueroAlex_Farbe "Farbe" <ColorLight> (igBueroAlexLight,sgOfficeAlex,tgLSchange)["Control", "Light"] { autoupdate="false", channel="mqtt:topic:myMosquitto:HueBulbOfficeAlex:color", alexa="Color" }
Dimmer BueroAlex_Farbtemperatur "Farbtemperatur" <ColorLight> (igBueroAlexLight,tgLSinterrupt,sgOfficeAlex)["Control", "ColorTemperature"] { autoupdate="false", channel="mqtt:topic:myMosquitto:HueBulbOfficeAlex:color_temperature", alexa="ColorTemperature" }
Dimmer BueroAlex_Helligkeit "Licht" <DimmableLight> (igBueroAlexLight,tgLSinterrupt,sgOfficeAlex)["Control", "Brightness"] { autoupdate="false", channel="mqtt:topic:myMosquitto:HueBulbOfficeAlex:brightness", alexa="Brightness,PowerState" }
String BueroAlex_Lightshow "Lightshow" (igBueroAlexLight,tgLightshow,sgOfficeAlex)["Control", "DynamicScene"] { alexa="Mode" [capabilityNames="@Setting.Mode",supportedModes="Normal,Kerzenlicht,Polarlicht,Farbwechsel,Zufallsfarben,Gewitter,TV-Simulation"] }
Dimmer BueroAlex_LightshowSpeed "Geschwindigkeit" (igBueroAlexLight,sgOfficeAlex)["Control", "DynamicSpeed"] { alexa="RangeValue" [capabilityNames="Geschwindigkeit,Speed", supportedRange="0:100:10", presets="10=@Value.Low:@Value.Minimum,50=@Value.Medium:Normal,100=@Value.High:@Value.Maximum"] }
String BueroAlex_Interface "Interface" (igBueroAlexLight)["Control", "Interface"] { channel="mqtt:topic:myMosquitto:HueBulbOfficeAlex:interface" }
String x001788010b9b7b15_Interface (igBueroAlexLight)["Lightbulb", "Entity"] { channel="mqtt:topic:myMosquitto:0x001788010b9b7b15:interface" }
String x001788010b9b7c33_Interface (igBueroAlexLight)["Lightbulb", "Entity"] { channel="mqtt:topic:myMosquitto:0x001788010b9b7c33:interface" }
String x0017880104370a3d_Interface (igBueroAlexLight)["Lightbulb", "Entity"] { channel="mqtt:topic:myMosquitto:0x0017880104370a3d:interface" }
5. OpenHAB Rule
Jetzt müssen nur noch die Szenen definiert werden. Diese müssen nun so generisch wie möglich agieren. In meinem Beispiel in einer rules/dynamic-scenes.rules habe ich eine Vielzahl von Szenen bereits einmal vorgeschlagen. Zum triggeringItem wird die zugehörige ItemGroup ermittelt und daraus dann die notwendigen Members abgeleitet und angesprochen. Ändert sich eines der üblichen Steuer-Items wird die Szene unterbrochen.
import org.openhab.core.model.script.ScriptServiceUtil
import java.util.List
import java.util.Random
import java.util.Map
var Map<String, HSBType> colors = newHashMap
var Map<String, String> mode = newHashMap
val getSpeedFactorFromDimmer = [ DimmerItem speedItem |
//logInfo("Test", "speedItem: {}", speedItem)
if( speedItem.state != NULL ){
// x10 ... x1 ... x0.1
// 0 ... 50 ... 100
10 * Math.exp( -0.04605 * (speedItem.state as Number).intValue )
} else {
1.0
}
]
rule "Lightshow"
when
Member of tgLightshow changed
then
var double speed = 1.0
val Random rand = new Random()
//Get the Bulb-Group of the trigger
val String bulbGroupName = triggeringItem.getGroupNames.findFirst[ String groupName | groupName.startsWith("ig") ]
val GroupItem bulbGroup = ScriptServiceUtil.getItemRegistry.getItem(bulbGroupName) as GroupItem
//detect specific of the group
//val ColorItem colorItem = bulbGroup.members.findFirst[ a | a.tags.contains("Control") && a.tags.contains("Light")]
//val DimmerItem colorTemperatureItem = bulbGroup.members.findFirst[ a | a.tags.contains("Control") && a.tags.contains("ColorTemperature")]
val StringItem interfaceItem = bulbGroup.members.findFirst[ a | a.tags.contains("Control") && a.tags.contains("Interface")]
val DimmerItem speedItem = bulbGroup.members.findFirst[ a | a.tags.contains("Control") && a.tags.contains("DynamicSpeed")]
//break conditions
mode.put(bulbGroupName,triggeringItem.state.toString()) //um bei neuem Kommando nicht mit altem Thread weiterzumachen
//Lampen in Gruppe ansteuern
if(mode.get(bulbGroupName) == "Gewitter") {
createTimer(now, [ |
var String lightCmdStandby = '{"brightness_percent":40,"transition":0}' // Grundhelligkeit 0 - 254: 40
interfaceItem.sendCommand(lightCmdStandby)
while(mode.get(bulbGroupName) == "Gewitter" && triggeringItem.state.toString() == mode.get(bulbGroupName)) {
speed = getSpeedFactorFromDimmer.apply(speedItem)
var sleep = (1000 * speed).intValue // Schleifen-Durchlaufzeit
var float randomnumber = rand.nextFloat() // 0.0 - 1.0
if(randomnumber > 0.95){
var B = 100 // Helligkeit
interfaceItem.sendCommand('{"brightness_percent":' + B + ',"transition":0}')
Thread::sleep(10)
interfaceItem.sendCommand(lightCmdStandby)
}
else if(randomnumber > 0.9){
var B = 60 // Helligkeit
interfaceItem.sendCommand('{"brightness_percent":' + B + ',"transition":0}')
Thread::sleep(10)
interfaceItem.sendCommand(lightCmdStandby)
Thread::sleep(100)
interfaceItem.sendCommand('{"brightness_percent":' + B + ',"transition":0}')
Thread::sleep(10)
interfaceItem.sendCommand(lightCmdStandby)
}
//to break the loop immediately while waiting for the nex iteration too
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < sleep; i = i + 100){
Thread::sleep(100)
//sometimes the commands are not received in the correct order, so:
interfaceItem.sendCommand(lightCmdStandby)
}
}
])
}
else if(mode.get(bulbGroupName) == "Alarm") {
createTimer(now, [ |
var sleep = 1400
while(mode.get(bulbGroupName) == "Alarm" && triggeringItem.state.toString() == mode.get(bulbGroupName)){
//logInfo("Test", "triggeringItem1: {}", mode.get(bulbGroupName))
interfaceItem.sendCommand('{"color":{"hsb":"18,100,100"},"transition":1}') //red
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < sleep; i = i + 100){
Thread::sleep(100)
}
if(triggeringItem.state.toString() == mode.get(bulbGroupName)){
interfaceItem.sendCommand('{"color":{"hsb":"18,100,30"},"transition":1}')
}
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < sleep; i = i + 100){
Thread::sleep(100)
}
}
interfaceItem.sendCommand('{"brightness_percent":100}')
])
}
else if(mode.get(bulbGroupName) == "TV-Simulation") {
createTimer(now, [ |
while(mode.get(bulbGroupName) == "TV-Simulation" && triggeringItem.state.toString() == mode.get(bulbGroupName)) {
var led_bright = "255"
var led_half = "128"
var led_min = "60"
var List<String> transtions = newArrayList("0.0","0.0","0.0","0.0","0.0","0.0","0.4","0.4","1.0","2.0")
var List<String> pictures = newArrayList(
led_half + "," + led_half + "," + led_half,
led_min + "," + led_min + "," + led_min,
led_bright + "," + led_bright + "," + led_half,
led_bright + "," + led_half + "," + led_bright,
led_half + "," + led_bright + "," + led_bright,
led_bright + "," + led_half + "," + led_min,
led_half + "," + led_min + "," + led_bright,
led_min + "," + led_half + "," + led_bright,
led_half + "," + led_bright + "," + led_min,
led_bright + "," + led_min + "," + led_half,
led_min + "," + led_bright + "," + led_half,
led_half + "," + led_half + "," + led_bright,
led_half + "," + led_bright + "," + led_half,
led_bright + "," + led_half + "," + led_half,
led_half + "," + led_half + "," + led_min,
led_half + "," + led_min + "," + led_half,
led_min + "," + led_half + "," + led_half,
led_half + "," + led_min + "," + led_min,
led_min + "," + led_half + "," + led_min,
led_min + "," + led_min + "," + led_half
)
speed = getSpeedFactorFromDimmer.apply(speedItem)
var sleep = ((500 + Math::random * 5000.0) * speed).intValue // Wechselzeit: 500 - 5500ms
interfaceItem.sendCommand( '{"color":{"rgb":"' + pictures.get(rand.nextInt(pictures.size())) + '"},"brightness_percent":' + rand.nextInt(100).toString + ',"transition":' + transtions.get(rand.nextInt(transtions.size())) + '}' )
//to break the loop immediately while waiting for the nex iteration too
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < sleep; i = i + 100){
Thread::sleep(100)
}
}
])
}
//Lampen einzeln ansteuern
else{
bulbGroup.members.forEach[ StringItem entityInterfaceItem |
if(entityInterfaceItem.tags.contains("Lightbulb") && entityInterfaceItem.tags.contains("Entity")){
createTimer(now, [ |
while(mode.get(bulbGroupName) == "Kerzenlicht" && triggeringItem.state.toString() == mode.get(bulbGroupName)) {
var H = 18 + (Math::random * 20.0).intValue // Color: 18 - 38
var B = 50 + (Math::random * 50.0).intValue // Helligkeit: 50 - 100
speed = getSpeedFactorFromDimmer.apply(speedItem)
var sleep = ((750 + Math::random * 1250.0) * speed).intValue // Wechselzeit: 750 - 2000
entityInterfaceItem.sendCommand('{"color":{"hsb":"' + H.toString + ',100,' + B.toString + '"},"transition":0.1}')
//to break the loop immediately while waiting for the nex iteration too
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < sleep; i = i + 100){
Thread::sleep(100)
}
}
if(mode.get(bulbGroupName) == "Polarlicht"){
colors.put(bulbGroupName,new HSBType("210,100,100"))
}
while(mode.get(bulbGroupName) == "Polarlicht" && triggeringItem.state.toString() == mode.get(bulbGroupName)) {
var H = (colors.get(bulbGroupName).getHue().intValue() +310) % 360 + (Math::random * 100.0).intValue // Color: 160 - 260
var B = 60 + (Math::random * 40.0).intValue // Helligkeit: 60 - 100
speed = getSpeedFactorFromDimmer.apply(speedItem)
var sleep = ((1000.0 + Math::random * 5000.0) * speed).intValue // Wechselzeit: 1000 - 6000
entityInterfaceItem.sendCommand('{"color":{"hsb":"' + H.toString + ',100,' + B.toString + '"},"transition":' + (sleep/1000.0).floatValue + '}')
//to break the loop immediately while waiting for the nex iteration too
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < (sleep + 500); i = i + 100){
Thread::sleep(100)
}
}
while(mode.get(bulbGroupName) == "Zufallsfarben" && triggeringItem.state.toString() == mode.get(bulbGroupName)) {
var H = (Math::random * 360.0).intValue + 1 // Color: +5
speed = getSpeedFactorFromDimmer.apply(speedItem)
var sleep = ((750 + Math::random * 1250.0) * speed).intValue // Wechselzeit: 750 - 2000
entityInterfaceItem.sendCommand('{"color":{"hue":' + H.toString + ',"saturation":100},"transition":' + (sleep/1000.0).floatValue + '}')
//to break the loop immediately while waiting for the nex iteration too
for (var i = 0; triggeringItem.state.toString() == mode.get(bulbGroupName) && i < sleep; i = i + 100){
Thread::sleep(100)
}
}
])
Thread::sleep(100)
}
]
}
end
rule "Lightshow Change"
when
Member of tgLSchange received command
then
val String bulbGroupName = triggeringItem.getGroupNames.findFirst[ String groupName | groupName.startsWith("ig") ]
if(receivedCommand == OFF || receivedCommand == ON){
colors.put(bulbGroupName, HSBType::WHITE )
} else {
colors.put(bulbGroupName, (receivedCommand as HSBType) )
}
//logInfo("Test", "receivedCommand: {}", receivedCommand)
end
rule "Lightshow Interrupt"
when
Member of tgLSinterrupt received command
then
val String bulbGroupName = triggeringItem.getGroupNames.findFirst[ String groupName | groupName.startsWith("ig") ]
val GroupItem bulbGroup = ScriptServiceUtil.getItemRegistry.getItem(bulbGroupName) as GroupItem
val StringItem lightshowItem = bulbGroup.members.findFirst[ a | a.tags.contains("Control") && a.tags.contains("DynamicScene")]
lightshowItem.sendCommand("Normal")
end
rule "Set default values"
when
Time cron "0 0 * * * ?"
or Time cron "0 * * * * ?"
or System started
then {
var items = ScriptServiceUtil.getItemRegistry.getItemsByTag("DynamicScene")
items.forEach[ GenericItem item |
if(item.state == NULL || item.state == UNDEF){
item.sendCommand("Normal")
}
]
items = ScriptServiceUtil.getItemRegistry.getItemsByTag("DynamicSpeed")
items.forEach[ GenericItem item |
if(item.state == NULL || item.state == UNDEF){
item.sendCommand(50)
}
]
}
end
Pingback: Alarmanlage und Anwesenheitssimulator mit OpenHAB - Smarthome DIY - Heimautomatisierung selbst gemacht