Setting colors on a LIFX Z-strip

Hi,

I am a pretty new user to HomeAssistant – roughly a year ago I set it up for the first time but at that time only for controlling a few electric radiators.

Now it was time to move over all my LIFX devices from my custom made automation based on GitHub - mclarkk/lifxlan: Python library for accessing LIFX devices locally using the official LIFX LAN protocol. into HomeAssistant.

One preset I have had before that I liked very much I got by sending this via lifxlan:

  • color (hue): 48620
  • saturation 655
  • kelvin 2750

I got some help here: Struggling to re-creating same LIFX color with HomeAssistant · Issue #99 · aiolifx/aiolifx · GitHub – but the result of sending the suggested values ( [267, 1, 100, 2750]) for lifx.paint_theme is very cold blue instead for a very warm violet.

Could someone please point me in the right direction for how to accomplish this warm violet colour I am after?

Thanks in advance!

Could you provide the exact code you use with lifxlan so I can recreate it with aiolifx? I’m guessing values are being converted differently between the two.

Also, a picture of your Z strip in the desired colour would be useful for validation purposes.

Thankyou for replying once again!

This might be more than what you are asking but I am posting everything to make sure I am not omitting any context.

This is my wrapper script for lifxlan:

cat /usr/local/bin/lifx_control.py   
#!/usr/bin/env python3
from lifxlan import *
import sys
import json
import getopt
from time import sleep


def usage():
    print("\nUsage\n")
    print('Usage control specific device: '+sys.argv[0]+' -i <ip> -m <mac> [options]')
    print('Usage get all devices: '+sys.argv[0]+' -g -j')

def getAllDevices(mode):
    lifx = LifxLAN()

    # get devices
    devices = lifx.get_lights()

    #print(json.dumps(d, default=lambda o: o.__dict__))
    if mode == 'json':
        jsonObj = {}
        for d in devices:
                jsonObj[d.mac_addr] = {
                        'mac': d.mac_addr,
                        'ip': d.ip_addr,
                        'label': d.get_label(),
                        'location': d.get_location_label(),
                        'group': d.get_group_label(),
                        'product': d.get_product(),
                        'color': d.get_color(),
                        'power': d.get_power()
                }
        print(json.dumps(jsonObj))
    else:
        for d in devices:
                print("{} ({} - {}) HSBK: {}".format(d.get_label(), d.ip_addr, d.mac_addr, d.get_color()))


def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hr:i:m:t:c:s:b:k:d:vgj", ["help", "group=", "ip=", "mac=", "toggle=", "color=", "saturation=","brightness=","kelvin=","duration=","json"])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(str(err))  # will print something like "option -a not recognized"
        usage()
        sys.exit(2)    

    mode = None
    ip = None
    group = None
    mac = None
    toggle = None
    saturation = None
    color = None
    brightness = None
    kelvin = None
    duration = 1
    verbose = False

    for o, a in opts:
        if o == "-v":
            verbose = True
        elif o in ("-j", "--json"):
            mode = 'json'
            getAllDevices(mode)
            sys.exit()
        elif o in ("-g"):
            getAllDevices(mode)
            sys.exit()
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-r", "--group"):
            group = a       
        elif o in ("-i", "--ip"):
            ip = a       
        elif o in ("-m", "--mac"):
            mac = a        
        elif o in ("-t", "--toggle"):
            toggle = a
        elif o in ("-s", "--saturation"):
            saturation = a
        elif o in ("-c", "--color"):
            color = a
        elif o in ("-b", "--brightness"):
            brightness = a
        elif o in ("-k", "--kelvin"):
            kelvin = a        
        elif o in ("-d", "--duration"):
            duration = a
        else:
            assert False, "unhandled option"
    

    if verbose:
        print("IP: " + ip)
        print("MAC: " + mac)
        print("GROUP: " + group)

    if group is not None:
        print("Group action")
        #create group
        lifx = LifxLAN()
        bulb = lifx.get_devices_by_group(group)

    else:
        # create device
        bulb = Light(mac, ip)
        #print(bulb.__dict__)

    if toggle == 'blink':
        print('Blinking device')
        toggle_device_power(bulb)
        sys.exit(0)


    if toggle == 'off':
        print('Turning device off')
        bulb.set_power('off', duration)
        sys.exit(0)


    if not (color and saturation and brightness and kelvin):
        if color is not None:
            bulb.set_hue(color, duration)
        if saturation is not None:
            bulb.set_saturation(saturation, duration)
        if brightness is not None:
            bulb.set_brightness(brightness, duration)
        if kelvin is not None:
            bulb.set_colortemp(kelvin, duration)
    else:
        bulb.set_color([color, saturation, brightness, kelvin], duration)
    
    if toggle is not None:
        bulb.set_power(toggle, duration)

    sys.exit(0)
    

    #print(bulb.__dict__)
    #bulb.get_power()
    print(bulb.get_power())

    #print(bulb.__dict__)
    print("Selected {}".format(bulb.get_label()))

    # get original state
    original_power = bulb.get_power()
    original_color = bulb.get_color()
    bulb.set_power("on")

    sleep(0.2) # to look pretty

    print("Toggling power...")
    toggle_device_power(bulb, 0.2)

    print("Toggling color...")
    toggle_light_color(bulb, 0.2)

    # restore original color
    # color can be restored after the power is turned off as well
    print("Restoring original color and power...")
    bulb.set_color(original_color)

    sleep(1) # to look pretty.

    # restore original power
    bulb.set_power(original_power)

def toggle_device_power(device, interval=0.5, num_cycles=3): #TEST
    #original_power_state = device.get_power()
    device.set_power("off")
    rapid = True if interval < 1 else False
    for i in range(num_cycles):
        device.set_power("on", rapid)
        sleep(interval)
        device.set_power("off", rapid)
        sleep(interval)
    #device.set_power(original_power_state)
    device.set_power("on")

def toggle_light_color(light, interval=0.5, num_cycles=3):
    original_color = light.get_color()
    rapid = True if interval < 1 else False
    for i in range(num_cycles):
        light.set_color(BLUE, rapid=rapid)
        sleep(interval)
        light.set_color(GREEN, rapid=rapid)
        sleep(interval)
    light.set_color(original_color)

if __name__=="__main__":
    main()

If I invoke this script like this I will get the warm violet I am after:

/usr/local/bin/lifx_control.py -m d0:73:d5:xx:xx:x -i 192.168.xx.xx -c 48620 -s 655 -k 2750

Attached you find photos showing the results of invoking lifxlan-command vs the lifx.paint_theme with the values you very kindly calculated for me.


Try using [267, 100, 100, 2750] because I only get the same violet colour with your script if I use -s 65535 which is the same as 100% in Home Assistant. You may have to tweak the third value for brightness, as this is not specified in any of your provided examples.

Thanks for your patience!

I have tried with your suggestion – but I still get the same blue color – but is there a chance that I do something wrong?

What I have tried is to create a script with this content:

sequence:
  - action: lifx.paint_theme
    metadata: {}
    data:
      palette:
        - - 267
          - 100
          - 100
          - 2750
        - - 267
          - 100
          - 100
          - 2750
      transition: 1
      power_on: true
    target:
      device_id: 53e41db7444428590c860b2b86df9c2d
alias: Test Z-strip
description: ""

How are you testing it?

Do you get the mild violet color when you try?

I get a mild violet colour with the script above, though it’s also very close to blue. It’s difficult to tell the difference. I’m testing with a LIFX Beam, not a Z Strip, so my colours may not be identical to yours, but the process works.

To verify, set the colour with Home Assistant and then use your script to interrogate the strip to see what colour values it has set. They should be the same (or within a margin of error of each other).

Interesting!

After applying the above script [267, 100, 100, 2750] and then querying with my own wrapper for lifxlan I get this:

HSBK: (48605, 65535, 65535, 2750)

However if I adjust the above script and change saturation to 1 and brightness to 90 ( [267, 1, 90, 2750]) I still get this:

HSBK: (48605, 65535, 58982, 2750)

To me it seem like saturation is not taken into consideration – or am I missing something?

(I really appreciate your support!)

To be honest, I’m a bit stumped myself. I’ll try running your script again soon (hopefully this weekend, if not before) to see if I can spot anything I’ve missed thus far.