We now have a complete, operational SDK and application.
This codebase is compiled into four targets; native Swift-based frameworks that are focused on one (or more) of the above platforms. Currently, the functionality is as barely simple as possible. It just scratches the surface of Core Bluetooth, but does demonstrate a complete system, from a Peripheral, advertising Services, to a Central, scanning for Services, and connecting to Peripherals, in order to use those Services to communicate with the Peripheral.
After the fact, I needed to make one change to the SDK.
The deal was that the protocol requirement had to declare the two
localizedDescription computed properties as
public, because they were actually being ignored.
WHAT DID WE LEARN?
- (LINK) We learned about S.Q.U.I.D.s.
- (LINK) We learned to map out device communication in timelines.
- (LINK) We learned to put a lot of thought into the structure of our SDK.
- (LINK) We learned to use an SDK as a simple, opaque façia for a complex system.
- (LINK) We learned about Bluetooth UUIDs, and how to generate them.
- (LINK) We learned that we need to add a special privacy row to the info.plist file on all Apple operating systems.
- (LINK) We learned that on the Mac, we also need to select a checkbox in the App Sandbox.
- (LINK) We learned the structure of Central Managers, Peripheral Managers, Services, and Characteristics.
We also touched on Characteristic Properties and Permissions.
- (LINK) We learned that Peripherals advertise their Services, and that Centrals scan for these Services.
- (LINK) We learned that a Central can “filter” its scans, searching only for Peripherals that publish certain Services.
- (LINK) We learned that the process of scanning and finding Peripherals is a rather “messy” one.
There’s a significant element of timing.
- (LINK) We learned that Peripherals are the entities that create, publish, and control Services and Characteristics.
Centrals cannot create them, and only establish local read-only “proxies” of Services and Characteristics published by Peripherals.
When the Central wants to make changes to their local proxy, they send an update request to the Peripheral, and Core Bluetooth takes care of communicating these changes to the Peripheral that manages the Service being “proxied” by the Central. If the Peripheral agrees with the change request, then the Peripheral changes the mutable instance under its control. It then might (if the central requested it) notify the Central that the Service was changed.
- (LINK) We learned that we need to specifically ask a Peripheral to “discover” its Services.
It doesn’t just automatically tell us about them.
- (LINK) We learned that we need to ask a Peripheral to “discover” Characteristics for its Services.
They are not automatically available, when we first discover the Service.
We should note that we don’t ask Services to discover their Characteristics. Instead, we ask the Peripheral to discover Characteristics for one of its Services.
- (LINK) We learned that we need to be highly “reactive” in our coding.
We need to be ready for anything; especially on the Central end.
Also, we need to verify the state of things. Never assume anything.
- (LINK) We learned that we need to maintain a strong reference to the Central object’s CBPeripheral instances, once they are discovered.
- (LINK) We learned that you cannot use Watches or AppleTVs as Peripheral devices.
- They must run as Centrals. Only the Mac or iOS devices (iPhones, iPads or iPod Touches) can act as Peripheral devices.
- (LINK) We learned that you can’t implement Core Bluetooth functionality in simulators; it has to run on-device.
In the last tag, I took the liberty of adding a Jazzy implementation. This generates documentation from the code comments. If we review the code, we see that it is actually heavily documented. This documentation turns into some excellent SDK documentation, which can be reviewed here.
We can call this part of the lesson “done,” but we still have a great deal of room for improvement. The application is very “sparse.”
WHAT NEEDS TO BE EXPLORED:
- The error handling is primitive, at best.
We didn’t really do much to capture errors. We have the ability in the apps to catch and display them, but we didn’t take advantage of this in the SDK.
This was mostly because I wanted to keep the lesson as simple and to-the-point as possible. If it were a “shipping” SDK, error handling would have been one of my first priorities.
- The Central “locks up” Peripherals.
Because we connect, then hold the connection, a Peripheral is dedicated to a Central. It might be nice to allow a Peripheral to be used by multiple Centrals.
- We could put the entire Peripheral functionality inside the SDK.
We could remove the ability to select a response, thus pretty much obviating the need for user intervention. It could be entirely possible to simply do the response automatically in the SDK, and report the results to the Peripheral user.
- It would be nice to know whether or not the question made it to the Peripheral.
At the moment, we have the
.writeWithoutResponseproperty set on the question, so we aren’t sure that the question made it to the Peripheral. We can ask the Peripheral to let us know if the question made it.
- This barely scratches the surface of Bluetooth Programming.
Agreed. The purpose of this series (so far) has been to introduce Core Bluetooth. I expect to be exploring Bluetooth programming much further, and will use this SDK as the vehicle for that.
- The iOS app doesn’t clean up after itself very well.
The Mac app closes all resource connections when it quits, but the iOS app can “hold the connection open.” That’s really something that would require work on the apps, as well as the SDK.
- We’re Not Sure Who’s Asking the Question.
It would be nice to have a label on the Peripheral screen that showed who was asking the question.
- The App is Pathetic
Yeah…It’s just enough to show that the SDK works. We can do better.
- We could explore Bluetooth “Classic” (BR/EDR) with this project.
We’re using BLE for this, and it’s really the perfect type of task for BLE, but this would also be something that could be done with Bluetooth “Classic.”