I a trying to understand and modify the BLE sample von Android.com, now I can discover my sample BLE Device (HTC Fetch) and now I want to understand all that GATT and BLE stuff.
What are Characteristics and what are Profile and what are Serivces and what do they mean in the Bluetooth Low Energy World? I used HTC Dev and found a Service and a Characteristics UUID.
https://www.htcdev.com/devcenter/opensense-sdk/bluetooth-smart/htc-fetch/
But I guess what I need is the Find Me Profile, cause for the first steps I only want to get the Find Me react to a Button click.
https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.find_me.xml
How to implement this in my App?
When I understand everything I try Power and Proximity (reading RSSI and compare with defined range).
Can some one help me understanding Bluetooth LE?
Here's a related post
How to use the profile of PROXIMITY PROFILE,IMMEDIATE ALERT SERVICE and Find Me Profile in android 4.3 BLE?
Basically you can approximate a proximity level using tx+power - rssi or distance roughly with
d = (rssi-A)/-20 (where A = rssi at one meter) or simply use rssi mapping out ranges to display You could also initially base it on just the connection range and skip rssi.
As for the FindMe, simply write the low or high alert values to make it sound when you press a button in your app. For pressing a button on the device use the UUIDs shown in the documentation.
sample code for that device is forthcoming
Related
Long Description:
I have a DJI Osmo Mobile 3 gimbal with Bluetooth 5.0, which supports ActiveTrack 3.0 technology. It connects to your phone via Bluetooth and using the DJI Mimo app you can select an object and track it.
I want to implement this technique in Python using OpenCV.
As I understood, the phone calculates position of the object using computer vision and then sends the coordinates via Bluetooth to the gimbal, which then follows them. I connected to the gimbal with NRF Connect app for android and looked for its services and characteristics, and this is what I found:
Services
Some unknown information getting sent
UPD: looks like the 4 bytes after 57 on the picture mean the joystick values. Fisrt 2 are responsible for left-right tilt, the other ones indicate up-down state. Looks like all of them can be max. 256, but I don't understand, why do they need 2 bytes for each action?
First 2 Bytes:
d2, 03 (210, 3) - full right
c2, fb (194 251) - full left
Last 2 Bytes:
5a, 04 (90, 4) - full up
a6, fc (166, 252) - full down
HID Control, which doesn't return any information
The characteristic with UUID
0xFFF5
Looks like what I need, but now I need to find out, in which format the coordinates are getting sent. For this purpose I want do simulate same BLE services as on the gimbal and let the phone think it is a real one. After the connection it should send data to some of the characteristics. So now the main question.
Main question:
How to emulate BLE Services and their Characteristics using Android, RPI, ESP32 or whatever to get data being sent to those characteristics? Is there any app, library or piece of code for such purpose?
I've seen dongles like CC2045, which are designed to work on 2.4GHz frequencies and sniff BLE Traffic, but it will take for a long time for them to arrive to me. Also nRF52840 based donglas are not an option right now. So I want to implement it using things I have. Is it possible? Thanks!
The project I am currently working on involves a weight scale that has built-in BLE and my smartphone. The scale connects to the smartphone via BLE to send the current weight data to its app (I assume this is prioritized.) Although I can't figure out how to get the correct UUID to communicate with the scale in my own Android App as it doesn't seem to be using the standard GATT Services. The devices seem to use 0x2901, 0x2902...0x290X
Scale model: HNY200 (Color Black)
Link to scale: https://www.healthometernuyu.com/nuyu-products/scales/wireless-scale/HNY200KD.html
After using a BLE scanner on my phone I was able to determine the BLE Name for the device (Much like the SSID in a network) and the MAC Address. However, it also shows a long list of CUSTOM SERVICE and CUSTOM CHARACTERISTIC options each with Descriptors and their properties such as read and write. I would assume the data im searching for (The weight value) would come packaged in a CUSTOM CHARACTERISTIC with the properties including READ. After analyzing each individual one the value is either the exact same hexadecimal number each time or has no value at all. The ones with no value instead have "OTA_STATUS", "OTA_CMD", or "OTA_DATA" but does not reveal anything besides that.
BLE Scan of the device looking at the most interesting characteristics (but not all):
https://imgur.com/a/iHWDoSM
I currently dont have any code for the android app as I am just following along with the Android Developers Tutorial. However, in previous research, It seems as though I will need the correct UUID's as I might have to reverse engineer the protocol the scale is using to send prioritized data to its app. Some BLE scanners work to find the scale and some do not.
I expected one characteristic to reveal a value of the weight being displayed on the scale and instead I got very large hex values, nothing at all, or some string value such as "OTA_DATA".
I am developing an android app that fetches temperature from a bluetooth thermometer. I followed the instructions on the google developer page.
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html
I could scan the devices and get connected to the thermometer. I am exactly using the same code from the following github.
https://github.com/googlesamples/android-BluetoothLeGatt/
Instead of using the the heart rate service and associated characteristics. I am using temperature service and the characteristic. I have changed these value on the following page that I downloaded from github
android-BluetoothLeGatt/Application/src/main/java/com/example/android/bluetoothlegatt/SampleGattAttributes.java
I using the following bluetooth thermometer.
http://www.cooper-atkins.com/Products/Blue2/
This is the API document I got from COOPER-ATKINS.
https://drive.google.com/open?id=1eq93Qc6uy0Vv9KompukLuIUnJK4B-e-0
In page 6 I have highlighted the service uuids and characteristic uuids I have replaced in the github code.
I could read the temperature data but only once. If the temperature changes I could not see the temperature value is refreshed in app automatically. I have to hit the temperature list button to get the recent value. Could anyone suggest what I am missing or doing wrong.
Please let me know if you need more info.
The characteristics you highlighted have both read and indicate property.
Reading the characteristic (Calling BluetoothGatt.readCharacteristic in Android) only obtains the value at that instant by definition.
You have to enable the indication to get every update of the value.
You can find how to enable a notification (not indication) on this SO thread. You can substitute the constant value to enable indication.
Is BLE supporting pinging, i.e. sending a message to other devices and receiving their status?
I want to write an app on Android, which will ping each of the nearby devices and calculate the time between sending time and receiving answer, is it possible?
As you pointed out in your comment you like to use as time-of-arrival or time-difference-of-arrival algorithm to calculate the distance based on bluetooth.
To my knowledge this is currently more a theoretical approach in a bluetooth environment. As radio signals travel at light speed (~29.979 cm in one nanosecond) you will need a high sampling resolution to get a accurate result. Each nanosecound deviation will cause an error of roughly 30 cm.
With WiFi this is accomplished with a specalized chipset. To my knowledge this is currently not possibile with android as it would need a lot of low level support (Chipset and OS)
Hope this helps!
here are some sources
Android relative positioning, Wifi:Time of Arrival
Evaluation of indoor positioning based on
Bluetooth Smart technology - page 76
You can easily see the timestamp of discovery for each device in your onScanResult method:
#Override
public void onScanResult(int callbackType, ScanResult result){
Long lastSeen = result.getTimestampNanos();
//rest of your code
}
See the Android Documentation. You can use this timestamp and the time that you started your scan to get an approximate response time for each device.
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;