The Bluetooth v4.0 specification says:
A service may have multiple characteristic definitions with the same Characteristic UUID. [1]
Are there any GATT services that have multiple characteristics with the same UUID?
What is the use case for this?
[1] (Vol 3, Part G, 3.3.1 "Characteristic Declaration")
Normally it won't be that useful… A simple use case can be:
Like if I have a BTLE device try to measure the Magnetic Flux Density difference between two points in space and also provide the flux density on both points to user, instead of publishing two Environmental Sensing services, it's making more sense to publish one Environmental Sensing service with two "Magnetic Flux Density - 2D" characteristics.
Related
We're designing a Bluetooth LE peripheral that implements some primary GATT service and needs to advertise the existence of the service as well as a few bytes of data related to the service. The device is intended to connect to arbitrary consumer smartphones (therefore mostly Android and iOS). We use a 16-bit service UUID and plan to advertise the related data via the advertising data type 0x16 (Service Data - 16 bit UUID). Due to the limited size of the advertising PDU, we'd like to avoid any additional advertising data, most notably we'd like to avoid advertising the same UUID also via data type 0x03 (Complete List of 16-bit UUIDs).
As the device should be used with consumer smartphones, compatibility is a major concern and therefore the compliance with relevant standards is as well. A critical aspect seems to be that the smartphone OSes should be able to do efficient filtering for devices advertising our service, so the app may run and listen in the background.
A safe approach would be to advertise both, 'service data' as well as 'complete list of UUIDs', because all OSes are certainly able to filter for UUIDs advertised in the latter, but this would exceed the size of the advertising PDU. We could also configure the mobile's BLE scanner to return all BLE devices nearby, without any filtering and do the filtering in our own code, but this wouldn't be efficient and wouldn't allow to run in the background.
We did some testing with different smartphones (Android and iPhones, older and newer ones) and at the first glance filtering for service UUIDs when only the service data type is advertised, seems to work just fine. However, we couldn't find any documentation (neither for Android nor for iOS) that definitely states that this is a supported scenario, so we can't be sure that it works on all phones and also in the future.
The Apple Accessory Design Guidelines section 36.4 refers to the Bluetooth Core Specification Supplement, Part A and states the following:
The advertising data sent by the accessory should contain at least the following information as described in the Bluetooth Core Specification Supplement, Part A:
Flags
TX Power Level
Local Name
Services
[...]
The primary services should always be advertised in the advertising PDU.
However, this doesn't make clear which kind of advertising data type should be used and the same is true for the Android documentation.
With this context my questions are:
Is it a good idea to advertise the primary GATT service solely via the 'service data' data type?
Would this even comply to the Bluetooth Core Specification?
Is there any documentation for Android and iOS that makes clear, whether this is a supported scenario from the OS standpoint (I actually don't mean the OS source code)?
Are there any Android (>= 5.0) or iOS (>= 11) devices that would not be able to filter for service UUIDs advertised via the 'service data' data type?
What is the best practice in such a case, given the limited size of the advertising PDU?
Thank you for your thoughts!
I have a beacon device that broadcasts different UUID values based on a custom rotation scheme.
Usually, the developer has to set static UUID to be recognized by the app like that (example for iOS):
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:major minor:minor identifier:identifier];
I was wondering if there is a way to dynamically generate (or receive from a server) the UUIDs to be recognized.
Having said that I am still having difficulties understanding the internal mechanisms of how beacons are understood by iOS and Android. From my understanding, the BLE module of the phone forwards all well-formated iBeacons to the OS which maintains a list of recognized UUIDs. After a simple look-up and if a match is found the OS will bring the corresponding app to the foreground.
However, when does the app's recognized UUID(s) get registered with the OS? How often do they get re-registered? I would be grateful if anyone would point me to any relevant online material or at least the mention the mechanisms involved in this process.
On both Android and iOS registering for beacon ProximityUUIDs to detect amounts to nothing more than applying a filter on Bluetooth packets that match the byte pattern of the beacon and ProximityUUID. The important difference is that on iOS the operating system framework that does the filtering, CoreLocation, puts severe limits on the filters you can have. The iOS limits include:
You can have only 20 UUIDs monitored at any given time for a single app.
A device-wide limit of the first 30 UUIDs monitored gets hardware assisted fast detection. Later UUIDs to register get slower (several minute delays in the background) detections.
You cannot monitor or range for any UUID (global wildcard)
You can, however, change the 20 UUIDs you app is monitoring at any time -- even once every few seconds. The trick is that your app must be in the foreground to do this, or have a permitted way to run in the background to do this UUID rotation.
To register a UUID for monitoring on iOS, you simply declare a region with that UUID ( typically without specifying major and minor values) then call:
[locationManager startMonitoringForRegion:region];
To keep from going over your 20 region limit you also have to call:
[locationManager stopMonitoringForRegion:oldRegion];
On your old regions you do not want to monitor anymore. Otherwise if you go over the 20 limit you will not get detections on newly registered regions.
Of course, you may use a web service to provide the UUIDs for your new regions to monitor.
On Android it is much simpler -- you can monitor for all UUIDs by specifying a global wildcard using the Android Beacon Library and similar SDKs.
Full disclosure: I am the lead developer on the Android Beacon Library, the first beacon implementation on that platform.
Among the various officially registered Bluetooth device services, which are listed on the Bluetooth.org website, there is no mention of F002 or F003. But I recently was scanning for BLE in public and some unnamed device had these two services. Does anyone here know what device uses F002 or F003? Thanks.
Services in BLE can be adopted or custom. They have UUIDs that are 128bit long but are usually identified by their 16-bit offset:-
Adopted services are those listed by the Bluetooth SIG as
standard Bluetooth UUIDs. They're given a unique number and you have
probably already seen them here. Examples of those include the
Heart Rate (offset 180D), Health Thermometer (offset 1809), Battery
(offset 180F), etc. Those UUIDs are universal and if you see 180D
anywhere it should mean that it's the heart rate service.
Custom UUIDs on the other hand are undefined and in many cases can be just randomly generated. F002 is not an identified offset and therefore can belong to anyone using it for any random service.
I do remember coming across TI sensor tags with a similar UUID so it's worth investigating if you have any of those lying around.
A good read of UUIDs and BLE in general can be found here:-
https://www.safaribooksonline.com/library/view/getting-started-with/9781491900550/ch04.html
As a 3rd party is there a viable way to correctly interpret data from a Bluetooth Low Energy device for which there is not a published GATT profile specification?
The BLE device is a body scale that supports weight, BMI, body fat, and hydration level. My understanding is that there is no adopted GATT profile for body scales like there are for, say, blood pressure devices or heart rate monitors (https://developer.bluetooth.org/gatt/profiles/Pages/ProfilesHome.aspx).
Using the following tools:
iPod (iOS 6.1.3) with various BLE utility apps (Ti BLE Multitool, LightBlue, and BLE Utility)
Android (4.3) tablet (Dell Venue 8 3830) with nRF Master Control Panel, plus a custom Xamarin developed solution
I can scan for, locate, connect to, and read the GATT services available on the scale. All of the above tools give me the same service information. There are 5 services discovered on the scale:
Generic Access (0x1800)
Generic Attribute (0x1801)
Device Information (0x180A)
Battery Service (0x180F)
An unknown service with a custom 128-bit UUID
All of the above tools are able to read from the known services, like retrieving the battery information or the device name. My assumption is that the unknown service with the custom UUID is the service that provides the scale data.
This service has 5 unknown characteristics with custom UUIDs:
Characteristic 1 is Read/Write
Characteristic 2 is Read
Characteristic 3 is Read/Write
Characteristic 4 is Notify
Characteristic 5 is Read
Using the tools that were specified above to read from characteristics 1, 2, and 3, each returns it's own value, but that value never changes. For example, a read of characteristic 1 always returns a value of 20 octets 0x01-0x05-0x06-0x07-0x08-and 15 0x00 octets. Subsequent reads of characteristic 1 always return that value. Characteristic 2 reads always return a value of 20 octets 0x02-and 19 0x00 octets. And so on.
Reading characteristic 5 appears to either not return a value, or more commonly on Android, issue a pairing request. No common pairing code (like 0000 or 1234, etc.) is valid.
Characteristic 4 appears to be what actually transmits the scale data. Using the tools above I can enable notifications and the applications retrieve 13 octets. For example:
FF-16-09-00-03-04-01-00-83-6F-F4-18-0F
FF-16-09-00-03-04-01-00-3E-88-F4-18-E3
FF-16-09-00-03-04-01-00-C8-89-F4-18-6E
Obviously all of those values begin with the same set of octets. The main problem though is what do those octets represent and how do they translate to weight/bmi/hydration/body fat values, if in fact they do at all.
The scale is built with the Ti CC2541 chip (http://www.ti.com/product/cc2541).
Using Ti's SmartRF Protocol Packet Sniffer along with the CC2540 USB Evaluation Module Kit I can capture packets going between an iPhone 5S (iOS 7.1) and the scale. This has provided some additional insight, but mostly just shows what I've already observed using the other tools, though albeit it at a lower level. Any additional information provided by the packet sniffer still leads back to the same question: what do these sets of octets the scale is sending represent and how do they translate to weight/bmi/etc? I've utilized the Bluetooth Core Specification documentation and that has helped to understand what octets for standard functionality mean/do, but that isn't helping understand the actual scale data.
I'm very new to Bluetooth development and this exercise has basically resulted in a crash course in the technology. Any help is appreciated.
Thanks.
You must contact the manufacturer and ask for clarification about the custom service and characteristics.
Characteristic 5 seems to have higher security settings, hence why it triggers pairing when you try to read it. Most likely contains some sensitive data.
Characteristics 1,2,3 are likely for configuration, while 4 notifies the useful data.
Since these are all custom, there's simply no way to find out what they mean without information from the manufacturer.
It's like you create your own "We're out of yogurt" notification profile... one can only guess by looking at the data.
I have looked at the BLE specification, and found that the Bluetooth SIG has predefined a number of services, like heart rate. I am just wondering if it is possible for me to define a service myself? If can, is there any example available? Thanks.
yes, it's perfectly possible to define services yourself.
Services and characteristics are all identified by a UUID. For example the BLE Services page lists all standardized services and the assigned UUIDs.
As you can see the Heart Rate services uses 0x180D, which is a 16-bit short form reserved for standardized services only. The only requirement when defining your own service is that you use a 128-bit long form UUID.
Use uuidgen (available on Mac OS X) to generate a random (unique) UUID yourself:
uuidgen
# example result: 94B01578-5603-4D5A-8DFF-9365A1C4AC93
You can use this to publish and identify your own service. This can either be done on your own custom hardware, or through software on iOS (since you mention core-bluetooth).
Create your CBMutableService:
CBUUID *serviceUUID = [CBUUID UUIDWithString:#"94B01578-5603-4D5A-8DFF-9365A1C4AC93"];
CBMutableService *myService = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];
// add some characteristics, also identified by your own custom UUIDs.
Finally see addService: &
startAdvertising: on CBPeripheralManager to start publishing your custom service.
After publishing this service using an iOS device you can scan for and connect to that service using another iOS device or a Mac, using the CBCentralManager class.
Here's demo app with an example of setting up your own Bluetooth LE service on an iOS device: SimpleShare
You need to generate a UUID that's unique to your app's service. This site will generate one for you to use.