[OBSOLETE] LIFX Group of Groups

##LIFX Group of Groups (LGoG) provides the following capabilities through a device handler and an optional companion application (LIFX Sync):

Control a Group of LIFX Bulbs as a Single Device

(Note: LGoG does not sync your bulbs, it communicates directly with LIFX to control them as a single group. This way you will see all of the lights change at the same time, not one by one. )This capability is the primary reason I created LGoG. By default, using the LIFX (Connect) app that comes with SmartThings all of your light bulbs will get added to SmartThings. If you have 1 bulb, this is likely just fine for you, however if you have many bulb, specifically bulbs you would like to control as a single device you are out of luck. Before LGoG you had to either download a SmartApp that would watch your bulbs and update the status of some of your bulbs based on the status of a master bulb or control them through CoRE (which you can still do with LGoG, however you are stuck selecting multiple lightbulbs. Specifically how LGoG works is…

  1. Create the groups of lights in your LIFX app. Yea, I know you can’t have a bulb in multiple groups, but LGoG fixes that!
  2. Generate and API key, instructions below.
  3. Install the LGoG device handler.
  4. Configure the device, add a single group or multiple groups.

Why is this better? It is more efficient. Let’s say you have a kitchen which as 10 LIFX bulbs in it. If you use the standard bulbs that ST gives you, if you want to turn them all on you have to turn 10 bulbs on. Weather you do it one by one manually, use a syncing app, or use CoRE, you are sending 10 commands to LIFX and then 10 commands back to your bulbs. Using LGoG you send a single command to LIFX and they in turn send a single command to your bulbs. You will find that your groups will become much more reliable.

Control Multiple Groups of LIFX Bulbs as a Single Device

Yes, that is right. You can create multiple groups within the LIFX app and configure this device handler to control multiple groups as a single device. For example, I have bulbs in my kitchen, dining room, foyer, & family room. I have 1 device setup in SmartThings to control each of these (so 4 in total) and another device configured to control all of these groups as a single device called “First Floor Lights”.

Create Multiple Devices for the Same Group or Set of Groups

This comes in handy when you want quick access to all of your light groups in a single “Room” within the SmartThings app, but also want to have the same device inside of the specific Room. For example I have my device “Kitchen Lights” in my Kitchen room and I have another device called “Kitchen Lights 2” which controls the same lights.

Sync the Status of your Groups

As you can create multiple groups that control a device, you can now use the LIFX Sync companion application. Once configured, if you turn on “Kitchen Lights” it will automatically update the status of the “Kitchen Lights 2” device and vis versa. You can also setup the sync to be either one way or two way. Must have companion app installed

  1. 2-way Example: When “Group A” is changed (switch or level) “Group B” is updated. “Group B” is changed then “Group A” is updated to match “Group B”.

  2. 1-way Example: When “Group D” (Group D contains Group A, B, and C) is changed (switch or level), “Group C” is updated. When “Group C” is changed, “Group D” does not get updated.

Scheduled Sync with LIFX

Schedule the DH to double check the light status via lifx and update the ST status accordingly.

Power Usage Reporting

Report power usage based on the number of bulbs in a group. This was all based on real world testing as accurate as I could get.

How is this different than @AdamV device handler for LIFX Group?

1 - This creates a virtual device for groups of LIFX groups, not just a single group.
2 - Accepts your api token as preference, not in the code.
3 - Allows you to enter groups using preferences by name, not id using the device id.
4 - I’ve also updated the UI a bit.

However, the inspiration for this came from @AdamV.

3 Likes

Thanks a ton - trying this now. Looking to combine it with the Button Control app and a Minimote

Edit - so how to install this? I copied in the code as a new device handler and then added a new device using the new device type.

Edit 2: Okay I found the preferences - but what do I use for the Device Network ID field? I am trying it with just a 1 in there (as it is required field) and when I try to trigger from the app I get this error

groovy.lang.MissingMethodException: No signature of method: script1467814777236349926205.$() is applicable for argument types: (script1467814777236349926205$_log_closure2) values: [script1467814777236349926205$_log_closure2@70f05ade]
Possible solutions: on(), is(java.lang.Object), now(), off(), run(), any()

Thanks :slight_smile:

1 Like

You don’t need a special network ID. Just make one up, but I think it has to be unique. I usually do my initials and a 9 digit number. Think “WM000000007”.

In the preferences, you need to enter your API token you get from LIFX. The README has this instruction. Then you just enter the group name (case-sensitive).

I believe I have it configured correctly but am getting the following error:

groovy.lang.MissingMethodException: No signature of method: script1467814855678349926205.$() is applicable for argument types: (script1467814855678349926205$_log_closure2) values: [script1467814855678349926205$_log_closure2@42dc79e9]
Possible solutions: on(), is(java.lang.Object), now(), off(), run(), any()

The group names are case sensitive. Do your match exactly as they do in the LIFX app?

I updated the code to add some better exception handling. I am not sure that problem you are having is related to the names of the groups or the api token. Can you send screenshot of your preferences page? Including the scenes if you are using them? Also, what are you pressing when you get that error?

I was originally just pressing the power button on the Android app. I pulled in your new code and it seems to have fixed the problem. Now, I seem to get this error multiple times - but I think everything is working like one would expect.

 java.lang.NullPointerException: Cannot invoke method toUpperCase() on null object

Ok, I can fix that issue with ?.toUpperCase(). Try updating now.

That seemed to have fixed the problem. Now I can get the lights to turn on. However, something strange is happening. I am using the app “Button Controller - Enhanced Lighting”. The lights will come on and in their proper color, but then one second later they shift to a different hue. If I choose the same bulbs individually, the problem goes away. This happens with both your handler and AdamV’s version. I see in the log that a setColor command is issued after setColorTemperature. For some reason the log comes up in reverse order.

 6:27:11 PM: debug Response: [results:[[id:d073d512b640, status:ok, label:LivingRm_LFlrLamp1], [id:d073d513364e, status:ok, label:LivingRm_RFlLamp1], [id:d073d51346db, status:ok, label:LivingRm_RFlrLamp2], [id:d073d5135055, status:ok, label:LivingRm_LFlrLamp2], [id:d073d51388a6, status:ok, label:LivingRm_CXLamp]]]
 6:27:09 PM: debug PUT Http Params ([uri:https://api.lifx.com, path:/v1/lights/group_id:b1de7b5cc3e46d69c57769c78dc75ae0/state.json, headers:[Content-Type:application/x-www-form-urlencoded, Authorization:Bearer ********], body:[color:saturation:0.56+hue:82.8, power:on]])
 6:27:09 PM: **debug setColor: [hue:23, saturation:56, level:100, colorTemperature:3200]**
 6:27:08 PM: debug Results: [id:d073d512b640, status:ok, label:LivingRm_LFlrLamp1]
 6:27:08 PM: debug Response: [results:[[id:d073d512b640, status:ok, label:LivingRm_LFlrLamp1], [id:d073d513364e, status:ok, label:LivingRm_RFlLamp1], [id:d073d51346db, status:ok, label:LivingRm_RFlrLamp2], [id:d073d5135055, status:ok, label:LivingRm_LFlrLamp2], [id:d073d51388a6, status:ok, label:LivingRm_CXLamp]]]
 6:27:07 PM: debug PUT Http Params ([uri:https://api.lifx.com, path:/v1/lights/group_id:b1de7b5cc3e46d69c57769c78dc75ae0/state.json, headers:[Content-Type:application/x-www-form-urlencoded, Authorization:Bearer ********], body:[brightness:1.0, power:on]])
 6:27:07 PM: debug generic name is : Warm White
 6:27:07 PM: debug Results: [id:d073d512b640, status:ok, label:LivingRm_LFlrLamp1]
 6:27:07 PM: debug Response: [results:[[id:d073d512b640, status:ok, label:LivingRm_LFlrLamp1], [id:d073d513364e, status:ok, label:LivingRm_RFlLamp1], [id:d073d51346db, status:ok, label:LivingRm_RFlrLamp2], [id:d073d5135055, status:ok, label:LivingRm_LFlrLamp2], [id:d073d51388a6, status:ok, label:LivingRm_CXLamp]]]
 6:27:05 PM: debug PUT Http Params ([uri:https://api.lifx.com, path:/v1/lights/group_id:b1de7b5cc3e46d69c57769c78dc75ae0/state.json, headers:[Content-Type:application/x-www-form-urlencoded, Authorization:Bearer ********], body:[color:kelvin:3200, power:on]])
 6:27:05 PM: debug Executing 'setColorTemperature' to 3200

Those logs are not from my device handler. Mine should be prefixed with "LIFXGoG – ". Can you switch it over to mine? BTW - Are you using the LIFX Groups or the LIFX Group of Groups? The LIFX Groups handler in my GitHub is just a copy of @AdamV handler with some small fixes. LIFX Group of Groups should work fine. Make sure under Type is stays “LIFX Group of Groups”.

yes sir, that is what I have running:

I believe that output is from the button app. Here is the debug from yours:

Can you show me just the logs from the on event from the button controller? Are you sure it isn’t doing anything to the color? I don’t seem to have the same issue.

Based on your logs, something is calling the setColorTemperature(), then calling setLevel(), and then setColor(). Those are the methods that are executed when something external to the handler (or the device UI) makes a change. There is nothing in the code that would make those three calls happen without some external input.

This is what I figured. However, this only appears when targeting the LIFX Group, and not individual bulbs. I’ve engaged the developer on the Button Control app to see if he might have an idea why the setColor() is being called.

I found the code for the Button Control App. It looks like there is a method…

def executeHandlers(buttonNumber)

that looks to see if you configured your lights

def lightsConfigured = settings["lights_${buttonNumber}"]

if they are not configured it calls the method…

def setLight(light, lightName, lightCapabilities, buttonNumber, lightId, toggle)

which…

def rgbValue = huesatToRGB(hueColor, saturation) def hexValue = rgbToHex(r: rgbValue[0], g: rgbValue[1], b: rgbValue[2]) def colorValue if (colorTemperature != null) { // Changing the amount of data that is sent because of hue device handler change // colorValue = [alpha: 1.0, red: rgbValue[0], green: rgbValue[1], blue: rgbValue[2], hex: hexValue, hue: hueColor as double, saturation: saturation, level: level as Integer ?: 100, colorTemperature: colorTemperature] colorValue = [hue: hueColor as Integer, saturation: saturation, level: level as Integer ?: 100, colorTemperature: colorTemperature] try{ delayBetween(light.setColorTemperature(colorTemperature), light.setLevel(level as Integer ?: 100), 1000) }catch(e){ light.setColor(colorValue) }

This might be what is doing it. I’m not sure if it is a bug or an issue with how the lights are configured in the app.

EDIT: Not the case. You know, too, I found in the code for that app that the color settings might actually be more applicable to the Hue system. In my example for the code above, I was using the softwhite setting:

 case "Soft White":
                    hueColor = 23
                    saturation = 56
                    colorTemperature = 3200

What is strange here though is that when acting on a single bulb, the script works. Only when using the group do I get the strange green color after the bulb comes up to the right color. This is what the stock SmartThings LIFX handler (single bulb) looks like with the same settings as the group:

7:30:38 PM: debug setColor [hue:23, saturation:56, level:100, colorTemperature:3200]
7:30:37 PM: debug setLevel 100
7:30:36 PM: debug Executing 'setColorTemperature' to 3200

When using a color, which does not use a setColorTemperature, the system works. When I try to comment out hue, it comes up in the right color temp but then shifts to hue 0 (red).

Edit 2: It is worth mentioning that setting the color temperature does work from the device handler on my phone:

7:55:58 PM: debug LIFXGoG -- End setting groups color temperature to 3065.
7:55:58 PM: debug LIFXGoG -- Results: [id:d073d512b640, status:ok, label:LivingRm_LFlrLamp1]
7:55:57 PM: debug LIFXGoG -- End method buildGroupList().
7:55:57 PM: debug LIFXGoG -- GroupsList = <<<group:Living room,>>>
7:55:57 PM: debug LIFXGoG -- Begin method buildGroupList().
7:55:57 PM: debug LIFXGoG -- Begin setting groups color temperature to 3065.

So seeing this, I commented out some of the Button Controller’s code:

if (colorTemperature != null) {
                    // Changing the amount of data that is sent because of hue device handler change
                	// colorValue = [alpha: 1.0, red: rgbValue[0], green: rgbValue[1], blue: rgbValue[2], hex: hexValue, hue: hueColor as double, saturation: saturation, level: level as Integer ?: 100, colorTemperature: colorTemperature]
                    colorValue = [hue: hueColor as Integer, saturation: saturation, level: level as Integer ?: 100, colorTemperature: colorTemperature]
                    //try{
                       delayBetween(light.setColorTemperature(colorTemperature),
                       light.setLevel(level as Integer ?: 100), 1000)
                    //}catch(e){
                     // light.setColor(colorValue)
                    //}
                } 
                else {
                     //Changing the amount of data that is sent because of hue device handler change
                	 //colorValue = [alpha: 1.0, red: rgbValue[0], green: rgbValue[1], blue: rgbValue[2], hex: hexValue, hue: hueColor as double, saturation: saturation, level: level as Integer ?: 100]
                    colorValue = [hue: hueColor as Integer, saturation: saturation, level: level as Integer ?: 100]
                    light.setColor(colorValue)
                }

Now it works for setting color temp! :slight_smile:

So one thing I wanted to try was to have setColor() set the brightness as well, without needing a setLevel() command. I modified it as such:

def setColor(value) {
	log("Begin setting groups color to ${value}.", "DEBUG")
    
    def data = [:]
    data.hue = value.hue
    data.saturation = value.saturation
    data.level = value.level
       
   if (data.level < 1 && data.level > 0) {
		data.level = 1
	}
	if (data.level == 0) {
		sendEvent(name: "level", value: 0)
		return off()
	}
    
    def brightness = data.level / 100
    
    buildGroupList()
    sendMessageToLIFX("lights/" + state.groupsList + "/state", "PUT", [color: "saturation:${data.saturation / 100}+hue:${data.hue * 3.6}","brightness": brightness,"duration": "2.0", "power": "on"])
    
    sendEvent(name: "hue", value: value.hue)
    sendEvent(name: "saturation", value: value.saturation)
    sendEvent(name: "color", value: value.hex)
    sendEvent(name: "switch", value: "on")
    
    
    log("End setting groups color to ${value}.", "DEBUG")
}

EDIT: After experimenting some more, I did the same with colorTemperature:

def setColorTemperature(value) {
	log("Begin setting groups to ${value}.", "DEBUG")
    
    def data = [:]
    data.level = value.level
    data.colorTemperature = value.colorTemperature
       
   if (data.level < 1 && data.level > 0) {
		data.level = 1
	}
	if (data.level == 0) {
		sendEvent(name: "level", value: 0)
		return off()
	}
    
    def brightness = data.level / 100
    
    buildGroupList()
    sendMessageToLIFX("lights/" + state.groupsList + "/state", "PUT", [color: "kelvin:${data.colorTemperature}","brightness": brightness,"duration": "2.0",power: "on"])
            
	sendEvent(name: "colorTemperature", value: value.colorTemperature)
	sendEvent(name: "color", value: "#ffffff")
	sendEvent(name: "saturation", value: 0)
    
    log("End setting groups color temperature to ${value}.", "DEBUG")
}

I did have to modify Button Controller as such:

if (colorTemperature != null) {
                    // Changing the amount of data that is sent because of hue device handler change
                	// colorValue = [alpha: 1.0, red: rgbValue[0], green: rgbValue[1], blue: rgbValue[2], hex: hexValue, hue: hueColor as double, saturation: saturation, level: level as Integer ?: 100, colorTemperature: colorTemperature]
                    colorValue = [level: level as Integer ?: 100, colorTemperature: colorTemperature]
                    //try{
                       //light.setColorTemperature(colorTemperature)
                       light.setColorTemperature(colorValue)
                       //light.setLevel(level as Integer ?: 100)
                       //light.setColor(colorValue)
                    //}catch(e){
                     // light.setColor(colorValue)
                    //}
                } 
                else {
                     //Changing the amount of data that is sent because of hue device handler change
                	 //colorValue = [alpha: 1.0, red: rgbValue[0], green: rgbValue[1], blue: rgbValue[2], hex: hexValue, hue: hueColor as double, saturation: saturation, level: level as Integer ?: 100]
                    colorValue = [hue: hueColor as Integer, saturation: saturation, level: level as Integer ?: 100]
                    light.setColor(colorValue)
                    //light.setLevel(level as Integer ?: 100)
                }

Of course now the setColorTemperature is messed up for the stock handler :laughing:. Hope this helps someone in the future :slight_smile:

Just making a post so I can watch this thread and gives thanks to Eric for his hard work.

No problem. If you have any suggested features let me know. I have a lot of LIFX color bulbs. 5 groups, kitchen, dining room, family room, foyer, upstairs hallway, & office. My kitchen, dining room, foyer are all close together so I created a virtual group using this to control all three at once. 17 lights with dim with me took basically forever, but this device handler does the work instantly.