Startseite » Dynamische Szenen mit Zigbee2MQTT, OpenHAB, Hue und anderen Leuchtmitteln

Dynamische Szenen mit Zigbee2MQTT, OpenHAB, Hue und anderen Leuchtmitteln

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

1 Kommentar zu „Dynamische Szenen mit Zigbee2MQTT, OpenHAB, Hue und anderen Leuchtmitteln“

  1. Pingback: Alarmanlage und Anwesenheitssimulator mit OpenHAB - Smarthome DIY - Heimautomatisierung selbst gemacht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..

Translate »