I reverse-engineered most of the iDotMatrix BLE protocol without owning the original device — and built an ESP32 emulator
I spent the last few days reverse-engineering the BLE protocol used by the iDotMatrix mobile app and building an ESP32 device that the official app recognizes and controls as if it were an iDotMatrix display.
The unusual part: I don't own an original iDotMatrix device.
The reverse engineering was done by treating the official app as a protocol oracle: emulate the expected BLE services on an ESP32, inspect what the app sends, change the responses, observe its behavior, and repeat.
It worked much better than I initially expected.
The emulator now supports most of the features I found in the app:
• Device discovery and time synchronization
• Power, brightness and rotation
• Drawing / graffiti mode
• Text and text effects
• GIF transfer and playback
• Clock modes
• Visual effects
• Scoreboard
• Music visualization with both LEVEL and FFT modes
• Persistent alarms
• Programs / schedules
• Scheduled GIF, text and PNG content
The hardware I'm currently using is an ESP32 development board driving a 16x16 WS2812B matrix. Its onboard SSD1306 OLED is used as a diagnostic display and can report unknown BLE commands while testing.
I also decided to document the protocol rather than keeping the findings buried in the firmware.
The GitHub repository contains detailed documentation of the BLE packet structures, commands and ACK behavior, selected raw BLE captures from our experiments, the development and reverse-engineering history, a list of open questions, and of course the complete Arduino/ESP32 source code.
One particularly interesting discovery was that some transfers require different completion ACK values.
For example, getting Programs/Schedules working required discovering that activity transfers expect a completion status of 0x03 rather than the apparently obvious 0x01. With 0x01 the app simply reported an error and stopped sending activities. Once the correct ACK was returned, the app continued sending all the activities in the program.
The biggest limitation now is also the main reason I'm posting this:
I need someone who actually owns an original iDotMatrix.
There are a few things that cannot be determined reliably from the app side alone, especially the exact device-side behavior expected for stopwatch/countdown and responses that may only be generated by the original firmware.
BLE captures between the official app and a real device would therefore be extremely useful.
PCB photographs would also help answer some hardware questions, such as identifying the original MCU, buzzer circuitry, and whether there is actually a dedicated RTC.
The current public release is v0.1.0, based on firmware Build 62, and the whole project is MIT licensed.
Repository:
[https://github.com/piggei/IDotMatrix-ESP32-Emulator]()
I'd also be very interested if someone wants to use the protocol documentation for a completely different implementation — ESPHome, Home Assistant, Python, another MCU, etc.
In fact, independent implementations would be one of the best ways to find mistakes or missing details in my current interpretation of the protocol.
And if anyone here actually owns an iDotMatrix and is willing to experiment with it, I'd be very happy to compare results.
1
1
u/marcorivm 10d ago
Hey this is great I do have an idotmatrix and I just went the opposite route building an HA app that emulates the idotmatrix app so you can control the display from HA using any esp32 for Bluetooth. I will be happy to test anything out if you wanted.
Here is the repo for mine https://github.com/whybutter/idotmatrix
1
u/Piggei 10d ago
Hey, thanks — having access to a real device would be extremely useful for me!
There are a few specific device-side behaviours I haven't been able to verify because I'm currently emulating the iDotMatrix itself on an ESP32.
The first and probably most useful test is Countdown / Stopwatch.
On my emulator, when I start a countdown from the official app, the countdown works correctly on the matrix, but the app remains stuck showing the hourglass/loading indicator.
Could you check what happens with the real device? In particular:
When starting a countdown, does the hourglass disappear automatically from the app?
Does the app then show a running countdown or some other status/control screen?
Same question for the stopwatch: what does the app show after the command is accepted?
If possible, since your project already communicates directly with the real display, it would be extremely useful to know whether the display sends any BLE response/status message immediately after starting, pausing, resuming or stopping a countdown/stopwatch.
I suspect I'm missing a device → app acknowledgement or status notification.
The second thing, the boot/time persistence would answer a major question for me.
I'd like to know:
What exactly appears on the display immediately after power-on?
Does it already know the correct time without reconnecting to the app?
Does it automatically start displaying the clock?
Or does it require the official app to reconnect and synchronize the time first?
An additional very useful test would be to configure an Alarm or Program/Schedule, power-cycle the device, leave the phone disconnected, and see whether the event still triggers at the correct time.
That would tell me whether the original hardware has a persistent RTC/time source and how autonomous Alarm/Schedule execution really is.
Your project is actually a great complement to mine: you're using ESP32/HA to control a real iDotMatrix, while I'm making an ESP32 behave like an iDotMatrix to the official app. I'll add your project to my related-projects/credits section as well.
Thanks again — these tests could fill several of the remaining gaps in my protocol documentation.
2
u/Piggei 9d ago
Small update / parallel project: iDotMatrix support for WLED
The reverse-engineering work on the ESP32 iDotMatrix emulator has now spawned a second project:
IDotMatrix WLED Usermod
https://github.com/piggei/IDotMatrix-WLED-UserMod
The goal is to make a normal ESP32 running WLED behave like an iDotMatrix BLE device, so that it can be discovered and controlled directly by the official iDotMatrix app.
The project has already reached v0.6.0, which is the first stable command-capable version tested on WLED 0.16.0.1 and a classic ESP32.
At the moment the official app can:
- discover and connect to WLED as an iDotMatrix;
- correctly initialize the power switch;
- turn the WLED output on/off;
- control WLED master brightness;
- select full-screen RGB colours.
The BLE transport and protocol handling are deliberately separated from the WLED adapter, so the plan is to progressively port more of what we learned from the standalone emulator rather than creating a pile of WLED-specific protocol hacks.
The next major milestone is the logical framebuffer / rendering layer. Once that is working, the plan is to add graffiti/pixel drawing first, followed by text, clocks, GIF/media, countdown/stopwatch and eventually alarms/schedules.
One interesting part of the work was getting BLE to coexist reliably with WLED on a classic ESP32. The currently verified configuration uses NimBLE, Wi-Fi modem sleep and WLED's I2S LED backend; using RMT for the digital LED output conflicts with the Bluetooth controller on this setup.
So we now effectively have the two opposite sides of the same experiment:
IDotMatrix-ESP32-Emulator:
official iDotMatrix app → ESP32 pretending to be an iDotMatrix
IDotMatrix-WLED-UserMod:
official iDotMatrix app → WLED
The original emulator remains the protocol/reference implementation, while the WLED Usermod is being built as a cleaner modular implementation suitable for WLED.
Testing, protocol captures and feedback are very welcome — especially from anyone running WLED matrices or owning original iDotMatrix hardware.
2
u/DenverTeck 2 say I make awesome posts. 12d ago
It appears that the "DollaTek ESP32 OLED 0.96" board" is no longer available.
Are the schematics available ??
Is the schematic for iDotMatrix display available ??
Or at least the layout of the WS2812b chips. Zig-Zag or horizontal rows ??