Skip to content

Commit

Permalink
Merge pull request #5 from teufelaudio/peripheral-delegation
Browse files Browse the repository at this point in the history
Peripheral delegation
  • Loading branch information
melle authored May 28, 2024
2 parents fce6886 + 2b7f8ed commit d3b30a3
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ extension CoreBluetoothCentralManager: CentralManager {
return newInstance
}

public func peripheral(for uuid: UUID) -> CBPeripheral? {
public func peripheral(for uuid: UUID) -> BluetoothPeripheral? {
cachedPeripheralsAccess.lock()
defer { cachedPeripheralsAccess.unlock() }
if let instance = cachedPeripherals[uuid] { return instance.peripheral }
if let instance = cachedPeripherals[uuid] { return instance }
return nil
}

Expand Down
26 changes: 26 additions & 0 deletions Sources/CombineBluetooth/Internal/CoreBluetoothPeripheral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,69 @@ class CoreBluetoothPeripheral: NSObject, Identifiable {
super.init()
self.peripheral.delegate = self
}

var proxyDelegate: CBPeripheralDelegate?
}

extension CoreBluetoothPeripheral: CBPeripheralDelegate {
func peripheralDidUpdateName(_ peripheral: CBPeripheral) { }

func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) { }

func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
didReadRSSI.send(error.map(Result.failure) ?? .success(RSSI))
proxyDelegate?.peripheral?(peripheral, didReadRSSI: RSSI, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
didDiscoverServices.send(error.map(Result.failure) ?? .success(peripheral.services ?? []))
proxyDelegate?.peripheral?(peripheral, didDiscoverServices: error)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverIncludedServicesFor service: CBService, error: Error?) {
didDiscoverIncludedServices.send(error.map(Result.failure) ?? .success((parent: service, included: service.includedServices ?? [])))
proxyDelegate?.peripheral?(peripheral, didDiscoverIncludedServicesFor: service, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
didDiscoverCharacteristics.send(error.map(Result.failure) ?? .success((service: service, characteristics: service.characteristics ?? [])))
proxyDelegate?.peripheral?(peripheral, didDiscoverCharacteristicsFor: service, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
readValueForCharacteristic.send(error.map(Result.failure) ?? .success(characteristic))
proxyDelegate?.peripheral?(peripheral, didUpdateValueFor: characteristic, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
didWriteValueForCharacteristic.send(error.map(Result.failure) ?? .success(characteristic))
proxyDelegate?.peripheral?(peripheral, didWriteValueFor: characteristic, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
didUpdateNotificationStateForCharacteristic.send(error.map(Result.failure) ?? .success(characteristic))
proxyDelegate?.peripheral?(peripheral, didUpdateNotificationStateFor: characteristic, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
readValueForDescriptor.send(error.map(Result.failure) ?? .success(descriptor))
proxyDelegate?.peripheral?(peripheral, didUpdateValueFor: descriptor, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
didDiscoverDescriptors.send(error.map(Result.failure) ?? .success((characteristic: characteristic, descriptors: characteristic.descriptors ?? [])))
proxyDelegate?.peripheral?(peripheral, didDiscoverDescriptorsFor: characteristic, error: error)
}

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
didWriteValueForDescriptor.send(error.map(Result.failure) ?? .success(descriptor))
proxyDelegate?.peripheral?(peripheral, didWriteValueFor: descriptor, error: error)
}

func peripheralIsReady(toSendWriteWithoutResponse peripheral: CBPeripheral) {
becameReadyForWriteWithoutResponse.send(())
proxyDelegate?.peripheralIsReady?(toSendWriteWithoutResponse: peripheral)
}

func peripheral(_ peripheral: CBPeripheral, didOpen channel: CBL2CAPChannel?, error: Error?) {
didOpenChannel.send(
error.map(Result.failure)
Expand All @@ -74,6 +99,7 @@ extension CoreBluetoothPeripheral: CBPeripheralDelegate {
userInfo: nil
))
)
proxyDelegate?.peripheral?(peripheral, didOpen: channel, error: error)
}
}

Expand Down
1 change: 1 addition & 0 deletions Sources/CombineBluetooth/Models/BluetoothPeripheral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public protocol BluetoothPeripheral: BluetoothPeer {
var services: [BluetoothService]? { get }
var canSendWriteWithoutResponse: Bool { get }
var isReadyAgainForWriteWithoutResponse: AnyPublisher<Void, Never> { get }
var proxyDelegate: CBPeripheralDelegate? { get set }
func readRSSI() -> AnyPublisher<NSNumber, BluetoothError>
func discoverServices(_ serviceUUIDs: [CBUUID]?) -> AnyPublisher<BluetoothService, BluetoothError>
func discoverIncludedServices(_ includedServiceUUIDs: [CBUUID]?, for service: BluetoothService) -> AnyPublisher<BluetoothService, BluetoothError>
Expand Down
2 changes: 1 addition & 1 deletion Sources/CombineBluetooth/Models/CentralManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public protocol CentralManager: BluetoothManager {
func retrieveConnectedPeripherals(withServices serviceUUIDs: [CBUUID]) -> [BluetoothPeripheral]
func connect(_ peripheral: BluetoothPeripheral) -> AnyPublisher<BluetoothPeripheral, BluetoothError>
func connect(_ peripheral: BluetoothPeripheral, options: [String : Any]) -> AnyPublisher<BluetoothPeripheral, BluetoothError>
func peripheral(for uuid: UUID) -> CBPeripheral?
func peripheral(for uuid: UUID) -> BluetoothPeripheral?
// TODO: Nice to have, but complicate to handle single delegate (subscribing again with different options should end prior observations, which can
// be a bit unexpected).
// - (void)registerForConnectionEventsWithOptions:(nullable NSDictionary<CBConnectionEventMatchingOption, id> *)options NS_AVAILABLE_IOS(13_0);
Expand Down

0 comments on commit d3b30a3

Please sign in to comment.