Lifx support out of the box

Thanks, I thought I'd read that the tiles section wasn't used, but things move fast around here :slight_smile:

I'll have to have a play with dashboards I suppose

Okay, new version merged into master on GitHub - robheyes/lifxcode

You'll need to update LIFX Master (first remove the existing app instance which will delete the devices) and the two drivers LIFX Discovery and LIFX Color - you can include LIFX Tile if you wish but it's pretty much empty. Once you've done that, create a new app instance of LIFX Master.

Changes:
LIFX Color:

  • Color Temperature support

LIFX Master UI:

  • Added Discover New Devices button
  • Now shows a message while scanning which indicates the current pass
  • Shows the count and names of known LIFX devices
1 Like

Awesome - it discovers all of my LIFX lights. No device yet for Day/Dusk or the Z Strips of course, but they do in fact show in discovery.

1 Like

I have Mini White, Mini Day and Dusk and Mini Plus (with infrared) bulbs here, just not hooked them up yet.

I want to make some more changes to the LIFX Color device handler before tackling those - still need to reliably fetch the current state before telling the bulb to change. Once that's working I'll start on the other drivers. Hoping to get that done this week sometime.

1 Like

New version is up there.

You'll definitely need to remove the app instance before updating the code. Check for any LIFX Color devices and remove them before rescanning - they should all be removed automatically, but you never know

  • Polling the bulbs once a minute so the current saved state of the bulb should mostly match up to the real state. This is simpler than my original plan to ask the bulb for its state before performing an update.

  • Discovery progress display is much nicer now, devices are shown by the group assigned within LIFX. If you have lots of bulbs this should make it easier to see if any are missing. Also had a bit of a play with styling UI elements :slight_smile:

3 Likes

Day & Dusk working well! Nice one! It appears the "set color time" (duration) is ignored for color temperature on both the D&D and Color bulbs.

I may add a separate setting for that

This just started happening and on top of it, it keeps turning on

Not sure what I'm seeing there - I don't use dashboards.

What kind of bulb is it? I've noticed some odd behaviour with the LIFX+ bulb that I've been meaning to investigate e.g. the bulb turning on unexpectedly - not seen the same with the ordinary Colour, White or Day and Dusk bulbs.

I was able to discover and add my bulbs, but the two white ones I have are saying that there's no LIFX White driver installed, even though it is. I noticed the code for the white says LIFX White Mono. Do I need to change something there to get them to work?

Edit - I deleted mono from the code and now it's working.

I'll add a proper LIFX White driver - the Mini White Mono is different since you can't change the colour temperature. Pretty sure that's the only difference. I won't be able to test it since I don't have any suitable devices.

Any chance you or anyone is working on something for calling LIFX scenes? I use WebCore heavily to call on some scenes and would love to have something similar here.
There was a Device Type in ST that i remember seeing that has this ability. I'll attempt to find it.

Edit: Found it

Scenes only work with the HTTP version of the protocol.

That code should work with some minor changes.

  1. Change the asynchttp_v1.put('responseHandler', params) on line 149 to
    asyncHttpPut('responseHandler', params)
  2. Remove the include on line 22
  3. Remove the tiles section lines 47-55

Let me know if those changes work, or otherwise.

Made the changes. Getting this error when trying to execute.

org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method activateScene() to invoke from this list:
public java.lang.Object user_driver_nunkistein_LIFX_Scene_233#activateScene(java.lang.Object)
public java.lang.Object user_driver_nunkistein_LIFX_Scene_233#activateScene(java.lang.Object, java.lang.Object) (activateScene)

groovy.lang.MissingMethodException: No signature of method: user_driver_nunkistein_LIFX_Scene_233.asyncHttpPut() is applicable for argument types: (java.lang.String, java.util.LinkedHashMap) values: [responseHandler, [uri:https://api.lifx.com, path:/v1/scenes/scene_id:eeb33653-7bf1-4681-9c95-a68b39d234ff/activate, ...]] on line 139 (push)

Try this

/**
 * LIFX Scene
 *
 * Copyright 2016 Eric Vitale
 *
 * Version 1.0.3 - Fix to support the new SmartThings app. (08/20/2018)
 * Version 1.0.2 - Added the switch capability in order to use this device with Alexa (10/3/2017)
 * Version 1.0.1 - Converted to Async API (06/21/2017)
 * Version 1.0.0 - Initial Release (05/31/2017)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */


metadata {
	definition (name: "LIFX Scene", namespace: "ericvitale", author: "ericvitale@gmail.com", vid: "generic-button") {
		capability "Actuator"
		//capability "Button"
		capability "Momentary"
		capability "Sensor"
        capability "Switch"
        
        command "activateScene"
	}
    
    preferences {
       	section("LIFX Configuration") {
            input "token", "text", title: "API Token", required: true
            input "scene", "text", title: "Scene UUID", required: true
            input "defaultTransition", "decimal", title: "Default Transition Time", required: true, defaultValue: 1.0
        }
       
       	section("Settings") {
	        input "logging", "enum", title: "Log Level", required: false, defaultValue: "INFO", options: ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"]
        }
    }

	
}

private determineLogLevel(data) {
    switch (data?.toUpperCase()) {
        case "TRACE":
            return 0
            break
        case "DEBUG":
            return 1
            break
        case "INFO":
            return 2
            break
        case "WARN":
            return 3
            break
        case "ERROR":
        	return 4
            break
        default:
            return 1
    }
}

def log(data, type) {
    data = "LIFX -- ${device.label} -- ${data ?: ''}"
        
    if (determineLogLevel(type) >= determineLogLevel(settings?.logging ?: "INFO")) {
        switch (type?.toUpperCase()) {
            case "TRACE":
                log.trace "${data}"
                break
            case "DEBUG":
                log.debug "${data}"
                break
            case "INFO":
                log.info "${data}"
                break
            case "WARN":
                log.warn "${data}"
                break
            case "ERROR":
                log.error "${data}"
                break
            default:
                log.error "LIFX -- ${device.label} -- Invalid Log Setting of ${type}."
                log.error "Message = ${data}."
        }
    }
}

def parse(String description) {
}

def push() {
	activateScene(scene, defaultTransition)
	sendEvent(name: "button", value: "pushed", isStateChange: true)
}

def on() {
	push()
}

def off() {
	log("Method off() not implemented, this is ok.", "INFO")
}

def activateScene(uuid, duration=defaultTransition) {
	//commandLIFX(uuid, "PUT", "duration=${duration}")
    def command = ["duration": duration]
    commandLIFX(uuid, "PUT", command)
}

////////////   BEGIN LIFX COMMANDS ///////////
def commandLIFX(light, method, commands) {
    def rawURL = "https://api.lifx.com"
    def rawPath = ""
    
    rawPath = "/v1/scenes/scene_id:" + light + "/activate"
    
    def rawHeaders = ["Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer ${token}"]
    
    def params = [
        uri: rawURL,
		path: rawPath,
		requestContentType: "application/json",
		headers: rawHeaders,
        body: commands
    ]
    
    log("Full URL/Path = ${rawPath}.", "DEBUG")
    log("rawHeaders = ${rawHeaders}.", "DEBUG")
    log("body = ${commands}.", "DEBUG")
    log.debug params
    asynchttpPut('responseHandler', params)
}

def responseHandler(response, data) {

    if(response.getStatus() == 200 || response.getStatus() == 207) {
		log("Scene Activated.", "DEBUG")    
    } else {
    	log("Scene failed to activate. LIFX returned ${response.getStatus()}.", "ERROR")
    }
}
////////////// END LIFX COMMANDS /////////////

Still have errors unfortunately.
org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method activateScene() to invoke from this list:
public java.lang.Object user_driver_ericvitale_LIFX_Scene_233#activateScene(java.lang.Object)
public java.lang.Object user_driver_ericvitale_LIFX_Scene_233#activateScene(java.lang.Object, java.lang.Object) (activateScene)

Can't tell you why. The above worked for me.
You are installing the code as a Driver and not an App correct?

Yup. Let me try deleting and re adding

That seems to have done it! Thanks for your help!

Anytime...keep in mind that this driver will not present itself as a button device in apps. It could be edited to do so, but will not work as is.