Using CoreBluetooth to connect two Apple devices

Egbert-Jan
Apple Developer Academy | Federico II
3 min readApr 10, 2020

--

For a project I had to send data between an Apple Watch and a Mac. After looking through some options I found out that MultipeerConnectivity is not available for the Apple Watch so Bluetooth would have been the best way because I did not want to use WIFI or build my own server.

Bluetooth

Bluetooth is a wireless technology used to exchange data between devices using radio waves. In Bluetooth you have two important key players: the central and the peripheral.

Typically a peripheral has data a central wants. For example a heart rate monitor that monitors the heart rate of a person.

A central could be a iPhone app that subscribes to the heart rate monitor and shows the heart rate to the user.

CoreBluetooth

CoreBluetooth is a framework made by Apple available on iOS, macOS, watchOS and tvOS that provides classes for apps to communicate over Bluetooth Low Energie.

In CoreBluetooth the central side is represented by the CBCentralManager and the peripheral side by the CBPeripheralManager class. Because the Apple Watch can only be a central (unlike an iOS and a macOS device) we have to make our Mac app the peripheral.

Peripheral manager

A peripheral manager manages and advertises peripheral services.

A peripheral represents it’s data by services and characteristics. A peripheral can have multiple services and the services have often multiple characteristics.

For example, a heart rate service may contain one characteristic that describes the intended body location of the device’s heart rate sensor and another characteristic that transmits heart rate measurement data.

A peripheral can choose to advertise his data so centrals can see him and connect to the peripheral.

Central manager

The central manager scans for, discovers, connects to and manages peripherals. If a peripheral is advertising and the central is scanning for peripherals it will discover it. If you discover a peripheral you can connect to it. Once you are in the connected state you can write data to the peripheral, read data from the peripheral and listen for characteristics updates.

Flow

The flow of the connection of my watch app was like this:
1. The user sees all the Macs with the Mac app installed on the Watch
2. The user can connect to the Mac on the Watch
3. The user has to accept or decline the connection on the mac
4. The devices can send data to each other
5. The user can disconnect from the Mac and from the watch

For this flow I connect to the Mac. After that I subscribe to a characteristic called connection. This connection characteristic can update to accepted, declined and disconnect. The central would listen for this characteristic to update and act correctly according to what the characteristic updated its value.

Issue

If the user closes the Mac app the app still shows up on the watch. I want the Mac app to remove all services, stop advertising and disconnect the watch app when the app closes but that doesn’t happen. I think this is because I lose all references to my peripheral manager and they system does not remove my services from the database.

Also all the documentation is about iOS devices who behave differently with background task in the background than macOS. I could not fix this by code and the only way to fix this is is turning the Bluetooth off and on on the Mac

Conclusion

CoreBluetooth is a nice framework that works about the same way any apple framework does. Apple has a nice archive where they explain a lot of stuff about how to set up a bluetooth connection and it works very good once connected.

Sadly there are not that many people that used it so you will find only a few topics on it on question and answer sites like Stack Overflow and all the documentation is about iOS devices so to find macOS related topics is very hard.

Thanks for reading.

--

--