Skip to content

Commit

Permalink
Merge pull request #24 from DrAma999/develop
Browse files Browse the repository at this point in the history
Fixing log and Back pressure
  • Loading branch information
DrAma999 authored Apr 5, 2021
2 parents 77a7885 + 4e73f41 commit 9149d71
Show file tree
Hide file tree
Showing 9 changed files with 503 additions and 316 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<key>LittleBlueTooth-Package.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
<integer>3</integer>
</dict>
<key>LittleBlueTooth.xcscheme_^#shared#^_</key>
<dict>
Expand All @@ -17,22 +17,22 @@
<key>LittleBlueToothForTest.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
<integer>4</integer>
</dict>
<key>LittleBlueToothPackageDescription.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
<integer>5</integer>
</dict>
<key>LittleBlueToothPackageTests.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
<integer>6</integer>
</dict>
<key>LittleBlueToothTests.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
<integer>2</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
Expand Down
17 changes: 14 additions & 3 deletions Sources/LittleBlueTooth/Classes/Model/Loggable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,28 @@ import os.log

protocol Loggable {
var isLogEnabled: Bool {get set}
func log(_ message: StaticString, log: OSLog, type: OSLogType, arg: CVarArg...)
func log(_ message: StaticString, log: OSLog, type: OSLogType, arg: [CVarArg])
}


extension Loggable {
func log(_ message: StaticString, log: OSLog, type: OSLogType, arg: CVarArg...) {
func log(_ message: StaticString, log: OSLog, type: OSLogType, arg: [CVarArg]) {
#if !TEST
// https://stackoverflow.com/questions/50937765/why-does-wrapping-os-log-cause-doubles-to-not-be-logged-correctly/50942917#50942917
guard isLogEnabled else {
return
}
os_log(type, log: log, message, arg)
assert(arg.count <= 2)
switch arg.count {
case 1:
os_log(type, log: log, message, arg[0])
case 2:
os_log(type, log: log, message, arg[0], arg[1])
case 3:
os_log(type, log: log, message, arg[0], arg[1], arg[2])
default:
os_log(type, log: log, message)
}
#endif
}
}
480 changes: 326 additions & 154 deletions Sources/LittleBlueTooth/Classes/Model/Peripheral.swift

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ extension CBCentralManagerDelegateProxy: CBCentralManagerDelegate {
log("[LBT: CBCMD] DidUpdateState %{public}d",
log: OSLog.LittleBT_Log_CentralManager,
type: .debug,
arg: central.state.rawValue)
arg: [central.state.rawValue])
_centralStatePublisher.send(BluetoothState(central.state))
}

Expand All @@ -109,7 +109,7 @@ extension CBCentralManagerDelegateProxy: CBCentralManagerDelegate {
log("[LBT: CBCMD] DidDiscover %{public}@",
log: OSLog.LittleBT_Log_CentralManager,
type: .debug,
arg: peripheral.description)
arg: [peripheral.description])
let peripheraldiscovery = PeripheralDiscovery(peripheral, advertisement: advertisementData, rssi: RSSI)
centralDiscoveriesPublisher.send(peripheraldiscovery)
}
Expand All @@ -119,7 +119,7 @@ extension CBCentralManagerDelegateProxy: CBCentralManagerDelegate {
log("[LBT: CBCMD] DidConnect %{public}@",
log: OSLog.LittleBT_Log_CentralManager,
type: .debug,
arg: didConnect.description)
arg: [didConnect.description])
if isAutoconnectionActive {
isAutoconnectionActive = false
let event = ConnectionEvent.autoConnected(didConnect)
Expand All @@ -134,8 +134,8 @@ extension CBCentralManagerDelegateProxy: CBCentralManagerDelegate {
log("[LBT: CBCMD] DidDisconnect %{public}@, Error %{public}@",
log: OSLog.LittleBT_Log_CentralManager,
type: .debug,
arg: didDisconnectPeripheral.description,
error?.localizedDescription ?? "")
arg: [didDisconnectPeripheral.description,
error?.localizedDescription ?? ""])
isAutoconnectionActive = false
var lttlError: LittleBluetoothError?
if let error = error {
Expand All @@ -159,7 +159,7 @@ extension CBCentralManagerDelegateProxy: CBCentralManagerDelegate {
log("[LBT: CBCMD] WillRestoreState %{public}@",
log: OSLog.LittleBT_Log_Restore,
type: .debug,
arg: dict.description)
arg: [dict.description])
_willRestoreStatePublisher.send(CentralRestorer(centralManager: central, restoredInfo: dict))
}

Expand Down
68 changes: 40 additions & 28 deletions Sources/LittleBlueTooth/Classes/Proxies/CBPeripheralProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,28 @@ class CBPeripheralDelegateProxy: NSObject {

let peripheralChangesPublisher = PassthroughSubject<PeripheralChanges, Never>()
let peripheralRSSIPublisher = PassthroughSubject<(Int, LittleBluetoothError?), Never>()
let peripheralDiscoveredServicesPublisher = PassthroughSubject<([CBService]?, LittleBluetoothError?), Never>()
let peripheralDiscoveredIncludedServicesPublisher = PassthroughSubject<(CBService, Error?), Never>()
let peripheralDiscoveredCharacteristicsForServicePublisher = PassthroughSubject<(CBService, LittleBluetoothError?), Never>()

lazy var peripheralDiscoveredServicesPublisher = { _peripheralDiscoveredServicesPublisher.share().eraseToAnyPublisher()
}()
let _peripheralDiscoveredServicesPublisher = PassthroughSubject<([CBService]?, LittleBluetoothError?), Never>()

lazy var peripheralDiscoveredIncludedServicesPublisher = { _peripheralDiscoveredIncludedServicesPublisher.share().eraseToAnyPublisher()
}()
let _peripheralDiscoveredIncludedServicesPublisher = PassthroughSubject<(CBService, Error?), Never>()

lazy var peripheralDiscoveredCharacteristicsForServicePublisher = { _peripheralDiscoveredCharacteristicsForServicePublisher.share().eraseToAnyPublisher()
}()
let _peripheralDiscoveredCharacteristicsForServicePublisher = PassthroughSubject<(CBService, LittleBluetoothError?), Never>()

lazy var peripheralUpdatedNotificationStateForCharacteristicPublisher = { _peripheralUpdatedNotificationStateForCharacteristicPublisher.share().eraseToAnyPublisher()
}()
let _peripheralUpdatedNotificationStateForCharacteristicPublisher =
PassthroughSubject<(CBCharacteristic, LittleBluetoothError?), Never>()

let peripheralUpdatedValueForCharacteristicPublisher = PassthroughSubject<(CBCharacteristic, LittleBluetoothError?), Never>()
let peripheralUpdatedValueForNotifyCharacteristicPublisher = PassthroughSubject<(CBCharacteristic, LittleBluetoothError?), Never>()
let peripheralWrittenValueForCharacteristicPublisher = PassthroughSubject<(CBCharacteristic, LittleBluetoothError?), Never>()
let peripheralIsReadyToSendWriteWithoutResponse = PassthroughSubject<Void, Never>()

let peripheralUpdatedNotificationStateForCharacteristicPublisher =
PassthroughSubject<(CBCharacteristic, LittleBluetoothError?), Never>()

let peripheralDiscoveredDescriptorsForCharacteristicPublisher =
PassthroughSubject<(CBCharacteristic, LittleBluetoothError?), Never>()
Expand All @@ -44,23 +56,23 @@ extension CBPeripheralDelegateProxy: CBPeripheralDelegate {
func peripheralIsReady(toSendWriteWithoutResponse peripheral: CBPeripheral){
log("[LBT: CBPD] ReadyToSendWRiteWOResp",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug)
type: .debug, arg: [])
peripheralIsReadyToSendWriteWithoutResponse.send()
}

func peripheralDidUpdateName(_ peripheral: CBPeripheral) {
log("[LBT: CBPD] DidUpdateName %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: peripheral.name ?? "na")
arg: [peripheral.name ?? "na"])
peripheralChangesPublisher.send(.name(peripheral.name))
}

func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]){
log("[LBT: CBPD] DidModifyServices %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: invalidatedServices.description)
arg: [invalidatedServices.description])
peripheralChangesPublisher.send(.invalidatedServices(invalidatedServices))
}

Expand All @@ -76,46 +88,46 @@ extension CBPeripheralDelegateProxy: CBPeripheralDelegate {
log("[LBT: CBPD] DidDiscoverServices, Error %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: error?.localizedDescription ?? "")
arg: [error?.localizedDescription ?? "None"])
if let error = error {
peripheralDiscoveredServicesPublisher.send((nil,.serviceNotFound(error)))
_peripheralDiscoveredServicesPublisher.send((nil,.serviceNotFound(error)))
} else {
peripheralDiscoveredServicesPublisher.send((peripheral.services, nil))
_peripheralDiscoveredServicesPublisher.send((peripheral.services, nil))
}
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverIncludedServicesFor service: CBService, error: Error?) {
log("[LBT: CBPD] DidDiscoverIncludedServices %{public}@, Error %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: service.description,
error?.localizedDescription ?? "")
arg: [service.description,
(error?.localizedDescription ?? "None")])
if let error = error {
peripheralDiscoveredIncludedServicesPublisher.send((service, error))
_peripheralDiscoveredIncludedServicesPublisher.send((service, error))
} else {
peripheralDiscoveredIncludedServicesPublisher.send((service, nil))
_peripheralDiscoveredIncludedServicesPublisher.send((service, nil))
}
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?){
log("[LBT: CBPD] DidDiscoverCharacteristic %{public}@, Error %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: service.description,
error?.localizedDescription ?? "")
arg: [service.description,
(error?.localizedDescription ?? "None")])
if let error = error {
peripheralDiscoveredCharacteristicsForServicePublisher.send((service, .characteristicNotFound(error)))
_peripheralDiscoveredCharacteristicsForServicePublisher.send((service, .characteristicNotFound(error)))
} else {
peripheralDiscoveredCharacteristicsForServicePublisher.send((service, nil))
_peripheralDiscoveredCharacteristicsForServicePublisher.send((service, nil))
}
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){
log("[LBT: CBPD] DidUpdateValue %{public}@, Error %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: characteristic.description,
error?.localizedDescription ?? "")
arg: [characteristic.description,
(error?.localizedDescription ?? "None")])
if let error = error {
peripheralUpdatedValueForCharacteristicPublisher.send((characteristic, .couldNotReadFromCharacteristic(characteristic: characteristic.uuid, error: error)))
} else {
Expand All @@ -131,8 +143,8 @@ extension CBPeripheralDelegateProxy: CBPeripheralDelegate {
log("[LBT: CBPD] DidWriteValue %{public}@, Error %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: characteristic.description,
error?.localizedDescription ?? "")
arg: [characteristic.description,
(error?.localizedDescription ?? "None")])
if let error = error {
peripheralWrittenValueForCharacteristicPublisher.send((characteristic, .couldNotWriteFromCharacteristic(characteristic: characteristic.uuid, error: error)))
} else {
Expand All @@ -144,12 +156,12 @@ extension CBPeripheralDelegateProxy: CBPeripheralDelegate {
log("[LBT: CBPD] DidUpdateNotifState %{public}@, Error %{public}@",
log: OSLog.LittleBT_Log_Peripheral,
type: .debug,
arg: characteristic.description,
error?.localizedDescription ?? "")
arg: [characteristic.description,
(error?.localizedDescription ?? "None")])
if let error = error {
peripheralUpdatedNotificationStateForCharacteristicPublisher.send((characteristic, .couldNotUpdateListenState(characteristic: characteristic.uuid, error: error)))
_peripheralUpdatedNotificationStateForCharacteristicPublisher.send((characteristic, .couldNotUpdateListenState(characteristic: characteristic.uuid, error: error)))
} else {
peripheralUpdatedNotificationStateForCharacteristicPublisher.send((characteristic, nil))
_peripheralUpdatedNotificationStateForCharacteristicPublisher.send((characteristic, nil))
}
}

Expand Down
73 changes: 36 additions & 37 deletions Sources/LittleBlueTooth/LittleBlueTooth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public class LittleBlueTooth: Identifiable {
"[LBT] init options %{public}@",
log: OSLog.LittleBT_Log_General,
type: .debug,
arg: configuration.centralManagerOptions?.description ?? ""
arg: [configuration.centralManagerOptions?.description ?? ""]
)
}

Expand Down Expand Up @@ -473,42 +473,41 @@ public class LittleBlueTooth: Identifiable {
public func read<T: Readable>(from characteristic: LittleBlueToothCharacteristic) -> AnyPublisher<T, LittleBluetoothError> {

let readSubject = PassthroughSubject<T, LittleBluetoothError>()
let key = UUID()

let futKey = UUID()
ensureBluetoothState()
.customPrint("[LBT] ReadPublisher", isEnabled: isLogEnabled)
.flatMap { [unowned self] _ in
self.ensurePeripheralReady()
}
.flatMap { periph in
periph.read(from: characteristic.id, of: characteristic.service)
}
.tryMap { (data) -> T in
guard let data = data else {
throw LittleBluetoothError.emptyData
.customPrint("[LBT] ReadPublisher", isEnabled: isLogEnabled)
.flatMap { [unowned self] _ in
self.ensurePeripheralReady()
}
return try T.init(from: data)
}
.mapError { (error) -> LittleBluetoothError in
if let er = error as? LittleBluetoothError {
return er
.flatMap { [characteristic] periph in
periph.read(from: characteristic.id, of: characteristic.service)
}
return .couldNotReadFromCharacteristic(characteristic: characteristic.id, error: error)
}
.sink(receiveCompletion: { [unowned self, key] (completion) in
switch completion {
case .finished:
break
case .failure(let error):
readSubject.send(completion: .failure(error))
self.removeAndCancelSubscriber(for: key)
.tryMap { (data) -> T in
guard let data = data else {
throw LittleBluetoothError.emptyData
}
return try T.init(from: data)
}
}) { [unowned self, key] (readvalue) in
readSubject.send(readvalue)
readSubject.send(completion: .finished)
self.removeAndCancelSubscriber(for: key)
}
.store(in: &disposeBag, for: key)
.mapError { (error) -> LittleBluetoothError in
if let er = error as? LittleBluetoothError {
return er
}
return .couldNotReadFromCharacteristic(characteristic: characteristic.id, error: error)
}
.sink(receiveCompletion: { [unowned self, futKey] (completion) in
switch completion {
case .finished:
break
case .failure(let error):
readSubject.send(completion: .failure(error))
self.removeAndCancelSubscriber(for: futKey)
}
}) { [unowned self, futKey] (readvalue) in
readSubject.send(readvalue)
readSubject.send(completion: .finished)
self.removeAndCancelSubscriber(for: futKey)
}
.store(in: &disposeBag, for: futKey)

return readSubject.eraseToAnyPublisher()
}
Expand Down Expand Up @@ -851,7 +850,7 @@ public class LittleBlueTooth: Identifiable {
log("[LBT] Scan restore %{public}@",
log: OSLog.LittleBT_Log_Restore,
type: .debug,
arg: restorer.centralManager.isScanning ? "true" : "false")
arg: [restorer.centralManager.isScanning ? "true" : "false"])
return .scan(discoveryPublisher: restoreDiscoveryPublisher)
}
if let periph = restorer.peripherals.first, let cbPeripheral = periph.cbPeripheral {
Expand Down Expand Up @@ -884,9 +883,9 @@ public class LittleBlueTooth: Identifiable {
log("[LBT] Periph restore %{public}@, has delegate: %{public}@ state %{public}d",
log: OSLog.LittleBT_Log_Restore,
type: .debug,
arg: cbPeripheral.description,
arg: [cbPeripheral.description,
cbPeripheral.delegate != nil ? "true" : "false",
cbPeripheral.state.rawValue)
cbPeripheral.state.rawValue])
return Restored.peripheral(self.peripheral!)
}
return Restored.nothing
Expand Down Expand Up @@ -932,7 +931,7 @@ public class LittleBlueTooth: Identifiable {
prom(.failure(error))
self.removeAndCancelSubscriber(for: futKey)
}
}) { [unowned self] (state) in
}) { [unowned self, futKey] (state) in
prom(.success(state))
self.removeAndCancelSubscriber(for: futKey)
}
Expand Down
Loading

0 comments on commit 9149d71

Please sign in to comment.