Skip to content

Commit

Permalink
Merge pull request #5 from DrAma999/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
DrAma999 authored Aug 13, 2020
2 parents 25f8bd1 + e06041b commit 2795958
Show file tree
Hide file tree
Showing 19 changed files with 723 additions and 173 deletions.
38 changes: 31 additions & 7 deletions LittleBlueTooth.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
654BCE8B24E03544002FC7A4 /* Extraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 654BCE8A24E03544002FC7A4 /* Extraction.swift */; };
654BCE8E24E077DC002FC7A4 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 654BCE8D24E077DC002FC7A4 /* Helper.swift */; };
654BCE8F24E07804002FC7A4 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 654BCE8D24E077DC002FC7A4 /* Helper.swift */; };
655330DD24BF159D007D299B /* CentralRestorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 655330DC24BF159D007D299B /* CentralRestorer.swift */; };
655F49E224CF3DA400C24461 /* StateRestoration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 655330DE24BF5446007D299B /* StateRestoration.swift */; };
658A75C224BB74FC00F874EF /* CoreBluetoothTypeAliases.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* CoreBluetoothTypeAliases.swift */; };
658A75C524BB765C00F874EF /* LittleBlueTooth.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* LittleBlueTooth.h */; settings = {ATTRIBUTES = (Public, ); }; };
6590D38224D0030000BEE864 /* WriteWithoutResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6590D38124D0030000BEE864 /* WriteWithoutResponse.swift */; };
65A6B35024DD29000068FE1C /* Loggable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A6B34F24DD29000068FE1C /* Loggable.swift */; };
65A6B35124DD29070068FE1C /* Loggable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A6B34F24DD29000068FE1C /* Loggable.swift */; };
65AD4BD424D437B700C0CBE6 /* LittleBlueTooth.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* LittleBlueTooth.h */; settings = {ATTRIBUTES = (Public, ); }; };
65AD4BD624D437B700C0CBE6 /* LittleBlueToothError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* LittleBlueToothError.swift */; };
65AD4BD724D437B700C0CBE6 /* AdvertisingData.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* AdvertisingData.swift */; };
Expand Down Expand Up @@ -86,9 +91,12 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
654BCE8A24E03544002FC7A4 /* Extraction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extraction.swift; sourceTree = "<group>"; };
654BCE8D24E077DC002FC7A4 /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = "<group>"; };
655330DC24BF159D007D299B /* CentralRestorer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CentralRestorer.swift; sourceTree = "<group>"; };
655330DE24BF5446007D299B /* StateRestoration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRestoration.swift; sourceTree = "<group>"; };
6590D38124D0030000BEE864 /* WriteWithoutResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteWithoutResponse.swift; sourceTree = "<group>"; };
65A6B34F24DD29000068FE1C /* Loggable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loggable.swift; sourceTree = "<group>"; };
65AD4BEB24D437B700C0CBE6 /* LittleBlueToothForTest.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LittleBlueToothForTest.framework; sourceTree = BUILT_PRODUCTS_DIR; };
65AD4BEC24D437B700C0CBE6 /* LittleBlueTooth copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "LittleBlueTooth copy-Info.plist"; path = "/Users/Andrea/Documents/GitHub/LittleBlueTooth/LittleBlueTooth copy-Info.plist"; sourceTree = "<absolute>"; };
65BA2D0E24CDDE99008B4BD7 /* LittleBluetoothConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LittleBluetoothConfiguration.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -150,6 +158,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
654BCE8C24E077B3002FC7A4 /* Extension */ = {
isa = PBXGroup;
children = (
654BCE8D24E077DC002FC7A4 /* Helper.swift */,
);
path = Extension;
sourceTree = "<group>";
};
65AD4BEF24D438AD00C0CBE6 /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand All @@ -160,6 +176,7 @@
OBJ_11 /* Classes */ = {
isa = PBXGroup;
children = (
654BCE8C24E077B3002FC7A4 /* Extension */,
OBJ_12 /* Error */,
OBJ_14 /* Model */,
OBJ_19 /* Proxies */,
Expand All @@ -185,6 +202,7 @@
OBJ_18 /* PeripheralDiscovery.swift */,
655330DC24BF159D007D299B /* CentralRestorer.swift */,
65BA2D0E24CDDE99008B4BD7 /* LittleBluetoothConfiguration.swift */,
65A6B34F24DD29000068FE1C /* Loggable.swift */,
);
path = Model;
sourceTree = "<group>";
Expand Down Expand Up @@ -238,6 +256,7 @@
OBJ_40 /* WriteReadTest.swift */,
655330DE24BF5446007D299B /* StateRestoration.swift */,
6590D38124D0030000BEE864 /* WriteWithoutResponse.swift */,
654BCE8A24E03544002FC7A4 /* Extraction.swift */,
);
name = LittleBlueToothTests;
path = Tests/LittleBlueToothTests;
Expand Down Expand Up @@ -439,7 +458,9 @@
65AD4BD924D437B700C0CBE6 /* Peripheral.swift in Sources */,
65AD4BDA24D437B700C0CBE6 /* PeripheralDiscovery.swift in Sources */,
65AD4BDB24D437B700C0CBE6 /* CentralRestorer.swift in Sources */,
65A6B35124DD29070068FE1C /* Loggable.swift in Sources */,
65AD4BDC24D437B700C0CBE6 /* CBCentralManagerDelegateProxy.swift in Sources */,
654BCE8F24E07804002FC7A4 /* Helper.swift in Sources */,
65AD4BDD24D437B700C0CBE6 /* CBPeripheralProxy.swift in Sources */,
65AD4BDE24D437B700C0CBE6 /* ReplaySubject.swift in Sources */,
65AD4BDF24D437B700C0CBE6 /* ReplaySubjectSubscription.swift in Sources */,
Expand All @@ -461,7 +482,9 @@
OBJ_55 /* Peripheral.swift in Sources */,
OBJ_56 /* PeripheralDiscovery.swift in Sources */,
655330DD24BF159D007D299B /* CentralRestorer.swift in Sources */,
65A6B35024DD29000068FE1C /* Loggable.swift in Sources */,
OBJ_57 /* CBCentralManagerDelegateProxy.swift in Sources */,
654BCE8E24E077DC002FC7A4 /* Helper.swift in Sources */,
OBJ_58 /* CBPeripheralProxy.swift in Sources */,
OBJ_59 /* ReplaySubject.swift in Sources */,
OBJ_60 /* ReplaySubjectSubscription.swift in Sources */,
Expand All @@ -488,6 +511,7 @@
OBJ_82 /* ConnectionTest.swift in Sources */,
655F49E224CF3DA400C24461 /* StateRestoration.swift in Sources */,
OBJ_83 /* ListenTest.swift in Sources */,
654BCE8B24E03544002FC7A4 /* Extraction.swift in Sources */,
OBJ_84 /* LittleBlueToothTests.swift in Sources */,
OBJ_85 /* MockPeripherals.swift in Sources */,
6590D38224D0030000BEE864 /* WriteWithoutResponse.swift in Sources */,
Expand Down Expand Up @@ -584,7 +608,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.3.1;
MARKETING_VERSION = 0.4.0;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited) -DTEST";
Expand Down Expand Up @@ -675,7 +699,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.3.1;
MARKETING_VERSION = 0.4.0;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
Expand Down Expand Up @@ -709,7 +733,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.3.1;
MARKETING_VERSION = 0.4.0;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited) -DTEST";
Expand Down Expand Up @@ -743,7 +767,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.3.1;
MARKETING_VERSION = 0.4.0;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
Expand Down Expand Up @@ -882,7 +906,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.3.1;
MARKETING_VERSION = 0.4.0;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
Expand Down Expand Up @@ -916,7 +940,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.3.1;
MARKETING_VERSION = 0.4.0;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
Expand Down Expand Up @@ -1119,7 +1143,7 @@
repositoryURL = "https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock.git";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 0.9.0;
minimumVersion = 0.11.1;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let package = Package(
// Dependencies declare other packages that this package depends on.
.package(name: "CoreBluetoothMock",
url: "https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock.git",
.upToNextMinor(from: "0.9.0")),
.upToNextMinor(from: "0.11.0")),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The library is still on development so use at own you risk.
Add the following to your Cartfile:

```
github "DrAma999/LittleBlueTooth" ~> 0.3.0
github "DrAma999/LittleBlueTooth" ~> 0.4.0
```
Since the framework supports most of the Apple devices, you probably want to to build for a specific platform by adding the option `--platform` after the `carthage update` command. For instance:
```
Expand All @@ -35,7 +35,7 @@ The library has a sub-dependency with Nordic library [Core Bluetooth Mock](https
### Swift Package Manager
Add the following dependency to your Package.swift file:
```
.package(url: "https://github.com/DrAma999/LittleBlueTooth.git", from: "0.3.0")
.package(url: "https://github.com/DrAma999/LittleBlueTooth.git", from: "0.4.0")
```
Or simply add the URL from XCode menu Swift packages.

Expand Down Expand Up @@ -520,13 +520,26 @@ Note:
* Restoration can happen in background and foreground
* The Peripheral object returned can be in different state depending on what has been restored. If a peripheral has been disconnected and an `autoconnectionHandler` is provided LittleBluetooth will try to re-establish a connection.

### CBCentralManager CBPeripheral extraction
Sometimes it could be uselful to extract an already connected peripheral and a central manger and pass them to another framework. For instance if you need to make an OTA firmware update using the nordic library this would be required.
The extraction is made exaclty for this purpuse.
```
let extractedState = littleBT.extract()
```
Before extraction you need to stop listen to all the characteristics you where listening to.
The extracted state is a tuple `(central: CBCentralManager, peripheral: CBPeripheral?)` that contains the used `CBCentralManger` and a `CBPeripheral` if connected.
You can also *restart* LittleBlueTooth instance by passing the same object that you have extracted.
```
self.littleBT.restart(with: extractedState.central, peripheral: extractedState.peripheral)
```

## ROADMAP
- [x] SwiftPM support
- [x] State preservation and state restoration
- [ ] Improve code coverage
- [ ] `CBManager` and `CBPeripheral` extraction
- [ ] Add multiple peripheral support
- [x] `CBManager` and `CBPeripheral` extraction
- [x] Add support to: **macOS**, **watchOS**, **tvOS**, **macOS catalyst**
- [] Implement custom operator

## ISSUES
Please use Gihub, explaining what you did, how you did, what you expect and what you get.
Expand Down
56 changes: 56 additions & 0 deletions Sources/LittleBlueTooth/Classes/Extension/Helper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// Helper.swift
// LittleBlueTooth
//
// Created by Andrea Finollo on 09/08/2020.
//

import Foundation
import Combine
import os.log
#if TEST
import CoreBluetoothMock
#else
import CoreBluetooth
#endif

extension AnyCancellable {
func store(in dictionary: inout [UUID : AnyCancellable],
for key: UUID) {
dictionary[key] = self
}
}
extension Publisher {

func flatMapLatest<T: Publisher>(_ transform: @escaping (Self.Output) -> T) -> AnyPublisher<T.Output, T.Failure> where T.Failure == Self.Failure {
return map(transform).switchToLatest().eraseToAnyPublisher()
}
}

extension TimeInterval {
var dispatchInterval: DispatchTimeInterval {
let microseconds = Int64(self * TimeInterval(USEC_PER_SEC)) // perhaps use nanoseconds, though would more often be > Int.max
return microseconds < Int.max ? DispatchTimeInterval.microseconds(Int(microseconds)) : DispatchTimeInterval.seconds(Int(self))
}
}

extension OSLog {
public static var Subsystem = "it.vanillagorilla.LittleBlueTooth"
public static var General = "General"
public static var CentralManager = "CentralManager"
public static var Peripheral = "Peripheral"
public static var Restore = "Restore"

public static let LittleBT_Log_General = OSLog(subsystem: Subsystem, category: General)
public static let LittleBT_Log_CentralManager = OSLog(subsystem: Subsystem, category: CentralManager)
public static let LittleBT_Log_Peripheral = OSLog(subsystem: Subsystem, category: Peripheral)
public static let LittleBT_Log_Restore = OSLog(subsystem: Subsystem, category: Restore)

}
#if TEST
extension CBMPeripheral {
public var description: String {
return "Test peripheral"
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public struct LittleBluetoothConfiguration {
/// Handler used to manage state restoration. `Restored` object will contain the restored information
/// could be a peripheral, a scan or nothing
public var restoreHandler: ((Restored) -> Void)?
/// Enable logging, log is made using os_log and it exposes some information even in release configuration
public var isLogEnabled = false

public init() {}
}
26 changes: 26 additions & 0 deletions Sources/LittleBlueTooth/Classes/Model/Loggable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// Loggable.swift
// LittleBlueTooth
//
// Created by Andrea Finollo on 07/08/2020.
//

import Foundation
import os.log

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


extension Loggable {
func log(_ message: StaticString, log: OSLog, type: OSLogType, arg: CVarArg...) {
#if !TEST
guard isLogEnabled else {
return
}
os_log(type, log: log, message, arg)
#endif
}
}
35 changes: 34 additions & 1 deletion Sources/LittleBlueTooth/Classes/Model/Peripheral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,16 @@ public class Peripheral: Identifiable {
public let cbPeripheral: CBPeripheral
public var rssi: Int?

private let peripheralProxy = CBPeripheralDelegateProxy()

var isLogEnabled: Bool {
get {
return _isLogEnabled
}
set {
_isLogEnabled = newValue
peripheralProxy.isLogEnabled = newValue
}
}

lazy var changesPublisher: AnyPublisher<PeripheralChanges, Never> =
peripheralProxy.peripheralChangesPublisher
Expand All @@ -81,6 +90,9 @@ public class Peripheral: Identifiable {
.eraseToAnyPublisher()

let peripheralStatePublisher: AnyPublisher<PeripheralState, Never>

private let peripheralProxy = CBPeripheralDelegateProxy()
private var _isLogEnabled: Bool = false

init(_ peripheral: CBPeripheral) {
self.cbPeripheral = peripheral
Expand Down Expand Up @@ -170,6 +182,25 @@ public class Peripheral: Identifiable {
return discovery
}

func readRSSI() -> AnyPublisher<Int, LittleBluetoothError> {
let readRSSI =
peripheralProxy.peripheralRSSIPublisher
.tryMap { (value) -> Int in
switch value {
case let (_, error?):
throw error
case let (rssi, _):
return rssi
}
}
.mapError {$0 as! LittleBluetoothError}
.eraseToAnyPublisher()
defer {
cbPeripheral.readRSSI()
}
return readRSSI
}

func read(from charateristicUUID: CBUUID, of serviceUUID: CBUUID) -> AnyPublisher<Data?, LittleBluetoothError> {
let read = discoverCharacteristic(charateristicUUID, fromService: serviceUUID)
.flatMap { characteristic -> AnyPublisher<CBCharacteristic, LittleBluetoothError> in
Expand Down Expand Up @@ -331,3 +362,5 @@ extension Peripheral: CustomDebugStringConvertible {
"""
}
}

extension Peripheral: Loggable {}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ extension PeripheralDiscovery: CustomDebugStringConvertible {
return """
Name: \(name ?? "not available")
CB Peripheral: \(cbPeripheral)
Adv: \(advertisement)
Adv: \(advertisement.debugDescription)
RSSI: \(rssi)
"""
}
Expand Down
Loading

0 comments on commit 2795958

Please sign in to comment.