spezibluetooth

Connect and communicate with Bluetooth devices.

https://github.com/stanfordspezi/spezibluetooth

Science Score: 67.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 3 DOI reference(s) in README
  • Academic publication links
    Links to: zenodo.org
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (13.5%) to scientific vocabulary
Last synced: 6 months ago · JSON representation ·

Repository

Connect and communicate with Bluetooth devices.

Basic Info
Statistics
  • Stars: 18
  • Watchers: 11
  • Forks: 4
  • Open Issues: 11
  • Releases: 26
Created over 2 years ago · Last pushed 6 months ago
Metadata Files
Readme License Citation

README.md

SpeziBluetooth

Build and Test codecov DOI

Connect and communicate with Bluetooth devices using modern programming paradigms.

Overview

The Spezi Bluetooth module 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.

This package uses Apples CoreBluetooth framework under the hood.

[!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

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 set up the core Spezi infrastructure.

Register the Module

The Bluetooth module needs to be registered in a Spezi-based application using the configuration in a SpeziAppDelegate: swift class ExampleAppDelegate: SpeziAppDelegate { override var configuration: Configuration { Configuration { Bluetooth { // discover devices ... } } } }

[!NOTE]
You can learn more about a Module in the Spezi documentation.

Example

Create your Bluetooth device

The Bluetooth module allows to declarative define your Bluetooth device using a BluetoothDevice implementation and property wrappers like Service and Characteristic.

The below code examples demonstrate how you can implement your own Bluetooth device.

First of all we define our Bluetooth service by implementing a BluetoothService. We use the Characteristic property wrapper to declare its characteristics. Note that the value types needs to be optional and conform to ByteEncodable, ByteDecodable or ByteCodable respectively.

```swift struct DeviceInformationService: BluetoothService { static let id: BTUUID = "180A"

@Characteristic(id: "2A29")
var manufacturer: String?
@Characteristic(id: "2A26")
var firmwareRevision: String?

} ```

We can use this Bluetooth service now in the MyDevice implementation as follows.

[!TIP] We use the DeviceState and DeviceAction property wrappers to get access to the device state and its actions. Those two property wrappers can also be used within a BluetoothService type.

```swift class MyDevice: BluetoothDevice { @DeviceState(.id) var id: UUID @DeviceState(.name) var name: String? @DeviceState(.state) var state: PeripheralState

@Service var deviceInformation = DeviceInformationService()

@DeviceAction(\.connect)
var connect
@DeviceAction(\.disconnect)
var disconnect

required init() {}

} ```

Configure the Bluetooth Module

We use the above BluetoothDevice implementation to configure the Bluetooth module within the SpeziAppDelegate.

```swift import Spezi

class ExampleDelegate: SpeziAppDelegate { override var configuration: Configuration { Configuration { Bluetooth { // Define which devices type to discover by what criteria . // In this case we search for some custom FFF0 service that is advertised. Discover(MyDevice.self, by: .advertisedService("FFF0")) } } } } ```

Using the Bluetooth Module

Once you have the Bluetooth module configured within your Spezi app, you can access the module within your Environment.

You can use the scanNearbyDevices(enabled:with:minimumRSSI:advertisementStaleInterval:autoConnect:) and autoConnect(enabled:with:minimumRSSI:advertisementStaleInterval:) modifiers to scan for nearby devices and/or auto connect to the first available device. Otherwise, you can also manually start and stop scanning for nearby devices using scanNearbyDevices(minimumRSSI:advertisementStaleInterval:autoConnect:) and stopScanning().

To retrieve the list of nearby devices you may use nearbyDevices(for:).

[!TIP] To easily access the first connected device, you can just query the SwiftUI Environment for your BluetoothDevice type. Make sure to declare the property as optional using the respective Environment(_:) initializer.

The below code example demonstrates all these steps of retrieving the Bluetooth module from the environment, listing all nearby devices, auto connecting to the first one and displaying some basic information of the currently connected device.

```swift import SpeziBluetooth import SwiftUI

struct MyView: View { @Environment(Bluetooth.self) var bluetooth @Environment(MyDevice.self) var myDevice: MyDevice?

var body: some View {
    List {
        if let myDevice {
            Section {
                Text("Device")
                Spacer()
                Text("\(myDevice.state.description)")
            }
        }

        Section {
            ForEach(bluetooth.nearbyDevices(for: MyDevice.self), id: \.id) { device in
                Text("\(device.name ?? "unknown")")
            }
        } header: {
            HStack {
                Text("Devices")
                    .padding(.trailing, 10)
                if bluetooth.isScanning {
                    ProgressView()
                }
            }
        }
    }
        .scanNearbyDevices(with: bluetooth, autoConnect: true)
}

} ```

[!TIP] Use ConnectedDevices to retrieve the full list of connected devices from the SwiftUI environment.

Retrieving Devices

The previous section explained how to discover nearby devices and retrieve the currently connected one from the environment. This is great ad-hoc connection establishment with devices currently nearby. However, this might not be the most efficient approach, if you want to connect to a specific, previously paired device. In these situations you can use the retrieveDevice(for:as:) method to retrieve a known device.

Below is a short code example illustrating this method.

```swift let id: UUID = ... // a Bluetooth peripheral identifier (e.g., previously retrieved when pairing the device)

let device = bluetooth.retrieveDevice(for: id, as: MyDevice.self)

await device.connect() // assume declaration of @DeviceAction(.connect)

// Connect doesn't time out. Connection with the device will be established as soon as the device is in reach. ```

Integration with Spezi Modules

A Spezi Module is a great way of structuring your application into different subsystems and provides extensive capabilities to model relationship and dependence between modules. Every BluetoothDevice is a Module. Therefore, you can easily access your SpeziBluetooth device from within any Spezi Module using the standard Module Dependency infrastructure. At the same time, every BluetoothDevice can benefit from the same capabilities as every other Spezi Module.

Below is a short code example demonstrating how a BluetoothDevice uses the @Dependency property to interact with a Spezi Module that is configured within the Spezi application.

```swift class Measurements: Module, EnvironmentAccessible, DefaultInitializable { required init() {}

func recordNewMeasurement(_ measurement: WeightMeasurement) {
    // ... process measurement
}

}

class MyDevice: BluetoothDevice { @Service var weightScale = WeightScaleService()

// declare dependency to a configured Spezi Module
@Dependency var measurements: Measurements

required init() {}

func configure() {
    weightScale.$weightMeasurement.onChange { [weak self] value in
        self?.handleNewMeasurement(value)
    }
}

private func handleNewMeasurement(_ measurement: WeightMeasurement) {
    measurements.recordNewMeasurement(measurement)
}

} ```

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

Owner

  • Name: Stanford Spezi
  • Login: StanfordSpezi
  • Kind: organization

Citation (CITATION.cff)

#
# This source file is part of the Stanford Spezi open source project
#
# SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md)
#
# SPDX-License-Identifier: MIT
# 

cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Schmiedmayer"
  given-names: "Paul"
  orcid: "https://orcid.org/0000-0002-8607-9148"
- family-names: "Bauer"
  given-names: "Andreas"
  orcid: "https://orcid.org/0000-0002-1680-237X"
title: "SpeziBluetooth"
doi: 10.5281/zenodo.10020080
url: "https://github.com/StanfordSpezi/SpeziBluetooth"

GitHub Events

Total
  • Create event: 11
  • Issues event: 8
  • Release event: 4
  • Watch event: 7
  • Delete event: 7
  • Issue comment event: 18
  • Push event: 60
  • Pull request review comment event: 20
  • Pull request event: 16
  • Pull request review event: 22
  • Fork event: 3
Last Year
  • Create event: 11
  • Issues event: 8
  • Release event: 4
  • Watch event: 7
  • Delete event: 7
  • Issue comment event: 18
  • Push event: 60
  • Pull request review comment event: 20
  • Pull request event: 16
  • Pull request review event: 22
  • Fork event: 3

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 21
  • Total pull requests: 35
  • Average time to close issues: 5 months
  • Average time to close pull requests: 20 days
  • Total issue authors: 4
  • Total pull request authors: 7
  • Average comments per issue: 0.57
  • Average comments per pull request: 1.54
  • Merged pull requests: 31
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 3
  • Pull requests: 9
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 2 months
  • Issue authors: 2
  • Pull request authors: 4
  • Average comments per issue: 0.67
  • Average comments per pull request: 1.33
  • Merged pull requests: 6
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • Supereg (13)
  • PSchmiedmayer (6)
  • philippzagar (1)
Pull Request Authors
  • Supereg (44)
  • PSchmiedmayer (8)
  • lukaskollmer (5)
  • pauljohanneskraft (2)
  • philippzagar (1)
  • vishnuravi (1)
Top Labels
Issue Labels
enhancement (15) bug (4) help wanted (4) good first issue (2) documentation (1)
Pull Request Labels
enhancement (18) bug (2) documentation (2)

Packages

  • Total packages: 1
  • Total downloads: unknown
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 26
swiftpackageindex.com: github.com/StanfordSpezi/SpeziBluetooth

Connect and communicate with Bluetooth devices.

  • Versions: 26
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent packages count: 16.5%
Dependent repos count: 33.6%
Average: 49.9%
Forks count: 61.9%
Stargazers count: 87.5%
Last synced: 6 months ago