Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/starryinternet/combinecorebluetooth
A wrapper API for CoreBluetooth using Combine Publishers
https://github.com/starryinternet/combinecorebluetooth
bluetooth combine corebluetooth ios macos reactive-programming swift tvos watchos
Last synced: 3 days ago
JSON representation
A wrapper API for CoreBluetooth using Combine Publishers
- Host: GitHub
- URL: https://github.com/starryinternet/combinecorebluetooth
- Owner: StarryInternet
- License: mit
- Created: 2021-08-23T19:26:45.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2024-10-28T02:03:00.000Z (2 months ago)
- Last Synced: 2024-10-30T08:27:47.433Z (2 months ago)
- Topics: bluetooth, combine, corebluetooth, ios, macos, reactive-programming, swift, tvos, watchos
- Language: Swift
- Homepage:
- Size: 146 KB
- Stars: 130
- Watchers: 9
- Forks: 12
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# CombineCoreBluetooth
[![CI](https://github.com/StarryInternet/CombineCoreBluetooth/actions/workflows/ci.yml/badge.svg)](https://github.com/StarryInternet/CombineCoreBluetooth/actions/workflows/ci.yml)
[![GitHub](https://img.shields.io/github/license/StarryInternet/CombineCoreBluetooth)](https://github.com/StarryInternet/CombineCoreBluetooth/blob/master/LICENSE)
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStarryInternet%2FCombineCoreBluetooth%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/StarryInternet/CombineCoreBluetooth)
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStarryInternet%2FCombineCoreBluetooth%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/StarryInternet/CombineCoreBluetooth)CombineCoreBluetooth is a library that bridges Apple's `CoreBluetooth` framework and Apple's `Combine` framework, making it possible to subscribe to perform bluetooth operations while subscribing to a publisher of the results of those operations, instead of relying on implementing delegates and manually filtering for the results you need.
## Requirements:
- iOS 13, tvOS 13, macOS 11, or watchOS 6
- Xcode 15 or higher
- Swift 5.9 or higher(If you are using carthage, or if you wish to open the project to play with the demo app, you will need to use Xcode 16)
## Installation
### Swift Package Manager
Add this line to your dependencies list in your Package.swift:
```swift
.package(name: "CombineCoreBluetooth", url: "https://github.com/StarryInternet/CombineCoreBluetooth.git", from: "0.8.0"),
```### Cocoapods
Add this line to your Podfile:
```ruby
pod 'CombineCoreBluetooth'
```### Carthage
Add this line to your Cartfile:
```
github "StarryInternet/CombineCoreBluetooth"
```## Usage
This library is heavily inspired by [pointfree.co's approach](https://www.pointfree.co/collections/dependencies) to designing dependencies, but with some customizations. Many asynchronous operations returns their own `Publisher` or expose their own long-lived publisher you can subscribe to.
This library doesn't maintain any additional state beyond what's needed to enable this library to provide a combine-centric API. This means that you are responsible for maintaining any state necessary, including holding onto any `Peripheral`s returned by discovering and connected to via the `CentralManager` type.
To scan for a peripheral, much like in plain CoreBluetooth, you call the `scanForPeripherals(withServices:options:)` method. However, on this library's `CentralManager` type, this returns a publisher of `PeripheralDiscovery` values. If you want to store a peripheral for later use, you could subscribe to the returned publisher by doing something like this:
```swift
let serviceID = CBUUID(string: "0123")centralManager.scanForPeripherals(withServices: [serviceID])
.first()
.assign(to: \.peripheralDiscovery, on: self) // property of type PeripheralDiscovery
.store(in: &cancellables)
```To do something like fetching a value from a characteristic, for instance, you could call the following methods on the `Peripheral` type and subscribe to the resulting `Publisher`:
```swift
// use whatever ids your peripheral advertises here
let characteristicID = CBUUID(string: "4567")peripheralDiscovery.peripheral
.readValue(forCharacteristic: characteristicID, inService: serviceID)
.sink(receiveCompletion: { completion in
// handle any potential errors here
}, receiveValue: { data in
// handle data from characteristic here, or add more publisher methods to map and transform it.
})
.store(in: &cancellables)
```The publisher returned in `readValue` will only send values that match the service and characteristic IDs through to any subscribers, so you don't need to worry about any filtering logic yourself. Note that if the `Peripheral` never receives a value from this characteristic over bluetooth, it will never send a value into the publisher, so you may want to add a timeout if your use case requires it.
## Caveats
All major types from `CoreBluetooth` should be available in this library, wrapped in their own types to provide the `Combine`-centric API. This library has been tested in production for most `CentralManager` related operations. Apps acting as bluetooth peripherals are also supported using the `PeripheralManager` type, but that side hasn't been as rigorously tested.