Skip to content

Instantly share code, notes, and snippets.

@quonic
Last active February 21, 2024 16:38
Show Gist options
  • Save quonic/72604443b2385a02e7880b86d7900bc5 to your computer and use it in GitHub Desktop.
Save quonic/72604443b2385a02e7880b86d7900bc5 to your computer and use it in GitHub Desktop.
Function to control Divoom's Pixoo 64 over the network. This presumes that you have PowerShell 7 installed. Examples at the bottom of the file. Sometime the Pixoo will reboot when sending a command. No way to fix this at the moment.
#Requires -Version 7
# Current API documentation
# http://doc.divoom-gz.com/web/#/12?page_id=143
function Invoke-PlayGif {
[CmdletBinding()]
param(
[Parameter()]
[string]
$DeviceIP,
[Parameter(Mandatory = $true)]
[string]
$UrlGif
)
process {
if (-not $DeviceIP) {
$DeviceIP = Find-Pixoo | Select-Object -First 1
}
if ($UrlGif -like "http://*") {
$get = Invoke-RestMethod -Uri "http://$DeviceIP/get"
if ($get -like "*Hello World divoom!*") {
$Body = [PSCustomObject]@{
Command = "Device/PlayTFGif"
FileType = 2
FileName = $UrlGif
} | ConvertTo-Json -Compress
$res = Invoke-RestMethod -Method Post -Uri "http://$DeviceIP/post" -Body $Body
if ($res.error_code -and $res.error_code -eq 0) {
Write-Verbose "Success"
$Body = [PSCustomObject]@{
Command = "Draw/GetHttpGifId"
} | ConvertTo-Json -Compress
$res = Invoke-RestMethod -Method Post -Uri "http://$DeviceIP/post" -Body $Body
if ($res.error_code -and $res.error_code -eq 0) {
$res.PicId
Write-Verbose "Success"
return $true
# Don't know if this is needed
# Set-Channel -DeviceIP "192.168.1.199" -Channel Cloud
}
}
else {
Write-Error "Failed to send gif to $DeviceIP."
return $false
}
}
else {
Write-Error "Device not found. Please check the IP address."
return $false
}
}
else {
Write-Error "Invalid url: https isn't supported."
return $false
}
}
}
function Set-Channel {
[CmdletBinding()]
[OutputType([int])]
param(
[Parameter()]
[string]
$DeviceIP,
[Parameter(Mandatory = $true)]
[ValidateSet("Faces", "Cloud", "Visualizer", "Custom")]
[String]
$Channel
)
begin {
$Index = if ($Channel -eq "Faces") {
0
}
elseif ($Channel -eq "Cloud") {
1
}
elseif ($Channel -eq "Visualizer") {
2
}
elseif ($Channel -eq "Custom") {
3
}
else {
Write-Error "Invalid channel"
}
}
process {
if (-not $DeviceIP) {
$DeviceIP = Find-Pixoo | Select-Object -First 1
}
$Body = [PSCustomObject]@{
Command = "Channel/SetIndex"
SelectIndex = $Index
} | ConvertTo-Json -Compress
$res = Invoke-RestMethod -Method Post -Uri "http://$DeviceIP/post" -Body $Body
if ($res.error_code -and $res.error_code -eq 0) {
Write-Verbose "Success"
return $true
}
else {
Write-Error "Failed to set channel"
return $false
}
}
}
function Get-Channel {
[CmdletBinding()]
param (
$DeviceIP
)
process {
if (-not $DeviceIP) {
$DeviceIP = Find-Pixoo | Select-Object -First 1
}
$Body = [PSCustomObject]@{
Command = "Channel/GetIndex"
} | ConvertTo-Json -Compress
$res = Invoke-RestMethod -Method Post -Uri "http://$DeviceIP/post" -Body $Body
if (($res.error_code -eq 0) -or $res.SelectIndex) {
Write-Verbose "Success"
$ret = switch ($res.SelectIndex) {
0 { "Faces" }
1 { "Cloud Channel" }
2 { "Visualizer" }
3 { "Custom" }
Default { "Error" }
}
return $ret
}
else {
Write-Error "Failed to get channel, Error: $($res.error_code)"
return $false
}
}
}
function Find-Pixoo {
param(
$IPAddress
)
begin {
function Get-PixooIP {
$network = (
(
Get-NetIPInterface -ConnectionState Connected -AddressFamily IPv4 -Dhcp Enabled |
Get-NetIPAddress
).IPAddress -split '\.'
)[0..2] -join '.'
(Get-NetNeighbor | Where-Object { $_.IPAddress -like "$network*" -and $_.LinkLayerAddress -like "7C-87-CE*" }).IPAddress
}
}
process{
if ($IPAddress) {
$get = Invoke-RestMethod -Uri "http://$IPAddress/get"
if ($get -like "*Hello World divoom!*") {
$IPAddress
}
}
else {
$IPs = Get-PixooIP
if ($IPs.Count -eq 0) {
1..254 | ForEach-Object {
$(($network -split '\.')[0..2])
Test-Connection -Ping -Count 1 -TimeoutSeconds 1 -IPv4 -TargetName "$(($network -split '\.')[0..2]).$_"
}
$IPs = Get-PixooIP
if ($IPs.Count -eq 0) {
throw "Pixoo64 not found on network"
}
}
foreach ($ip in $IPs) {
try {
$get = Invoke-RestMethod -Uri "http://$Ip/get"
if ($get -like "*Hello World divoom!*") {
$Ip
}
break
}
catch {
#
}
}
}
}
}
function Get-FaceType {
[CmdletBinding()]
param ()
process {
$Url = "https://app.divoom-gz.com/Channel/GetDialType"
$ret = Invoke-RestMethod -Method Post -Uri $Url
if ($ret.ReturnCode -eq 0) {
return $ret.DialTypeList
}
}
}
function Get-FaceList {
[CmdletBinding()]
param (
[Parameter()]
[ValidateSet("Social", "normal", "financial", "Game", "HOLIDAYS", "TOOLS")]
$Type = "normal",
[Parameter()]
[ValidateRange(1, 30)]
$Page = 1
)
process {
$Url = "https://app.divoom-gz.com/Channel/GetDialList"
$Body = [PSCustomObject]@{
DialType = $Type
Page = $Page
} | ConvertTo-Json -Compress
$ret = Invoke-RestMethod -Method Post -Uri $Url -Body $Body
if ($ret.ReturnCode -eq 0) {
return $ret.DialList
}
}
}
function Set-Face {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[int]
$FaceId,
[string]
$DeviceIP
)
process {
if (-not $DeviceIP) {
$DeviceIP = Find-Pixoo | Select-Object -First 1
}
$Body = [PSCustomObject]@{
Command = "Channel/SetClockSelectId"
ClockId = $FaceId
} | ConvertTo-Json -Compress
$res = Invoke-RestMethod -Method Post -Uri "http://$DeviceIP/post" -Body $Body
if ($res.error_code -eq 0) {
Write-Verbose "Success"
return $true
}
else {
Write-Error "Failed to set Face, Error: $($res.error_code)"
return $false
}
}
}
function Get-Face {
[CmdletBinding()]
param (
$DeviceIP
)
process {
if (-not $DeviceIP) {
$DeviceIP = Find-Pixoo | Select-Object -First 1
}
$Body = [PSCustomObject]@{
Command = "Channel/GetClockInfo"
} | ConvertTo-Json -Compress
$res = Invoke-RestMethod -Method Post -Uri "http://$DeviceIP/post" -Body $Body
if ($res) {
Write-Verbose "Success"
return $ret
}
else {
Write-Error "Failed to set Face, Error: $($res.error_code)"
return $false
}
}
}
# $Face = Get-FaceList | Where-Object {$_.Name -like "Big Time"}
# $IP = Find-Pixoo
# # Get-Channel -DeviceIP $IP
# # Set-Channel -Channel Faces -DeviceIP $IP
# Set-Face -FaceId $Face.ClockId -DeviceIP $IP
@JJWatMyself
Copy link

This is really helpful, thank you!

Have you had any luck with some of the undocumented configurations like being able to set the value for SingleGalleyTime?

Running:

{
    "Command":"Channel/GetAllConf"
}

Returns:

{
  "error_code": 0,
  "Brightness": 100,
  "RotationFlag": 0,
  "ClockTime": 0,
  "GalleryTime": 0,
  "SingleGalleyTime": 0,
  "PowerOnChannelId": 0,
  "GalleryShowTimeFlag": 0,
  "CurClockId": 144,
  "Time24Flag": 0,
  "TemperatureMode": 0,
  "GyrateAngle": 0,
  "MirrorFlag": 0,
  "LightSwitch": 1
}

@quonic
Copy link
Author

quonic commented Jul 14, 2022

@JJWatMyself

I don't think so, but I haven't had the time to work on it.

The last time I worked on it was about 4 months ago and I built a mock server for testing. Unless they add more API's to their documentation, I couldn't figure out how.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment