Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause feature + multi-characteristic discovery. #91

Open
wants to merge 10 commits into
base: development
Choose a base branch
from
44 changes: 31 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ Easily communicate between iOS devices using BLE.
[![Cocoapods Compatible](https://img.shields.io/cocoapods/v/BluetoothKit.svg)](https://img.shields.io/cocoapods/v/BluetoothKit.svg)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)

##Background
## Background
Apple mostly did a great job with the CoreBluetooth API, but because it encapsulated the entire Bluetooth 4.0 LE specification, it can be a lot of work to achieve simple tasks like sending data back and forth between iOS devices, without having to worry about the specification and the inner workings of the CoreBluetooth stack.

BluetoothKit tries to address the challenges this may cause by providing a much simpler, modern, closure-based API all implemented in Swift.

##Features
## Features

####Common
#### Common
- More concise Bluetooth LE availability definition with enums.
- Bluetooth LE availability observation allowing multiple observers at once.

####Central
#### Central
- Scan for remote peripherals for a given time interval.
- Continuously scan for remote peripherals for a give time interval, with an in-between delay until interrupted.
- Connect to remote peripherals with a given time interval as time out.
- Receive any size of data without having to worry about chunking.

####Peripheral
#### Peripheral
- Start broadcasting with only a single function call.
- Send any size of data to connected remote centrals without having to worry about chunking.

Expand All @@ -32,7 +32,7 @@ BluetoothKit tries to address the challenges this may cause by providing a much

## Installation

####CocoaPods
#### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects.

CocoaPods 0.38.2 is required to build BluetoothKit. It adds support for Xcode 7, Swift 2.0 and embedded frameworks. You can install it with the following command:
Expand All @@ -57,7 +57,7 @@ Then, run the following command:
$ pod install
```

####Carthage
#### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.

You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
Expand All @@ -73,20 +73,20 @@ To integrate BluetoothKit into your Xcode project using Carthage, specify it in
github "rasmusth/BluetoothKit" ~> 0.4.0
```

####Manual
#### Manual
Add the BluetoothKit project to your existing project and add BluetoothKit as an embedded binary of your target(s).

##Usage
## Usage

Below you find some examples of how the framework can be used. Accompanied in the repository you find an example project that demonstrates a usage of the framework in practice. The example project uses [SnapKit](https://github.com/SnapKit/SnapKit) and [CryptoSwift](https://github.com/krzyzanowskim/CryptoSwift) both of which are great projects. They're bundled in the project and it should all build without further ado.

####Common
#### Common
Make sure to import the BluetoothKit framework in files that use it.
```swift
import BluetoothKit
```

####Peripheral
#### Peripheral

Prepare and start a BKPeripheral object with a configuration holding UUIDs uniqueue to your app(s) and an optional local name that will be broadcasted. You can generate UUIDs in the OSX terminal using the command "uuidgen".
```swift
Expand All @@ -104,6 +104,24 @@ do {
}
```

Pause advertising without disconnecting from connected centrals.
```swift
do {
try peripheral.pause()
} catch let error {
// Handle error.
}
```

Resume advertising using the same data given at startup time (only valid if the peripheral was previously paused and not completely stopped).
```swift
do {
try peripheral.resume()
} catch let error {
// Handle error.
}
```

Send data to a connected remote central.
```swift
let data = "Hello beloved central!".dataUsingEncoding(NSUTF8StringEncoding)
Expand All @@ -114,7 +132,7 @@ peripheral.sendData(data, toRemoteCentral: remoteCentral) { data, remoteCentral,
}
```

####Central
#### Central
Prepare and start a BKCentral object with a configuration holding the UUIDs you used to configure your BKPeripheral object.
```swift
let central = BKCentral()
Expand Down Expand Up @@ -163,5 +181,5 @@ central.connect(remotePeripheral: peripherals[indexPath.row]) { remotePeripheral
}
```

##License
## License
BluetoothKit is released under the MIT License.
106 changes: 53 additions & 53 deletions Source/BKAvailability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,26 @@ import CoreBluetooth

public func == (lhs: BKAvailability, rhs: BKAvailability) -> Bool {
switch (lhs, rhs) {
case (.available, .available): return true
case (.unavailable(cause: .any), .unavailable): return true
case (.unavailable, .unavailable(cause: .any)): return true
case (.unavailable(let lhsCause), .unavailable(let rhsCause)): return lhsCause == rhsCause
default: return false
case (.available, .available): return true
case (.unavailable(cause: .any), .unavailable): return true
case (.unavailable, .unavailable(cause: .any)): return true
case (.unavailable(let lhsCause), .unavailable(let rhsCause)): return lhsCause == rhsCause
default: return false
}
}

/**
Bluetooth LE availability.
- Available: Bluetooth LE is available.
- Unavailable: Bluetooth LE is unavailable.

The unavailable case can be accompanied by a cause.
*/
Bluetooth LE availability.
- Available: Bluetooth LE is available.
- Unavailable: Bluetooth LE is unavailable.
The unavailable case can be accompanied by a cause.
*/
public enum BKAvailability: Equatable {

case available
case unavailable(cause: BKUnavailabilityCause)

#if os(iOS) || os(tvOS)
@available(iOS 10.0, tvOS 10.0, *)
@available(OSX, unavailable)
Expand All @@ -57,14 +57,14 @@ public enum BKAvailability: Equatable {
}
}
#endif

internal init(centralManagerState: CBCentralManagerState) {
switch centralManagerState {
case .poweredOn: self = .available
default: self = .unavailable(cause: BKUnavailabilityCause(centralManagerState: centralManagerState))
}
}

internal init(peripheralManagerState: CBPeripheralManagerState) {
switch peripheralManagerState {
case .poweredOn: self = .available
Expand All @@ -74,25 +74,25 @@ public enum BKAvailability: Equatable {
}

/**
Bluetooth LE unavailability cause.
- Any: When initialized with nil.
- Resetting: Bluetooth is resetting.
- Unsupported: Bluetooth LE is not supported on the device.
- Unauthorized: The app isn't allowed to use Bluetooth.
- PoweredOff: Bluetooth is turned off.
*/
Bluetooth LE unavailability cause.
- Any: When initialized with nil.
- Resetting: Bluetooth is resetting.
- Unsupported: Bluetooth LE is not supported on the device.
- Unauthorized: The app isn't allowed to use Bluetooth.
- PoweredOff: Bluetooth is turned off.
*/
public enum BKUnavailabilityCause: ExpressibleByNilLiteral {

case any
case resetting
case unsupported
case unauthorized
case poweredOff

public init(nilLiteral: Void) {
self = .any
}

#if os(iOS) || os(tvOS)
@available(iOS 10.0, tvOS 10.0, *)
@available(OSX, unavailable)
Expand All @@ -106,7 +106,7 @@ public enum BKUnavailabilityCause: ExpressibleByNilLiteral {
}
}
#endif

internal init(centralManagerState: CBCentralManagerState) {
switch centralManagerState {
case .poweredOff: self = .poweredOff
Expand All @@ -116,7 +116,7 @@ public enum BKUnavailabilityCause: ExpressibleByNilLiteral {
default: self = nil
}
}

internal init(peripheralManagerState: CBPeripheralManagerState) {
switch peripheralManagerState {
case .poweredOff: self = .poweredOff
Expand All @@ -126,21 +126,21 @@ public enum BKUnavailabilityCause: ExpressibleByNilLiteral {
default: self = nil
}
}

}

/**
Classes that can be observed for Bluetooth LE availability implement this protocol.
*/
Classes that can be observed for Bluetooth LE availability implement this protocol.
*/
public protocol BKAvailabilityObservable: class {
var availabilityObservers: [BKWeakAvailabilityObserver] { get set }
func addAvailabilityObserver(_ availabilityObserver: BKAvailabilityObserver)
func removeAvailabilityObserver(_ availabilityObserver: BKAvailabilityObserver)
}

/**
Class used to hold a weak reference to an observer of Bluetooth LE availability.
*/
Class used to hold a weak reference to an observer of Bluetooth LE availability.
*/
public class BKWeakAvailabilityObserver {
weak var availabilityObserver: BKAvailabilityObserver?
init (availabilityObserver: BKAvailabilityObserver) {
Expand All @@ -149,45 +149,45 @@ public class BKWeakAvailabilityObserver {
}

public extension BKAvailabilityObservable {

/**
Add a new availability observer. The observer will be weakly stored. If the observer is already subscribed the call will be ignored.
- parameter availabilityObserver: The availability observer to add.
*/
Add a new availability observer. The observer will be weakly stored. If the observer is already subscribed the call will be ignored.
- parameter availabilityObserver: The availability observer to add.
*/
func addAvailabilityObserver(_ availabilityObserver: BKAvailabilityObserver) {
if !availabilityObservers.contains(where: { $0.availabilityObserver === availabilityObserver }) {
availabilityObservers.append(BKWeakAvailabilityObserver(availabilityObserver: availabilityObserver))
}
}

/**
Remove an availability observer. If the observer isn't subscribed the call will be ignored.
- parameter availabilityObserver: The availability observer to remove.
*/
Remove an availability observer. If the observer isn't subscribed the call will be ignored.
- parameter availabilityObserver: The availability observer to remove.
*/
func removeAvailabilityObserver(_ availabilityObserver: BKAvailabilityObserver) {
if availabilityObservers.contains(where: { $0.availabilityObserver === availabilityObserver }) {
availabilityObservers.remove(at: availabilityObservers.index(where: { $0 === availabilityObserver })!)
}
}

}

/**
Observers of Bluetooth LE availability should implement this protocol.
*/
Observers of Bluetooth LE availability should implement this protocol.
*/
public protocol BKAvailabilityObserver: class {

/**
Informs the observer about a change in Bluetooth LE availability.
- parameter availabilityObservable: The object that registered the availability change.
- parameter availability: The new availability value.
*/
Informs the observer about a change in Bluetooth LE availability.
- parameter availabilityObservable: The object that registered the availability change.
- parameter availability: The new availability value.
*/
func availabilityObserver(_ availabilityObservable: BKAvailabilityObservable, availabilityDidChange availability: BKAvailability)

/**
Informs the observer that the cause of Bluetooth LE unavailability changed.
- parameter availabilityObservable: The object that registered the cause change.
- parameter unavailabilityCause: The new cause of unavailability.
*/
Informs the observer that the cause of Bluetooth LE unavailability changed.
- parameter availabilityObservable: The object that registered the cause change.
- parameter unavailabilityCause: The new cause of unavailability.
*/
func availabilityObserver(_ availabilityObservable: BKAvailabilityObservable, unavailabilityCauseDidChange unavailabilityCause: BKUnavailabilityCause)
}
Loading