Welcome to UnexpectedMatrixPixels — a direct, performance-focused Home Assistant integration for cheap BLE pixel matrices (32×32, 64×16 and similar). If you bought a random AliExpress LED matrix, this project makes it actually useful: draw text, icons, images, animations, and even a live-preview camera entity. Low-level BLE control + a high-level drawing service = full creative freedom.
Think of it like running a tiny LED GPU from Home Assistant. Retro, fast, and practical.
- Cheap Chinese LED matrices are fun but hard to integrate reliably.
- UMP exposes raw frame control over BLE and a friendly
unexpected_matrix_pixels.draw_matrixservice. - You can send pixel arrays, icons, fonts, scrolling text, images (local or URL), and simple animations.
- Supports IDOTMatrix / iPixel devices (IDM BLE protocol) with fast frame streaming.
- Send PNG frames or pixel lists directly to the display.
- Built-in pixel fonts (3x5, 5x7) and an "awtrix" glyph set.
- Material Design Icon (MDI) rendering (requires adding the provided font/meta if you want icons).
- Services for drawing, clearing, and syncing time.
- Optional camera entity for a quick live-preview of the last-sent frame.
- Works well even at higher FPS on stable hardware or with a Bluetooth proxy.
- Copy the
custom_components/unexpected_matrix_pixelsfolder into your Home Assistantcustom_componentsdirectory. - Ensure required packages are available (Pillow, bleak, bleak-retry-connector). Home Assistant will usually handle installation when the integration is added, or install them in your environment.
- Add the integration via Home Assistant UI (Integrations → Add Integration → Unexpected Matrix Pixels). Use Bluetooth discovery or manual MAC entry.
- Use the created
lightentity to control drawing. Optionally enable the camera entity to preview the last frame.
- Provide the MAC address of the BLE device and the matrix width/height (defaults: 32×32).
- After setup you get a light entity (control + draw) and an optional camera entity (preview).
unexpected_matrix_pixels.draw_matrix- elements: list of drawing elements (text, textscroll, textlong, icon, pixels, image, line)
- background: RGB list (e.g.
[0,0,0]) - transition: optional object with
type/duration/fps
unexpected_matrix_pixels.clear_display— clear the screen and reset internal stateunexpected_matrix_pixels.sync_time— sync device clock (when supported)
Elements format (examples)
text:{ "type": "text", "content": "Hi", "x": 0, "y": 0, "font": "5x7", "color": [255,255,255] }textlong: long text with automatic wrapping/pagingtextscroll: single-line horizontal marqueeicon:{ "type": "icon", "name": "mdi:home", "x": 0, "y": 0, "size": 16, "color": [255,255,0] }pixels:{ "type": "pixels", "pixels": [ [x,y,r,g,b[,a]], ... ] }image:{ "type": "image", "url": "http://...", "x": 0, "y": 0, "width": 16, "height": 16 }line:{ "type": "line", "x":0, "y":0, "x2":10, "y2":0, "color":[r,g,b] }
Below are two sample displays that show what UMP can do. Replace the GIF files in examples/ with your own recordings to preview them in this README.
Spotify display (artist/title + progress bar):
Large dual clock with edge snake and rotating info panel (64×16):
If you want me to add the GIFs to the repository for you, upload the spotify.gif and clock.gif files here or confirm and I will add them (please provide the GIF binaries).
- For smooth high-FPS animation, consider using a Bluetooth proxy (ESP32-S3 or similar) to improve throughput.
- Use
textlongfor paged text andtextscrollfor marquees. - Prefer PNG with alpha for layered images.
- Keep payloads reasonable — very large frames will be chunked and may slow streaming.
Provided as-is. Contributions welcome: issues, PRs, and examples are the best way to improve this integration. Share your dashboards and animations!
Enjoy turning cheap LED matrices into useful displays — long live the pixels.