Core Bluetooth in watchOS Tutorial

Learn how to communicate with external BLE devices from within watchOS in this Core Bluetooth tutorial! By Audrey Tam.

Leave a rating/review
Save for later
Share

Core Bluetooth has been around since 2011 on macOS and iOS, since 2016 on tvOS, and now it’s available on watchOS, with an Apple Watch Series 2.

What’s Core Bluetooth? It’s Apple’s framework for communicating with devices that support Bluetooth 4.0 low-energy, often abbreviated as BLE. And it opened up standard communication protocols to read and/or write from external devices.

Back in 2011, there weren’t many BLE devices, but now? Well, this is from the Bluetooth site (bit.ly/2j1DqpU):

“More than 31,000 Bluetooth member companies introducing over 17,000 thousand new products per year and shipping more than 3.4 billion units each year.”

BLE is everywhere: in health monitors, home appliances, fitness equipment, Arduino and toys. In July 2017, Apple announced its collaboration with hearing-aid implant manufacturer Cochlear, to create the first “Made for iPhone” implant. (bit.ly/2vZahUU)

Note: Cochlear is an Australian company, and the app was built here in Australia! (bit.ly/2uztOHX)

But you don’t have to acquire a specific gadget to work through this tutorial: the sample project uses an iPhone as the BLE device. In the app you’ll build, the iOS device provides a two-part service: it transfers text to the Watch, or the Watch can open Maps at the user’s location on the iOS device.

The first part is a Swift translation of Apple’s BLE_Transfer sample app. It’s a very useful example, because it shows how to send 20-byte chunks of data. I added the Maps part to show you how to send a control instruction to the BLE device, and I thought it’s something you’d want to do from the Watch Maps app: open Maps on a larger display so you can find what you need more easily!

Getting Started

Note: The simulator does not support Core Bluetooth. To run the starter app, you need two iOS 11 devices. To run the finished app, you need an Apple Watch Series 2 and an iOS 11 device.

Download the starter app for this tutorial here.

Open the starter app. Build and run on two iOS devices. Go into Settings to trust the developer, then build and run again.

Select Peripheral Mode on one device, and Central Mode on the other. Tap the peripheral’s Advertising switch to start advertising.

PeripheralViewController has a textView, prepopulated with some text. When the central manager subscribes to textCharacteristic, the peripheral sends this text in 20-byte chunks to the central, where it appears in a textView:

Modify the peripheral’s text, and tap Done. The peripheral sends the updated value to the central:

Note: I deleted “sample” from the first sentence.

When the central has discovered mapCharacteristic, CentralViewController bar button’s title changes to Map Me. Tap this bar button, allow the app to use your location, then tap Map Me again: the peripheral device opens the Maps app, at your location:

Stop the app on both devices. It’s time to learn about Core Bluetooth, and look at some code!

Note: You can tap TextMeMapMe to go back to the peripheral view, but sometimes, Maps keeps re-opening.

What is Core Bluetooth?

Lets’s start with some vocabulary.

A Generic Attributes (GATT) profile describes how to bundle, present and transfer data using Bluetooth Low Energy. It describes a use case, roles and general behaviors. A device’s GATT database can describe a hierarchy of services, characteristics and attributes.

The classic server/client roles are the central app and the peripheral or accessory. In the starter app, either iOS device can be central or peripheral. When you build the Watch app, it can only be the central device:

A peripheral offers services. For example, Blood Pressure monitor is a pre-defined GATT service (bit.ly/2lfpqwB). In the starter app, the service is TextOrMap.

A service has characteristics. The Blood Pressure service has pre-defined GATT characteristics (bit.ly/2vOhGqa): Blood Pressure Feature, which blood pressure monitor features this sensor supports, and Blood Pressure Measurement. A characteristic has a value, properties to indicate operations the characteristic supports, and security permissions.

A central app can read or write a service’s characteristics, such as reading the user’s heart rate from a heart-rate monitor, or writing the user’s preferred temperature to a room heater/cooler. In the starter app, the TextOrMap service has two characteristics: the peripheral sends updates of the textCharacteristic value to the central; when the central writes the mapCharacteristic value, the peripheral opens the Maps app at the user’s location.

Services and characteristics have UUIDs: universally unique identifiers. There are predefined UUIDs for standard peripheral devices, like heart monitors or home appliances. You can use the command line utility uuidgen to create custom UUID strings, then use these to initialize CBUUID objects.

The Maximum Transmission Unit (MTU) is 27 bytes, but really 20 bytes, because each packet uses 7 bytes as it travels through three protocol layers. You can improve throughput using write without response, if the characteristic allows this, because you don’t have to wait for the peripheral’s response. If your central app and peripheral are running on iPhone 7, the new iPad Pro, or Apple Watch Series 2, you get the Extended Data Length of 251 bytes! I’m testing the sample app on an iPhone SE, so I’m stuck with 20-byte chunks.

Overview

The most interesting classes in the Core Bluetooth framework are CBCentralManager and CBPeripheralManager. Each has methods and a comprehensive delegate protocol, to monitor activity between central and peripheral devices. There’s also a peripheral delegate protocol. Everything comes together in an intricate dance!

Think about what the devices need to do:

  • Central devices need to scan for and connect to peripherals. Peripherals need to advertise their services.
  • Once connected, the central device needs to discover the peripheral’s services and characteristics, using peripheral delegate methods. Often at this point, an app might present a list of these for the user to select from.
  • If the central app is interested in a characteristic, it can subscribe to notifications of updates to the characteristic’s value, or send a read/write request to the peripheral. The peripheral then responds by sending data to the central device, or doing something with the write request’s value. The central app receives updated data from another peripheral delegate method, and usually uses this to update its UI.
  • Eventually, the central device might disable a notification, triggering delegate methods of the peripheral and the peripheral manager. Or the central device disconnects the peripheral, which triggers a central manager delegate method, usually used to clean up.

Now look at what each participant does.