reelyactive / advlib-ble

Open source library for decoding ambient Bluetooth Low Energy (BLE) advertising packets. We believe in an open Internet of Things.
https://www.reelyactive.com/ambient-data/
MIT License
1 stars 0 forks source link

ADV_NONCONN_IND not implemented? #1

Closed LaKing closed 3 years ago

LaKing commented 3 years ago

Dear reelyactive.

I'm trying to parse BLE device rawData that comes from minew E8 tag using a minew G1 gateway. While parsing the data string with advlib, the headers are parsed, but then no further action is taken, thus an empty object is returned. While looking at the code, I think the advlibble.js switch with ADV_NONCONN_IND is not yet implemeted?

Is there anything I can do to help further development?

jeffyactive commented 3 years ago

Hi @LaKing, the Minew parsing is implemented in advlib-ble-services which you'll need to include to complete the processing of Minew packets. Take a look at Hello advlib-ble and don't forget to include the LIBRARIES.

You may also wish to use advlib as a wrapper for advlib-ble.

Please close the issue if that works (we've successfully tested with the Minew E8). If you're interested in contributing to further development, don't hesitate to Contact us. Would be interested to know how you're using the G1 and E8 as that may help us steer future development. Thanks!

LaKing commented 3 years ago

Hello @jeffyactive, thank you for your response.

node modules installed: advlib advlib-ble advlib-ble-manufacturers advlib-ble-services the online tool gives same results, this is my minimal code for reproduction:


const advlib = require('advlib-ble');

const LIBRARIES = [ require('advlib-ble-services'),
                    require('advlib-ble-manufacturers') ];

let packet = '0201060303AAFE1616AAFE10E803643235302E68752F3536302F736D3538';
let processedPacket = advlib.process(packet, LIBRARIES);

console.log(processedPacket);
/* running results int the foillowing log:
{
  rxAdd: 'public',
  txAdd: 'public',
  type: 'ADV_NONCONN_IND',
  length: 1,
  advA: '16feaa030306'
}
*/

I've started writing some code, and contacted minew for support. I have the feeling that the rawData field from the G1 gateway transmits the netto payload of the BLE advertizing package.

The packet in the upper example is an eddystone URL field.

Offset Length Type Data Details
0 1 Data Length 0x02 /
1 1 Flag data type 0x01 /
2 1 Flag data 0x06 /
3 1 Data Length 0x03 /
4 1 Complete list of 16-bit Service UUIDs 0x03 /
5 2 UUID data 0xAAFE (little-endian) 0xFEAA
7 1 Data Length 0x10 0x07 + sizeof(Encoded URL)
8 1 Service data 0x16 /
9 2 UUID data 0xAAFE (little-endian) 0xFEAA
11 1 Frame Type 0x10 /
12 1 Ranging Data 0x00 Calibrated txpwr at 0m
13 1 URL Scheme Prefix 0x00 http://www.
14 1-16 Encoded URL “minewtech” /
15+ 1 HTTP URL encoding 0x00 .com/

So possibly I'm trying to use adlib to parse this data with preamble, crc and headers, while this might be just a payload package.

Investigating further, .. . A couple of packages:

0201060303E1FF1016E1FFA108640CE5A73F23AC506C7573
0201060303E1FF1216E1FFA103640002FFEC00F80CE5A73F23AC
0201060303AAFE1516AAFE00E800112233445566778890ABCDE39A01BF
LaKing commented 3 years ago

Indeed. The Raw PDU has additional 16 characters at the start. ... So the question then is, how I could use adlib to parse only the payload. .)

jeffyactive commented 3 years ago

Thanks for the details @LaKing, you'll want to use barnowl with barnowl-minew to reconstruct the payload to its original form so that it can be parsed with advlib.

Every gateway manufacturer seems to alter the raw Bluetooth Low Energy payload in some way, including Minew. We were able to work with Minew so that they added some flags in their latest firmware which allows barnowl-minew to pretty much reconstruct the original (raw) PDU.

If you want to go a step further, you can install hlc-server which is set up to receive the Minew G1 data stream. See: https://reelyactive.github.io/diy/minew-g1-config/

LaKing commented 3 years ago

Thanks for the suggestions, I will take a look, but I already wrote an adatpter, end ended up using it this way:

const advlib = require("advlib-ble-services");

// the input argument is the rawData property from the gateway.
module.exports = function (data) {
    // we will recieve a string from our json
    if (typeof data !== "string") return {};
    if (data.length < 10) return {};
    // the string will be uppercase, we need lowercase
    data = data.toLowerCase();
    // make sure we really only have valid characters.
    if (!/[0-9a-f]+/.test(data)) return {};
    // create the buffer
    let buf = Buffer.from(data, "hex");

    // check these constants first
    if (buf.readUInt8(0) !== 0x02) return {};
    if (buf.readUInt8(1) !== 0x01) return {};
    if (buf.readUInt8(2) !== 0x06) return {};
    if (buf.readUInt8(3) !== 0x03) return {};
    if (buf.readUInt8(4) !== 0x03) return {};
    if (buf.readUInt8(8) !== 0x16) return {};

    // now comes the uuid part, which is placed twice in the code.
    const uuid = buf.toString("hex", 6, 7) + buf.toString("hex", 5, 6);
    if (uuid !== buf.toString("hex", 10, 11) + buf.toString("hex", 9, 10)) return {};

    // leave the rest to adlib.
    return advlib.processServiceData(uuid, buf.subarray(11, 11 + buf.readUInt8(7)));
};

Propably not the best solution, but its minimalistic, and works with the few types we need to decode for now.

jeffyactive commented 3 years ago

Glad to hear you're able to use the processServiceData function successfully. Marking as closed. Happy coding!