Device/Set-LifxDevicePower.ps1
<#
.SYNOPSIS Controls the power state of a Lifx device .DESCRIPTION This cmdlet controls whether or not a Lifx device is On or Off. In addition, it also supports an optional TransitionInSeconds to control how fast On/Off occurs. .EXAMPLE $devices = Get-LifxDevice | Initialize-LifxDevice $devices | Where-Object {$_.Group -eq "Living Room"} | Set-LifxDevicePower -Power $true .EXAMPLE $devices = Get-LifxDevice | Initialize-LifxDevice $devices | Where-Object {$_.Name -eq "Kitchen01"} | Set-LifxDevicePower -Power $false -TransitionInSeconds 3 .EXAMPLE $devices = Get-LifxDevice | Initialize-LifxDevice Set-LifxDevicePower -Device $devices[0] -Power $false -TransitionInSeconds 3 #> function Set-LifxDevicePower { <##> param ( #Discovered Lifx device. Accepts input from Get-LifxDevice or Initialize-LifxDevice [parameter( Mandatory = $true, ValueFromPipeline = $true)] [PSCustomObject[]]$Device, #Turn the light on or off. $true = on. $false = off. [parameter( Mandatory = $true)] [bool]$Power, #the number of seconds it will take the light to turn on/off [parameter( Mandatory = $false)] [decimal]$SecondsToTransition = 0 ) BEGIN { switch ($power) { $true {$level = 65535; $state = "ON"} $false {$level = 0; $state = "OFF"} } $packet = [PSCustomObject] @{ packet_type = [uint16]117; protocol = [uint16]21504 ack_required = [bool]$true level = [uint16]$level duration = [uint32]($SecondsToTransition * 1000) reserved1 = [uint32]0 reserved2 = [uint32]0 reserved3 = [uint32]0 reserved4 = [uint32]0 site = New-Object byte[] 8 size = [uint16]49 target_mac_address = New-Object byte[] 8 timestamp = [uint64]0 } [Byte[]]$buffer = New-Object byte[] $packet.size; [System.Array]::Copy([System.BitConverter]::GetBytes($packet.size), 0, $buffer, 0, 2); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.protocol), 0, $buffer, 2, 2); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.reserved1), 0, $buffer, 4, 4); [System.Array]::Copy($packet.target_mac_address, 0, $buffer, 8, 6); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.reserved2), 0, $buffer, 14, 2); [System.Array]::Copy($packet.site, 0, $buffer, 16, 6); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.reserved3), 0, $buffer, 22, 2); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.timestamp), 0, $buffer, 24, 8); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.packet_type), 0, $buffer, 32, 2); [System.Array]::Copy([System.BitConverter]::GetBytes($packet.reserved4), 0, $buffer, 30, 2); if ($packet.Level -eq 0) {[System.Array]::Copy([System.BitConverter]::GetBytes($packet.level), 0, $buffer, 36, 2);} if ($packet.Level -eq 65535) {[System.Array]::Copy([System.BitConverter]::GetBytes($packet.level), 0, $buffer, 36, 2);} [System.Array]::Copy([System.BitConverter]::GetBytes($packet.duration), 0, $buffer, 38, 4); [Byte[]]$payload = New-Object byte[] 0 #$packet.GetPayloadBuffer(); [System.Array]::Copy($payload, 0, $buffer, 36, $payload.Length); } PROCESS { #provide some status Write-Output "Turning $($Device.Name) $state" #prep the packet [Byte[]]$powerPacket = $buffer $localIP = [System.Net.IPAddress]::Parse([System.Net.IPAddress]::Any) $RemoteIpEndPoint = New-Object System.Net.IPEndpoint($localIP, $Port) #New-Object System.Net.IPEndpoint([System.Net.IPAddress]::Any, 0) $receivingUdpClient = New-Object System.Net.Sockets.UDPClient($RemoteIpEndPoint) #(, $Port) $receivingUdpClient.Client.Blocking = $false $receivingUdpClient.DontFragment = $true $receivingUdpClient.Client.SetSocketOption([System.Net.Sockets.SocketOptionLevel]::Socket, [System.Net.Sockets.SocketOptionName]::ReuseAddress, $true) #send the packet $send = $receivingUdpClient.SendAsync($powerPacket, $powerPacket.Length, $Device.IPAddress.Address, $Device.IPAddress.Port) #shut the socket down $receivingUdpClient.Close() $receivingUdpClient.Dispose() } END { } } |