Integrating the Swift EstimoteUWB SDK into your SwiftUI project
With the introduction of Ultra-wideband in consumer smartphones and Apple’s Nearby Interaction enabling communication with third-party accessories, interesting opportunities are emerging using UWB in the mobile space.
This tutorial gives an overview of the process of integrating the Swift EstimoteUWB SDK into your SwiftUI project for proximity-based use cases by measuring the distance to the beacons.
Let’s get started
First, we are going to download the Swift EstimoteUWB framework from the link you receive after purchasing the development kit.
Drag and drop the framework folder ending with .xcframework into your project.
It should look something like this:
In the General tab of the project under Frameworks, set the Embed field on the Estimote frameworks to Embed & Sign.
After that, we add “Privacy — Bluetooth Always Usage Description” and “Privacy — Nearby Interaction Usage Description” in Info.plist to inform the user that our app uses UWB and Bluetooth (Bluetooth is used to establish connections to the beacons).
Then we create the class UWBManagerExample
, which inherits ObservableObject
and import the library EstimoteUWB
at the beginning of the file.
To store and manage the beacons in the app, we create a dictionary, where the key is the ID of a beacon. It will look like this:
@Published var uwbDevices: [String: UWBDevice] = [:]
You could also use a different data structure or just manage one Beacon.
Afterwards, create an optional instance of the class EstimoteUWBManager
.
private var uwbManager: EstimoteUWBManager?
It is used to scan, manage the connection, and determine the distance to the beacons.
Next, we inherit from UWBDiscoveryObserver
and auto-complete the functions. In these functions, you can implement the logic to be executed after a beacon is detected, connected or disconnected.
For example, we can put an expression in the didConntect(to device:)
function to know that we have successfully connected to the beacon.
func didConnect(to device: EstimoteUWB.UWBIdentifable) {
print("Connected to: \(device.publicId)")
}
We also set the variable shouldConnectAutomatically
to true in order to automatically connect to the beacons.
var shouldConnectAutomatically: Bool {
return true
}
In addition, inherit the required protocol, UWBPositioningObserver
, which provides the following function:
func didUpdatePosition(for device: UWBDevice)
When the beacons are connected, this feature provides the app with position updates for a specific beacon.
The function has a parameter of type UWBDevice
that contains the ID of the beacon and the distance to it in meters. We can use the ID of the UWB device to store it in the dictionary.
uwbDevices[device.publicId] = device
After all this is done, we initialize the uwbManager
in the init()
function as follows and start the scan.
init(){
uwbManager = EstimoteUWBManager(positioningObserver: self, discoveryObserver: self)
uwbManager?.startScanning()
}
In the view, we create an ObservedObject
of the UWBManagerExample
we previously created:
@ObservedObject var uwbManagerExample = UWBManagerExample()
In the body, we iterate over the dictionary and display the ID of the beacon and the current distance to it.
var body: some View {
VStack(alignment: .leading) {
ForEach(Array(uwbManagerExample.uwbDevices.keys), id: \.self) { key in
Text("ID: \(uwbManagerExample.uwbDevices[key]!.publicId)")
.bold()
Text("Distance: \(String(format: "%.2f", uwbManagerExample.uwbDevices[key]!.distance))"+"m")
.bold()
.padding(.bottom)
}
}
}
On the mobile phone, it looks like this, with the distance being constantly adjusted:
Have fun implementing
We think it was really fun to implement a use case with the exciting Ultrawideband technology and with the help of the Estimote beacons.
We hope you found this overview useful and are excited to see what apps you are working on. Let us know about your experiences with Estimote products.
And don’t miss out on checking out the link below for information about the Estimote beacons.
(By Sebastian Hensel)