The primary goal of this project is to solve a common compatibility issue: many affordable haptic toys use generic Bluetooth Low Energy (BLE) protocols that are not natively recognized by the Windows/Linux Bluetooth stacks or by middleware like Intiface Central.
This solution bridges that gap by:
- Emulating a well-known Buttplug.io protocol on your PC.
- Communicating via Serial with an ESP32-CAM (or similar hardware).
- The ESP32 then handles the direct Bluetooth communication with the toy.
This enables "unsupported" or "generic" hardware to work seamlessly with any game or application compatible with the standard Buttplug.io interface.
- Python Version: Recommended
3.12.13(managed viauv)
graph LR
A[Game Event] -->|Buttplug.io/Intiface Protocol| B[Python Gateway]
B -->|USB-Serial Protocol| C[ESP32-CAM]
C -->|Proprietary Bluetooth| D[Generic Chinese Toy]
This project uses uv for dependency management and PlatformIO for firmware flashing.
To install or upgrade PlatformIO Core, follow these steps:
- Download: Save the get-platformio.py script.
- Navigate: Open terminal and go to the folder where you saved it:
# Change to the download folder cd C:/path-to-dir/where/get-platformio.py/is-located
- Run: Execute the installer:
python.exe get-platformio.py
[!TIP] For more details, see the Official PlatformIO Installation Guide.
- Configure Firmware: Edit
PlatformIO/config.cfgto set your initial serial and server parameters for the ESP32. - Configure Gateway: Edit
config.yamlin the root directory. Ensure theSerial: portmatches your ESP32-CAM COM port.
Note
This project was successfully tested and verified using the ESP32-CAM-MB model shown above (featuring built-in WiFi and Bluetooth).
- USB Driver (Windows 11): Ensure you have the
USB-SERIAL CH340 v3.7.2022.1driver installed.
- Connect your ESP32-CAM to your PC.
- Turn on your Bluetooth Toy (it must be on before the next steps).
- Setup Environment: Install project dependencies using
uv:uv sync
- Upload Firmware: Navigate to the PlatformIO directory and flash the device:
cd PlatformIO uv run pio run -e esp32cam -t upload
Before starting the gateway, verify that the ESP32 can control the toy directly:
uv run python ..\test\test.pyIf the toy vibrates correctly, your serial-to-Bluetooth bridge is ready.
- Start the gateway server:
cd .. uv run python main.py
- Success Confirmation: When the gateway connects to the ESP32, the toy will vibrate briefly. This confirms the software and hardware are talking.
For a quick test without launching a real game, you can use our built-in simulator:
uv run python test/simulated_game.pyThis script will:
- Connect to your Gateway via WebSocket.
- Perform the Toy handshake.
- Send random combat-like vibration events.
Alternatively, connect your real game List of compatible games, following the standard Buttplug.io interface.
Our comprehensive testing has confirmed the following successes:
- Firmware Upload: Successfully flashed the ESP32-CAM via PlatformIO with correct serial configurations.
- Hardware Handshake: Verified that the ESP32-CAM correctly bridges to Lovense-compatible hardware upon gateway connection.
- Protocol Emulation: Confirmed that the Python Gateway correctly emulates a Buttplug.io server, allowing external clients to discover and control the device.
- Game Simulation: The
simulated_game.pytest (as shown above) successfully performs the handshake and sends complex haptic events like the new "Punch" Combat Pattern.
Example of successful haptic integration using the Music Vibes software.
- Order of Operations: Always follow this sequence for a stable connection:
- Connect ESP32 via USB.
- Start the Python Gateway (
uv run python main.py). - Launch the Game.
- Reconnecting: If you restart the Python Gateway for any reason, you must close and reopen the game to re-establish the Buttplug.io handshake.
- Stopping: To safely shut down the gateway, press
Ctrl+Cin the terminal. This will automatically send a stop signal to your hardware.
The Gateway includes an automatic Safety Watchdog:
- If vibration lasts for more than 2 seconds (configurable) without a new update command or stop command, the Gateway sends an emergency
Vibrate:0command to the hardware. - This protects against game crashes or unexpected disconnections.
main.py: WebSocket Gateway entry point.buttplug/: Protocol implementation and serial connector (derived from buttplug-py).test/test.py: Direct Serial communication test.test/simulated_game.py: Full WebSocket Gateway connection simulator.config.yaml: Central configuration file.PlatformIO/: C++ source code for the ESP32-CAM (use PlatformIO to upload).
- Solution Developer: EchoLord
- Buttplug Library: The core protocol logic in the
buttplug/directory is based on the buttplugio/buttplug-py repository. - License: This project follows the BSD 3-Clause License. See the original LICENSE for full details.
- Testing Purposes Only: All protocol emulations and features in this project are intended for testing and personal research only.
- Non-Commercial: This project is not for commercial use.
- Protocol Notice: This implementation is a custom bridge and is not affiliated with, endorsed by, or meant to replace official hardware or protocols from Lovense or other manufacturers.
Maintained by EchoLord








