Sunday 7 December 2014

Scripting to create effects with your Hue / LIFX bulbs

This tutorial uses Hue-topia (for Philips Hue bulbs) or LIFXstyle (for LIFX bulbs)

It also uses Applescript. Code is provided below (which you'll be able to modify and develop) and you'll need Applescript Editor which you'll find on your Mac.

This previous article explained how to send a command to switch to a named preset. As from version 1.4 of LIFXstyle and v1.8.1 of Hue-topia it's also possible to read and set the state of individual bulbs or groups (on/off, hue, brightness, whiteness) from a script.

Accessing a bulb / group

To get started, type:

tell application "LIFXStyle"
# or tell application "Hue-topia"
get properties of first lamp
end tell

The result should be something like:

{class:lamp, hue:39, whiteness:225, brightness:225, title:"Living A", identity:"d073d500cc1c", state:true}


You can access a bulb / group by its name or ID. We're using name here (actually called  'title' when scripting). But of course you can easily change this, so to futureproof your script, you might like to use the ID instead (actually called 'identity' when scripting). You can find the identity of a bulb by using the example above.

To access a particular bulb, use something like:

properties of first lamp whose title is "Living A"

(Obviously one of my lamps is called 'Living A' - change that for the name of one of your lamps) 

lamp  is one of your lamps
group  is one of your groups
lamps  gets you a collection containing all of your lamps
groups gets you a collection containing all of your groups

Accessing individual bulbs within a group 

(since HT v1.8.2 and LS v1.4.1)  group contains lamps so:

        set collectionOfLamps to a reference to lamps of (first group whose title is "AllBarSecurity")
        set brightness of first item of collectionOfLamps to 80

Changing the colour of a bulb

This example switches the bulb on and sets the colour to red:

set state of first lamp whose title is "Living A" to 1
set hue of first lamp whose title is "Living A" to 0  # zero is red
set whiteness of first lamp whose title is "Living A" to 0


Note a lamp must be on when you send hue, whiteness or brightness, otherwise the instruction will have no effect. That's just the way the bulbs work. 

Note also that the state being off isn't the same thing as the brightness being 0 (LIFX bulbs fade right down to nothing with the state still set to on. Hue bulbs' minimum brightness is still quite a bit of light.)

whiteness, brightness and hue can be an integer between 0 and 255. state is a boolean so can be true/false or 0/1

Some approximate colour values:

Red: 0
Green: 85
Blue: 170
Yellow: 32
Orange: 20
Purple: 200

Loops and pauses 

All the usual Applescript program flow applies here. The script below will cycle all of your lamps randomly red, green and white. (Perfect for Christmas)

tell application "LIFXStyle"
#or tell application "Hue-topia"
repeat
set n to (number of items in lamps)
set i to (random number from 1 to n)
set whiteness of lamp i to 0
set hue of lamp i to 85 # green 
delay 0.5
set i to (random number from 1 to n)
set whiteness of lamp i to 0
set hue of lamp i to 0 # red 
delay 0.5
set i to (random number from 1 to n)
set whiteness of lamp i to 255 # white 
delay 0.5
#press cmd . to stop
end repeat
end tell


This script cycles a given lamp through the whole colour spectrum:

tell application "LIFXStyle"
# or tell application "Hue-topia"
repeat
repeat with hueValue from 0 to 255
set (hue of first lamp whose title is "Living A") to hueValue
delay 0.1
end repeat
end repeat
end tell

For more documentation see AppleScript Editor's File > Open Dictionary... (choose LIFXstyle or Hue-topia)

If you write a cool script, do share.

13 comments:

  1. an updated "color cycling" script
    * change the word "group" to "lamp" to control just one lamp
    * easier on the CPU
    * cycles a little faster
    * uses a reference object
    * will pick up the cycle from where it currently is, rather than abruptly starting at red.
    --------------------------------------------------------

    tell application "LIFXStyle"
    set lampName to "your_group_name"
    set hueScaleFactor to 3

    set maxValue to 255
    set myLamp to a reference to (first group whose title is lampName)

    set (whiteness of myLamp) to 25
    set (brightness of myLamp) to maxValue

    set hueStart to hue of myLamp
    set hueStartScaled to (hueStart / hueScaleFactor) as integer
    set hueEndScaled to (maxValue / hueScaleFactor) as integer

    repeat
    repeat with hueValue from hueStartScaled to hueEndScaled
    set (hue of myLamp) to (hueValue * hueScaleFactor)
    delay 0.25
    end repeat

    set hueStartScaled to 0
    end repeat
    end tell

    ReplyDelete
  2. That's brilliant David, I really appreciate your contribution, I hope people find this script useful

    ReplyDelete
  3. I've updated my script for offsetting the color cycling of each bulb. The latest will always be posted here: https://karaoke.kjams.com/wiki/Disco_Lights

    ReplyDelete
  4. Wow, you've really run with this, it's great to see.

    ReplyDelete
  5. How would I add increments to a current level. After returning the value from the properties command, I can't seem to use the set command with mathematical equation. I also can't seem to set the property to variable.

    Sorry my apple script knowledge is limited. Thanks.

    ReplyDelete
  6. Ok got it working:

    tell application "LIFXStyle"


    properties of first lamp whose identity is "d073d501ca52"
    copy (get brightness of first lamp whose identity is "d073d501ca52") to blevel

    set brightness of first lamp whose identity is "d073d501ca52" to blevel - 60

    end tell

    ReplyDelete
  7. Did the color cycling script in JavaScript for Automation instead of Applescript:


    try {

    const hueScaleFactor = 6 // eg. 4 How fast colors change, the bigger the faster (< 128, as its a 256 divisor)
    const maxValue = 256 // Byte max Constant
    const NrofCycles = 3 // Number of Colorcycles
    var lifxApp = Application('LIFXStyle') ;

    app = Application.currentApplication()
    app.includeStandardAdditions = true // for standardadditions into Javascript like displayAlert
    app.activate() // get this App in Foreground

    // lifxApp.getproperties in Javascript
    myLamp = lifxApp.lamps[0]
    myLampID = myLamp.identity()
    myLampName = myLamp.title()
    brightLvl = myLamp.brightness()
    hueLvl = myLamp.hue()
    whiteLvl = myLamp.whiteness()
    stateLvl = myLamp.state()

    if (stateLvl !== true) { myLamp.state = true }; // Turn Lamp on if not on

    /* for Troubleshooting only
    ReplyRec = app.displayAlert("START "+ NrofCycles + " Colorwheel Cycles with Lifx ?",
    {
    withTitle: 'Name LifX', as: "informational",
    message: "Answer within 20 seconds, or script will abort. " + "\n" +
    "Here are the current settings of the lamp: " + "\n" +
    "ID : " + myLampID + "\n" +
    "Name : " + myLampName + "\n" +
    "Brightness : " + brightLvl + "\n" +
    "Hue : " + hueLvl + "\n" +
    "Whiteness : " + whiteLvl + "\n" +
    "Status : "+ stateLvl+ "\n" ,
    buttons: ["OK", "Cancel"] ,
    // Array of buttons
    defaultButton: 1, givingUpAfter: 20
    // : number of seconds to wait before automatically dismissing the alert
    })

    if ( ReplyRec.buttonReturned !== "OK" ) return;
    */

    // lifxApp.brightness is not touched ! can work with any
    // lifxApp.whiteness Leveling - otherwise colors do not show
    if (whiteLvl > 30) { myLamp.whiteness = 25 }


    hueStart = hueLvl
    hueStartScaled = (hueStart / hueScaleFactor)
    hueEndScaled = (maxValue / hueScaleFactor)
    cont = true

    for (i=0 ; i<NrofCycles && cont; i++ )
    {

    for (hueValue = hueStartScaled ; hueValue < hueEndScaled; hueValue++ )
    {
    myLamp.hue = parseInt(hueValue * hueScaleFactor) ;
    delay(0.25);
    }

    hueStartScaled = ( ((hueValue * hueScaleFactor) - maxValue ) | 0 ) / hueScaleFactor
    // in order not to start over at 0 but where the bulb was before
    // bitwise OR equals Truncate in JS

    }


    } catch (e) { app.displayAlert('Error!', { message: String(e)} ) }


    ReplyDelete
  8. Can't seem to get this working. Using any of the scripts I simply get the syntax error highlighting "lamp":

    "Expected class name but found identifier."

    ReplyDelete
  9. Hi Tim, I'm not really an Applescript expert but if you'd like to copy your script into an email and send to the support address (support@peacockmedia.co.uk) I'll certainly have a look at it.

    ReplyDelete
  10. I was struggling so much to get what I needed, but finally succeeded: A random but subtle and sophisticated way to animate the lights. The usual problem was that I didn't want it to feel like some manic Christmas. Since I found no other examples of this online, I'm sharing it for those who seek for it.
    This animation simulates burning fire:

    tell application "Hue-topia"
    repeat
    set HueValue to (random number from 20 to 45)
    set brightnessValue to (random number from 70 to 120)
    set whitenessValue to (random number from 20 to 80)
    set hue of some lamp to HueValue
    delay 0.2
    set brightness of some lamp to brightnessValue
    delay 0.2
    set whiteness of some lamp to whitenessValue
    delay 0.2
    end repeat
    end tell






    ReplyDelete
  11. That's excellent Riku, thanks for sharing. Works great and I really like it. For LIFX users I'd suggest changing the HueValue parameters to 20 - 35 because above 35 the colour gets a bit green.

    ReplyDelete
    Replies
    1. Glad to know that it works. Kick the brightness zone up a notch and the hue values to greens and a tiny bit of teal, and you've got yourself a sense of trees swaying in the wind.
      Bring whiteness zone to very low levels, and this works great as party lighting. But you still might not want that full spectrum Christmas feeling. I noticed that you can create multiple brackets, the zone of values used doesn't have to be linear.
      Try this funky looper that contains magentas, indigos, salmon and the occasional gold for accent, excluding blues and greens altogether:

      tell application "Hue-topia"
      repeat
      set HueValue to (random number from 45 to 70)
      set HueValue2 to (random number from 200 to 240)
      set HueValue3 to (random number from 180 to 255)
      set brightnessValue to (random number from 150 to 255)
      set whitenessValue to (random number from 0 to 30)
      set hue of some lamp to HueValue
      delay 0.2
      set brightness of some lamp to brightnessValue
      delay 0.2
      set whiteness of some lamp to whitenessValue
      delay 0.2
      set hue of some lamp to HueValue2
      delay 0.2
      set hue of some lamp to HueValue3
      delay 0.2
      end repeat
      end tell

      My only problem now is, how do I stop this? I'd really like to make it into an application, but then there will be no ways to stop it. Any ideas?
      I have just chatted with David who commented above, and he had a separate applescript to work as a controller that opens an handles the looper script. But there was one bit in the end of his code where I get an error because he wrote it for LIFX and I'm using Hue-Topia, and the particular lingo isn't universal at that specific point.

      Delete