ESP32 REMOTE turns a supported ESP32 board into a Bluetooth HID remote learner, emulator and translator. It can learn the remote supplied with a device, present compatible controls back to that device, and map a different Bluetooth remote onto those controls. One useful application is adding a device that a Harmony Hub or another universal remote does not know about.
The XGIMI Titan Noir remote is included as a verified profile because its Power On command uses an unusual address-bound Bluetooth advertisement. XGIMI hardware is not required. Guided setup can build profiles for other supported Bluetooth HID remotes.
The web interface has no password. Use ESP32 REMOTE only on a trusted network.
You need:
- a board using the original dual-mode ESP32 chip with at least 4 MB flash
- a data-capable USB cable
- a computer running Chrome or Edge
The M5Stack Atom Lite is one tested, compact option, but it is not required.
- Open this repository's Releases page and download
esp32-remote.factory.binfrom the latest release. - Connect the ESP32 board to the computer by USB.
- Open ESPHome Web in Chrome or Edge.
- Select Connect, choose the USB device, then select Install.
- Choose
esp32-remote.factory.binand wait for installation to finish.
If no USB device appears, try another cable. Many USB cables provide power but do not carry data.
- Wait about 20 seconds after installation.
- On a phone or computer, join the Wi-Fi network ESP32 REMOTE.
- If the Wi-Fi setup page does not open, visit http://192.168.4.1/.
- Choose your 2.4 GHz home Wi-Fi network and enter its password.
- Rejoin your normal Wi-Fi, then open http://esp32-remote.local/.
If the local address does not open, find esp32-remote in your router's device
list and open the IP address shown there. A fresh device opens guided setup. The
web interface then explains how to learn the original remote, map another remote
and pair ESP32 REMOTE with the target device.
“Any ESP32” is not quite accurate for the current firmware. It uses Bluetooth
Classic and Bluetooth Low Energy at the same time, so the ready-made image
targets the original dual-mode ESP32. Current ESP32-S2, ESP32-S3, ESP32-C and
ESP32-H boards are not drop-in targets because they do not provide the Classic
Bluetooth input path used here. The default build uses the generic esp32dev
definition and expects at least 4 MB flash.
The ready-made image uses GPIO39 as its physical confirmation input. That suits
the Atom Lite front button. On another original-ESP32 board, connect a momentary
button between GPIO39 and ground, or change confirmation_button_gpio when
building the firmware. The button confirms sensitive operations; ordinary web
remote use does not require it.
The current profile format supports:
| Role | Current support |
|---|---|
| Remote being cloned | BLE HID with keyboard and consumer-control input reports |
| Remote used as the controller | BLE HID or Bluetooth Classic HID |
| Power-on behaviour | Static or counter-based BLE manufacturer advertisements |
| Bundled verified profile | XGIMI Titan Noir, including its address-bound Power On packet |
This is a broad Bluetooth HID implementation, not a universal Bluetooth protocol recorder. Vendor-specific GATT protocols, non-HID remotes, arbitrary HID report shapes and Bluetooth Classic target emulation need additional protocol adapters. The learner reports an unsupported capture instead of inventing a profile.
One firmware image contains two modes:
- Setup mode learns a target remote's BLE identity, HID reports, timings and Power On advertisement, then learns the controller remote and its mappings.
- Bridge mode exposes the compatible BLE HID target interface, translates input from the controller remote, serves the browser remote and runs the learned Power On programme.
A normal restart changes modes. Profiles, mappings, bonds and rolling wake counters are stored in NVS. The target component remains profile-driven; its XGIMI-specific advertising layout is selected only when the installed wake programme matches that bundled profile.
The implementation is deliberately small for the original ESP32's shared Wi-Fi and Bluetooth memory. Scanning runs only when requested, captured evidence and runtime tables have fixed bounds, Bluetooth callbacks avoid avoidable allocation, and both interfaces are stored as deterministic gzip data in flash. The build fails if an OTA slot has less than 10% free or a static memory region exceeds 92%.
Install Python 3.11 or newer, then run:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m pip install -e .
.venv/bin/python scripts/create_secrets.py
.venv/bin/esp32-remote firmware buildTo use another original-ESP32 board or confirmation pin, edit the substitutions
and board definition in esp32-remote.yaml before building.
Flash a connected board from the command line with:
.venv/bin/esp32-remote firmware flash --device /dev/cu.usbserial-XXXXXXXXOn Linux the serial path is usually /dev/ttyUSB0. On macOS, run
ls /dev/cu.usbserial-* after connecting the board.
Run the checks with:
.venv/bin/python -m unittest discover -v
.venv/bin/esphome config esp32-remote.yamlThe project CLI compresses and embeds the HTML interfaces during firmware builds. The generated C++ headers are temporary and are not stored in Git.
Validate or sanitise a profile with:
.venv/bin/esp32-remote profile validate profiles/xgimi-titan-noir.profile.json
.venv/bin/esp32-remote profile sanitise private-remote.json \
--output shareable-remote.jsonesp32-remote.yamlassembles the production image and generic HID skeleton.components/esp32_remote_configcontains guided discovery, capture and mapping.components/esp32_remote_webcontains the everyday browser remote.components/esp32_remotevalidates installed profiles and translates input.components/target_remoteemulates the target-side BLE HID remote.esp32_remotevalidates profiles, analyses captures and enforces build budgets.profilescontains shareable profiles, including the bundled XGIMI example.
See docs/architecture.md for the system boundary and
docs/implementation-status.md for verified
behaviour. The remaining XGIMI documents are profile-specific evidence, not
requirements of ESP32 REMOTE itself.
This project is licensed under GPL-3.0. See LICENSE and
THIRD_PARTY_NOTICES.md.