I'm developing an app both Android and iOS that needs to read iBeacons and search for an id in the database.
This Id should be the macadress or the beacon uuid?
Unfortunately both the MAC address and iBeacon UUID are largely useless for identifying beacons on iOS. Here's why:
An iBeacon Bluetooth LE advertisement has four identifiers:
A MAC address (48 bits)
An iBeacon UUID (128 bits)
A major identifier (8 bits)
A minor identifier (8 bits)
The first two identifiers are highly restricted on iOS, so you effectively can't use these to identify the beacon. Apple blocks you from reading the MAC, which makes it unusable on iOS, and Apple APIs require you to specify the iBeacon UUID up front when as a "filter" when looking for beacons. This makes it mostly useless for telling one beacon from the other.
As a result, on iOS you really need to use the major and minor fields to tell beacons apart (although you can use them along with the UUID if that is helpful.)
Android doesn't have the same restrictions. You can read the MAC, and you don't have to specify the UUID up front when looking for iBeacon packets. But you may want to do the same thing with Android detections as iOS detections just to keep it simple.
Related
I want to send some sensor data over BLE to multiple nodes.
I thought of changing advertising data at 4Hz. Can it be done?
Yes! It is a common approach to use a BLE beacon packet to advertise sensor data. A few points:
Embedded BLE platforms typically allow advertising at a minimum of 10Hz, and let you change the advertisement between transmissions. I have done this on the Nordic 52x chips, but hopefully STM32 supports it as well.
BLE 4.0 advertising packets are limited to 23 usable data bytes, but you typically need to reserve a few to indicate it is "your" transmission. There are significant further restrictions if you intend to use iOS devices to scan the transmissions. If using Android, Linux, or other embedded system scanners you can use nearly the full 23 bytes.
Keep in mind that anybody in radio range can scan for these advertisements and read the data. Make sure the sensor data are not sensitive enough to warrant a security layer.
I'm using Android Things 1.0.4 in a prototype where it acts as BLE peripheral device: advertising services and running a GATT server.
I encounter an issue in the BLE pairing process when trying to bond the Android Things board (Raspberry Pi 3) and a smartphone.
Since the device has no display, I set using BluetoothConfigManager:
IoCapability = BluetoothConfigManager.IO_CAPABILITY_NONE
which results in the error AUTH_FAILED every time.
Instead,
IoCapability = BluetoothConfigManager.IO_CAPABILITY_OUT
logs the pairing key and prompts the smartphone to enter it during pairing, but it results in the REMOVED error.
Questions:
Is Android Things in peripheral role capable of handling BLE pairing or not yet?
Are there more things that need to be implemented in the app's code to replicate the full-fledged Android logic?
Here's the source code of the Android Things app to test BLE pairing and bonding
The same code stripped from Android Things specific elements completes BLE pairing and bonding successfully when running on an Android phone as Peripheral (server), and an Android device or iPhone as Central (client).
Generally speaking, if you attempt to read an encrypted GATT characteristic before pairing (which triggers the pairing logic automatically), this results in GATT error 137 returned from the read request (AUTH_FAIL). This is because the device doesn't have enough time to finish setting up the bond before a response is sent by the Bluetooth stack. Retying the read request again generally succeeds.
I have not tested this with an iOS client device, but it certainly holds true with an Android client connecting to an Android (Things) peripheral. As such, I would recommend a few things:
Have the client (mobile) device explicitly initiate pairing, and Android Things should simply react to these incoming requests in the BluetoothPairingCallback. This lets the mobile device decide the pairing type based on the reported capabilities of the IoT device.
Separate the pairing flow from the GATT flow. Pair to the discovered device separately from making any attempts to read the characteristics. This tends to be the best way to avoid timing problems.
Regarding capability choices, this depends on your device. In my experience, if you choose IO_CAPABILITY_NONE this results in PAIRING_VARIANT_CONSENT inside of onPairingInitiated() and the pairing operation succeeds once finishPairing() is called. If you adjust your capabilities, you should be prepared for any number of the variants requiring you to display a PIN for the mobile device to enter. I have not not personally tested these paths.
Hello,
The context: I'm currently working on a BLE device that is connected with Just Works connection type to its Master (android tablet).
Since :
Android devices with recent versions of Android do not use the public address when connecting. Rather, they use a random address. This is part of the BLE spec. For the purpose of privacy, in addition to the public device address there are random device addresses. New versions of Android uses a random address when connecting to peripherals. (source of that quote)
I understood that my Android tablet is using a random address. For that, i made a programme to verify this information and it actually works (fortunately).
So my BLE public addressed device can connect to the master by receiving its pairing ask.
The question: First of all, what exactly are BLE addresses (random, static, public(mac) it's a bit confusing from the docs) ?
The MAIN question: Can my master (android tablet) connect to my device when those two are private addressed ?
My specifications:
Using VisualStudio
Using VisualGDB and openOCD
BLE_lib.h and BlueNRG
Ask for more information
The answer: Public BLE address is given by Bluetooth SIG and is guaranteed to unique. Random BLE address does not have this property. In addition random address can be either static or public. Static address cannot be changed while the BT chip is on. Public is divided into resolvable and non-resolvable, both can change whenever and the basic difference is the amount of bytes that change.
The main answer: Yes but you will need a way to identify the device. You could broadcasting specific data (e.g. manufacturer data or a 128b service UUID) and have your tablet scan for it. Then you can connect to whatever address you find provided the device advertises correct data.
And recommendation: You can find a lot of stuff at Nordic semiconductor-related sites. Even if you do not use their stack, their tutorials and explanations are easy to understand and cover pretty much everything.
Edit: I could probably provide better answer if I knew what exactly you intend to do.
To test bluetooth scalability, I want the same device (a Raspberry Pi or a laptop) to emit several BLE advertisements. So far, I have tried using bleno (NodeJS), hcitool and CoreBluetooth for OSX, but I can not setup more than one.
Is this a hardware/system/bluetooth limitation? Has somebody managed to do this?
Different bluetooth devices have different maximum advertising rates. These typically range from 10Hz to 40Hz. Some bluetooth devices have the ability to spoof their MAC address so different advertisements appear to come from different physical devices. This is often important for scalability testing, because some receivers keep track of unique devices by MAC address.
As #Emil says in his answer, it is possible to "interleave" advertisements such that you change the advertisement (and ideally the MAC address) every few hundred milliseconds so it appears by receiving devices that there are multiple advertisers around. I have done this with both Raspberry Pi and iOS transmitters, but in neither case could I alter the MAC address.
It is important to understand, though, that the actual number of packets received when you do this does not change. So while you may be testing scalability of unique advertisements detected, you will not be doing the same thing as testing with multiple physical advertisers.
That's not possible by the Bluetooth specification. However you can start off with one data then set a timer in your app that stops advertising. Then you start off again with the next data. And so on.
I would like to detect a beacon and then write a value to some of its GATT characterictics, so other BLE-devices can read it. Is this possible at all? Or some special device is needed for this?
This is not possible with a standard iBeacon because it is a transmit only device.
You might be able to build your own custom device to do this, but making it work on iOS when more than one Bluetooth device is around will be almost impossible. This is because there is no way to correlate detected iBeacon identifiers with as connectable Bluetooth device -- iOS has sandboxed the CoreLocation iBeacon detection APIs and the CoreBluetooth APIs needed to read and write GATT characteristics.
As a result, you can never know for sure if you are writing to the same device you detected.
For a detailed explanation of the sandboxing of the CoreBluetooth and CoreLocation iBeacon APIs, see here.