In our previous guide, we went over BLE advertising and how BLE advertising works in general. But we’ve still gotten many questions about how to do the Bluetooth LE advertising right for many use cases. This guide will cover creating BLE advertising packets in depth, to help you create better products.
BLE Advertising and scan response packets serve primarily to allow a Central device to find a Peripheral. The way to do this properly depends greatly on the product, but we’ll cover a lot of techniques and rules of thumb we’ve used at Argenox to help develop products, and they've worked out great for hundreds of thousands of devices.
It's important to know that aside from connecting, advertising packets also allow a product to communicate information and status. There's limitations in the amount of data and some other considerations like power consumption and security, but many applications that use connections don't necessarily need them and would be better off done with advertising.
We’re not going to cover beacons here specifically because Beacons, both iBeacons, EddyStone and others have a fixed structure already defined and other articles already cover them.
Where to start on the advertising? perhaps the first place is to understand what is the cost of each byte of advertising. Longer advertising packets with more bytes of data mean extra power consumption since the radio has to stay on the air longer to transmit. We've analyzed the Nordic nRF52832, a popular BLE chipset and quite representative in terms of TX/RX BLE radio output power.
You can see that analysis in the chart above. There's a clear linear relationship here. Advertising at 500ms will reduce the cost per byte significantly. At 100ms, each byte in the advertising packet will cost about 1.5uA to 2.1uA depending on output power. Clearly, at these high advertising rates, each byte contributes in a very real way to the average current. Consider that the sleep current of most BLE devices, including the nRF52832, is around 1uA-2uA. Each byte by itself will consume that. However, at 500ms, the cost per byte is significantly reduced.
Because of the heavy cost of the advertising, one must be very careful when choosing what to advertise, how often. This can literally make or break a product. Advertising is a tradeoff primarily between Power consumption and latency, and how to do a proper tradeoff depends on the use case.
Another item to take into account when building a BLE advertising scheme is that accepting Scan Response packet adds extra power consumption to the device. At each advertising event, the Peripheral radio must stay to listen in RX Mode. How significant this is depends on your use case, battery, etc.
For use cases where operational lifetime is extreme or the battery very small and advertising is significant part of the lifetime, optimizing these aspects can be critical. Whether the battery can be replaced, what the customer expectations are, latency, power profile of the Central are all aspects.
We mentioned Power consumption, but there are plenty of factors to consider when building a Bluetooth LE advertising scheme. Here's a few you should keep in mind:
We want to address one design choice that we commonly see in devices and that's using the local name in BLE advertising packets. It's very common to see a name added to the advertising packets, and we increasingly believe this practice needs to be limited. Part of the issue is that it's the default BLE IC vendors set in their SDKs, which ends up being adopted by everyone. The advantages of adding a local name to the advertising packet is that it's easy to find using an iOS or Android BLE app. But for Mobile Apps, the name isn't necessarily unique enough.
There's a big disadvantage in using the name field and that's inefficiency at the Central device. BLE Central devices cannot typically filter by name at a low level, meaning they have to wakeup an application to perform the filtering. UUIDs, however, can be filtered at the controller level. This means lower power consumption.
You may wonder why it matters to care about the Central. Well, many Android phones and even iOS are also limited by batteries. High power use is correlated with users disabling BLE and uninstalling applications. For BLE devices that are deployed to AC powered gateways, this doesn't matter much, but it's best to design for the common denominator.
So if the goal is to identify a device quickly to allow enable a connection or selection, there's a few ways to do it. A few are below:
Let's go over each one of these options
Name - There are two parts to the name. "Device" is intended to be the category of the device. We typically have customers that put the product name here. The second part is "8912" which is intended to be used as a generic serial number. This method can be inefficient. First, the name "Device" doesn't encode the product/model efficiently. What if you need to have multiple variants of a similar products? Or if you need more space for advertisement? This is also inefficient for finding devices as we mentioned.
128-bit UUID: This method uses 16 bytes. It's not the smallest, but it is unique. We like this option because of the efficiency of finding Peripherals at the Central. Note that one can encode a unique category of products. After a connection to the product, the actual serial number can be identified from the device information service.
16-bit UUID: this method is identical to the 128-bit UUID except that it uses 2 bytes instead of 16 bytes, with the other 96-bits formed by the Bluetooth SIG standard UUID base. This method requires purchasing a UUID from the Bluetooth SIG ($2500 per UUID). We usually see this done by large established companies.
While the two UUID approaches don't include a unique identifier, it can be retrieved from the device after connection. Including the serial number isn't helpful to users when they first connect in most cases, and proximity pairing can be used. Once the device is correctly connected, iOS or Android store the unique identifier and use that to connect. The advertisement data is then often unnecessary.
The scan response is identical to the Advertising packets, except that they're optional. We typically use the Bluetooth name in the scan response until disabling it later during development if not needed. However, in some devices, a lot of data can be placed in the scan response.
Since the 128-bit UUID takes 16-bytes and leaves little room in the Bluetooth advertising packet, placing Manufacturer Custom Data usually goes in the scan response. The advantage here is that you will not need to connect
If your device is not connectable, then advertisements and scan response packets are the only way you can get your data. In this case, they'll need to be as large as needed to fit. But, if your device is connectable, then you should place as little data in the advertisements as is needed to determine whether you should connect or show the device to a user to select.
No discussion on advertising packets would be complete without touching on MAC addresses. Some developers are very used to using MAC addresses. Some obvious issues with these are that BLE addresses may be static, but it's impossible to predict which MAC address will be needed to connect. You could purchase a MAC address block, but this approach is not scalable and unnecessary. In fact, the privacy features in BLE will randomly cycle the MAC addresses.
The elements that can be placed in each BLE advertising and scan response packets are defined by the Bluetooth Specification. Below we cover the most important and common ones (we include all the rest for reference in case it fits your use case)
|16BIT_SERVICE_UUID_MORE_AVAILABLE||Provides 16-bit services and indicates more 16-bit services are available|
|16BIT_SERVICE_UUID_COMPLETE||Provides a complete list of 16-bit service|
|32BIT_SERVICE_UUID_MORE_AVAILABLE||Provides 32-bit services and indicates more 32-bit services are available|
|32BIT_SERVICE_UUID_COMPLETE||Provides a complete list of 32-bit service|
|128BIT_SERVICE_UUID_MORE_AVAILABLE||Provides 128-bit services and indicates more 128-bit services are available in the device|
|128BIT_SERVICE_UUID_COMPLETE||Provides a complete list of 128-bit service|
|SHORT_LOCAL_NAME||Shortened Local (Device) Name|
|COMPLETE_LOCAL_NAME||Complete Local (Device) Name|
|TX_POWER_LEVEL||Device TX Output Power|
|CLASS_OF_DEVICE||Class of Device|
|SERVICE_DATA||Allows you to include data that belongs to a standard Bluetooth Service|
|ADVERTISING_INTERVAL||Provides details of the advertising interval used by the device|
|LE_BLUETOOTH_DEVICE_ADDRESS||MAC Address of the BLE Device|
|LE_ROLE||Indicates whether Central or Peripheral|
|Indoor Positioning||Used by the Indoor positioning profile|
|Channel Map Update Indication||Used by the Mesh Profile for provisioning|
|PB-ADV||Used by the Mesh Profile for provisioning|
|Mesh Message||Used by the Mesh Profile|
|Mesh Beacon||Used by the Mesh Profile|
|MANUFACTURER_SPECIFIC_DATA||Manufacturer Specific data bytes|
We recommend using the device name for debug only, in the scan response with low priority items and ideally remove it during production. There's little advantage in including a device name overall, and a better system can be designed without it.
In most cases, an app does not need a human friendly string to connect and neither does a gateway. The possibility of collision of strings is also possible. The same applies to custom BLE devices.
Same as COMPLETE_LOCAL_NAME, except the name is cut to fit inside the packet.
The TX Power level is useful in specific scenarios involving ranging and calibration or dynamic power control. if you need to know the TX power level of a device without connecting, you should use this element. In practice, there's been little use for it aside from debug.
Whether you use this element or the 16BIT_SERVICE_UUID_COMPLETE variant depends only on whether you have more services. This element has the advantage of having the most compact unique representation of a UUID that you can give your device. But, there's a big catch. 16-bit UUIDs are all reserved by the Bluetooth SIG. If you remember services such as the Device Information Service, Battery Information Service, etc. These are all standard Bluetooth services and they all have 16-bit UUID. The other 96-bits of the UUID are the standard Bluetooth UUID bits.
If you decide you want to advertise just a 16-bit UUID due to power or other considerations, you will have to request a custom UUID for you. The Bluetooth SIG charges for these UUID. Without this, you're limited to the standard Bluetooth UUIDs, but these are of limited use: any device can advertise the same UUIDs and if your app or gateway are looking to connect to the device, it won't be able to identify it uniquely unless you use the unique 16-bit UUID. You can't get your product certified if you try to invent your own 16-bit UUID that was not assigned by the BT-SIG.
The main use of these UUIDs are for devices that provide standardized behavior. For example, any Weight Scale that uses standard the standard Weight Scale Service and advertises it should provide standard behavior. This could allow any app with the functionality to use it. The benefit is that your product can work in a large ecosystem of existing apps.
The 16-bit manufacturer UUID is assigned by the Bluetooth SIG and is available to any company. For example, Argenox has the company identifier 0x0240.
This element and 32BIT_SERVICE_UUID_COMPLETE element are both similar to the 16-bit except that they use 32-bit. Like the 16-bit, the UUID has to be assigned by the Bluetooth SIG and has limited value. We have rarely seen this element being used since 16-bit UUIDs are still available from the BT-SIG.
This element and its related 128BIT_SERVICE_UUID_COMPLETE are perhaps some of the most useful UUID elements to use. The main reason is that they don't require any registration with the BT-SIG. You can use any 128-bit UUID and Random UUID generators will almost always guarantee uniqueness. The downside is of course that instead of using 2 bytes, you will need 16 bytes, which means additional power consumption and difficulty fitting more information in advertisements that don't have advertising length extensions.
In products we develop we have used 128-bit UUIDs significantly. Their flexibility allows unique identification of a device or multiple devices. We don't recommend using the UUID as a serial for the devices.
Central devices can easily filter devices based on the 128-bit UUID, and many implementations are low level firmware filtering, so that the power consumption on the Central device is reduced.
Manufacturer specific data is another very useful element to include in advertising. This field allows for custom data, which means endless possibilities. Some of the most common used manufacturer data formats are iBeacon and Eddystone
The format of this element is: Length <16-bit Manufacturer UUID> Data
The data in this field that's common to use includes sensor data, device state and anything else that's specific to your product. Obviously, the amount of data is limited unless you're using advertising length extensions, so there's some tradeoffs to consider.
Using the Manufacturer Specific Data field in a scan response packet instead of the advertising packet, but this means the device has to now listen to scan request packets, which causes a small but sometimes significant increase in the power consumption of the.
This element is very useful for devices providing standard services. You can use it to advertise the data of any Bluetooth Standard Service. For example, want to advertise the battery value of the Battery Information Service or the temperature of the Thermometer Service? This is the element to use.
Building the right BLE advertising packets is an endeavor that requires some insight and proper tradeoff analysis. But with some of the information here, you should be able to make better choices for your products.