Skip to content

Commit

Permalink
Merge pull request #20 from DrAma999/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
DrAma999 authored Mar 11, 2021
2 parents b5182b5 + 88d85c9 commit 447eca6
Show file tree
Hide file tree
Showing 16 changed files with 125 additions and 25 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/swift3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Publish Documentation
on:
release:
types: [published]
jobs:
deploy_docs:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v1
- name: Publish Jazzy Docs
uses: steven0351/publish-jazzy-docs@v1
with:
personal_access_token: ${{ secrets.GITHUBTOKEN }}
config: .jazzy.yaml
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
Package.resolved

docs/
5 changes: 5 additions & 0 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
author_url: https://www.facebook.com/CloudInTouchLabs
author: Andrea Finollo
github_url: https://github.com/DrAma999
theme: fullwidth
module: LittleBlueTooth
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@

import Foundation
import Combine

public let StartLittleBlueTooth = Just(()).setFailureType(to: LittleBluetoothError.self)
/// Syntactic sugar to start a `LittleBlueTooth` pipeline
public var StartLittleBlueTooth: Result<(), LittleBluetoothError>.Publisher {
Just(()).setFailureType(to: LittleBluetoothError.self)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension Publisher where Self.Failure == LittleBluetoothError {
// MARK: - RSSI
/// Returns a publisher with the `Int`value of the RSSI.
/// - parameter littleBluetooth: the `LittleBlueTooth` instance
/// - returns: A publisher with the `Int` value of the RSSI..
/// - returns: A publisher with the `Int` value of the RSSI.
public func readRSSI(for littleBluetooth: LittleBlueTooth) -> AnyPublisher<Int, LittleBluetoothError> {

func readRSSI<Upstream: Publisher>(upstream: Upstream,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import CoreBluetoothMock
#else
import CoreBluetooth
#endif

/// Collection of errors that can be returned by LittleBlueTooth
public enum LittleBluetoothError: Error {
case bluetoothPoweredOff
case bluetoothUnauthorized
Expand Down
3 changes: 2 additions & 1 deletion Sources/LittleBlueTooth/Classes/Extension/Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ extension AnyCancellable {
}
}
extension Publisher {

/// Republishes elements sent by the most recently received 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 {
/// Get a `DispatchTimeInterval` from a TimeInterval.
public 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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import CoreBluetoothMock
import CoreBluetooth
#endif

/// A wrapper around the advertisement data returned from a BLE device.
public struct AdvertisingInfo {
public let advertisementData: [String: Any]

Expand Down
3 changes: 2 additions & 1 deletion Sources/LittleBlueTooth/Classes/Model/CentralRestorer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public struct CentralRestorer {
}

extension CentralRestorer: CustomDebugStringConvertible {
/// Extended description of the `CentralRestorer`
public var debugDescription: String {
return """
Peripherals: \(peripherals)
Expand All @@ -70,7 +71,7 @@ public enum Restored: CustomDebugStringConvertible {
case peripheral(Peripheral)
/// Nothing has been restored
case nothing

/// Extended description of the `Restored` object
public var debugDescription: String {
switch self {
case .scan(_):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,52 @@ import CoreBluetoothMock
import CoreBluetooth
#endif

/// Type alias for a CBUUID string used to identify services
public typealias LittleBlueToothServiceIndentifier = String
/// Type alias for a CBUUID string used to identify characteristic
public typealias LittleBlueToothCharacteristicIndentifier = String


/// A representation of a bluetooth characteristic
public struct LittleBlueToothCharacteristic: Identifiable {
/// The `CBUUID` of the characteristic
public let id: CBUUID
/// The `CBUUID` of the service
public let service: CBUUID
/// Properties of the characteristic. They are mapped from `CBCharacteristicProperties`
public let properties: Properties

/// Inner value of the `CBCaharacteristic`
public var rawValue: Data? {
cbCharacteristic?.value
}

private var cbCharacteristic: CBCharacteristic?

/// Initialize a `LittleBlueToothCharacteristic`.
/// - parameter characteristic: the `LittleBlueToothCharacteristicIndentifier` instance, basically a string
/// - parameter service: the `LittleBlueToothServiceIndentifier` instance, basically a string
/// - parameter properties: an option set of properties
/// - returns: An instance of `LittleBlueToothCharacteristic`.
public init(characteristic: LittleBlueToothCharacteristicIndentifier, for service: LittleBlueToothServiceIndentifier, properties: LittleBlueToothCharacteristic.Properties) {
self.id = CBUUID(string: characteristic)
self.service = CBUUID(string: service)
self.properties = properties
}

/// Initialize a `LittleBlueToothCharacteristic` from a `CBCharacteristic`
/// - parameter characteristic: the `CBCharacteristic` instance that you want to use
/// - returns: An instance of `LittleBlueToothCharacteristic`.
public init(with characteristic: CBCharacteristic) {
self.id = characteristic.uuid
self.service = characteristic.service.uuid
self.cbCharacteristic = characteristic
self.properties = Properties(properties: characteristic.properties)
}

/// A helper method to get a concrete value from the value contained in the characteristic.
/// The type must conform to the `Readable` protocol
/// - parameter characteristic: the `CBCharacteristic` instance that you want to use
/// - returns: An instance of of the requested type.
/// - throws: If the transformation from the `Data` to the `T` type cannot be made an error is thrown
public func value<T: Readable>() throws -> T {
guard let data = rawValue else {
throw LittleBluetoothError.emptyData
Expand All @@ -51,6 +68,7 @@ public struct LittleBlueToothCharacteristic: Identifiable {
}

extension LittleBlueToothCharacteristic: Equatable, Hashable {
/// If two `LittleBlueToothCharacteristic` are compared and they have the same characteristic and service identifier they are equal
public static func == (lhs: Self, rhs: Self) -> Bool {
if lhs.id == rhs.id &&
lhs.service == rhs.service {
Expand All @@ -59,6 +77,7 @@ extension LittleBlueToothCharacteristic: Equatable, Hashable {
return false
}

/// Combute the hash of a `LittleBlueToothCharacteristic`
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(service)
Expand Down
28 changes: 23 additions & 5 deletions Sources/LittleBlueTooth/Classes/Model/Peripheral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,28 @@ import CoreBluetoothMock
import CoreBluetooth
#endif

/// An enumeration that represent the changes in peripheral services or name
public enum PeripheralChanges {
/// The name has been changed
case name(String?)
/// Some services have been invalidated
case invalidatedServices([CBService])
}

/// The state of the peripheral
public enum PeripheralState {
/// Peripheral is disconnected
case disconnected
/// Peripheral is connecting
case connecting
/// Peripheral is connected
case connected
/// Peripheral is disconnecting
case disconnecting
/// The peripheral state is not know, could be transitory
case unknown

/// Initilize a Peripheral state using a `CBPeripheralState`
init(state: CBPeripheralState) {
switch state {
case .disconnected:
Expand All @@ -43,23 +53,27 @@ public enum PeripheralState {
}
}

/// It represents a peripheral along with its properties
public class Peripheral: Identifiable {
/// An identifier for the peripheral it is the same as the wrapped `CBPeripheral`
public var id: UUID {
cbPeripheral.identifier
}

/// The name of the peripheral it is the same as the wrapped `CBPeripheral`
public var name: String? {
cbPeripheral.name
}

/// The state of the peripheral it is the same as the wrapped `CBPeripheral`
public var state: PeripheralState {
PeripheralState(state: cbPeripheral.state)
}

/// The wrapped `CBPeripheral`
public let cbPeripheral: CBPeripheral
/// The rssi value of the peripheral
public var rssi: Int?


/// Logging on the peripheral can be disable or enabled acting of that property
var isLogEnabled: Bool {
get {
return _isLogEnabled
Expand All @@ -70,11 +84,12 @@ public class Peripheral: Identifiable {
}
}

/// The publisher that listen to changes in peripheral name or services
lazy var changesPublisher: AnyPublisher<PeripheralChanges, Never> =
peripheralProxy.peripheralChangesPublisher
.share()
.eraseToAnyPublisher()

/// The publisher that listen to characteristic notifications
lazy var listenPublisher: AnyPublisher<CBCharacteristic, LittleBluetoothError> =
peripheralProxy.peripheralUpdatedValueForNotifyCharacteristicPublisher
.tryMap { (value) -> CBCharacteristic in
Expand All @@ -94,6 +109,8 @@ public class Peripheral: Identifiable {
private let peripheralProxy = CBPeripheralDelegateProxy()
private var _isLogEnabled: Bool = false

/// Initialize a `Peripheral` using a `CBperipheral`
/// It also attach the publisher to monitor the state of the peripheral
init(_ peripheral: CBPeripheral) {
self.cbPeripheral = peripheral
self.cbPeripheral.delegate = self.peripheralProxy
Expand Down Expand Up @@ -200,7 +217,7 @@ public class Peripheral: Identifiable {
}
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 @@ -353,6 +370,7 @@ public class Peripheral: Identifiable {
}

extension Peripheral: CustomDebugStringConvertible {
/// Extended description of the peripheral
public var debugDescription: String {
return """
Id: \(id)
Expand Down
30 changes: 25 additions & 5 deletions Sources/LittleBlueTooth/Classes/Model/PeripheralDiscovery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,32 @@ public protocol PeripheralIdentifiable: Identifiable {
}
/// An object that contains the unique identifier of the `CBPeripheral` and the name of it (if present)
public struct PeripheralIdentifier: PeripheralIdentifiable {
/// The `UUID`of the peripheral
public var id: UUID
/// The name of the peripheral
public var name: String?
/// The wrapped `CBPeripheral`
public var cbPeripheral: CBPeripheral?

/// Initialize a `PeripheralIdentifier` using a `CBPeripheral`
public init(peripheral: CBPeripheral) {
self.id = peripheral.identifier
self.name = peripheral.name
self.cbPeripheral = peripheral
}

/// Initialize a `PeripheralIdentifier`.
/// - parameter uuid: the `UUID` of a peripheral.
/// - parameter name: the name of a peripheral
/// - returns: An instance of `PeripheralIdentifier`.
public init(uuid: UUID, name: String? = nil) {
self.id = uuid
self.name = name
}

/// Initialize a `PeripheralIdentifier`.
/// - parameter string: the uuid in string of a peripheral.
/// - parameter name: the name of a peripheral
/// - throws: and error is thrown if the converstion string->UUID fails
/// - returns: An instance of `PeripheralIdentifier`.
public init(string: String, name: String? = nil) throws {
if let id = UUID(uuidString: string) {
self.init(uuid: id, name: name)
Expand All @@ -45,6 +56,7 @@ public struct PeripheralIdentifier: PeripheralIdentifiable {
}

extension PeripheralIdentifier: CustomStringConvertible {
/// Extended description
public var description: String {
return """
UUID: \(id)
Expand All @@ -57,14 +69,21 @@ extension PeripheralIdentifier: CustomStringConvertible {
An object that contains the unique identifier of the `CBPeripheral`, the name of it (if present) and the advertising info.
*/
public struct PeripheralDiscovery: PeripheralIdentifiable {
/// The `UUID` of the discovery
public var id: UUID
/// The name of the discovery
public var name: String?

/// The wrapped `CBPeripheral` of the discovery
public let cbPeripheral: CBPeripheral
/// The wrapped `AdvertisingInfo` of the discovery
public let advertisement: AdvertisingInfo
/// The wrapped rssi of the discovery
public let rssi: Int

/// Initialize a `PeripheralDiscovery`.
/// - parameter peripheral: the `CBPeripheral` that you want to wrap
/// - parameter advertisement: the advertising info as they are returned from `CBManager`
/// - parameter rssi: the rssi iof the `CBPeripheral`
/// - returns: An instance of `PeripheralDiscovery`.
init(_ peripheral: CBPeripheral, advertisement: [String : Any], rssi: NSNumber) {
self.cbPeripheral = peripheral
self.name = peripheral.name
Expand All @@ -75,6 +94,7 @@ public struct PeripheralDiscovery: PeripheralIdentifiable {
}

extension PeripheralDiscovery: CustomDebugStringConvertible {
/// Extended description of the discovery
public var debugDescription: String {
return """
Name: \(name ?? "not available")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,38 @@ import CoreBluetoothMock
#else
import CoreBluetooth
#endif

/// An enum representing the connection event that has occurred
public enum ConnectionEvent {
/// Peripheral is connected but not ready to receive command
case connected(CBPeripheral)
/// Peripheral is connected after a disconnection automatically but not ready to receive command
case autoConnected(CBPeripheral)
/// Peripheral is ready to receive command
case ready(CBPeripheral)
/// Peripheral is not ready probaly due to some unexpected disconnection
case notReady(CBPeripheral, error: LittleBluetoothError?)
/// Process of connection has failed
case connectionFailed(CBPeripheral, error: LittleBluetoothError?)
/// Peripheral has been disconnected, if it was unexpected a `LittleBluetoothError` is returned
case disconnected(CBPeripheral, error: LittleBluetoothError?)
}

/// An enumeration representing the state of the bluetooth stack of the device
public enum BluetoothState {

/// Unknown, probably transient
case unknown
/// Bluetooth is resetting
case resetting
/// Bluetooth is not supported for this device
case unsupported
/// The application is not authorized to use bluetooth
case unauthorized
/// The bluetooth is off
case poweredOff
/// The bluetooth is on and ready
case poweredOn

/// Inizialize using a `CBManagerState`
init(_ state: CBManagerState) {
switch state {
case .unknown:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import Foundation
import Combine

///The ShareReplay is used to share a single subscription to the upstream publisher and replay items emitted by that one.
public final class ReplaySubject<Output, Failure: Error>: Subject {
private var buffer = [Output]()
private let bufferSize: Int
private var subscriptions = [ReplaySubjectSubscription<Output, Failure>]()
private var completion: Subscribers.Completion<Failure>?
private let lock = NSRecursiveLock()

/// Initialize a `ReplaySubject` subject with a buffer size
public init(_ bufferSize: Int = 0) {
self.bufferSize = bufferSize
}
Expand Down
Loading

0 comments on commit 447eca6

Please sign in to comment.