Closed lauleehong closed 8 years ago
Some devices don't advertise a name.
Once you're connected you could try reading the Device Name Characteristic 0x2A00 from the Generic Access Service 0x1800
I think Android looks for the Complete Local Name 0x09 from the advertised GAP information. You could try parsing the advertising data from the peripheral and seeing if 0x09 exists or perhaps 0x08 Shortened Local Name.
Does NRF Master Control Panel show the name correctly?
How should I go about reading the device name characteristics on cordova/js? Spot on that my Complete Local Name is "N/A" and MCP on Android shows "N/A" as well (but shows Full Name on iOS).
You'll need to connect to the peripheral and do something like
var success = function(buffer) {
var name = ''; // convert bytes in ArrayBuffer to a string
console.log('device name is', name);
};
ble.read(peripheral.id, '1800', '2a00', success, app.onError);
I'm working on a BLE scanner list, so to sequentially connect each peripheral to parse out the device name seems impractical.
If you don't want to connect, I'd use N/A or the MAC address for the name.
If I were to populate a list with BLE peripherals, an average joe wouldn't know which device he is looking for to connect to if the name was N/A or the MAC address.
If the device doesn't advertise a name, it's not going to be in the scan results on Android. iOS and Android handle this differently.
nRF Master Control Panel is a generic scanning app. It shows N/A for devices that don't advertise names. Most devices that are connectable advertise a name.
My plugin provides access to the Android and iOS API. I can't give you data that's not there. You need to figure out what makes sense for your app. Maybe N/A is good. Maybe you need to connect and read the device name if it's not advertised.
My hardware does advertise a name, and thus I'm able to pick it up on my iPhone. I'm using your plugin to make a "remote controller" like app which list the names of the devices at start. The user then selects which device to connect to for UART-BLE data transmission.
Based on what you've told me, the device name you see on iOS is coming from the Generic Access Service 0x1800, Device Name Characteristic 0x2a00. On iOS, CoreBluetooth gets the name internally, and makes it available as peripherals are discovered. It is probably by doing a Read By UUID Request (but this API isn't exposed.) CoreBluetooth does other stuff during discovery like hiding the MAC address and generating a UUID for the peripheral.
On Android the device name needs to be in the advertising or scan response packet.
Can you update the firmware on the device? I think you'll get the best results if you advertise the local name and set the device name.
Don, thanks for clarifying. From my understanding, a device name would not be short enough to fit into a packet if it was already advertising NID and BID through Eddystone. I have encoded 2 bytes in my eddystone NID as a "device name" identifier. I plan to fish it out from the Generic Access Profile 0x16.Am I able to access that through your plugin in anyway?
Remember you can send 31 additional bytes in the scan response packet. It works like the advertising info. I'd add the device name there.
You can get access to the Eddystone data from the plugin, however it's a bit manual right now. I plan to add helper functions in a future version (see #192). Until then, here's an example of creating a hash map from the advertising data and parsing out some service data.
I did the following:
var adData = new Uint8Array(device.advertising);
html = adData[byteOffset]; // find byte offset from JSON.stringify(adData)
Do you see any potential problem in doing so?
I'd do something like this
var SERVICE_DATA_KEY = '0x16';
var advertisingData = parseAdvertisingData(device.advertising);
serviceData = advertisingData[SERVICE_DATA_KEY];
if (serviceData) {
// first 2 bytes are the 16 bit UUID
var uuidBytes = new Uint16Array(serviceData.slice(0,2));
var uuid = uuidBytes[0].toString(16); // hex string
console.log("Found service data for " + uuid); // should be 0xFEAA
// remaining bytes are the Eddystone beacon data
var eddystoneData = new Uint8Array(serviceData.slice(2));
// do something with the eddystoneData
}
I'm getting "undefined" as my BLE-peripheral name on my Android. Any idea how I will be able to detect it like in iOS? I'm able to get the device name of the same hardware on your Cordova SimpleSerial iOS.
I added: console.log(JSON.stringify(device)); //check peripheral info packet inside onDiscoveryDevice. "{"id":"AA:BB:CC:DD:EE:FF","advertising":{},"rssi":-55}" // real id masked; missing "name"