This is a low-level, native Swift Bluetooth SDK for "Central" (Client) Core Bluetooth (BLE) implementation.
It abstracts some of the more "tedious" aspects of using Core Bluetooth; allowing the app to easily implement a Bluetooth Client functionality.
This is the GitHub repo for this project.
This is the project technical documentation
Implementing the Apple Core Bluetooth SDK can be a rather tedious process. For example, discovery of Services, Characteristics, and Descriptors can be intricate and time-consuming. RVS_BlueThoth takes care of that in the "background," allowing you to concentrate on providing a richer experience to the users of your application or SDK.
RVS_BlueThoth is not really designed to be a direct dependency of an application-layer system (although it is demonstrated that way, in the test harnesses). Rather, it is designed to be the basis for application-specific "Façade" layers, such as OBD adapters, or mesh device drivers.
The basic philosophy behind RVS_BlueThoth, is that it is a fundamental infrastructure element, and, as such, it needs to be of the highest quality possible. All efforts have been made to ensure that it works flawlessly.
RVS_BlueThoth is 100% open-source, MIT-licensed code.
You are free to use it as you wish, but be aware that we are under no obligation to support the project, and there are NO GUARANTEES as to whether or not it is fit for your purposes.
If you are unfamiliar with the SPM, this series may be helpful.
RVS_BlueThoth has one external build dependency: the RVS_Generic_Swift_Toolbox Project (also written and supported by The Great Rift Valley Software Company). If you wish to build the test harnesses, then you also need the RVS_PersistentPrefs Project.
The included XCode workspace has these dependencies already.
RVS_BlueThoth is a fully native Swift SDK. It does not interface with Objective-C.
RVS_BlueThoth will work on all of the Apple operating systems (iOS/iPadOS, MacOS, tvOS, and WatchOS). It can be incorporated into projects that target any of these environments.
The SPM build is provided as a static library, as opposed to a dynamic framework. RVS_BlueThoth is a fairly "light" codebase, and is likely to be one of the smaller components of any given project. If you prefer a dynamic library, it can be easily changed in the Package.swift
file for the project. There are no resource, or non-code components, in the SDK. It is a simple executable codebase.
It should be noted that Core Bluetooth requires use of a device; not a simulator. The library will not work on a simulator, registering a Bluetooth Not Available error.
RVS_BlueThoth does not implement unit tests. Instead, it provides four test harness apps; one for each of the supported platforms (iOS/iPadOS, MacOS, tvOS, and WatchOS).
Here is an article that explains the philosophy behind the use of test harnesses.
Each of the test harness apps is a fully-qualified, "App Store release-ready" application. They act as "Bluetooth sniffer" apps. In fact, the iOS test harness has actually been converted into a released app on the iOS App Store (here is the source code).
They should provide excellent "starting points," when learning to implement the SDK.
As noted previously, you should use the Swift Package Manager (SPM) to import the project into your own project. If you are unsure how to do that, then this article may be quite helpful.
The SSH GitHub URI is git@github.com:RiftValleySoftware/RVS_BlueThoth.git
, and the HTTPS GitHub URI is https://github.com/RiftValleySoftware/RVS_BlueThoth.git
).
Once you have the package installed, you'll need to import the module into any files that use it, by adding the following to the beginning of the file:
import RVS_BlueThoth
RVS_BlueThoth implements a Delegate pattern (but implemented more like an Observer).
In order to reduce the complexity of the SDK, we have created a single "bottleneck" delegate protocol, that handles all responses from the SDK.
If you are implementing an application-focused layer over RVS_BlueThoth, then you may want to consider dividing this into Observers or Bindings. That's up to you. In order to use the SDK, you need to have a single delegate that can handle the various callbacks, and dispatch them accordingly.
The delegate is "one-way," like an observer. It receives callbacks from the SDK, and does not respond in any way.
All delegate callbacks are in the main thread.
The delegate needs to be a class (as opposed to a struct), and is weakly referenced from within the SDK (meaning that you need to make sure that it stays around).
Examples of the delegate in the four test harnesses are in the following source files:
We start by instantiating the RVS_BlueThoth class:
CGA_AppDelegate.centralManager = RVS_BlueThoth(delegate: self)
This example is from the tvOS Test Harness
Note that we provide the delegate immediately. It is likely to get a callback quickly, indicating that the Bluetooth system is set up, and ready to start scanning for peripherals.
Once the Bluetooth system is ready, we can start scanning for Peripherals (also from the tvOS test harness):
centralManager?.scanCriteria = scanCriteria
centralManager?.minimumRSSILevelIndBm = prefs.minimumRSSILevel
centralManager?.discoverOnlyConnectablePeripherals = prefs.discoverOnlyConnectableDevices
centralManager?.allowEmptyNames = prefs.allowEmptyNames
centralManager?.startScanning(duplicateFilteringIsOn: !prefs.continuouslyUpdatePeripherals)
It is possible to set a few properties that control how to deal with discovered Peripherals.
From here, on, it is best to use the API documentation, or the [in-depth technical documentation](the technical documentation).
If you have any bugs, feature requests, feedback, etc., please feel free to open a GitHub issue, or contact us directly.