Bluetooth Binding - Emulate Bluetooth remote control?

I have a Xiaomi Projector, but Im sure this will apply to other makes/devices out there. It runs Android OS and has a Bluetooth remote control.

I have been using a Harmony Hub with this, as well as ADB commands to get what I want, however, there has always been a sticking point which is, if you power the device off fully (not sleep it) you can ONLY turn it back on with the power button on the remote control. The Harmony Hub cannot power back on from fully off, only from sleep and the Network is not available in this powered off state, so no ADB commands. Also, in this powered off state, the projector’s Bluetooth’s connection is either not visible to other devices or off (though I dont know how the remote powers it on, if Bluetooth is fully off).

Does anyone know if with something like the Bluetooth binding and perhaps with BlueZ (Linux Bluetooth stack), you can emulate an Android remote control (like you may get with any Android TV device)?

OR if its possible to capture a Bluetooth packet trace from a remote control and then somehow play it back from whatever you captured it on? e.g. my Openhab server.

Also, if it is possible, do you need a special Bluetooth Dongle (like a Bluegiga) or will it probably work with your computers onboard Bluetooth chip?

And if so, anyone any hints on how to do this?

Many thanks!

FYI, I have noticed these Bluetooth related projects, but they are currently beyond my understanding, but they may provide the solution somehow:

Based on my understanding something like this would require a new extension to the Bluetooth binding. I do see some extensions working like a remote (e.g. controlling AM43 rollershutter motors). But you’ll have to find or reverse engineer the messages and protocol used by the remotes. I’ll often search GitHub to see is someone has already done this work. Sometimes that can be used as is or used as a reference in implementing an OH add-on. But what you are looking for is a remote control for your specific device. You’ve unearthed some generic bluetooth libraries which enable the development of stuff that works with bluetooth but won’t tell you anything about the actual protocol.

Also be aware that many devices that have BT remotes (e.g. Gooble TV) have a pairing protocol that has to be implemented and performed before the device will listen to the commands from that device. Simply capturing and playing back the messages isn’t going to work.

Assuming it’s standard Bluetooth and the onboard BT supports the correct version of BT required by the device I see no reason why it wouldn’t work.

1 Like

Thanks for the reply, its roughly in line with where I had reached in my own thoughts/research.

I found people on some other forums looking into this for other home automation reasons, even specifically for the same device, though no one had the tech know how to implement anything, though I found the github links above and assumed they would help.

As for the commands/specification of the Bluetooth profile for the remote, Im pretty confident its based off this:

Though merging all this into a working solution, thats a whole different ballgame. Thought I would try here first and see if anyone has any knowledge/experience in reverse engineering these things and could offer any hints.

If nothing pops up here, I may try posting for help on those githubs and see if anyone there might be able to guide me in a direction.

Of course, if there is a relatively simple way to do it, Ill post an article on here so others can reverse engineer anything bluetooth.

Thanks

The power on/off button operates via IR technology, not Bluetooth. To make it work with Harmony, simply let it learn the IR button. The absence of a running system means no Bluetooth is active, making IR the primary method for turning the device on. To verify this, point the remote away and hide it from the projector; the power button should not trigger it. In contrast, other buttons relying on Bluetooth can still communicate with the projector after establishing a connection.

@Narendra_Raz Thanks for the reply, however the Xiaomi Laser projector I was looking at is 100% bluetooth operated:

As per the above image, there is no IR LED on the remote, it has the Bluetooth symbol on the rear and it will fully control the projector when the remote and yourself are wrapped up in a blanket with no line of sight to the projector.

The logitech Harmony does work with the projector if you set it as a Nvidia Shield, however, I was looking for a better solution as the Xiaomi Projector and its bluetooth on/off via the remote is the only thing I now keep my Harmony hub plugged in and powered on for.

Thanks

@ewrw, thanks for opening up this post some months back, since I have exactly the same projector and exactly the same question.

I noticed that, via the Google TV Binding, I can operate the projector perfectly well. But switching it on again does not work when the projector is switched off, since WiFi seems to be down when switched off, and only „listening to a BT signal“ seems to be active in this case.

Have you found a solution in the meantime?

Edit: Our friends over at HA are having similar discussions.

To be honest I didn’t get any further. Currently I use a Logitech Harmony hub that has the projector programmed in as a “Nvidia Shield”. With that you an send it a low power state/standby power off command, which is as close as you can get to switching it off. From that it will respond to a remote power on from the Harmony Hub or from the remote control. In short, the same as having a keyboard with a power button on it:

Its a bit annoying though as the only device I need the Harmony Hub for, is the projector and its only for this standby power setting… so I’m running a Harmony hub for that convenience. Mind you, it does allow for an instant on with the projector, taking maybe 2-3 seconds to be up and running from pressing a power button via the harmony hub or the remote control.

As ChatGPT and of the like has moved on a bit since I asked the question… here is its response when posing the question about possible ways to figure out/resolve it:


Understood—if the TV is completely unreachable over LAN or Wi-Fi when fully powered off, Wake-on-LAN is indeed not an option. This reinforces the likelihood that the TV’s Bluetooth module is operating in a low-power standby state specifically to listen for wake-up commands.

To replicate the power-on functionality of the remote, let’s focus on decoding and sending the Bluetooth wake signal.


1. Understand Bluetooth Remote Behavior

Your remote likely operates as a HID (Human Interface Device) or uses a custom Bluetooth Low Energy (BLE) profile. In either case, the wake-up command is likely a predefined signal sent directly to the Bluetooth module in the TV. Here’s how you can proceed:

a. Use a Bluetooth Sniffer

  • Tools to Capture Traffic:
    • Hardware: Ubertooth One, Nordic Semiconductor nRF Sniffer, or any Bluetooth-capable device with HCI debugging enabled.
    • Software: Wireshark with a compatible Bluetooth adapter.
  • Capture the Wake Command:
    • Turn on Bluetooth traffic capture.
    • Observe the signal sent from the remote when you press the power button to wake the TV.

b. Analyze the Packet

  • Check for the following in the captured data:
    • Device Address (MAC): The TV’s Bluetooth MAC address.
    • Command Content: The specific data payload sent by the remote.

If the remote uses BLE, focus on characteristic writes or notifications that may represent the wake command.


2. Reproduce the Command

Once you identify the wake command, you can use a Bluetooth transmitter to replicate it.

a. Hardware Options

  • Raspberry Pi: Equipped with a Bluetooth module and libraries like pybluez or bluepy.
  • ESP32: Affordable and capable of handling BLE commands with frameworks like Arduino or ESP-IDF.
  • PC Bluetooth Adapter: A laptop or desktop with a good Bluetooth adapter can also work with Python libraries.

b. Software Libraries

  • Python with PyBluez: For classic Bluetooth HID.
  • BLE Frameworks: Use BLE-specific libraries (e.g., bluepy or bleak) if the remote operates on BLE.

Example (using Python and PyBluez for a classic Bluetooth command):

import bluetooth

target_address = "XX:XX:XX:XX:XX:XX"  # Replace with TV's Bluetooth MAC address

sock = bluetooth.BluetoothSocket(bluetooth.L2CAP)
sock.connect((target_address, 0x11))  # Replace with appropriate channel
sock.send(b'\xXX\xXX')  # Replace with captured wake command
sock.close()

3. Test and Refine

  • Send the Command: Use the identified payload and the TV’s Bluetooth MAC address.
  • Refine the Signal: If the TV doesn’t respond, the command may be encrypted, or additional pairing information may be required. Debug the pairing process or try varying the payload based on your sniffed data.

Alternative Exploration

If sniffing and replicating the signal prove challenging:

  1. Contact Developer Communities: Forums like XDA Developers or specialized reverse-engineering groups may have insights about Google TV remote protocols.
  2. Look for Developer Tools: Some TV models have developer settings or hidden menus that might provide diagnostic tools, including Bluetooth debug information.
  3. Experiment with Universal Remotes: Some universal remotes, like Logitech Harmony, emulate Bluetooth signals. These tools might expose wake command functionality that you can adapt.

If you’d like, I can guide you step-by-step on setting up a Bluetooth sniffer or writing code for a specific platform to send the wake command. Let me know!

Thanks for the offer! I’d be interested in trying this and (if I understand your post correctly) you could then also get rid of your harmony hub as well (assuming this would work).

The problem is, however, that I have no idea where to start (and Chat GPT “instructions” are often also nothing more than well-sounding hallucinations, perfect to waste your time). So what would be good is knowing that this could even work theoretically.

I do have some experience in working with Bluetooth though (e.g. I wrote this step-by-step to extract the signals of a bathroom scale via BTLE). But to be fair, I could only do this after finding some rough instructions on the net and, after some hours of trial and error, was knowledgeable enough to write a thorough tutorial for openHAB myself that is easy enough to understand for someone who’s not an expert.

So, long story short: If you have some knowledge, we could try to get this working.

Hi @Cplant Unfortunately I am dealing with other life issues currently and wont be free to look at something like this for a good few months… not wanting to put my life story on the internet you can look here at another one of my projects for an explanation https://github.com/erew123/alltalk_tts/issues/377 Im sure you will understand once you read that.

Though, here is a bit more info I have knocked together with AI if you want to give it a shot…

:blue_square: Will Bluetooth HID commands work? (Probably not)

For Bluetooth HID (Human Interface Device) remotes, there is indeed a standardized power button code, but it’s important to understand a few key points:

  1. The standard HID Usage Code for Power is 0x66 (defined in the USB HID Usage Tables)
  2. However, just sending this code alone won’t work - it needs to be properly formatted in a HID report

Here’s a typical HID report format for a power button press:

power_command = [
    0xA1,  # Report type (input)
    0x01,  # Report ID (usually 1 for consumer controls)
    0x66,  # Power button usage code
    0x00   # Release button
]

However, I should note that:

  1. Modern Google TVs and many smart TVs often don’t use the standard HID protocol - they frequently use proprietary BLE services and characteristics
  2. Even if using standard HID, the TV needs to be already paired and connected to accept commands
  3. Some manufacturers implement additional security measures or custom protocols on top of the standard HID

The most reliable way to know the exact command would be to:

  1. Get your TV’s Bluetooth MAC address
  2. Look up your specific TV model’s Bluetooth services using a BLE scanner
  3. Capture the actual command from an original remote

If you want to try the generic HID power command anyway, you’d need to:

  1. Ensure your TV is actually using HID protocol (rather than a proprietary protocol)
  2. Have already completed the pairing process
  3. Send the command to the HID service characteristic (UUID: 0x2A4D)

Unfortunately, given how modern smart TVs handle their remotes, the generic HID power command has a relatively low chance of working without additional device-specific implementation details.

:blue_square: Potential hardware for capturing Bluetooth Low Energy (BLE) Commands

Yes, there are several alternatives to the Ubertooth One for Bluetooth sniffing. Here are the main options:

  1. Nordic nRF52840-based devices ($10-30):

    • Makerdiary nRF52840 MDK USB Dongle
    • Adafruit nRF52840 Dongle
    • Generic nRF52840 dongles from AliExpress
      These are much cheaper but have more limited range and capabilities.
  2. ESP32 Development Boards ($5-15):

    • While not as powerful for sniffing, they can be used with the ESP-IDF Bluetooth stack
    • Look for boards with external antennas for better reception
  3. HackRF One ($300+):

    • More expensive than Ubertooth One
    • Much more versatile but more complex to use
    • Can handle many protocols beyond just Bluetooth
  4. Bluetooth Development Kits:

    • Texas Instruments CC2540 ($50-100)
    • Silicon Labs BG22 Explorer Kit ($40-50)

If you’re specifically looking for something similar to Ubertooth One but cheaper, I’d recommend:

  1. Preferred budget option: Any nRF52840-based board with an external antenna

    • Look for ones using the genuine Nordic nRF52840 chipset
    • Should cost around $20-30
    • Will work with standard Nordic tools
  2. Best value alternative: Cypress CYW20819 or CYW20820 evaluation kits

    • Usually around $50-75
    • Good Bluetooth sniffing capabilities
    • Official development support

I should mention that if you do find extremely cheap “Ubertooth One clones” (under $50) on sites like AliExpress or similar, they’re often not functional for actual Bluetooth sniffing - they may be missing crucial components or using incompatible chipsets.

:blue_square: Capturing BLE commands (2x Methods)

Required Equipment

Hardware

  1. Ubertooth One ($120-150 USD) OR Nordic nRF52840 dongle ($30 USD)
  2. USB extension cable (optional but recommended for better positioning)
  3. The original remote control
  4. The Google TV that’s being controlled
  5. A computer running Linux (Ubuntu 20.04 or later recommended)
    • Windows can work but requires additional setup steps not covered here
    • Could always boot linux from a USB stick if you dont have Linux installed

Software

  1. Wireshark (latest version)
  2. Ubertooth tools (if using Ubertooth One)
  3. Nordic Semiconductor nRF Connect (if using nRF52840)
  4. Python 3.8 or later

Part 1: Setting Up the Capture Environment

Installing Required Software (Ubuntu)

# Update system
sudo apt update && sudo apt upgrade -y

# Install Wireshark
sudo apt install wireshark
sudo usermod -a -G wireshark $USER

# Install Ubertooth tools (if using Ubertooth One)
sudo apt install cmake libusb-1.0-0-dev make gcc g++ libbluetooth-dev \
    pkg-config libpcap-dev python3-numpy python3-qtpy python3-distutils
sudo apt install ubertooth

# Install Python requirements
sudo apt install python3-pip
pip3 install pyubertooth pybluez bluepy

Configuring Wireshark

  1. Launch Wireshark
  2. Go to Edit → Preferences → Protocols → Bluetooth
  3. Enable “Try to decode BREDR as BLE”
  4. Enable “Analyze BR/EDR packets in LE tab”
  5. Click “OK”

Part 2: Capturing the Bluetooth Traffic

:yellow_square: Method 1: Using Ubertooth One

  1. Connect the Ubertooth One to your computer
  2. Open terminal and verify connection:
ubertooth-util -v
  1. Start Wireshark and configure:

    • Click the gear icon next to “Ubertooth One”
    • Enable promiscuous mode
    • Set channel to “Auto-detect”
  2. Start capture:

ubertooth-btle -f -c bluetooth.pcap
  1. In a separate terminal, start Wireshark:
wireshark -k -i bluetooth.pcap
  1. Capture the power-on sequence:
    • Press the power button on your remote 3-4 times
    • Wait 5 seconds between each press
    • Make sure the TV responds each time

:yellow_square: Method 2: Using nRF52840

  1. Install nRF Connect for Desktop
  2. Launch nRF Connect
  3. Select “Bluetooth Low Energy” monitor
  4. Click “Start scan”
  5. Press the remote’s power button several times
  6. Look for packets that appear when the button is pressed

Part 3: Analyzing the Captured Data

Identifying Relevant Packets

  1. In Wireshark, apply the following display filter:
btatt or btle
  1. Look for patterns that occur when the power button is pressed:
    • Note packets that appear consistently with each button press
    • Record the following for each relevant packet:
      • Source MAC address
      • Destination MAC address
      • Service UUID (if present)
      • Characteristic UUID (if present)
      • Data payload (hexadecimal)

Creating a Command Profile

Create a text file named remote_profile.txt with the following information:

TV MAC Address: XX:XX:XX:XX:XX:XX
Remote MAC Address: YY:YY:YY:YY:YY:YY
Service UUID: XXXX
Characteristic UUID: YYYY
Command Payload: [captured hex data]

Part 4: Replicating the Command

Python Script for Command Replication

import asyncio
from bleak import BleakClient
import sys

# Configuration
TV_MAC_ADDRESS = "XX:XX:XX:XX:XX:XX"  # Replace with your TV's MAC
CHARACTERISTIC_UUID = "YYYY"  # Replace with captured characteristic UUID
COMMAND_PAYLOAD = bytes.fromhex("ZZZZ")  # Replace with captured payload

async def send_power_command():
    try:
        # Connect to TV
        async with BleakClient(TV_MAC_ADDRESS) as client:
            print(f"Connected: {client.is_connected}")
            
            # Send command
            await client.write_gatt_char(CHARACTERISTIC_UUID, COMMAND_PAYLOAD)
            print("Command sent successfully")
            
            # Wait for confirmation
            await asyncio.sleep(1)
            
    except Exception as e:
        print(f"Error: {str(e)}")

# Run the command
asyncio.run(send_power_command())

Testing the Replication

  1. Save the script as send_power.py
  2. Update the script with your captured values
  3. Run the script:
python3 send_power.py

Part 5: Troubleshooting

Common Issues and Solutions

  1. No Packets Captured

    • Verify Ubertooth/nRF device is properly connected
    • Try repositioning the capture device closer to the remote
    • Ensure remote has working batteries
    • Try pressing other buttons to verify capture is working
  2. TV Doesn’t Respond to Replicated Command

    • Double-check all MAC addresses and UUIDs
    • Verify payload data is exact
    • Try adding small delays between connection and command
    • Check if remote uses rolling codes (payload changes with each press)
  3. Permission Issues

    • Run these commands:
sudo setcap 'cap_net_raw,cap_net_admin+eip' `which python3`
sudo setcap 'cap_net_raw,cap_net_admin+eip' `which hcitool`

Security Notes

  • This process is for educational purposes and personal use only
  • Some TVs may use encrypted communications
  • Verify you own all devices involved
  • Do not attempt to capture other devices’ traffic

Additional Resources

@Cplant I assume as you have managed to scan for BLE packets with a PI, that may well work for this scenario and you can just adapt the commands I gave you to capture the packets… it should be a similar process to what you have already done… I think.

@ewrw, quick question, before I start digging and investing a substantial amount of hours: I once learned that BT and BTLE does not allow to capture and emulate specific signals due to rolling code or two way communication / encryption, other than, say, IR. Are you sure that what you propose works?

I managed to emulate the entire Mi Remote via this nice little project and a 6€ NodeMCU. So far, so good.

Though I am still struggling with the fact that it emulates everything pretty nicely, except the „switching on“-part. :joy: „Switching off“ works fine though. :joy:

In case someone has an idea, let me know.