Viewing entries tagged
lifx

PowerShell: Control your LIFX light!

PowerShell: Control your LIFX light!

LET THERE BE LIGHT!

This post has been updated on 5/18/17 to reflect changes made to the Lifx API!

I stumbled upon the fact that LIFX has an API you can use today. Having found that out I wanted to do it in PowerShell and see what I can do. As it turns out there's a decent amount of things you can do and their API is "limited" to around 1 call per second.

If you would like to get into even more detail, step-by-step, and behind the scenes of how this works, check out this post!

Requirements

To get started with this you'll need...

Getting started

Here's what I did to get started. 

  1. Created a PowerShell script named Get-LifxApi.ps1.
  2. Opened the script up with basic parameters and variables to get started.
  3. Somewhat annoying my girlfriend with the light changing so much  ❤️

Starting code

[cmdletbinding(DefaultParameterSetName='SetState')]
param(
    [Parameter(
        ParameterSetName = "StateSetting"
    )]        
    [ValidateSet('SetState','FlashColor','RandomColors','ListLights')]    
    [string]
    $Action = 'SetState',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('on','off')]
    [string]
    $State = 'on',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('white','red','orange','yellow','cyan','green','blue','purple','pink')]
    [string]
    $Color = 'white',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateRange(0.0,1)]
    [double]
    $Brightness = '0.4',
    [Parameter(
        ParameterSetName = "Toggle"    
    )]    
    [Switch]
    $Toggle
)

$apiKey          = 'YourKeyGoesHere'
$headers         =  @{Authorization=("Bearer {0}" -f $apiKey)}
$allURL          = 'https://api.lifx.com/v1/lights/all' 
$acceptHeader    = 'application/json'
$baseURL         = 'https://api.lifx.com/v1/lights'
$foregroundColor = 'white'
[array]$colors   = @('white','red','orange','yellow','cyan','green','blue','purple','pink')

Notes

You'll want to change the $apiKey to match your API key from the LIFX cloud.
The $allURL variable will return all your lights, and then the $baseURL variable is used later when formatting calls to change colors or do other things. $foregroundColor let's you specify a color for some of the Write-Host returns, and $colors is an array of colors currently accepted by the API (and you'll see why it is there later in this post). 

Let's make our first call!

I store the results of my light(s) in the $lifxLights variable.

$lifxLights = Invoke-RestMethod -headers $headers -Uri $allURL -ContentType $acceptheader

And now to write our first function in this script.

This function will allow us to utilize the API's state setting option. I named this function Set-LightState

function Set-LightState { #Begin function Set-LightState
    [cmdletbinding()]
    param(
        [Parameter()]
        [ValidateSet('on','off')]
        [string]
        $state,
        [Parameter()]  
        [string]
        $color,
        [Parameter()]
        [ValidateRange(0.0,1)]
        [double]
        $brightness,
        [string]
        $selector
    )

    if ($lifxLight.Connected) {          

        $fullURL  = "$baseurl/$($lifxLight.id)/state"        
        $payload  = [PSCustomObject]@{

            power      = $state
            color      = $color
            brightness = $brightness

        }

        $payloadJson = $payload | ConvertTo-Json

        Write-Host "Attempting to Change light to:" -ForegroundColor $foregroundcolor
        Write-Host `t"State     :" $state
        Write-Host `t"Color     :" $color
        Write-Host `t"Brightness:" ($brightness * 100)"%" `n

        $stateReturn = Invoke-RestMethod -headers $headers -uri $fullURL -Method Put -Body $payloadJson -ContentType $acceptheader
    
        Write-Host "API status:" -ForegroundColor $foregroundcolor
        Write-Host `t"Light :" $stateReturn.results.label
        Write-Host `t"Status:" $stateReturn.results.status `n
    
    } else {
        
        $lightName = $lifxLight.label
        Write-Host "$lightName is offline or unreachable :("
        
    }    

} #End function Set-LightState

I only have one LIFX light. In the start of this function I set my 'selector' (a required field for API calls to LIFX when setting states) as the light's ID.  I then use the value of light's ID to setup the URL structure for the call. $fullURL becomes the URL used when accessing the API to set the state of the light.

Let's take some action!

At the start of the script I have a parameter for action. 
Below is how it is used, in conjunction with toggle.

if ($toggle) { #If we're just toggling
             
    $fullURL  = "$baseurl/$($lifxLight.id)/toggle"  
    $toggleResult = Invoke-RestMethod -Uri $fullURL -Method Post -ContentType $acceptHeader -Headers $headers

    if ($toggleResult.results.status -eq 'ok') {

        Write-Host "Light [$($toggleResult.results.label)] was toggled!"

    } else {

        Write-Host "Something went wrong: [$($toggleResult.results.status)]"
    }

} else { #Else we perform the actions!

    Switch ($action) { #Begin switch for script actions
        
        'SetState' {         
            
            Set-LightState -state $state -color $color -brightness $brightness

        }    
        
        'ListLights' {
            
            return $lifxLight
            
        }       

        'RandomColors' { 
            
            $originalBrightness = $lifxLight.Brightness
            $originalColor      = $lifxLight.Color
            $originalState      = $lifxLight.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin       
            
            $i = 0
            
            While ($i -le 10) {
                
                $color              = Get-Random $colors
                [double]$brightness = "{0:n2}" -f (Get-Random -Maximum 1 -Minimum 0.00)
    
                Set-LightState -color $color -brightness $brightness -selector $selector -state $state
                Start-Sleep -seconds 1
                $i++
                
            }
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness

        }
        
        'FlashColor' {
            
            $originalBrightness = $lifxLights.Brightness
            $originalColor      = $lifxLights.Color
            $originalState      = $lifxLights.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
            Start-Sleep -Seconds 1
                    
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness 
            Start-Sleep -Seconds 1        
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
                            
        }    
    
    } #End switch for light actions
}

My favorite action is the RandomColors. I have that set to use Get-Random to set the color and brightness randomly.  The other action is setstate. What that will do is set the light to a state you specify. If you do not give it options it will default to turning the light on to a brightness of 40% (0.4) and the color value of white (this is defined as per the default options for the parameters at the start of this script). You can change them by supplying the arguments when you run the script.

$fullURL example contents:

https://api.lifx.com/v1/lights/az0321123abc/state

Examples

.\Get-LifxAPI.ps1 -Action setstate -State on -Color blue -Brightness 0.5
lifx.PNG

Did it work?! 
(Yup)

.\Get-LifxAPI.ps1 -Action setstate

The above example is the simplest way to run it as it utilizes the default parameters. (actually, you could just run Get-LifxAPI.ps1)

Now for some fun!

.\Get-LifxAPI.ps1 -Action RandomColors

More to come!

I will be adding to this as I work on it more and clean it up. I will get adding:

  • Help nodes for Get-Help (done!).
  • More options to leverage different parts of the LIFX API (coming).
  • And more as I think of cool things to do with this!

Use:

Get-Help .\Get-LifxAPI.ps1 -Detailed

To see the help that is included. Be sure to change Get-LifxAPI.ps1 to what you named your script to!

The Code

<#
.SYNOPSIS   
    Use this script to control your Lifx light via PowerShell!
.DESCRIPTION 
    You can use this script to turn your light on and off, as well as change the brightness and colors.
.PARAMETER Action

    Argument: The action you'd like to take:
    SetState, FlashColor, RandomColors, and ListLights are valid actions.

.PARAMETER State
    This parameter accepts the state you'd like to set: on or off.
.PARAMETER Color
    Argument: The color you'd like to set the light to. 
    Valid colors can be tab completed.
.PARAMETER Brightness
    Argument: The brightness you want to set.
    Valid range: between 0-1 (0.5 being 50%)  
.PARAMETER Toggle
    Toggles the light      
.NOTES   
    Name: Get-LifxAPI.ps1
    Author: Mike Roberts aka Ginger Ninja
    DateCreated: 2/6/2016
    Last Modified: 5/18/2017

.EXAMPLE   
    $response = .\Get-LifxAPI.ps1 -Action ListLights
    ---------------------------------------------------------------

    1. Get an object returned that contains the result of the API call
    
    p$[18:52:20]> $response
    id                 : nun-ya
    uuid               : more nun-ya
    label              : Ninja room
    connected          : True
    power              : on
    color              : @{hue=249.9977111467155; saturation=0; kelvin=3400}
    brightness         : 0.48508430609597925
    group              : @{id=nun-ya; name=My Room}
    location           : @{id=nun-ya; name=My Home}
    product            : @{name=Original 1000; identifier=lifx_original_a21; company=LIFX; capabilities=}
    last_seen          : 2017-05-19T01:51:49Z
    seconds_since_seen : 32

.EXAMPLE   
    .\Get-LifxAPI.ps1 -Action RandomColors
    ---------------------------------------------------------------

    1. Light toggles between random colors 10 times

.EXAMPLE   
    .\Get-LifxAPI.ps1 -Toggle
    ---------------------------------------------------------------

    1. Toggles light state (on or off respectively)

.EXAMPLE   
    .\Get-LifxAPI.ps1 -Action SetState -State on -Color blue -Brightness 0.5
    ---------------------------------------------------------------

    1. Turns light on
    2. Changes color to blue
    3. Changes brightness to 0.5
.OUTPUTS
    If you use ListLights as the action, the output will be an
    object containing the results of the api call.

.LINK  
    http://www.gngrninja.com/script-ninja/2016/2/6/powershell-control-your-lifx-light
#>
[cmdletbinding(DefaultParameterSetName='SetState')]
param(
    [Parameter(
        ParameterSetName = "StateSetting"
    )]        
    [ValidateSet('SetState','FlashColor','RandomColors','ListLights')]    
    [string]
    $Action = 'SetState',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('on','off')]
    [string]
    $State = 'on',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('white','red','orange','yellow','cyan','green','blue','purple','pink')]
    [string]
    $Color = 'white',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateRange(0.0,1)]
    [double]
    $Brightness = '0.4',
    [Parameter(
        ParameterSetName = "Toggle"    
    )]    
    [Switch]
    $Toggle
)

$apiKey          = 'YourKeyGoesHere'
$headers         =  @{Authorization=("Bearer {0}" -f $apiKey)}
$allURL          = 'https://api.lifx.com/v1/lights/all' 
$acceptHeader    = 'application/json'
$baseURL         = 'https://api.lifx.com/v1/lights'
$foregroundColor = 'white'
[array]$colors   = @('white','red','orange','yellow','cyan','green','blue','purple','pink')

function Set-LightState { #Begin function Set-LightState
    [cmdletbinding()]
    param(
        [Parameter()]
        [ValidateSet('on','off')]
        [string]
        $state,
        [Parameter()]  
        [string]
        $color,
        [Parameter()]
        [ValidateRange(0.0,1)]
        [double]
        $brightness,
        [string]
        $selector
    )

    if ($lifxLight.Connected) {          

        $fullURL  = "$baseurl/$($lifxLight.id)/state"             
        $payload  = [PSCustomObject]@{

            power      = $state
            color      = $color
            brightness = $brightness

        }

        $payloadJson = $payload | ConvertTo-Json

        Write-Host "Attempting to Change light to:" -ForegroundColor $foregroundcolor
        Write-Host `t"State     :" $state
        Write-Host `t"Color     :" $color
        Write-Host `t"Brightness:" ($brightness * 100)"%" `n

        $stateReturn = Invoke-RestMethod -headers $headers -uri $fullURL -Method Put -Body $payloadJson -ContentType $acceptheader
    
        Write-Host "API status:" -ForegroundColor $foregroundcolor
        Write-Host `t"Light :" $stateReturn.results.label
        Write-Host `t"Status:" $stateReturn.results.status `n
    
    } else {
        
        $lightName = $lifxLight.label
        Write-Host "$lightName is offline or unreachable :("
        
    }    

} #End function Set-LightState

#Get Lifx Lights
$lifxLights = Invoke-RestMethod -headers $headers -Uri $allURL -ContentType $acceptheader
if ($lifxLights.Count -gt 1) {

    Write-Host "Pick a light:"`n
    for ($i = 0;$i -le $lifxLights.Count - 1;$i++) {

        Write-Host "[$i] -> $($lifxLights[$i].label)"

    }

    $picked = $false

    Do {
        [int]$number = Read-Host "Which [#]?"
        Write-Host "$number"
        if (![String]::IsNullOrEmpty($number) -and ($number -le ($lifxLights.Count - 1) -and $number -gt -1)) {

            $picked    = $true
            $lifxLight = $number  
            write-Host "sup"

        }
    } 
    While ($picked -eq $false)

} else {

    $lifxLight = $lifxLights[0]

}

if ($toggle) { #If we're just toggling
             
    $fullURL  = "$baseurl/$($lifxLight.id)/toggle"  
    $toggleResult = Invoke-RestMethod -Uri $fullURL -Method Post -ContentType $acceptHeader -Headers $headers

    if ($toggleResult.results.status -eq 'ok') {

        Write-Host "Light [$($toggleResult.results.label)] was toggled!"

    } else {

        Write-Host "Something went wrong: [$($toggleResult.results.status)]"
    }

} else { #Else we perform the actions!

    Switch ($action) { #Begin switch for script actions
        
        'SetState' {         
            
            Set-LightState -state $state -color $color -brightness $brightness

        }    
        
        'ListLights' {
            
            return $lifxLight
            
        }       

        'RandomColors' { 
            
            $originalBrightness = $lifxLight.Brightness
            $originalColor      = $lifxLight.Color
            $originalState      = $lifxLight.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin       
            
            $i = 0
            
            While ($i -le 10) {
                
                $color              = Get-Random $colors
                [double]$brightness = "{0:n2}" -f (Get-Random -Maximum 1 -Minimum 0.00)
    
                Set-LightState -color $color -brightness $brightness -selector $selector -state $state
                Start-Sleep -seconds 1
                $i++
                
            }
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness

        }
        
        'FlashColor' {
            
            $originalBrightness = $lifxLights.Brightness
            $originalColor      = $lifxLights.Color
            $originalState      = $lifxLights.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
            Start-Sleep -Seconds 1
                    
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness 
            Start-Sleep -Seconds 1        
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
                            
        }    
    
    } #End switch for light actions
}

Leave comment if you have any ideas or feedback!

-Ginger Ninja