The LIFX Classes tightly follow the LIFX Lan Protocol and are similar in structure to the Z-Wave classes.
Classes:
hubitat.lifx.commands.GetColor
byte[] getPayload()
String format()
hubitat.lifx.commands.SetColor
Integer hue
Integer saturation
Integer brightness
Integer kelvin
Long duration
byte[] getPayload()
String format()
hubitat.lifx.commands.LightState
Integer hue
Integer saturation
Integer brightness
Integer kelvin
Integer power
String label
byte[] getPayload()
String format()
hubitat.lifx.commands.GetLightPower
byte[] getPayload()
String format()
hubitat.lifx.commands.SetLightPower
Integer level
Integer duration
byte[] getPayload()
String format()
hubitat.lifx.commands.StateLightPower
Integer level
byte[] getPayload()
String format()
Every packet type specified in the LIFX Lan Protocol documentation has a class implemented. I will be documenting all of them, but if you need one sooner than the documentation is complete, please let me know which ones you need.
Sample Driver:
import hubitat.helper.ColorUtils
metadata {
definition (name: "LIFX Color", namespace: "hubitat", author: "Bryan Copeland") {
capability "SwitchLevel"
capability "ColorTemperature"
capability "ColorControl"
capability "Switch"
capability "Refresh"
capability "Actuator"
capability "SignalStrength"
capability "Configuration"
capability "ColorMode"
capability "Polling"
command "flash"
}
preferences {
input name: "pollInterval", type: "enum", title: "Poll Interval", defaultValue: 0, options: [0: "Disabled", 5: "5 Minutes", 10: "10 Minutes", 15: "15 Minutes", 30: "30 Minutes", 60: "1 Hour"], submitOnChange: true, width: 8
input name: "colorTransition", type: "enum", description: "", title: "Transition Time", defaultValue: 0, options: [0: "ASAP", 1: "1 second", 2: "2 seconds", 3: "3 seconds", 4: "4 seconds", 5: "5 seconds", 6: "6 seconds", 7: "7 seconds", 8: "8 seconds", 9: "9 seconds", 10: "10 seconds"]
input name: "flashRate", type: "enum", title: "Flash rate", options:[[750:"750ms"],[1000:"1s"],[2000:"2s"],[5000:"5s"]], defaultValue: 750
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
input name: "txtEnable", type: "bool", title: "Enable descriptionText logging", defaultValue: true
}
}
void logsOff(){
log.warn "debug logging disabled..."
device.updateSetting("logEnable",[value:"false",type:"bool"])
}
void configure() {
if (logEnable) log.debug "configure()"
List<String> cmds = []
cmds.add(new hubitat.lifx.commands.GetColor().format())
cmds.add(new hubitat.lifx.commands.GetHostFirmware().format())
cmds.add(new hubitat.lifx.commands.GetWifiFirmware().format())
cmds.add(new hubitat.lifx.commands.GetVersion().format())
sendToDevice(cmds)
refresh()
}
void updated() {
log.info "updated..."
log.warn "debug logging is: ${logEnable == true}"
log.warn "description logging is: ${txtEnable == true}"
unschedule()
if (pollInterval) {
switch (pollInterval.toInteger()) {
case 5:
runEvery5Minutes("poll")
break;
case 10:
runEvery10Minutes("poll")
break;
case 15:
runEvery15Minutes("poll")
break;
case 30:
runEvery30Minutes("poll")
break;
case 60:
runEvery60Minutes("poll")
break;
}
}
if (logEnable) runIn(1800,logsOff)
}
void parse(String description) {
if (logEnable) log.debug "parse:${description}"
hubitat.lifx.Command cmd = hubitat.lifx.Lifx.parse(description)
if (cmd) {
lifxEvent(cmd)
}
}
void eventProcess(Map evt) {
if (device.currentValue(evt.name).toString() != evt.value.toString()) {
sendEvent(evt)
if (txtEnable && evt.descriptionText) log.info evt.descriptionText
if (txtEnable && !evt.descriptionText) {
if (evt.unit == null) evt.unit = ""
log.info "${device.displayName} ${evt.name} is ${evt.value}${evt.unit}"
}
}
}
void lifxEvent(hubitat.lifx.Command cmd) {
if (logEnable) log.debug "Unhandled Command: ${cmd}"
}
void refresh() {
if (logEnable) log.debug "refresh()"
List<String> cmds = []
cmds.add(new hubitat.lifx.commands.GetColor().format())
cmds.add(new hubitat.lifx.commands.GetWifiInfo().format())
sendToDevice(cmds)
}
void privateRefresh() {
sendToDevice(new hubitat.lifx.commands.GetColor().format())
}
void poll() {
privateRefresh()
}
void flash() {
if (logEnable) log.debug "flash()"
String descriptionText = "${device.getDisplayName()} was set to flash with a rate of ${flashRate ?: 750} milliseconds"
if (txtEnable) log.info "${descriptionText}"
state.flashing = true
flashOn()
}
void flashOn() {
if (!state.flashing) return
runInMillis((flashRate ?: 750).toInteger(), flashOff)
sendToDevice(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: 0).format())
}
void flashOff() {
if (!state.flashing) return
runInMillis((flashRate ?: 750).toInteger(), flashOn)
sendToDevice(new hubitat.lifx.commands.SetLightPower(level: 0, duration: 0).format())
}
void on() {
state.flashing = false
if (logEnable) log.debug "on()"
Integer tt = 1000
if (colorTransition) tt = colorTransition.toInteger() * 1000
sendToDevice(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: tt).format())
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void off() {
state.flashing = false
if (logEnable) log.debug "off()"
Integer tt = 1000
if (colorTransition) tt = colorTransition.toInteger() * 1000
sendToDevice(new hubitat.lifx.commands.SetLightPower(level: 0, duration: tt).format())
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void setLevel(value, duration=null) {
state.flashing = false
List<String> cmds = []
if (logEnable) log.debug "setLevel(${value})"
Integer tt = 1000
if (duration != null) {
tt = duration * 1000
} else {
if (colorTransition) tt = colorTransition.toInteger() * 1000
}
cmds.add(new hubitat.lifx.commands.SetColor(hue: Math.round(device.currentValue("hue") * 655.35), saturation: Math.round(device.currentValue("saturation") * 655.35), brightness: Math.round(value * 655.35), kelvin: device.currentValue("colorTemperature"), duration: tt).format())
cmds.add(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: tt).format())
sendToDevice(cmds)
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void setHue(value) {
state.flashing = false
List<String> cmds = []
if (logEnable) log.debug "setHue(${value})"
Integer tt = 1000
if (colorTransition) tt = colorTransition.toInteger() * 1000
cmds.add(new hubitat.lifx.commands.SetColor(hue: Math.round(value * 655.35), saturation: Math.round(device.currentValue("saturation") * 655.35), brightness: Math.round(device.currentValue("level") * 655.35), kelvin: device.currentValue("colorTemperature"), duration: tt).format())
cmds.add(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: tt).format())
sendToDevice(cmds)
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void setSaturation(value) {
state.flashing = false
List<String> cmds = []
if (logEnable) log.debug "setSaturation(${value})"
Integer tt = 1000
if (colorTransition) tt = colorTransition.toInteger() * 1000
cmds.add(new hubitat.lifx.commands.SetColor(hue: Math.round(device.currentValue("hue") * 655.35), saturation: Math.round(value * 655.35), brightness: Math.round(device.currentValue("level") * 655.35), kelvin: device.currentValue("colorTemperature"), duration: tt).format())
cmds.add(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: tt).format())
sendToDevice(cmds)
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void setColor(value) {
state.flashing = false
List<String> cmds = []
if (logEnable) log.debug "setColor(${value})"
Integer tt = 1000
if (colorTransition) tt = colorTransition.toInteger() * 1000
if (value.hue == null || value.saturation == null) return
if (value.level == null) value.level=100
cmds.add(new hubitat.lifx.commands.SetColor(hue: Math.round(value.hue * 655.35), saturation: Math.round(value.saturation * 655.35), brightness: Math.round(value.level * 655.35), kelvin: device.currentValue("colorTemperature"), duration: tt).format())
cmds.add(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: tt).format())
sendToDevice(cmds)
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void setColorTemperature(Number temp, Number level=null, Number transitionTime=null) {
state.flashing = false
List<String> cmds = []
Integer tt = 1000
if (transitionTime == null) {
if (colorTransition) tt = colorTransition.toInteger() * 1000
} else {
tt = transitionTime * 1000
}
if (logEnable) log.debug "setColorTemperature(${temp}, ${level}, ${transitionTime})"
if (level == null) level = device.currentValue("level")
cmds.add(new hubitat.lifx.commands.SetColor(hue: Math.round(device.currentValue("hue") * 655.35), saturation: 0, brightness: Math.round(level * 655.35), kelvin: temp, duration: tt).format())
cmds.add(new hubitat.lifx.commands.SetLightPower(level: 65535, duration: tt).format())
sendToDevice(cmds)
runIn((Math.round(tt/1000) + 1), privateRefresh)
}
void lifxEvent(hubitat.lifx.commands.StateWifiFirmware cmd) {
if (logEnable) log.debug "${cmd}"
Double fwVersion = cmd.versionMajor + (cmd.versionMinor / 100)
device.updateDataValue("wifiFirmware", "${fwVersion}")
}
void lifxEvent(hubitat.lifx.commands.StateHostFirmware cmd) {
if (logEnable) log.debug "${cmd}"
Double fwVersion = cmd.versionMajor + (cmd.versionMinor / 100)
device.updateDataValue("hostFirmware", "${fwVersion}")
}
void lifxEvent(hubitat.lifx.commands.StateVersion cmd) {
if (logEnable) log.debug "${cmd}"
device.updateDataValue("model: ", "${cmd.product}")
Map<String, Object> lifxProduct = hubitat.helper.Lifx.lifxProducts[cmd.product]
if (lifxProduct != null) {
device.updateDataValue("modelName", lifxProduct.name)
}
}
void lifxEvent(hubitat.lifx.commands.StateWifiInfo cmd) {
Integer rssi = Math.floor(10 * Math.log10(cmd.signal.doubleValue()) + 0.5).toInteger()
eventProcess(name: "rssi", value: rssi, unit: "dBm")
}
void lifxEvent(hubitat.lifx.commands.LightState cmd) {
if (logEnable) log.debug cmd.toString()
if (cmd.saturation > 0) {
eventProcess(name: "colorMode", value: "RGB")
setGenericName(Math.round(cmd.hue / 655.35))
} else {
eventProcess(name: "colorMode", value: "CT")
setGenericTempName(cmd.kelvin)
}
eventProcess(name: "hue", value: Math.round(cmd.hue / 655.35))
eventProcess(name: "saturation", value: Math.round(cmd.saturation / 655.35), unit: "%")
eventProcess(name: "colorTemperature", value: cmd.kelvin, unit: "K")
eventProcess(name: "level", value: Math.round(cmd.brightness / 655.35), unit: "%")
if (cmd.power > 0) {
eventProcess(name: "switch", value: "on")
} else {
eventProcess(name: "switch", value: "off")
}
eventProcess(name: "color", value: ColorUtils.rgbToHEX(ColorUtils.hsvToRGB([Math.round(cmd.hue / 655.35), Math.round(cmd.saturation / 655.35), Math.round(cmd.brightness / 655.35)])))
}
private void setGenericTempName(temp){
if (!temp) return
String genericName
int value = temp.toInteger()
if (value <= 2000) genericName = "Sodium"
else if (value <= 2100) genericName = "Starlight"
else if (value < 2400) genericName = "Sunrise"
else if (value < 2800) genericName = "Incandescent"
else if (value < 3300) genericName = "Soft White"
else if (value < 3500) genericName = "Warm White"
else if (value < 4150) genericName = "Moonlight"
else if (value <= 5000) genericName = "Horizon"
else if (value < 5500) genericName = "Daylight"
else if (value < 6000) genericName = "Electronic"
else if (value <= 6500) genericName = "Skylight"
else if (value < 20000) genericName = "Polar"
String descriptionText = "${device.getDisplayName()} color is ${genericName}"
eventProcess(name: "colorName", value: genericName ,descriptionText: descriptionText)
}
private void setGenericName(hue){
String colorName
hue = hue.toInteger()
hue = (hue * 3.6)
switch (hue.toInteger()){
case 0..15: colorName = "Red"
break
case 16..45: colorName = "Orange"
break
case 46..75: colorName = "Yellow"
break
case 76..105: colorName = "Chartreuse"
break
case 106..135: colorName = "Green"
break
case 136..165: colorName = "Spring"
break
case 166..195: colorName = "Cyan"
break
case 196..225: colorName = "Azure"
break
case 226..255: colorName = "Blue"
break
case 256..285: colorName = "Violet"
break
case 286..315: colorName = "Magenta"
break
case 316..345: colorName = "Rose"
break
case 346..360: colorName = "Red"
break
}
String descriptionText = "${device.getDisplayName()} color is ${colorName}"
eventProcess(name: "colorName", value: colorName ,descriptionText: descriptionText)
}
void sendToDevice(List<String> cmds, Long delay = 300) {
sendHubCommand(new hubitat.device.HubMultiAction(commands(cmds, delay), hubitat.device.Protocol.LIFX))
}
void sendToDevice(String cmd, Long delay = 300) {
sendHubCommand(new hubitat.device.HubAction(cmd, hubitat.device.Protocol.LIFX))
}
List<String> commands(List<String> cmds, Long delay = 300) {
return delayBetween(cmds.collect { it }, delay)
}