NikolaiMadlener / SpeziBluetooth

Connect and communicate with Bluetooth devices.

Home Page:https://swiftpackageindex.com/StanfordSpezi/SpeziBluetooth

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SpeziBluetooth

Build and Test codecov DOI

Connect and communicate with Bluetooth devices.

Overview

The Spezi Bluetooth component provides a convenient way to handle state management with a Bluetooth device, retrieve data from different services and characteristics, and write data to a combination of services and characteristics.

Note

You will need a basic understanding of the Bluetooth Terminology and the underlying software model to understand the structure and API of the Spezi Bluetooth module. You can find a good overview in the Wikipedia Bluetooth Low Energy (LE) Software Model section or the Developer’s Guide to Bluetooth Technology.

Setup

1. Add Spezi Bluetooth as a Dependency

You need to add the Spezi Bluetooth Swift package to your app in Xcode or Swift package.

Important

If your application is not yet configured to use Spezi, follow the Spezi setup article to setup the core Spezi infrastructure.

2. Register the Component

The Bluetooth component needs to be registered in a Spezi-based application using the configuration in a SpeziAppDelegate:

class ExampleAppDelegate: SpeziAppDelegate {
    override var configuration: Configuration {
        Configuration {
            Bluetooth(services: [/* ... */])
            // ...
        }
    }
}

Note

You can learn more about a Component in the Spezi documentation.

Example

BluetoothExample provides a demonstration of the capabilities of the Spezi Bluetooth module. This class integrates the Bluetooth component to send string messages over Bluetooth and collects them in a messages array. It also showcases the interaction with the BluetoothService and the implementation of the BluetoothMessageHandler protocol.

Note

The type uses the Spezi dependency injection of the BluetoothMessageHandler component, the most common usage of the Bluetooth component. You can learn more about the Spezi dependency injection mechanisms in the Spezi documentation.

class BluetoothExample: DefaultInitializable, Component, ObservableObject, ObservableObjectProvider, BluetoothMessageHandler {
    /// UUID for the example characteristic.
    private static let exampleCharacteristic = CBUUID(string: "a7779a75-f00a-05b4-147b-abf02f0d9b17")
    /// Configuration for the example Bluetooth service.
    private static let exampleService = BluetoothService(
        serviceUUID: CBUUID(string: "a7779a75-f00a-05b4-147b-abf02f0d9b17"),
        characteristicUUIDs: [exampleCharacteristic]
    )
    
    /// Spezi dependency injection of the `Bluetooth` component; see https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/component#Dependencies for more details.
    @Dependency private var bluetooth: Bluetooth
    private let logger = Logger(subsystem: "edu.stanford.spezi.bluetooth", category: "Example")
    private var bluetoothAnyCancellable: AnyCancellable?
    
    /// Array of messages received from the Bluetooth connection.
    @Published private(set) var messages: [String] = []
    
    /// The current Bluetooth connection state.
    var bluetoothState: BluetoothState {
        bluetooth.state
    }
    
    /// Default initializer that sets up observation of Bluetooth state changes to propagate them to the user of `BluetoothExample`
    required init() {
        bluetoothAnyCancellable = bluetooth
            .objectWillChange
            .receive(on: RunLoop.main)
            .sink {
                self.objectWillChange.send()
            }
    }
    
    
    /// Configuration method to register the `BluetoothExample` as a `BluetoothMessageHandler` for the Bluetooth component.
    func configure() {
        bluetooth.add(messageHandler: self)
    }
    
    
    /// Sends a string message over Bluetooth.
    ///
    /// - Parameter information: The string message to be sent.
    func send(information: String) async throws {
        try await bluetooth.write(
            Data(information.utf8),
            service: Self.exampleService.serviceUUID,
            characteristic: Self.exampleCharacteristic
        )
    }
    
    func recieve(_ data: Data, service: CBUUID, characteristic: CBUUID) {
        // Example implementation of the `BluetoothMessageHandler` requirements.
        switch service {
        case Self.exampleService.serviceUUID:
            guard Self.exampleCharacteristic == characteristic else {
                logger.debug("Unknown characteristic Id: \(Self.exampleCharacteristic)")
                return
            }
            
            // Convert the received data into a string and append it to the messages array.
            messages.append(String(decoding: data, as: UTF8.self))
        default:
            logger.debug("Unknown Service: \(service.uuidString)")
        }
    }
}

You will have to ensure that the Bluetooth component is correctly setup with the right services, e.g., as shown in the following example:

class ExampleAppDelegate: SpeziAppDelegate {
    override var configuration: Configuration {
        Configuration {
            Bluetooth(services: [BluetoothExample.exampleService])
            // ...
        }
    }
}

For more information, please refer to the API documentation.

Contributing

Contributions to this project are welcome. Please make sure to read the contribution guidelines and the contributor covenant code of conduct first.

License

This project is licensed under the MIT License. See Licenses for more information.

Spezi Footer Spezi Footer

About

Connect and communicate with Bluetooth devices.

https://swiftpackageindex.com/StanfordSpezi/SpeziBluetooth

License:MIT License


Languages

Language:Swift 100.0%