From 9ee65b93add50189a1bc836a13b26ab0d4eaebe7 Mon Sep 17 00:00:00 2001 From: James Brundage <@github.com> Date: Mon, 14 Mar 2022 00:11:43 -0700 Subject: [PATCH 1/6] Connect-NanoLeaf: Storing DeviceName --- Connect-NanoLeaf.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Connect-NanoLeaf.ps1 b/Connect-NanoLeaf.ps1 index 529f02c..3b6f06d 100644 --- a/Connect-NanoLeaf.ps1 +++ b/Connect-NanoLeaf.ps1 @@ -51,7 +51,7 @@ $nanoLeafDataFile = Join-Path $lightScriptRoot ".$($nanoLeafInfo.serialNo).nanoleaf.clixml" - [PSCustomObject]@{IPAddress=$NanoLeafIP;NanoLeafToken=$authToken} | + [PSCustomObject]@{IPAddress=$NanoLeafIP;NanoLeafToken=$authToken;DeviceName=$nanoLeafInfo.DeviceName} | Export-Clixml -Path $nanoLeafDataFile } From 33368825a8b8df5ebd82f0c7166184e5bc854faf Mon Sep 17 00:00:00 2001 From: James Brundage <@github.com> Date: Mon, 14 Mar 2022 00:12:32 -0700 Subject: [PATCH 2/6] Set-NanoLeaf: Not setting Duration unless it has total seconds --- Set-NanoLeaf.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Set-NanoLeaf.ps1 b/Set-NanoLeaf.ps1 index 7864fcb..76772e6 100644 --- a/Set-NanoLeaf.ps1 +++ b/Set-NanoLeaf.ps1 @@ -259,7 +259,7 @@ if ($Brightness) { $sendData.brightness = @{value=[Math]::Round($Brightness * 100)} - if ($Duration) { + if ($Duration.TotalSeconds) { $sendData.brightness.duration = [int][Math]::Round($Duration.TotalSeconds) } } From 0a5a1f942ec27711de415502224f2a668ea6118b Mon Sep 17 00:00:00 2001 From: James Brundage <@github.com> Date: Mon, 14 Mar 2022 00:16:01 -0700 Subject: [PATCH 3/6] Fixing #2: Adding Disconnect-HueBridge, Disconnect-NanoLeaf, Disconnect-Twinkly --- Disconnect-HueBridge.ps1 | 49 ++++++++++++++++++++++++++++++++++++++++ Disconnect-NanoLeaf.ps1 | 49 ++++++++++++++++++++++++++++++++++++++++ Disconnect-Twinkly.ps1 | 49 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 Disconnect-HueBridge.ps1 create mode 100644 Disconnect-NanoLeaf.ps1 create mode 100644 Disconnect-Twinkly.ps1 diff --git a/Disconnect-HueBridge.ps1 b/Disconnect-HueBridge.ps1 new file mode 100644 index 0000000..9e140b3 --- /dev/null +++ b/Disconnect-HueBridge.ps1 @@ -0,0 +1,49 @@ +function Disconnect-HueBridge +{ + <# + .Synopsis + Disconnects a Hue Bridge. + .Description + Disconnects a new Hue Bridge and removes connection information. + .Link + Connect-HueBridge + .Example + Disconnect-HueBridge -HueBridgeIP 1.2.3.4 + #> + [CmdletBinding(DefaultParameterSetName='ExistingConnection')] + [OutputType([Nullable], [PSObject])] + param( + # The IP Address of the Hue Bridge + [Parameter(Mandatory,ParameterSetName='NewConnection',ValueFromPipelineByPropertyName)] + [Alias('IPAddress')] + [IPAddress] + $HueBridgeIP + ) + + begin { + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + if (-not (Test-Path $lightScriptRoot)) { + $createLightScriptDir = New-Item -ItemType Directory -Path $lightScriptRoot + if (-not $createLightScriptDir) { return } + } + + + #region Find and Remove Connection + $files = @(Get-ChildItem -Path $lightScriptRoot -ErrorAction SilentlyContinue -Filter *.huebridge.clixml -Force) + $files | + ForEach-Object { + $file = $_ + $fileInfo = Import-Clixml -LiteralPath $file.FullName + if ($fileInfo.IPAddress -eq $HueBridgeIP -and $PSCmdlet.ShouldProcess("Remove $($fileInfo.DeviceID)")) { + Remove-Item -LiteralPath $file.FullName -Force + } + } + #endregion Find and Remove Connection + } +} + diff --git a/Disconnect-NanoLeaf.ps1 b/Disconnect-NanoLeaf.ps1 new file mode 100644 index 0000000..65d20a7 --- /dev/null +++ b/Disconnect-NanoLeaf.ps1 @@ -0,0 +1,49 @@ +function Disconnect-Nanoleaf +{ + <# + .Synopsis + Disconnects a new Nanoleaf controller. + .Description + Disconnnects a new Nanoleaf controller and removes connection information. + .Example + Disconnect-NanoLeaf -IPAddress 1.2.3.4 + .Link + Connect-NanoLeaf + #> + [CmdletBinding(SupportsShouldProcess,ConfirmImpact='High')] + [OutputType([Nullable], [PSObject])] + param( + # The IP Address of the Nanoleaf + [Parameter(Mandatory,ValueFromPipelineByPropertyName)] + [Alias('IPAddress')] + [IPAddress] + $NanoLeafIP + ) + + begin { + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + if (-not (Test-Path $lightScriptRoot)) { + $createLightScriptDir = New-Item -ItemType Directory -Path $lightScriptRoot + if (-not $createLightScriptDir) { return } + } + + #region Find and Remove Connection + $files = @(Get-ChildItem -Path $lightScriptRoot -ErrorAction SilentlyContinue -Filter *.nanoleaf.clixml -Force) + $files | + ForEach-Object { + $file = $_ + $fileInfo = Import-Clixml -LiteralPath $file.FullName + if ($fileInfo.IPAddress -eq $NanoLeafIP -and $PSCmdlet.ShouldProcess("Remove $($fileInfo.DeviceName)")) { + Remove-Item -LiteralPath $file.FullName -Force + } + } + + + #endregion Find and Remove Connection + } +} diff --git a/Disconnect-Twinkly.ps1 b/Disconnect-Twinkly.ps1 new file mode 100644 index 0000000..c04754a --- /dev/null +++ b/Disconnect-Twinkly.ps1 @@ -0,0 +1,49 @@ +function Disconnect-Twinkly +{ + <# + .Synopsis + Disconnects a Twinkly light controller. + .Description + Disconnects a Twinkly light controller + .Example + Disconnect-Twinkly 192.168.0.144 + .Link + Connect-Twinkly + #> + [OutputType([Nullable], [PSObject])] + param( + # The IP Address for the Twinkly device. This can be discovered thru the phone user interface. + [Parameter(Mandatory,Position=0,ValueFromPipelineByPropertyName)] + [Alias('TwinklyIPAddress')] + [IPAddress] + $IPAddress, + + # If set, will output the connection information. + [switch] + $PassThru + ) + + begin { + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + if (-not (Test-Path $lightScriptRoot)) { + $createLightScriptDir = New-Item -ItemType Directory -Path $lightScriptRoot + if (-not $createLightScriptDir) { return } + } + + @(Get-ChildItem -Filter *.twinkly.clixml -Path $lightScriptRoot) | + Foreach-Object { + $file = $_ + $fileInfo = Import-Clixml -LiteralPath $file.FullName + if ($fileInfo.IPAddress -eq $IPAddress -and $PSCmdlet.ShouldProcess("Remove $($fileInfo.uuid)")) { + Remove-Item -LiteralPath $file.FullName -Force + } + } + + } +} + From 4cfe8ab8423f037de88512080c32e808d8e676d9 Mon Sep 17 00:00:00 2001 From: James Brundage <@github.com> Date: Mon, 14 Mar 2022 00:16:58 -0700 Subject: [PATCH 4/6] Fixing #4: Adding Connect/Disconnect/Get/Set-Pixoo --- Connect-Pixoo.ps1 | 78 ++++++++ Disconnect-Pixoo.ps1 | 40 ++++ Formatting/Pixoo.format.ps1 | 3 + Get-Pixoo.ps1 | 58 ++++++ LightScript.format.ps1xml | 66 ++++++- LightScript.types.ps1xml | 54 ++---- Set-Pixoo.ps1 | 378 ++++++++++++++++++++++++++++++++++++ 7 files changed, 632 insertions(+), 45 deletions(-) create mode 100644 Connect-Pixoo.ps1 create mode 100644 Disconnect-Pixoo.ps1 create mode 100644 Formatting/Pixoo.format.ps1 create mode 100644 Get-Pixoo.ps1 create mode 100644 Set-Pixoo.ps1 diff --git a/Connect-Pixoo.ps1 b/Connect-Pixoo.ps1 new file mode 100644 index 0000000..cfe6793 --- /dev/null +++ b/Connect-Pixoo.ps1 @@ -0,0 +1,78 @@ +function Connect-Pixoo +{ + <# + .Synopsis + Connects to a Pixoo + .Description + Connects to a Pixoo over Wifi + .Example + Connect-Pixoo 1.2.3.4 -PassThru + .Link + Get-Pixoo + #> + [OutputType([Nullable], [PSObject])] + param( + # The IP Address for the Twinkly device. This can be discovered thru the phone user interface. + [Parameter(Mandatory,Position=0,ValueFromPipelineByPropertyName)] + [Alias('PixooIPAddress')] + [IPAddress] + $IPAddress, + + # If set, will output the connection information. + [switch] + $PassThru + ) + + begin { + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + #region Attempt to Contact the Device + $pixooConf = Invoke-RestMethod -Uri "http://$IPAddress/post" -Method POST -Body ( + @{ + Command="Channel/GetAllConf" + } | ConvertTo-Json + ) + #endregion Attempt to Contact the Device + + + if ($pixooConf) { + $macAddress = + if ($PSVersionTable.Platform -like 'Win*' -or -not $PSVersionTable.Platform) { + Get-NetNeighbor | Where-Object IPAddress -eq $IPAddress | Select-Object -ExpandProperty LinkLayerAddress + } elseif ($ExecutionContext.SessionState.InvokeCommand.GetCommand('nmap','Application')) { + nmap -Pn "$ipAddress" | + Where-Object { $_ -like 'MAC Address:*'} | + ForEach-Object { @($_ -split ' ')[2] } + } + + if (-not $macAddress) { + Write-Error "Unable to resolve MAC address for $ipAddress, will not save connection" + return + } + #region Save Device Information + if ($home) { + if (-not (Test-Path $lightScriptRoot)) { + $createLightScriptDir = New-Item -ItemType Directory -Path $lightScriptRoot + if (-not $createLightScriptDir) { return } + } + + + $pixooDataFile = Join-Path $lightScriptRoot ".$($macAddress).pixoo.clixml" + $pixooConf.pstypenames.clear() + $pixooConf.pstypenames.add('Pixoo') + $pixooConf | + Add-Member NoteProperty IPAddress $IPAddress -Force -PassThru | + Add-Member NoteProperty MACAddress $macAddress -Force -PassThru | + Export-Clixml -Path $pixooDataFile + } + #endregion Save Device Information + if ($PassThru) { + $pixooConf + } + } + } +} diff --git a/Disconnect-Pixoo.ps1 b/Disconnect-Pixoo.ps1 new file mode 100644 index 0000000..9b018e3 --- /dev/null +++ b/Disconnect-Pixoo.ps1 @@ -0,0 +1,40 @@ +function Disconnect-Pixoo +{ + <# + .Synopsis + Disconnects a Pixoo + .Description + Disconnects a Pixoo, removing stored device info + .Example + Disconnect-Pixoo 1.2.3.4 + .Link + Connect-Pixoo + #> + [OutputType([Nullable], [PSObject])] + [CmdletBinding(SupportsShouldProcess,ConfirmImpact='High')] + param( + # The IP Address for the Twinkly device. This can be discovered thru the phone user interface. + [Parameter(Mandatory,Position=0,ValueFromPipelineByPropertyName)] + [Alias('PixooIPAddress')] + [IPAddress] + $IPAddress + ) + + begin { + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + @(Get-ChildItem -Filter *.pixoo.clixml -Path $lightScriptRoot) | + Foreach-Object { + $file = $_ + $fileInfo = Import-Clixml -LiteralPath $file.FullName + if ($fileInfo.IPAddress -eq $IPAddress -and $PSCmdlet.ShouldProcess("Remove $($fileInfo.MACAddress)")) { + Remove-Item -LiteralPath $file.FullName -Force + } + } + } +} + diff --git a/Formatting/Pixoo.format.ps1 b/Formatting/Pixoo.format.ps1 new file mode 100644 index 0000000..6fee6a6 --- /dev/null +++ b/Formatting/Pixoo.format.ps1 @@ -0,0 +1,3 @@ +Write-formatView -TypeName Pixoo -Property IPAddress, MACAddress, Brightness + +Write-formatView -TypeName Pixoo -Property RotationFlag, GyrateAngle, MirrorFlag -Name Orientation \ No newline at end of file diff --git a/Get-Pixoo.ps1 b/Get-Pixoo.ps1 new file mode 100644 index 0000000..8f59aa2 --- /dev/null +++ b/Get-Pixoo.ps1 @@ -0,0 +1,58 @@ +function Get-Pixoo +{ + <# + .Synopsis + Gets Pixoo Devices + .Description + Gets saved Pixoo Devices + .Example + Get-Pixoo + .LINK + Connect-Pixoo + .LINK + Set-Pixoo + #> + [CmdletBinding(DefaultParameterSetName="ListDevices")] + param( + # The IP Address for the Twinkly device. This can be discovered thru the phone user interface. + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('PixooIPAddress')] + [IPAddress[]] + $IPAddress + ) + + begin { + if (-not $script:PixooCache) { + $script:PixooCache = @{} + } + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + #region Default to All Devices + if (-not $IPAddress) { # If no -IPAddress was passed + if ($home) { + # Read all .twinkly.clixml files beneath your LightScript directory. + Get-ChildItem -Path $lightScriptRoot -ErrorAction SilentlyContinue -Filter *.pixoo.clixml -Force | + Import-Clixml | + ForEach-Object { + if (-not $_) { return } + $pixooConnection = $_ + $script:PixooCache["$($pixooConnection.IPAddress)"] = $pixooConnection + } + + $IPAddress = $script:PixooCache.Keys # The keys of the device cache become the -IPAddress. + } + if (-not $IPAddress) { # If we still have no -IPAddress + return # return. + } + } + #endregion Default to All Devices + + if ($PSCmdlet.ParameterSetName -eq 'ListDevices') { + return $script:PixooCache.Values + } + } +} diff --git a/LightScript.format.ps1xml b/LightScript.format.ps1xml index 06dd3f4..1c251f4 100644 --- a/LightScript.format.ps1xml +++ b/LightScript.format.ps1xml @@ -1,5 +1,5 @@ - - + + @@ -658,6 +658,68 @@ New-Object PSObject -Property ([Ordered]@{ + + Pixoo + + Pixoo + + + + + + + + + + + + + + + IPAddress + + + MACAddress + + + Brightness + + + + + + + + Orientation + + Pixoo + + + + + + + + + + + + + + + RotationFlag + + + GyrateAngle + + + MirrorFlag + + + + + + diff --git a/LightScript.types.ps1xml b/LightScript.types.ps1xml index e9dd4c9..7a9469f 100644 --- a/LightScript.types.ps1xml +++ b/LightScript.types.ps1xml @@ -1,5 +1,5 @@ - - + + Hue.Sensor @@ -88,21 +88,21 @@ $ct100 = $ColorTemperature / 100 $red, $green = if ($ct100 -le 66) { 255 # red - [Math]::Min([Math]::Max( + [Math]::Round([Math]::Min([Math]::Max( (99.4708025861 * [Math]::Log($ct100)) - 161.1195681661, 0 - ), 255) + ), 255)) } else { # red - [Math]::Min([Math]::Max( + [Math]::Round([Math]::Min([Math]::Max( 329.698727446 * [Math]::Pow($ct100 - 60,-0.1332047592), 0 - ), 255) + ), 255)) # green - [Math]::Min([Math]::Max( + [Math]::Round([Math]::Min([Math]::Max( 288.1221695283 * [Math]::Pow($ct100 - 60,-0.0755148492), 0 - ), 255) + ), 255)) } $blue = @@ -111,10 +111,10 @@ $blue = } elseif ($ct100 -le 19) { 0 } else { - [Math]::Min([Math]::Max( + [Math]::Round([Math]::Min([Math]::Max( (138.5177312231 * [Math]::Log($ct100 - 10)) - 305.0447927307, 0 - ), 255) + ), 255)) } @@ -128,40 +128,8 @@ $hslVal = $this.RGBToHSL($red, $green, $blue) Luminance=$hslVal.Luminance Red=$red Green=$green - Blue=$blue + Blue=$blue } - - -<# -If Temperature <= 66 Then - Green = Temperature - Green = 99.4708025861 * Ln(Green) - 161.1195681661 - If Green < 0 Then Green = 0 - If Green > 255 Then Green = 255 -Else - Green = Temperature - 60 - Green = 288.1221695283 * (Green ^ -0.0755148492) - If Green < 0 Then Green = 0 - If Green > 255 Then Green = 255 -End If - -Calculate Blue: - -If Temperature >= 66 Then - Blue = 255 -Else - - If Temperature <= 19 Then - Blue = 0 - Else - Blue = Temperature - 10 - Blue = 138.5177312231 * Ln(Blue) - 305.0447927307 - If Blue < 0 Then Blue = 0 - If Blue > 255 Then Blue = 255 - End If - -End If -#> diff --git a/Set-Pixoo.ps1 b/Set-Pixoo.ps1 new file mode 100644 index 0000000..300060a --- /dev/null +++ b/Set-Pixoo.ps1 @@ -0,0 +1,378 @@ +function Set-Pixoo +{ + <# + .Synopsis + Sets Pixoo Frames + .Description + Changes Pixoo Frames + .Example + Set-Pixoo -Brightness .5 + .LINK + Get-Pixoo + #> + [CmdletBinding(SupportsShouldProcess)] + param( + # One or more IP Addresses of Twinkly devices. + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('TwinklyIPAddress')] + [IPAddress[]] + $IPAddress, + + # Sets the brightness of all lights in a fixture + # When passed with -Hue and -Saturation, sets the color + # When passed with no other parameters, adjusts the absolute brightness + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('Luminance')] + [ValidateRange(0,1)] + [float] + $Brightness, + + # Sets the hue of all lights in a fixture + [Parameter(ValueFromPipelineByPropertyName)] + [double] + $Hue, + + # Sets the saturation of all lights in a fixture + [Parameter(ValueFromPipelineByPropertyName)] + [ValidateRange(0,1)] + [double] + $Saturation, + + # If set, will turn a Pixoo screen on. + [Parameter(ValueFromPipelineByPropertyName)] + [switch] + $On, + + # If set, will turn a Pixoo screen off. + [Parameter(ValueFromPipelineByPropertyName)] + [switch] + $Off, + + # If provided, will switch the Pixoo to a given numbered visualizer + [Parameter(ValueFromPipelineByPropertyName)] + [int] + $Visualizer, + + # If provided, will switch the Pixoo custom playlist + [Parameter(ValueFromPipelineByPropertyName)] + [int] + $CustomPlaylist, + + # If provided, will switch the Pixoo's current Cloud Channel. + [Parameter(ValueFromPipelineByPropertyName)] + [int] + $CloudChannel, + + # If provided, will switch the Pixoo channel. + [Parameter(ValueFromPipelineByPropertyName)] + [ValidateSet("Clock", "Cloud", "Visualizer", "Custom")] + [string] + $Channel, + + # If provided, will switch the Pixoo into Stopwatch mode, and Stop, Reset, or Start the StopWatch + [Parameter(ValueFromPipelineByPropertyName)] + [ValidateSet("Stop", "Start", "Reset")] + [string] + $Stopwatch, + + # If provided, will switch the Pixoo into a Timer, with the given timespan. + # (hours and subseconds will be ignored) + [Parameter(ValueFromPipelineByPropertyName)] + [Timespan] + $Timer, + + # If set, will display a noise meter. + [Parameter(ValueFromPipelineByPropertyName)] + [switch] + $NoiseMeter, + + # If provided, will switch the Pixoo into a Scoreboard. + # -RedScore is the score for the Red Team + # -BlueScore is the score for the Blue Team + [Parameter(ValueFromPipelineByPropertyName)] + [int] + $RedScore, + + # If provided, will switch the Pixoo into a Scoreboard. + # -RedScore is the score for the Red Team + # -BlueScore is the score for the Blue Team + [Parameter(ValueFromPipelineByPropertyName)] + [int] + $BlueScore, + + # If provided, will change the Pixoo into a single RGB color. + [Parameter(ValueFromPipelineByPropertyName)] + [ValidatePattern('#(?>[a-f0-9]{6}|[a-f0-9]{3})')] + [string] + $RGBColor + ) + + begin { + if (-not $script:PixooCache) { + $script:PixooCache = @{} + } + if ($home) { + $lightScriptRoot = Join-Path $home -ChildPath LightScript + } + } + + process { + $paramCopy = @{} + $PSBoundParameters + #region Default to All Devices + if (-not $IPAddress) { # If no -IPAddress was passed + if ($home -and -not $script:PixooCache.Count) { + # Read all .twinkly.clixml files beneath your LightScript directory. + Get-ChildItem -Path $lightScriptRoot -ErrorAction SilentlyContinue -Filter *.pixoo.clixml -Force | + Import-Clixml | + ForEach-Object { + if (-not $_) { return } + $pixooConnection = $_ + $script:PixooCache["$($pixooConnection.IPAddress)"] = $pixooConnection + } + + $IPAddress = $script:PixooCache.Keys # The keys of the device cache become the -IPAddress. + } elseif ($script:PixooCache.Count) { + $IPAddress = $script:PixooCache.Keys # The keys of the device cache become the -IPAddress. + } + if (-not $IPAddress) { # If we still have no -IPAddress + return # return. + } + } + #endregion Default to All Devices + + + + foreach ($ip in $ipAddress) { + $refreshDevice = $false + $invokeSplat = @{Uri="http://$ip/post";Method='POST'} + $restOutputs = @( + if ($paramCopy.ContainsKey("Brightness") -and -not + ($paramCopy.ContainsKey("Hue") -or $paramCopy.ContainsKey("Saturation"))) { + $realBrightness = [Math]::Ceiling($Brightness * 100) + $invokeSplat.Body = (@{ + Command = "Channel/SetBrightness" + Brightness = [int]$realBrightness + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + $refreshDevice = $true + } elseif ($paramCopy.ContainsKey("Brightness") -and + $paramCopy.ContainsKey("Hue") -and + $paramCopy.ContainsKey("Saturation") + ) { + $RGBColor = ([PSCustomObject]@{PSTypeName='LightScript.Color'}).FromHSL($Hue, $Saturation, $Brightness) + } + + + + if ($On -and -not $Off) { + $invokeSplat.Body = (@{ + Command = "Channel/OnOffScreen" + OnOff = 1 + } | ConvertTo-Json -Compress) + Invoke-RestMethod @invokeSplat + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($off) { + $invokeSplat.Body = (@{ + Command = "Channel/OnOffScreen" + OnOff = 0 + } | ConvertTo-Json -Compress) + Invoke-RestMethod @invokeSplat + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($paramCopy.ContainsKey("Visualizer")) { + $invokeSplat.Body = (@{ + Command = "Channel/SetEqPosition" + EqPosition = $Visualizer + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($RGBColor) { + $r,$g,$b = + if ($RGBColor.Length -eq 7) { + [byte]::Parse($RGBColor[1..2]-join'', 'HexNumber') + [byte]::Parse($RGBColor[3..4]-join '', 'HexNumber') + [byte]::Parse($RGBColor[5..6] -join'', 'HexNumber') + }elseif ($RGBColor.Length -eq 4) { + [byte]::Parse($RGBColor[1], 'HexNumber') * 16 + [byte]::Parse($RGBColor[2], 'HexNumber') * 16 + [byte]::Parse($RGBColor[3], 'HexNumber') * 16 + } + + $picId = + if ($whatIfPreference) { + Get-Random -Maximum 1000 + } else { + $invokeSplat.Body = (@{ + Command = "Draw/GetHttpGifId" + } | ConvertTo-Json -Compress) + Invoke-RestMethod @invokeSplat | + Select-Object -ExpandProperty PicID + } + + $picData = + @(foreach ($n in 1..(64 * 64)) { + $r + $g + $b + }) -as [byte[]] + + $invokeSplat.Body = (@{ + Command = "Draw/SendHttpGif" + PicNum = 1 + PicID = $picId + PicOffset = 0 + PicSpeed = 100 + PicWidth = 64 + PicData = [Convert]::ToBase64String($picData) + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } else { + Invoke-RestMethod @invokeSplat + } + + } + + if ($Channel) { + $valueList = @($myInvocation.MyCommand.Parameters.Channel.Attributes.ValidValues) + for ($index = 0; $index -lt $valueList.Count;$index++) { + if ($Channel -eq $valueList[$index]) { + $invokeSplat.Body = (@{ + Command = "Channel/SetIndex" + SelectIndex = $index + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + break + } + } + } + + if ($Stopwatch) { + $valueList = @($myInvocation.MyCommand.Parameters.StopWatch.Attributes.ValidValues) + for ($index = 0; $index -lt $valueList.Count;$index++) { + if ($Stopwatch -eq $valueList[$index]) { + $invokeSplat.Body = (@{ + Command = "Tools/SetStopWatch" + Status = $index + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + break + } + } + } + + if ($psBoundParameters.ContainsKey("CustomPlaylist")) { + $invokeSplat.Body = (@{ + Command = "Channel/SetCustomPageIndex" + CustomPageIndex = $CustomPlaylist + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($psBoundParameters.ContainsKey("CloudChannel")) { + $invokeSplat.Body = (@{ + Command = "Channel/CloudIndex" + Index = $CloudChannel + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($timer) { + $invokeSplat.Body = (@{ + Command = "Tools/SetTimer" + Minute = [int]$Timer.Minutes + Second = [int]$Timer.Seconds + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($NoiseMeter.IsPresent) { + $invokeSplat.Body = (@{ + Command = "Tools/SetNoiseStatus" + NoiseStatus = $NoiseMeter -as [bool] -as [int] + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + + if ($paramCopy.ContainsKey("RedScore") -or $paramCopy.ContainsKey("BlueScore")) { + $invokeSplat.Body = (@{ + Command = "Tools/SetScoreBoard" + BlueScore = + if ($paramCopy.ContainsKey("BlueScore")) { + $BlueScore + $script:PixooCache["$ip"] = $script:PixooCache["$ip"] | Add-Member NoteProperty BlueScore $BlueScore -Force -PassThru + } elseif ($script:PixooCache["$ip"].BlueScore) { + $script:PixooCache["$ip"].BlueScore + } else { + 0 + } + RedScore = + if ($paramCopy.ContainsKey("RedScore")) { + $RedScore + $script:PixooCache["$ip"] = $script:PixooCache["$ip"] | Add-Member NoteProperty RedScore $RedScore -Force -PassThru + } elseif ($script:PixooCache["$ip"].RedScore) { + $script:PixooCache["$ip"].RedScore + } else { 0 } + } | ConvertTo-Json -Compress) + if ($whatIfPreference) { + $invokeSplat + } elseif ($psCmdlet.ShouldProcess("$($invokeSplat.Command)")) { + Invoke-RestMethod @invokeSplat + } + } + ) + + if ($restOutputs -and $whatIfPreference) { + $restOutputs + } + + if ($refreshDevice -and -not ($restOutputs | Where-Object error_code -gt 0) -and -not $whatIfPreference) { + Connect-Pixoo -IPAddress $IP + } + } + } +} From 03409a0f64e985e8bc07de8048e6da7039365aaa Mon Sep 17 00:00:00 2001 From: James Brundage <@github.com> Date: Mon, 14 Mar 2022 00:20:12 -0700 Subject: [PATCH 5/6] Updating Module Version [0.2] and Changelog --- CHANGELOG.md | 9 +++++++++ LightScript.psd1 | 10 +++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15f77a0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +## 0.2: +Adding: Disconnect-HueBridge, Disconnect-NanoLeaf, Disconnect-Twinkly (#2) +Adding Pixoo commands: Connect/Disconnect/Get/Set-Pixoo (#4) + +--- +## 0.1: +Initial Release of LightScript: Smarter Lighting with PowerShell + +Script your Hue Bridge, NanoLeaf, or Twinkly lights. diff --git a/LightScript.psd1 b/LightScript.psd1 index 0a9f702..3484ebb 100644 --- a/LightScript.psd1 +++ b/LightScript.psd1 @@ -1,5 +1,5 @@ @{ - ModuleVersion = '0.1' + ModuleVersion = '0.2' RootModule = 'LightScript.psm1' Description = 'Smarter Lighting with PowerShell' FormatsToProcess = 'LightScript.format.ps1xml' @@ -14,8 +14,12 @@ LicenseURI = 'https://github.com/StartAutomating/LightScript/blob/main/LICENSE' IconURI = 'https://github.com/StartAutomating/LightScript/blob/main/Assets/LightScript.png' ReleaseNotes = @' -0.1 ----- +## 0.2: +Adding: Disconnect-HueBridge, Disconnect-NanoLeaf, Disconnect-Twinkly (#2) +Adding Pixoo commands: Connect/Disconnect/Get/Set-Pixoo (#4) + +--- +## 0.1: Initial Release of LightScript: Smarter Lighting with PowerShell Script your Hue Bridge, NanoLeaf, or Twinkly lights. From b52055e967a92acdb6e1f2f95a9303b615c0f588 Mon Sep 17 00:00:00 2001 From: James Brundage <@github.com> Date: Mon, 14 Mar 2022 00:34:26 -0700 Subject: [PATCH 6/6] Updating About Topic and README --- README.md | 31 +++++++++++++++++++++++++++++++ en-us/about_LightScript.help.txt | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/README.md b/README.md index d780d41..41542a8 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ It currently can control: * [Philips Hue Bridges](https://www.philips-hue.com/) * [NanoLeaf](https://nanoleaf.me/) * [Twinkly](https://www.twinkly.com/) +* [Divoom Pixoo64](https://www.divoom.com/products/pixoo-64) The goal of LightScript is to let you control every light in your house, and do more than what most applications will let you. @@ -228,4 +229,34 @@ Get-Twinkly | Connect-Twinkly ~~~ +## Pixoo64 +The Pixoo App will let you know the device's IP address. From there, you can: + +~~~PowerShell +Connect-Pixoo -IPAddress 1.2.3.4 +~~~ + +To list connected devices, use: + +~~~PowerShell +Get-Pixoo +~~~ + +Here are a few things you can do with your Pixoo: + +~~~PowerShell +Set-Pixoo -Channel Cloud # Switch to the cloud Channel + +Set-Pixoo -Channel Visualizer # Switch to the visualizer + +Set-Pixoo -Visualizer 20 # Switch to a hidden visualizer + +Set-Pixoo -Stopwatch Start # Start a Stopwatch + +Set-Pixoo -Stopwatch Reset # Reset a Stopwatch + +Set-Pixoo -Timer "00:01:00" # Set a timer for one minute + +Set-Pixoo -RedScore 1 -BlueScore 0 # Keep a scoreboard +~~~ diff --git a/en-us/about_LightScript.help.txt b/en-us/about_LightScript.help.txt index d780d41..41542a8 100644 --- a/en-us/about_LightScript.help.txt +++ b/en-us/about_LightScript.help.txt @@ -9,6 +9,7 @@ It currently can control: * [Philips Hue Bridges](https://www.philips-hue.com/) * [NanoLeaf](https://nanoleaf.me/) * [Twinkly](https://www.twinkly.com/) +* [Divoom Pixoo64](https://www.divoom.com/products/pixoo-64) The goal of LightScript is to let you control every light in your house, and do more than what most applications will let you. @@ -228,4 +229,34 @@ Get-Twinkly | Connect-Twinkly ~~~ +## Pixoo64 +The Pixoo App will let you know the device's IP address. From there, you can: + +~~~PowerShell +Connect-Pixoo -IPAddress 1.2.3.4 +~~~ + +To list connected devices, use: + +~~~PowerShell +Get-Pixoo +~~~ + +Here are a few things you can do with your Pixoo: + +~~~PowerShell +Set-Pixoo -Channel Cloud # Switch to the cloud Channel + +Set-Pixoo -Channel Visualizer # Switch to the visualizer + +Set-Pixoo -Visualizer 20 # Switch to a hidden visualizer + +Set-Pixoo -Stopwatch Start # Start a Stopwatch + +Set-Pixoo -Stopwatch Reset # Reset a Stopwatch + +Set-Pixoo -Timer "00:01:00" # Set a timer for one minute + +Set-Pixoo -RedScore 1 -BlueScore 0 # Keep a scoreboard +~~~