10

I'm writing an BLE application, where need to track if peripherals device is advertising or has stop.

I followed getting peripherals without duplications this and BLE Filtering behaviour of startLeScan() and I completely agree over here.

To make it feasible I kept timer which re-scan for peripherals after certain time (3 sec). But with new device available on market(with 5.0 update), some time re-scan take bit time to find peripherals.

Any suggestion or if anyone have achieved this?

CoDe
  • 10,214
  • 14
  • 74
  • 180

3 Answers3

5

Sounds like you're interested in scanning advertisements rather than connecting to devices. This is the "observer" role in Bluetooth Low Evergy, and corresponds to the "broadcaster" role more commonly known as a Beacon. (Bluetooth Core 4.1 Vol 1 Part A Section 6.2)

Typically you enable passive scanning, looking for ADV_IND packets broadcast by beacons. These may or may not contain a UUID. Alternatively, you can active scan by transmitting SCAN_REQ to which you may receive a SCAN_RSP. Many devices use different advertising content in ADV_IND and SCAN_RSP to increase the amount of information that can be broadcast - you could, for instance, fit a UUID128 into the ADV_IND followed by the Device Name in the SCAN_RSP. (Bluetooth Core 4.1 Vol 2 Part E Section 7.8.10)

Now you need to define "go away" - are you expecting the advertisements to stop or to fade away? You will get a Receive Signal Strength Indication "RSSI" with each advertisement (Bluetooth Core 4.1 Vol 2 Part E Section 7.7.65.2) - this is how iBeacon positioning works and there's plenty of support for beacon receivers in Android.

Alternatively you wait for N seconds for an advertisement that should be transmitted every T seconds where N>2T. The downside of the timed approach is that probably not receiving a beacon isn't the same as definitely receiving a weak beacon; to be sure you need N to be large and that impacts the latency between the broadcaster being switched off or moving out of range and your app detecting it.

One more thing - watch out that Advertising stops if something connects to a Peripheral (if you really are scanning for peripherals) another good reason to monitor RSSI.

  • 2
    Yes you are right, Connecting is not an issue as of now and I agree most of you mentioned. In my case Client peripheral do advertise for certain defined time, and central device (Android device) perform scanning. Now, some of Android Phone( like S5, Nx-5) scanning continuous packet and respond it back **continuous to app layer**. But some of phone(like Nx-4) might be do continuous scanning but don't respond for **DUPLICATE PACKET(i.e. same device)**..and this is issue here. Any input here ! – CoDe Jul 21 '15 at 05:00
3

First scenario: Bonded Devices

We know that if a bond is made, then most of the commercially available devices send directed advertisements in during re-connection. In situations such as this, according to BLE 4.0 specification, you cannot scan these devices on any BLE sniffer.

Second scenario: Connectable Devices

Peripheral devices are usually in this mode when they are initially in the reset phase. The central sends a connect initiator in response to an advertisement packet. This scenario offers you a lot of flexibility since you can play around with two predominant configuration options to alter connection time. These are: slavelatency on the peripheral and conninterval on the central. Now, I don't know how much effort it's going to take get it working on the Android platform, but if you use the Bluez BLE stack and a configurable peripheral such as a TI Sensor tag, then you can play around with these values.

Third scenario: Beacon devices

Since this is what your question revolves around, according to the BLE architecture, there are no parameters to play with. In this scenario, the central is just a dumb device left at the mercy of when a peripheral chooses to send it's beaconing signal.

Reference:

http://www.amazon.com/Inside-Bluetooth-Communications-Sensing-Library/dp/1608075796/ref=pd_bxgy_14_img_z

http://www.amazon.com/Bluetooth-Low-Energy-Developers-Handbook/dp/013288836X/ref=pd_bxgy_14_img_y

Jerry Ajay
  • 901
  • 8
  • 21
  • 1
    I guess there is no way to set conninterval from Central, or at least there is no API access at App level in Android ..refer http://stackoverflow.com/q/21398766/2624806 I asked before. Any suggestion here ! – CoDe Jul 20 '15 at 09:32
  • 1
    Well, I'm not sure about how flexible you can get if you dig deeper into the C implementation of the Bluetooth driver in the Android Source Code(assuming a straight-forward implementation exists). But, in order to gain flexibility, I use `bluez` which gives me control to play with `LL_CONNECTION_UPDATE_REQ` through which I can update the `conninterval` from the central. – Jerry Ajay Jul 20 '15 at 16:26
3

Edit: I forgot, have you tried setting the advertiser to non-connectable? That way you should be able to get duplicate scan results

I am dealing with a similar issue, that is, reliably track the RSSI values of multiple advertising devices over time.

It is sad, the most reliable way i found is not nice, rather dirty and battery consuming. It seems due to the number of android devices that handle BLE differently the most reliable.

I start LE scan, as soon as i get a callback i set a flag to stop and start scan again. That way you work around that DUPLICATE_PACKET filter issue since it resets whenever you start a fresh scan.

The ScanResults i dump into a sqlite db wich i shrink and evaluate once every x seconds.

It should be easy to adapt the shrinking to your use case, i.e. removing entries that are older than X, and then query for existance of a device to find out if you received a ScanResult in the last X seconds. However dont put that X value too low, as you must take into account that you still lose alot of advertisement packets on android LE scan, compared to a BLE scan on i.e. bluez..

Edit: I can add some information i already found for speeding up the performance on Advertisement discovery. It involves modifying and compiling the bluedroid sources and root access to the device. Easiest would be building a full android yourself, i.e. Cyanogenmod.

When a LE scan is running, the bluetooth module sends the scan sesponse via HCI to the bluedroid stack. There various checks are done until it finally gets handed to the Java onScanResult(...) which is accessed via JNI.

By comparing the log of the hci data sent from the bluetooth module (can be enabled in /etc/bluetooth/bt_stack.conf) with debug output in the bluedroid stack aswell as the Java side i noticed that alot of advertisement packets are discarded, especially in some check. i dont really understand, beside that it has something to do with the bluedroid inquiry database From the documentation of ScanResult we see that the ScanRecord includes the advertisement data plus the scan response data. So it might be that android blocks the report until it got the scan response data/ until it is clear there is no scan response data. This i could not verify, however a possibility.

As i am only interested in rapid updates on the RSSI of those packets, i simply commented that check out. It seems that way every single packet i get from the bluetooth moduly by hci is handed through to the Java side.

In file btm_ble_gap.c in function BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p) comment out to_report = FALSE; in the following check starting on line 2265.

/* active scan, always wait until get scan_rsp to report the result */
if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
     (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
{
    BTM_TRACE_DEBUG("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
                          scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
    p_i->scan_rsp = FALSE;
    // to_report = FALSE; // to_report is initialized as TRUE, so we basically leave it to report it anyways.
}
else
    p_i->scan_rsp = TRUE;
Dominik Gebhart
  • 2,640
  • 1
  • 11
  • 27
  • 1
    **Start-Stop Scanning:** I tried it but it hangs BLE stack and then have to **Turn ON/OFF** Bluetooth every time then. Another thing I observe, rescanning take some time(some 1-2 sec) to detect same device advertise packet. **Regard ROM build:** I might give it try but this I required for application layer. So change in OS source at any layer will not help here. I appreciate your effort, let me know if any other suggestion. – CoDe Jul 22 '15 at 05:46
  • 1-2 Second is bit weird in terms of User Experience application I'm developing. It force user to choose some other control. Well I tested on Samsung-S5 and Nexus-5, getting continuous data packet i.e. Duplicate packet. on other side Nexus-4 not respond duplicate packet. **Regarding advertiser** it send data packet for some defined second (< 1 Min) once it turn it ON with **conninterval** of 20 sec. I'm using TI based BLE Sensor. – CoDe Jul 23 '15 at 04:34