Lifx animations

Hi all,

I have a LIFX Z strip with 16 color zones. I like to use the Lifx app to choose a nice animation (for example, candlelight or color movement). I would like to control these animations via openHAB. Does anyone know how this could be achieved?

First I assumed the animations would be “rendered” by the app; but when I disconnect my phone, the animations keep running. So somehow they appear to be sent to the strip … However, the normal LIFX binding provides access to color & temperature per zone only. Is there any binding to get these commands from or set them to the strip?

Looking forward to your help!

Best,
Christoph

PS: I’m noob in terms of home automation. If I chose the wrong tags, please let me know.

Post scriptum:

I also tried to simply fade the strip off, as the button in the app does. But I want to stretch the fade duration to 10 instead of 1 seconds. How could one achieve this? My first approach was to define each of the 16 color zones as an individual item, and to fade them out separated, based on this Universaldimmer implementation.

Items:

// TODO: Deduplicate using reflection?
Color Strip_C_CouchBackgroundZone0 "Couchbeleuchtung (Zone 0)" <lightbulb> { channel="lifx:colormzlight:D073D52FE9DB:colorzone0" }
Color Strip_C_CouchBackgroundZone1 "Couchbeleuchtung (Zone 1)" <lightbulb> { channel="lifx:colormzlight:D073D52FE9DB:colorzone1" }
//...
Color Strip_C_CouchBackgroundZone15 "Couchbeleuchtung (Zone 15)" <lightbulb> { channel="lifx:colormzlight:D073D52FE9DB:colorzone15" }

String universaldimmer "Trigges a rule to fade in/out a light"

Rules:

rule "Button_C_FadeBackground"
when
	Item Button_C_FadeBackground changed
then
	val zones = (0..15).map [int i |
		ScriptServiceUtil.getItemRegistry.getItem('Strip_C_CouchBackgroundZone' + i)]
	zones.forEach [zone |
		universaldimmer.sendCommand('Color,0,10000,50,' + zone.name)]
end

Dimmer rules (widely copied from PeterK’s linked version; but use a mapping to allow for multiple timers):

import java.util.HashMap
import org.eclipse.smarthome.model.script.ScriptServiceUtil

val HashMap<GenericItem, Timer> timers = newHashMap()

// will dimm the item and report back the new brightness
var dimm = [ GenericItem myitem, String mytype, Number mytarget, Number mystep  |
	var int mybrightness = 0
	
	mybrightness = (if (mytype == "Color")
		(myitem.state as HSBType).getBrightness()
	else
		(myitem.state as DecimalType)).intValue
	
	if (mytarget.intValue > mybrightness) {
		mybrightness = mybrightness + mystep.intValue
		if (mybrightness > mytarget.intValue) mybrightness = mytarget.intValue
	} else {
		mybrightness = mybrightness - mystep.intValue
		if (mybrightness < mytarget.intValue) mybrightness = mytarget.intValue
	}
	
	myitem.sendCommand(mybrightness)
	
	mybrightness
]


rule "Universaldimmer"
when
	Item universaldimmer received command // expect e.g. Color,100,120000,12,col_E1_ES_Hue_Go_Farbe
then
	val buffer			= receivedCommand.toString.split(",")
	val mytype			= receivedCommand.toString.split(',').get(0)					// Color or Dimmer
	var int mytarget	= Integer::parseInt(buffer.get(1))								// where to go to 
	val int myfadetime	= Integer::parseInt(buffer.get(2))					 			// time for fading
	val int mystep		= Integer::parseInt(buffer.get(3))								// step for fading
	val myitem_name		= receivedCommand.toString.split(',').get(4)					// Item to handle
	val myitem			= ScriptServiceUtil.getItemRegistry.getItem(myitem_name)
	var int mytime		= 0
	
	logInfo("Universaldimmer", "Going to dim item " + myitem + "to target " + mytarget)
	
	if (timers.containsKey(myitem)) {
		logInfo("trying to cancel timer for " + myitem)
		timers.get(myitem).cancel()
		logInfo("canceled timer for " + myitem)
	}
	
	if		(mytarget > 100)	mytarget = 100
	else if (mytarget < 0)		mytarget = 0
	
	// fade
	var int mybrightness = dimm.apply(myitem, mytype, mytarget, mystep)
	
	mytime = Math::round(myfadetime * mystep /
		if (mybrightness > mytarget)
			mybrightness + mystep - mytarget
		else
			mytarget - (mybrightness + mystep))
	
	timers.put(myitem, createTimer(now.plusMillis(mytime)) [|
		// Check if finishes
		if (mybrightness != mytarget )  {
			// if not finished dim again 
			mybrightness = dimm.apply(myitem, mytype, mytarget, mystep)
			
			// rescheduling
			timers.get(myitem).reschedule(now.plusMillis(mytime))
			logInfo("dimmed " + myitem + " to " + myitem.state.toString)
		} else {
			timers.remove(myitem)
			myswitch.sendCommand(OFF)
			logInfo("Universaldimmer", "Completed dimming of " + myitem + "to target " + mytarget)
		}
	])
end

Unfortunately, this works very unreliably. I get tons of BasicIndexOutOfBoundsExceptions raised in XbaseInterpreter.evaluateArgumentExpressions and only few color zones are dimmed completely:

Any ideas what could I could have done wrong? What does this error mean? Anyway, I wonder whether the strip indeed does not provide a more specific interface …