Add PromiseKit dependency
- Added PromiseKit dependency
This commit is contained in:
78
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMAcessoryBrowser+Promise.swift
vendored
Normal file
78
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMAcessoryBrowser+Promise.swift
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import Foundation
|
||||
import HomeKit
|
||||
#if !PMKCocoaPods
|
||||
import PromiseKit
|
||||
#endif
|
||||
|
||||
#if !os(tvOS) && !os(watchOS)
|
||||
|
||||
public enum HMPromiseAccessoryBrowserError: Error {
|
||||
case noAccessoryFound
|
||||
}
|
||||
|
||||
public class HMPromiseAccessoryBrowser {
|
||||
private var proxy: BrowserProxy?
|
||||
|
||||
public func start(scanInterval: ScanInterval) -> Promise<[HMAccessory]> {
|
||||
proxy = BrowserProxy(scanInterval: scanInterval)
|
||||
return proxy!.promise
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
proxy?.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private class BrowserProxy: PromiseProxy<[HMAccessory]>, HMAccessoryBrowserDelegate {
|
||||
let browser = HMAccessoryBrowser()
|
||||
let scanInterval: ScanInterval
|
||||
|
||||
init(scanInterval: ScanInterval) {
|
||||
self.scanInterval = scanInterval
|
||||
super.init()
|
||||
|
||||
browser.delegate = self;
|
||||
browser.startSearchingForNewAccessories()
|
||||
|
||||
//if we have a timeout, set it up
|
||||
var timeout: TimeInterval? = nil
|
||||
switch scanInterval {
|
||||
case .returnAll(let interval): timeout = interval
|
||||
case .returnFirst(let interval): timeout = interval
|
||||
}
|
||||
|
||||
if let timeout = timeout {
|
||||
after(seconds: timeout)
|
||||
.done { [weak self] () -> Void in
|
||||
guard let _self = self else { return }
|
||||
_self.reject(HMPromiseAccessoryBrowserError.noAccessoryFound)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func fulfill(_ value: [HMAccessory]) {
|
||||
browser.stopSearchingForNewAccessories()
|
||||
super.fulfill(value)
|
||||
}
|
||||
|
||||
override func reject(_ error: Error ) {
|
||||
browser.stopSearchingForNewAccessories()
|
||||
super.reject(error)
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
browser.stopSearchingForNewAccessories()
|
||||
super.cancel()
|
||||
}
|
||||
|
||||
/**
|
||||
HMAccessoryBrowser delegate
|
||||
*/
|
||||
func accessoryBrowser(_ browser: HMAccessoryBrowser, didFindNewAccessory accessory: HMAccessory) {
|
||||
if case .returnFirst = scanInterval {
|
||||
fulfill([accessory])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMCharacteristic+Promise.swift
vendored
Normal file
46
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMCharacteristic+Promise.swift
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import Foundation
|
||||
import HomeKit
|
||||
#if !PMKCocoaPods
|
||||
import PromiseKit
|
||||
#endif
|
||||
|
||||
public enum AccessoryError: Error {
|
||||
case incorrectType
|
||||
case serviceMissing
|
||||
case characteristicMissing
|
||||
}
|
||||
|
||||
@available(iOS 8.0, tvOS 10.0, *)
|
||||
extension HMCharacteristic {
|
||||
/**
|
||||
A simple typesafe promise wrapper around readValue
|
||||
*/
|
||||
public func read<T>() -> Promise<T> {
|
||||
return Promise { seal in
|
||||
self.readValue { error in
|
||||
if let error = error { seal.reject(error) }
|
||||
else if let value = self.value as? T { seal.fulfill(value) }
|
||||
else { seal.reject(AccessoryError.incorrectType) }
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Because type inference is great... until you can't compile (thanks Swift)
|
||||
public func readFloat() -> Promise<Float> { return read() }
|
||||
public func readDouble() -> Promise<Double> { return read() }
|
||||
public func readInt() -> Promise<Int> { return read() }
|
||||
public func readString() -> Promise<String> { return read() }
|
||||
|
||||
/**
|
||||
A simple promise wrapper around writeValue
|
||||
*/
|
||||
public func write(_ value: Any?) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.writeValue(value, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
/// Explicit is good
|
||||
public func writeFloat(_ value: Float) -> Promise<Void> { return write(value) }
|
||||
public func writeDouble(_ value: Double) -> Promise<Void> { return write(value) }
|
||||
public func writeInt(_ value: Int) -> Promise<Void> { return write(value) }
|
||||
public func writeString(_ value: String) -> Promise<Void> { return write(value) }
|
||||
}
|
||||
82
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMHome+Promise.swift
vendored
Normal file
82
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMHome+Promise.swift
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import Foundation
|
||||
import HomeKit
|
||||
#if !PMKCocoaPods
|
||||
import PromiseKit
|
||||
#endif
|
||||
|
||||
#if !os(tvOS) && !os(watchOS)
|
||||
|
||||
extension HMHome {
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func updateName(_ name: String) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.updateName(name, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add and setup a new HMAccessory. Displays it's own UI
|
||||
@available(iOS 11.3, *)
|
||||
public func addAndSetupAccessories(with payload: HMAccessorySetupPayload) -> Promise<[HMAccessory]> {
|
||||
return Promise { seal in
|
||||
self.addAndSetupAccessories(with: payload, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add and setup a new HMAccessory. Displays it's own UI
|
||||
@available(iOS 10.0, *)
|
||||
public func addAndSetupAccessories() -> Promise<[HMAccessory]> {
|
||||
// We need to compare what we have before the action to after to know what is new
|
||||
let beforeAccessories = self.accessories
|
||||
let home = self
|
||||
|
||||
return Promise { seal in
|
||||
self.addAndSetupAccessories { error in
|
||||
if let error = error { seal.reject(error) }
|
||||
else {
|
||||
let newAccessories = home.accessories.filter { beforeAccessories.contains($0) == false }
|
||||
seal.fulfill(newAccessories)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func addAccessory(_ accessory: HMAccessory) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.addAccessory(accessory, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func assignAccessory(_ accessory: HMAccessory, to room: HMRoom) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.assignAccessory(accessory, to: room, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func removeAccessory(_ accessory: HMAccessory) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.removeAccessory(accessory, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Rooms
|
||||
*/
|
||||
@available(iOS 8.0, *)
|
||||
public func addRoom(withName name: String) -> Promise<HMRoom> {
|
||||
return Promise { seal in
|
||||
self.addRoom(withName: name, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func removeRoom(_ room: HMRoom) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.removeRoom(room, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
62
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMHomeManager+Promise.swift
vendored
Normal file
62
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/HMHomeManager+Promise.swift
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import Foundation
|
||||
#if !PMKCocoaPods
|
||||
import PromiseKit
|
||||
#endif
|
||||
import HomeKit
|
||||
|
||||
@available(iOS 8.0, tvOS 10.0, *)
|
||||
public enum HomeKitError: Error {
|
||||
case permissionDeined
|
||||
}
|
||||
|
||||
@available(iOS 8.0, tvOS 10.0, *)
|
||||
extension HMHomeManager {
|
||||
public func homes() -> Promise<[HMHome]> {
|
||||
return HMHomeManagerProxy().promise
|
||||
}
|
||||
|
||||
#if !os(tvOS) && !os(watchOS)
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func addHome(withName name: String) -> Promise<HMHome> {
|
||||
return Promise { seal in
|
||||
self.addHome(withName: name, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func removeHome(_ home: HMHome) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.removeHome(home, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public func updatePrimaryHome(_ home: HMHome) -> Promise<Void> {
|
||||
return Promise { seal in
|
||||
self.updatePrimaryHome(home, completionHandler: seal.resolve)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@available(iOS 8.0, tvOS 10.0, *)
|
||||
internal class HMHomeManagerProxy: PromiseProxy<[HMHome]>, HMHomeManagerDelegate {
|
||||
|
||||
fileprivate let manager: HMHomeManager
|
||||
|
||||
override init() {
|
||||
self.manager = HMHomeManager()
|
||||
super.init()
|
||||
self.manager.delegate = self
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 20.0) { [weak self] in
|
||||
self?.reject(HomeKitError.permissionDeined)
|
||||
}
|
||||
}
|
||||
|
||||
func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
|
||||
fulfill(manager.homes)
|
||||
}
|
||||
}
|
||||
45
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/Utils.swift
vendored
Normal file
45
Carthage/Checkouts/PromiseKit/Extensions/HomeKit/Sources/Utils.swift
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
#if !PMKCocoaPods
|
||||
import PromiseKit
|
||||
#endif
|
||||
|
||||
/**
|
||||
Commonly used functionality when promisifying a delegate pattern
|
||||
*/
|
||||
internal class PromiseProxy<T>: NSObject {
|
||||
internal let (promise, seal) = Promise<T>.pending();
|
||||
|
||||
private var retainCycle: PromiseProxy?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
// Create a retain cycle
|
||||
self.retainCycle = self
|
||||
// And ensure we break it when the promise is resolved
|
||||
_ = promise.ensure { self.retainCycle = nil }
|
||||
}
|
||||
|
||||
/// These functions ensure we only resolve the promise once
|
||||
internal func fulfill(_ value: T) {
|
||||
guard self.promise.isResolved == false else { return }
|
||||
seal.fulfill(value)
|
||||
}
|
||||
internal func reject(_ error: Error) {
|
||||
guard self.promise.isResolved == false else { return }
|
||||
seal.reject(error)
|
||||
}
|
||||
|
||||
/// Cancel helper
|
||||
internal func cancel() {
|
||||
self.reject(PMKError.cancelled)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Different ways to scan.
|
||||
*/
|
||||
public enum ScanInterval {
|
||||
// Return after our first item with an optional time limit
|
||||
case returnFirst(timeout: TimeInterval?)
|
||||
// Scan for this duration before returning all
|
||||
case returnAll(interval: TimeInterval)
|
||||
}
|
||||
Reference in New Issue
Block a user