[APP][Pro] Divoom Pixoo64

New app to support the Divoom Pixoo 64 with a focus on stability and ongoing maintenance. An older community app exists but hasn’t been updated in a while and may be unreliable depending on your setup.

Version 0.1.1 is live :

The Pixoo 64 is a 10.3” Wi-Fi pixel art display featuring a 64×64 LED matrix. It’s commonly used to showcase pixel art, act as a pixel clock, or display live information (social media counters, gaming stats, etc.). My main use case is displaying album artwork from my Apple audio ecosystem using Apple TV & HomePod | Homey.

Pairing

  1. Homey app → Devices → Add device → Pixoo64

  2. Use Auto-detect (cloud API finds devices on the same network) or enter the IP manually

  3. Find the IP in the Divoom app: Device → Settings → IP address

    Tip: Set a static DHCP reservation in your router so the IP never changes.

Core concept: two rendering systems

The app exposes two independent rendering systems that live side-by-side on the display. Understanding the difference is key to building reliable flows.

1 — Canvas (buffer-based)

The app maintains a 64×64 RGB canvas in memory for each device. Drawing operations (`Fill`, `Draw rect`, `Draw image`, `Draw pixel text`, `Draw LaMetric icon`) paint pixels onto this canvas. The canvas is sent to the device as an animated GIF via the `Draw/SendHttpGif` firmware command.

Managed by Homey app (RAM + disk cache)
Compositing : Layers stack — each draw adds on top
Animated sprites : Multiple GIF sources merged into one animation
Screenshot : Full capture possible
Font rendering : PixelFont library (Tiny + 7 PNG fonts)
Persistence : Saved to `/userdata/` — survives app restarts

Caveats:

  • Every canvas send triggers a full GIF upload. The Pixoo firmware can only receive one frame at a time, so animation frames are sent sequentially — large or fast animations take longer to push.
  • Animated GIFs are capped at 12 frames to avoid oversized payloads.
  • Multiple animated sprites (different GIFs on the same screen) are merged into a single animation whose length is the LCM of the individual frame counts.

2 — Firmware overlays (text-based)

Text placed with Draw text at or Display text uses `Draw/SendHttpText`, a separate firmware command. These overlays are rendered by the Pixoo firmware on top of the canvas GIF, independently of it.

Managed by Pixoo firmware
Fonts available : Firmware fonts 0–7 (selected by number)
Supports scrolling : Yes (`Display text`)
Captured by screenshot : No
Survives canvas sends : Automatically re-applied (see below)

Caveats:

  • `Draw/SendHttpGif` internally calls `Channel/SetIndex`, which wipes all firmware text overlays. The app works around this with an internal registry: every `Draw text at` call is stored, and after each canvas send the texts are automatically re-applied. You do not need to manage this manually.
  • Up to 19 independent text slots (IDs 2–20). Each ID is an independent overlay; writing to the same ID replaces it.
  • `Display text` (scrolling) uses a different mechanism - it clears the registry and takes over the display. Do not mix `Display text` with `Draw text at` in the same scene.
  • Firmware built-in widgets — Scoreboard, Timer - are also firmware-side and share the same limitations: they are not captured by screenshots and are cleared when the canvas is next sent.

Flow cards reference

Device control

  • Set channel: Switch to a built-in channel: 0=Clock, 1=Cloud, 2=Visualizer, 3=Custom, 4=Black
  • Sync time: Push the current time to the device’s internal clock
  • Play buzzer: Sound the built-in buzzer for N seconds
  • Screen on/off: Toggle via the device tile or an on/off flow card

Canvas (buffer) operations

  • Fill screen: Flood-fills the canvas with a solid colour. Previous content is replaced.
  • Draw rect: Paints a filled rectangle with opacity (0–100 %). |
  • Draw image at: Downloads a URL (PNG/GIF), resizes to W×H, composites at (X,Y).
  • Display Apple cover: Same as Draw image at, but auto-switches Apple CDN URLs from .jpg to .png.
  • Draw LaMetric icon: Fetches an icon from the LaMetric library by ID. `Frame=0` uses all frames (animated). Zoom 1–8 scales the 8×8 native size. LaMetric: Web (as allowed by the terms of use)
  • Draw pixel text: Renders text onto the canvas using a pixel font. See Font section below.
  • Display image: Sends a full-screen image, replacing the canvas entirely (no compositing).

Firmware overlay operations

  • Draw text at: Places static text at pixel coordinates using a firmware font (0–7). Use a unique Text ID per label.
  • Display text: Scrolling text — takes over the display, clears all Draw text at overlays.
  • Clear text overlays: Removes all `Draw text at` labels from device and registry.
  • Show scoreboard: Firmware scoreboard widget (red/blue scores).
  • Start / Stop timer: Firmware countdown timer.

Batching

  • Hold display: Suspends all canvas sends. Draw operations still update the local canvas.
  • Release display: Flushes everything accumulated since Hold as a single send. Use this to avoid the display updating progressively when building a complex scene.

Screenshots

  • Take screenshot: Saves the current canvas (with sprites at frame 0) to a numbered slot. Firmware text overlays are not captured.
  • Display screenshot: Restores a saved slot to the canvas and pushes it to the device.

Pixel fonts

`Draw pixel text` uses the built-in PixelFont renderer, text is painted directly onto the canvas buffer.

  • Tiny: 3×5 px, uppercase only
  • Other Fonts: 9 px tall, preserve case (a–z and A–Z both present). Accented characters are automatically stripped to their base form (é>e, ç>c, etc.). Some punctuations will be missing.

Typical flow patterns

Static scene with text:

  1. Hold display
  2. → Fill screen (black)
  3. → Draw image at (album art, 0,0, 48×48)
  4. → Draw text at (artist, x=0, y=50, font=2, textId=2)
  5. → Draw text at (title, x=0, y=57, font=2, textId=3)
  6. → Release display

Complex scene with text & icons:

  1. Hold display
  2. → Fill screen (black)
  3. → Draw image (png)
  4. → Draw pixel texts
  5. → Draw LaMetric icons / or Gifs
  6. → Release display

Samples

Flow example :

Warning (again)

The more elements you try to push in parallel the higher the risk of crash (app will auto restart after a few secondes). Same with GIFs usage or pushing very large PNG. Homey has strict control on ram usage and the Pixoo is itself not very flexible which in turn could cause reboot. Can’t do much about it.

Note
This app is partially vibe-coded. If that’s an issue for you (code quality/process/compliance expectations), please don’t use it.

Nice! Looking forward to it. The other Divoom app doesn’t seem to be stable and I couldn’t get it to display text correctly.

The old app works fine here.

Only using the deviceclass=light for Pixoo64 is bad, because it’s turned off every time I use the Homey flow card for “all lights off” :frowning:

I’ll check if moving it to the Video category doesn’t trigger any issue.
I’m working on a few new features to make building dashboards simpler, obviously it won’t be needed for everyone (and I’m not sure I’ll have feature parity with the legacy app), but it should for some people :slight_smile:

Changing an app’s category doesn’t change anything about the app itself, it’s just part of the App Store metadata which is being used to display the apps in the Homey App Store.

Sorry, I’ve meant Device Class

I hope to release the test version this week.
Here are some new screenshots as examples of what you can do :

If you have any needs that’s the time :slight_smile:
More information about current features in the first post.

AIO from my computer broke while I was working on the metadata for submission, it will be done next week unfortunately, but I had time to work on a new pixel font with dynamic width (so most characters are 3 pixels wide to optimize space, but some like the W are wider to actually look like a W).

First test version is now live for test.
You don’t have to uninstall the “legacy” app to test this one and its features.

Divoom Pixoo64 | Homey

Check the first post here to get an overview of how things works.
Don’t hesitate to share any issue or question :slight_smile:

Thanks for the new app! Using the old app (and coming from a PLC background) I created a flow mainly based on ‘bits’ to make me remember to turn off the pilot light of my water-heater when I don’t use it (now I use 3 m3 gas per month in stead of 15) and to make visible if there are lights turned on in the bedroom. A presence sensor avoid the Divoom to turn on if no one is there.

I use the Micro Webserver to save the 64x64 png pictures of the bitsituation:

And the flow ‘calculates the picture’ by combining the state of the Gas and S(bedroom) bits. Works like a charm. The rest of the pictures added more fun to this project. The flow became quite complex though :smiley:

the Divoom is now the pride and joy of my Homey installation.

Now the pictures can be smaller and have a location I might one day start all over again…

Bert

Yeah I saw your post on github, it was a big part of my “oh I’m not the only one who wants more from it !” moment :slight_smile:

I’m pretty sure with the new system you can so something a big easier to manage especially with the nice animated LaMetric Icons (for example Icon ID: 68233 : “gas_flame_alert”)) and the “Tiny Font” feature to write more text !
Keep me updated if you do so, even if only one person use it I’d be happy (actually I know there has been a total of 4 install for now, probably why I didn’t get any update from Homey on the app approval…)

6e7de350-0d13-4473-976c-f284808372e6

This whole design for example (appart from the logic to choose item, it’s more a template here, and sorry for the french), only takes this:

It’s pretty much FREEZE, ERASE, “line by line drawing”, GIF, DISPLAY
No need to host or build the image elsewhere.

There are only so many people that have a Homey AND a Divoom Pixoo 64 AND found this topic and the new app. So it makes sense that the downloads are not in there enourmous numbers. In the coming days I will start expirimenting with the new features. Thanks again.

The app is now officially published ! :tada:

I am one of the 4 downloads (Français aussi ;). I just begun dabbling with the app before beeing away from home. Rather impatient to be back and finally use my Pixoo to its full extent !

Using Homeyscript I could replace all 32 light- and gas pictures with 5 large and 6 full screen pictures and writing text (with finally a nice font).

The full screen icon part is somewhat simplified compared to the old flow.
It’s a matter of setting a value higher than 31. To remove it from screen it must be 0 again.

//Gettting values from flow 
let {slp, bed, bad, kst, gas, big} = JSON.parse(args[0]);
//Setting Pixoo dev address (to turn it off in script)
var Pixoo = await Homey.devices.getDevice
({id:<Pixoo dev. address>});
//Clearing tags to use in flow
await Show('','',0,0,0,'',0,'',0)
// Calculating the code what to show
let Code = 0;
if (slp == "✓") {Code += 2**0;}
if (bed == "✓") {Code += 2**1;}
if (bad == "✓") {Code += 2**2;}
if (kst == "✓") {Code += 2**3;}
if (gas == "✓") {Code += 2**4;}
if (big !== 0)  {Code = big;}
 if (Code >0){
Pixoo.setCapabilityValue('onoff', true);
}
switch (Code) {
 case 0: //Nothing to see? Turn off!
Pixoo.setCapabilityValue('onoff', false) ;break;
 case 1: //Slaapfan Only
await Show('FAN_L','',64,48,14,'SLAAPFAN',8);
await Dimlevel('slp'); break;
 case 2: //Bedlamp Only
await Show('BED_L','',64,48,14,'BEDLAMPJE',5);
await Dimlevel('bed'); break;
 case 3: //Slaapfan & Bedlamp
await Show('FAN_L','BED_L',32,24,20,'SLP  BED',6); break;
 case 4: //Badlamp Only
await Show('BOL_L','',64,48,14,'BADLAMP',10);
await Dimlevel('bad'); break;
 case 5: //Slaapfan & Badlamp
await Show('FAN_L','BOL_L',32,24,20,'SLP  BAD',6); break;
 case 6: //Bedlamp & Badlamp
await Show('BED_L','BOL_L',32,24,20,'BED  BAD',6); break;
 case 7: //Slaapfan & Bedlamp & Badlamp
await Show('LMP_L','',64,36,14,'BED  BAD',6,'BAD',24); break;
 case 16: //Gas Only
await Show('GAS_L','',64,36,14,'',0,'',0); break;
 case 17: //Gas & Slaapfan
await Show('GAS_L','',64,36,14,'SLAAPFAN',8); break;
await Show('WAS_F','',64,64,0); break;
 case 33: //Battery charging
await Show('BAT_F','',64,64,0); break;
 case 34: //Alarm!
}
async function Show (Plaatje, Qlaatje, Breed, Hoog, Posy, Woord, Start, Voord, Vtart){
await tag('Pic',Plaatje);await tag('Qic', Qlaatje)
await tag('Psx',Breed); await tag('Psy',Hoog); await tag('Ply',Posy);
await tag('Titel',Woord); await tag('Xpos',Start);
await tag('Vitel',Voord); await tag('Zpos',Vtart);
}
async function Dimlevel (Devy){
if (Devy == 'slp'){Devy = await Homey.devices.getDevice
	({id:'<Slaapfan dev. address>'});}
if (Devy == 'bed'){Devy = await Homey.devices.getDevice
    ({id:'<Bedlamp dev. address>});}
 if (Devy == 'bad'){Devy = await Homey.devices.getDevice
    ({id:'<Badlamp dev. address>'});}
if (Devy.capabilitiesObj.dim.value == 0.80) {
 await tag('Vitel','H'); await tag('Zpos',51);}
else
{await tag('Vitel','L'); await tag('Zpos',51);} 	
}

Cool, you can take screenshots of the divoom with the dedicated feature too show us (it’s stored here: Homey Developer Tools)

Yes, please @Lacobo.

The result is basically the same as before, but now with only 7 in stead of 32 pictures:

image image image image image image image

It’s a bit slower to build up, but more flexible.

I now have (large and small) BED_L, BED_S, BOL_L, BOL_S, FAN_L, FAN_S and GAS_L and can build any of the 32 pictures with some text. A Switch(case) of > 300 lines of code does the trick :grinning_face: .

if you think about potential improvements don’t hesitate :slight_smile:
(and we are at 15 install for now, better than 4)

Finished the project! Reduced my number of pictures to 11 (and added the lightbulb).
Scaling is good enough, so I could ditch the small pictures.

The number of tags to transfer from script to flow is reduced to 10 (from 16).
The script can now turn the Pixoo on (if it needs to show something) and off (if nothing to see!) and I use numbers 32 - 37 to show the Full screen pictures. Also added a dimming status on 3 lights.

It was a time consuming but fun conversion project. Also very happy that I now know how to get flow values into a script and tags out of it to use in the flow. That was always a bit unclear for me, but now I fully understand :man_technologist:. Is very useful knowledge for making more scripts.

I’ll update my flow and (parts of the) script in my previous post. If anyone is interested in the full script I can post it somewhere. Not sure if this forum is happy with 116 lines of code.

Update april 17: The script is now more compact using async functions. Its a great Java script code learning experience!