Ernst79 / bleparser

Parser for passive BLE advertisements
MIT License
29 stars 16 forks source link

Wellcore Beacons #39

Open JacoBezuidenhout opened 2 years ago

JacoBezuidenhout commented 2 years ago

Hello,

I have a bunch of these Wellcore W912N beacons. I am not very fluent in BLE Packets and data...

The manufacturer is super unhelpful so after 6 years of having them, I started to investigate again how to read the data as I have 50+ of these devices in a box.

This parsing library is awesome, and I thought maybe I can post how the Wellcore beacons work should you want to add it to the ecosystem.

Example of Advertising Packet (using esphome+ble_gateway): 043E4402010001F3849D8F15E7380201061AFF4C000215FDA50693A4E24FB1AFCFC6EB076478252733DCB2C50C166E353101F7C000146100000C095747585F69426561636F6EC8

After this entire weekend I reverse engineered the data and found the following: There is this service uuid: 0x356e Providing the data: 0c166e353101f7c00014610000

After moving, heating and rotating a lot of times I grouped the data in this way:

0c166e3531 01f7c0 0014 61 0000

0c166e3531: Not sure what this is 01f7c0: Accelerometer Data [01(x) f7(y) c0(z)] 0014: Temperature Data 61: Battery Level 0000: Not sure

I added a wellcore.py file and is busy extracting the data in the format above. My question now is, due to a lack of knowledge of hex data and little indians and big indians etc... (yes I meant it as a joke)

1stly for Accelerometer data: The app (provided as an .apk file by the manufacturer) shows negative and positive values for accelerometer x,y,z - I guess that the value is maybe offset to convert single hex to neg + pos decimal?

2ndly for Temperature data: Converting the hex 14 to decimal does give the correct temperature, but how does negative decimals work in hex? Is that where the little and big endians come in?

Am I on the right track or is there perhaps a standard that I do not know about that could make all this easier?

JacoBezuidenhout commented 2 years ago

Ahhh after reading through your code I found struct's unpack method....

Here is how to read Wellcore Beacons:

if packet_type == 0x16 and packet_size > 4: uuid16 = (packet[3] << 8) | packet[2]` if uuid16 == 0x356e:

raw example 0c166e35 3101f7c00014600000

    print(packet[4:].hex())
    (
        unknown0,
        acc_x,
        acc_y,
        acc_z,
        temp,
        batt,
        unknown1,
        unknown2,
    ) = unpack(">BbbbhBBB", packet[4:])
    result.update({
        "raw": packet.hex(),
        "unknown0": unknown0,
        "acc_x": acc_x,
        "acc_y": acc_y,
        "acc_z": acc_z,
        "temp": temp,
        "batt": batt,
        "unknown1": unknown1,
        "unknown2": unknown2,
    })
Ernst79 commented 2 years ago

Great. about the 0c166e3531: Not sure what this is

0c = length of the manufacturer specific data 16 = service data - 16 bit UUID (as defined by the Bluetooth org) 6e35 = 16 bit UUID (reversed, so the UUID = 356e, as you already found out) 31 = ?? don't know, could be a counter

Let me know if you need more help.