Beacon data from Ble scan cordova plugin problem

Hi

My objective is to get the beacon data from advertising data i.e. uuid+Manfacturing data+Major_Minor+txpower,

I used cordova Ble scan plugin in Visual studio 2015,

I am unable to get whole beacon data from ble.start scan,

Please help me in this regard,

The following is the code,

if (device.advertisementData) { return; }


if (!device.scanRecord) { return; }




var byteArray = evothings.util.base64DecToArr(device.scanRecord);
var pos = 0;
var advertisementData = {};
var serviceUUIDs;
var serviceData;

while (pos < byteArray.length) {
var length = byteArray[pos++];
if (length == 0) {
break;
}
length -= 1;
var type = byteArray[pos++];


var BLUETOOTH_BASE_UUID = '-0000-1000-8000-00805f9b34fb'

// Convert 16-byte Uint8Array to RFC-4122-formatted UUID.
function arrayToUUID(array, offset) {
var k = 0;
var string = '';
var UUID_format = [4, 2, 2, 2, 6];
for (var l = 0; l < UUID_format.length; l++) {
if (l != 0) {
string += '-';
}
for (var j = 0; j < UUID_format[l]; j++, k++) {
string += evothings.util.toHexString(array[offset + k], 1);
}
}
return string;
}

if (type == 0x02 || type == 0x03) // 16-bit Service Class UUIDs.
{
serviceUUIDs = serviceUUIDs ? serviceUUIDs : [];
for (var i = 0; i < length; i += 2) {
serviceUUIDs.push(
'0000' +
evothings.util.toHexString(
evothings.util.littleEndianToUint16(byteArray, pos + i),
2) +
BLUETOOTH_BASE_UUID);
}
}
if (type == 0x04 || type == 0x05) // 32-bit Service Class UUIDs.
{
serviceUUIDs = serviceUUIDs ? serviceUUIDs : [];
for (var i = 0; i < length; i += 4) {
serviceUUIDs.push(
evothings.util.toHexString(
evothings.util.littleEndianToUint32(byteArray, pos + i),
4) +
BLUETOOTH_BASE_UUID);
}
}
if (type == 0x06 || type == 0x07) // 128-bit Service Class UUIDs.
{
serviceUUIDs = serviceUUIDs ? serviceUUIDs : [];
for (var i = 0; i < length; i += 16) {
serviceUUIDs.push(arrayToUUID(byteArray, pos + i));
}
}
if (type == 0x08 || type == 0x09) // Local Name.
{
advertisementData.kCBAdvDataLocalName = evothings.ble.fromUtf8(
new Uint8Array(byteArray.buffer, pos, length));
}
if (type == 0x0a) // TX Power Level.
{
advertisementData.kCBAdvDataTxPowerLevel =
evothings.util.littleEndianToInt8(byteArray, pos);
}
if (type == 0x16) // Service Data, 16-bit UUID.
{
serviceData = serviceData ? serviceData : {};
var uuid =
'0000' +
evothings.util.toHexString(
evothings.util.littleEndianToUint16(byteArray, pos),
2) +
BLUETOOTH_BASE_UUID;
var data = new Uint8Array(byteArray.buffer, pos + 2, length - 2);
serviceData[uuid] = base64.fromArrayBuffer(data);
}
if (type == 0x20) // Service Data, 32-bit UUID.
{
serviceData = serviceData ? serviceData : {};
var uuid =
evothings.util.toHexString(
evothings.util.littleEndianToUint32(byteArray, pos),
4) +
BLUETOOTH_BASE_UUID;
var data = new Uint8Array(byteArray.buffer, pos + 4, length - 4);
serviceData[uuid] = base64.fromArrayBuffer(data);
}
if (type == 0x21) // Service Data, 128-bit UUID.
{
serviceData = serviceData ? serviceData : {};
var uuid = arrayToUUID(byteArray, pos);
var data = new Uint8Array(byteArray.buffer, pos + 16, length - 16);
serviceData[uuid] = base64.fromArrayBuffer(data);
}
if (type == 0xff) // Manufacturer-specific Data.
{
// Annoying to have to transform base64 back and forth,
// but it has to be done in order to maintain the API.
advertisementData.kCBAdvDataManufacturerData =
base64.fromArrayBuffer(new Uint8Array(byteArray.buffer, pos, length));
}

pos += length;
}
advertisementData.kCBAdvDataServiceUUIDs = serviceUUIDs;
advertisementData.kCBAdvDataServiceData = serviceData;
device.advertisementData = advertisementData;

Waiting for your response,

Thanks and Regards,
Murali

Rather than do all the parsing yourself, I’d recommend using one of the existing iBeacon Cordova plugins. This one is probably the most actively maintained one:

Hi,

Thanks for response,
https://github.com/petermetz/cordova-plugin-ibeacon-->this plugin user should mention the uuid,major,minor in app.js for region and ranging,
I need to get the beacon data from Bluetooth scan i.e. ble.startscan–>UUID+Major+Minor+txpower,

Please help me regarding this or suggest me any work around,

Thanks and Regards,
Murali

Then you need to manually parse the manufacturer data according to the iBeacon Specification, which you can download from https://developer.apple.com/ibeacon/ after accepting the iBeacon License.

The original code you provided doesn’t do any parsing of the manufacturer-specific data.

Why do you need the Tx power?

Hi,

The actually the code is wriiten for andriod ,After Ble.Scan we got scan record–>device.scanrecord (contains manufacturing data),
By pasing device.scanrecord–> I am trying to get Advertisementdata i.e. UUID’s+Txpower ,But I am unable to get Major and MInor etc…

Please correct me If I am wrong and give your guidance,

Thanks and Regards,
Murali

Have you tried going through the iBeacon spec and writing parsing code for the manufacturer data?

Hi,

Thanks for response,
Above code is written for Andriod device,I am parsing the scan record data to get Advertisment data,

Please guide me for Andriod device,

Best Regards,
Murali

Hi. I was looking for a similar solution and came across your code. I was able to modify it slightly and extract the UUID+Major+Minor+RSSI. It seems all this information is sent in the manufacturer data section.

if (!device.scanRecord) { return; }
var byteArray = evothings.util.base64DecToArr(device.scanRecord);
var pos = 0;
var advertisementData = {};
var serviceUUIDs;
var serviceData;
// Convert 16-byte Uint8Array to RFC-4122-formatted UUID.
function arrayToUUID(array, offset) {
  var k = 0;
  var string = '';
  var UUID_format = [4, 2, 2, 2, 6];
  for (var l = 0; l < UUID_format.length; l++) {
    if (l != 0) {
      string += '-';
    }
    for (var j = 0; j < UUID_format[l]; j++, k++) {
      string += evothings.util.toHexString(array[offset + k], 1);
    }
  }
  return string;
}

while (pos < byteArray.length) {
  var length = byteArray[pos++];
  if (length == 0) {
    break;
  }
  length -= 1;
  var type = byteArray[pos++];

  switch(type){
    case 0x08: 
    case 0x09: // Local Name.
      device.name = evothings.ble.fromUtf8(new Uint8Array(byteArray.buffer, pos, length));
    
      break;
    case 0xFF: //Manufacturer data + UUID + Major + Minor + RSSI
      advertisementData.kCBAdvDataManufacturerData = evothings.util.typedArrayToHexString(byteArray.slice(pos,pos+4))
      pos+=4;
      serviceUUIDs = serviceUUIDs ? serviceUUIDs : [];
      serviceUUIDs.push(arrayToUUID(byteArray,pos));
      device.uuid = serviceUUIDs[0];
      pos+=16;

      device.major = evothings.util.bigEndianToUint16(byteArray,pos);
      pos+=2;
      device.minor = evothings.util.bigEndianToUint16(byteArray,pos);
      pos+=2;
      device.rssi = evothings.util.littleEndianToUint8(byteArray,pos);
      break; 
    default:pos+=length;
      break;
  }

}