Adding unknown bluetooth devices

I’m installing Home Assistant in my camper and looking for a solution to integrate the various bluetooth devices that are in/on it already. I’ve dug around in the standard integrations and in HACS and there only seems to be support for “known” devices. I’d like to be able to pick up all devices, and have them added to HA so that I can scrape the various services offered.

Currently, I’m looking to integrate the following:

  • Hughes Power Watchdog (surge suppressor, power monitor)
  • TyMate Tire Pressure/Temperature Monitors
  • LevelMatePro camper level sensor

I’ve used BLE sniffers and found that for everything above the data is transmitted is somewhat easy to extract… Has anyone found an integration of any sort that can get abstract data in to HA from random BLE devices? If not, what in your opinion would be the next best approach?

TIA,
Terry

if you had already found out service IDs and data formats, you can add support to this custom integration (https://github.com/custom-components/ble_monitor) and you can start fetching data.

Adding a new device is fairly straightforward: Documentation on documentation - Passive BLE Monitor integration

Thanks, I had considered that as a possible route. I’ll look into it further.

Terry

The Hughes Power Watchdog is on a lot of smart RV people’s to-do lists, including mine. I’ve played around with a BLE sniffer app a little. The issue we run into is the Hughes only puts out a generic BLE advertisement. You don’t get the data until you connect. Apparently the RV Whisper guy found a way around this, but he’s not willing to share how. Have you found a way around this? I’d LOVE to be able to get my power consumption into HA from my Hughes.

Not sure if this brand is compatible, but Theengs and OpenMQTTGateway already decode generic BLE TPMS.

You don’t see any change of the advertisement depending on the power consumption ?

From what we can tell, it’s encrypted. Only one characteristic is subscribable and it updates 8-10 values every second, but the values themselves are meaningless. We’ve tried converting to various different formats but nothing works. It’s been suggested that someone attempt to flash Tasmota to the internal ESP32 to gain access to the encryption key needed. The good news is it’s possible to utilize the information (otherwise RVWhisper wouldn’t be able to use it). We just have to figure out how he gained access. Worst case scenario, we pay the $200 for his “gateway” (which is probably just a $12 ESP32) and look at the source code. But nobody wants to pay for something when we can probably do it ourselves.

1 Like

I know very little about BLE but I’ve been trying to figure out how to access the power watchdog myself. You can run the iOS app on an M1 Mac and use Xcode’s PacketLogger to see what’s happening but I’ve still to figure it out fully. Any progress I find I’ll happily share! I’m glad I’m not alone haha

Oh my goodness. Whilst I was sitting at our campfire outside our RV, I was able to reverse engineer the android app and figure out exactly how to pull the data out of the subscribable characteristic. I’ve written a python script using the bleak package which works on both Windows and macOS.

I’m not entirely sure what line means- it’s either 2 or 1- but the rest of the values are just 4 byte integers that need to be divided by 10,000. This was as much as there was when I decompiled the apk. It’s so inefficient and confusing but hey, the data is correct!

{'volts': 120.2846, 'amps': 15.32, 'watts': 1738.4, 'energy': 702.37, 'line': 2}

Looking at it, I guess we only need the first packet starting with 01 03 20. I’m gonna try to turn this into something I can use with home assistant and publish it on github, though I’m still trying to get a raspberry pi for my camper but I’m working on it in the meantime.

There’s an ascii diagram in the code but here it is anyway:

# 0 => 01 03 20 00 12 5b a4 00 01 43 07 00 93 c8 08 00 6a cd 68 00
#      \______/ \_________/ \_________/ \_________/ \_________/
#       header     volts       amps        watts       energy
#
# 1 => 00 03 d0 00 53 d7 01 ff df 10 00 00 00 17 6d c7 1c 00 00 00
#                                                         \______/
#                                                           line

Just make sure to run pip install bleak first:

import asyncio
import platform
from bleak import BleakScanner, BleakError, BleakClient

address = (
    "mac address here"
    if platform.system() != "Darwin" else
    "uuid here for macos"
)

async def main():
    # devices = await BleakScanner.discover()
    # for device in devices:
    #     print(device)

    device = await BleakScanner.find_device_by_address(address, timeout=5)
    if not device:
        raise BleakError("Device not found")

    async with BleakClient(device) as client:

        if not client.is_connected:
            await client.connect()

        first_chunk = None

        def on_data(sender, chunk):
            chunk = bytes(chunk)

            global first_chunk
            if chunk[0] == 1 and chunk[1] == 3 and chunk[2] == 32:
                first_chunk = chunk
            else:
                # we got the second chunk which includes the rest of the data
                buffer = first_chunk + chunk
                first_chunk = None

                # 0 => 01 03 20 00 12 5b a4 00 01 43 07 00 93 c8 08 00 6a cd 68 00
                #      \______/ \_________/ \_________/ \_________/ \_________/
                #       header     volts       amps        watts       energy
                #
                # 1 => 00 03 d0 00 53 d7 01 ff df 10 00 00 00 17 6d c7 1c 00 00 00
                #                                                         \______/
                #                                                           line

                volts = int.from_bytes(buffer[3:7], "big") / 10000
                amps = int.from_bytes(buffer[7:11], "big") / 10000
                watts = int.from_bytes(buffer[11:15], "big") / 10000
                energy = int.from_bytes(buffer[15:19], "big") / 10000

                line = None
                if buffer[37] == 0 and buffer[38] == 0 and buffer[39] == 0:
                    line = 2
                elif buffer[37] == 1 and buffer[38] == 1 and buffer[39] == 1:
                    line = 1

                print({
                    "volts": volts,
                    "amps": amps,
                    "watts": watts,
                    "energy": energy,
                    "line": line,
                })

        # for service in client.services:
        #     print(service)
        #     for char in service.characteristics:
        #         print(char)

        await client.start_notify("0000ffe2-0000-1000-8000-00805f9b34fb", on_data)

        while True:
            await asyncio.sleep(1)


asyncio.run(main())
2 Likes

Woo! Great work! Line (if it always says 2) could be the number of lines (2 for a 50amp service) or maybe the amperage of the lines combined? And I assume “energy” is the current wattage being pulled, while “watts” is the cumulative count. Now we just need to figure out how to get an ESP32 to capture that data and have HA decode it. One sensor on ESPHome to capture that characteristic, and a script to convert it? Feel free to DM me to collab, we’re full timers with HA running on a RPi4. I’d like to use an ESP32 instead of the built-in Bluetooth since I run a SSD attached to the RPi, which makes the built-in Bluetooth pretty useless. I already have an ESP32 in the pass-thru thats partially wired up to my black/grey tanks for my tank level project. So it can handle both projects.

Energy is cumulative kWh and watts is wattage. I just lifted the same variable names they used. I’d love to collaborate! I’ve never used ESPHome before but it’s definitely possible to write this onto a microcontroller, I’d prefer to do it that way too. I’ll look into it later today or alternatively we could contact each other and figure it out together. I’m on Discord

Well, we finally did it. The Hughes Power Watchdog is FINALLY integrated into HomeAssistant! Special thanks to all those who helped along the way. It’s still a very new integration, so if you experience any issues, please submit and issue on the github repo. Enjoy!

1 Like

Thank you so much!

Now I’ll need to work on tire pressure and level.

1 Like

Is the ESP device required, or can I use the BLE Bluetooth on my NUC?