I've got a problem. I'm developing an android application that scans for wireless accesspoints/routers. I've been testing a couple of devices and I'm getting scan rates of 2, 1, 0.5, 0.1 etc. scans per second.
My goal is to reach 10 scans per second because a router can send beacons 10 times a second. And we need this for our application.
Is there away to make this possible? Perhapse hack a rom and replace the wifi drivers? I've been looking in to this but I can't find anything about this frequentie inside the driver.
The driver used is BCM4329 driver, I can't find any datasheets of the BCM4329 so it's kinda hard to figure this out.
Thanks in advance.
flitjes
I'm not familiar with driver development but I know it's one of the hardest thing in computer science so unless you have good knowledge in linux kernel development I would forget about it.
Moreover, you still need to scan the 12 Wi-fi channels to be sure that you are detecting all access points. An access point broadcasts a beacon every 100ms * 12 channels = 1.2 seconds. Spending less time than that and you risk missing access points.
You don't need to change anything in the device driver, Android makes it available to you to scan for access points. See the documentation.
Although requesting that many scans will probably not be very good for the battery life and the responsiveness of your app...
Your assumption that beacon rate is 10 per second is incorrect. This is really an AP configuration parameter, although 10 per sec is default in most. Besides that, APs do not send beacons simultaneously, if this happens, it's called a collision and a back-off algorithm is used for retransmission. In addition, even scanning 10 times per second doesn't make it certain for you to capture all beacons, like was pointed out in the previous answers.
if u use 4339 driver, you could not set the scan rate in driver or android api which is fixed in 4339 firmware, scan is about all channels && time u spend on each channel, according to the 80211 spec, which is part of mac && phy. in this case u just need to get the beacon, so u should use passive scan and use fixed channel && MaxChannelTime u want.
u have to ask broadcom for speical fw to figure out your problem,
IEEE
Std 802.11-2012 page 978
10.1.4.2 Passive scanning
If the ScanType parameter indicates a passive scan, the STA shall listen to each channel scanned for no
longer than a maximum duration defined by the MaxChannelTime parameter.
Related
I use android phone to detect a beacon using startScan method, the interval time of beacon adversing is 800ms, but I got the beacon data from callback of startScan every 3~10 seconds. My expectation is I can get the data every 1 second.
Below is my codes. So is there any other ways to get my expectation. Or someone can explain why the interval time is not the same as the adversing time ?
ScanSettings.Builder builder = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
// scan filters has been set the right value.
bluetoothLeScanner.startScan(scanFilters, builder.build(), scanCallback);
Nothing about the code shown is a problem. I can confirm your expectation is met with equivalent code in other apps on other devices. This suggests a problem with :
Your BLE device not advertising as often as you expect
Your Android phone (possible but unlikely)
Some other aspect of your code that you did not show in your question.
Is you BLE device a beacon? If so, I suggest:
Install BeaconScope on the same phone, scan for your beacon, then check the PPS rating (Packets Per Second -- scan for at least 30 seconds until the measurement stabilizes). If you see a value of 0.1-0.3 then the problem is NOT with your code and must be (1) or (2). If you see a much higher PPS value, the problem is with some other aspect of your code not shown.
Use a second Android phone with BeaconScope as a transmitter and transmit a beacon at the 10 Hz default rate. Does your app get a packet every 100-200ms? If so, you have confirmed the problem is with your BLE device not transmitting as much as you expect.
If your BLE device is not a beacon you can at least perform the second test.
It's recommended to use 'SCAN_MODE_LOW_LATENCY' mode only hen the application is running in the foreground.
Incase you are in background, you can run a sticky foreground service and set a periodic frequency of 1 sec for your service.
Also scanning Ble for every 1 sec might be extremely heavy for the app.
I've seen a lot of discussions on battery for altbeacon, specially if beacons are inside a region for a long time. This post was actually very clarifying.
I am currently working in a solution that requires a good sensibility (which I define as being a small detection time for a new beacon in a region).
As some beacons may be anonymous (which I define as presenting unexpected MAC addresses but share a same matching byte sequence) to the scanner in this particular solution, I would like to achieve good sensibility to new beacons but also a balanced battery impact to the user.
What concerns me is if a first beacon is found and the region triggers based on the matching sequence, how could I get a notification once another beacon approaches (or leaves) ?
A guess I was going to try was to keep monitoring for a generic matching sequence and once a beacon is found for that general sequence, range it to get its address and them create a particular region for the mac I've taken. The only problem with this approach was how could I prevent the first beacon to keep triggering the generic region?
And just out of curiosity. Is the ScanFilter class related to those hardware filters introduced on android 5?
Thank you,
If you need to quickly find new beacons with the same byte patterns as ones that already exist in the vicinity, you really have no choice but to keep ranging.
In such a situation, there is no distinction between ranging and monitoring in terms of battery consumption. Both will require constant Bluetooth scans and decoding of all beacons in the vicinity. Scan filters (yes, the hardware filters introduced in Android 5,) will not help because you expect the byte patterns to be the same. There is no such thing as a packet "does not match" scan filter that could be used to find only new MAC addresses.
You may need to accept the battery drain of constant scans and just try to limit how long they last, if your use case allows. Short scans of 30 minutes or less might be acceptable.
You could possibly save some battery by writing your own BLE scanning parsing code tailored to this use case. You could first look for unique MAC addresses, and only do further processing and parsing if the MAC address has never been seen before. This will not reduce battery usage from the constant scan, but it would cut down on battery usage from CPU expended on parsing packets. This might save 10-30% depending on the number of beacons in the vicinity.
Bottom line: you are right to be concerned about battery usage with this use case.
People! I thought to include it in original question but didn't.
WHILE VOTING, YOU ARE ALLOWED TO COMMENT WHY DID YOU VOTE?
Please use it to enable learners get theirs things done and convey their thoughts/issues to others better way. Not everyone knows what you think. Thanks
In Short:
I need to synchronize clocks of two Android Phones (placed close to each other OR not; both cases) with each other AND with up to an accuracy of a few milliseconds (10, 20 ms max).
Either sync the clocks
Or get an offset of one from the other
What I am Doing:
I have a developed app that I am using to measure different GSM network statistics. I am using telephony manager to get three states (OFF-HOOK, IDLE, RINGING). Phone A calls phone B. Both phones are running an app that is saving the time-stamps with regards to the states mentioned above. After making many calls I export the time-stamps in a data file and analyze them to get different network stats.
What is my Issue:
I have to cross-match the time-stamps to get stats. Now the problem is that if the phones' clocks are not synced then I will not be able to get exact stats (e.g. how much time it takes to get phone B in ringing state after phone A initiates a call?).
What I have Tried: So far I have tried to sync clocks with NTP, GPS or atomic clock. I have used ClockSync (Android app) to get offset of both phone clocks from atomic clock. The issue is that this offset depends on RTT of network packets from my phone to server. I gives my difference of up to 100 ms when I check offset two times (tap refresh two times consecutively). The offsets at both phones can lead to error of up to 200 ms which is unacceptable for me.
All other syncing apps/methods have same issue.
Possible way forward: (What I think). I may develop an app that
takes the time-stamp at phone A
transfers that to phone B via Bluetooth or WiFi (connected to same router),
B then compares that time-stamp with its own clock, calculates offset,
And I run my original app, run experiments and,
Use the offset to correct time-stamps before processing data
Your Comments/Suggestions: How to do it? And comments on the method described in last part..
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?
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.
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
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;
My BLE application requires computation on the server side (BLE chip) which takes time and results with disconnection.
Th flow is like this:
1- Android phone writes the characteristic value to the BLE chip.
2- The chip evaluates this value and starts computation.
3- The connection is lost soon after the computation has started.
What solution can I apply to prevent the disconnecton? I have two solutions in my mind:
1- Changing the connection interval: Currently Android uses 7.5 msec as connection interval. Since the computation on BLE chip takes time, packets are not sent or received during the computation. Increasing the connection interval will decrease the number of lost packets. However there is no guarantee that Android phone will accept the new connection parameters.
2- Running the computation in a separate thread: I dont think that BLE chips' SDK support multi-threading such that while there is a computation process going on, it will keep receiving and sending packets and prevent the disconnection. I use CSR chip and I think it doesnt support.
Please correct me if I am wrong at my points.
Do you have any other suggestions to solve the issue?
Thanks in advance.
Thank you for the answers. I found out what the problem is after spending hours.
First of all, when Android gives error 133 or 129, it is most probably because of the remote device.
At the beginning I thought that the problem occurred because of the supervision timeout. Then I re-configured the connection parameters of the CSR chip but it didn't help.
There is a problem about CSR app development with xIDE (IDE of CSR). When there is run-time-error due to index overshoot or accessing some invalid pointers, then you would not receive any errors in xIDE. I finally found out the array problem and fixed it. Now it works perfect.
Thanks a lot!
I don't know exactly if what i going to explain it's feasible under Android because I used BLE only with a low level applications, anyway if your problems are the connection parameters you can try to change the Slave_Latency.
It should be usefull since playing with this parameter, you can change the number of connection intervals in which the Central device can wait until it considers the connection lost.
The following equation is usefull to derive the connection parameters:
Effective_Connection_Interval = (Connection_Interval)*(1+(Slave_Latency))
Remember that can exists some kind of Supervision_Timeout that can collide with your Effective_Connection_Interval