Last active
February 9, 2017 23:35
-
-
Save ankitthakur/7a5d7ea85d398fba3d33 to your computer and use it in GitHub Desktop.
Apple HomeKit Utilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AppleHomeKitUtilities.swift | |
// AppleHomeKit | |
// | |
// Created by Ankit Thakur on 2/7/15. | |
// Copyright (c) 2015 Ankit Thakur. All rights reserved. | |
// | |
import UIKit | |
import HomeKit | |
import Darwin | |
let HomeKitServiceTypes = [ | |
HMServiceTypeLightbulb:"Light Bulb", | |
HMServiceTypeSwitch:"Switch", | |
HMServiceTypeThermostat:"Thermostat", | |
HMServiceTypeGarageDoorOpener:"Garage Door Opener", | |
HMServiceTypeAccessoryInformation:"Accessory Information", | |
HMServiceTypeFan:"Fan", | |
HMServiceTypeOutlet:"Outlet", | |
HMServiceTypeLockMechanism:"Lock Mechanism", | |
HMServiceTypeLockManagement:"Lock Management"] | |
let HomeKitCharacteristicTypes = [ | |
HMCharacteristicTypePowerState:"Power State", | |
HMCharacteristicTypeHue:"Hue", | |
HMCharacteristicTypeSaturation:"Saturation", | |
HMCharacteristicTypeBrightness:"Brightness", | |
HMCharacteristicTypeTemperatureUnits:"Temperature Units", | |
HMCharacteristicTypeCurrentTemperature:"Current Temperature", | |
HMCharacteristicTypeTargetTemperature:"Target Temperature", | |
HMCharacteristicTypeCurrentHeatingCooling:"Current Heating Cooling", | |
HMCharacteristicTypeTargetHeatingCooling:"Target Heating Cooling", | |
HMCharacteristicTypeCoolingThreshold:"Cooling Threshold", | |
HMCharacteristicTypeHeatingThreshold:"Heating Threshold", | |
HMCharacteristicTypeCurrentRelativeHumidity:"Current Relative Humidity", | |
HMCharacteristicTypeTargetRelativeHumidity:"Target Relative Humidity", | |
HMCharacteristicTypeCurrentDoorState:"Current Door State", | |
HMCharacteristicTypeTargetDoorState:"Target Door State", | |
HMCharacteristicTypeObstructionDetected:"Obstruction Detected", | |
HMCharacteristicTypeName:"Name", | |
HMCharacteristicTypeManufacturer:"Manufacturer", | |
HMCharacteristicTypeModel:"Model", | |
HMCharacteristicTypeSerialNumber:"Serial Number", | |
HMCharacteristicTypeIdentify:"Identify", | |
HMCharacteristicTypeRotationDirection:"Rotation Direction", | |
HMCharacteristicTypeRotationSpeed:"Rotation Speed", | |
HMCharacteristicTypeOutletInUse:"Outlet In Use", | |
HMCharacteristicTypeVersion:"Version", | |
HMCharacteristicTypeLogs:"Logs", | |
HMCharacteristicTypeAudioFeedback:"Audio Feedback", | |
HMCharacteristicTypeAdminOnlyAccess:"Admin Only Access", | |
HMCharacteristicTypeMotionDetected:"Motion Detected", | |
HMCharacteristicTypeCurrentLockMechanismState:"Current Lock Mechanism State", | |
HMCharacteristicTypeTargetLockMechanismState:"Target Lock Mechanism State", | |
HMCharacteristicTypeLockMechanismLastKnownAction:"Lock Mechanism Last Known Action", | |
HMCharacteristicTypeLockManagementControlPoint:"Lock Management Control Point", | |
HMCharacteristicTypeLockManagementAutoSecureTimeout:"Lock Management Auto Secure Timeout" | |
] | |
typealias AddHomeObservingCallback = (home: HMHome!) -> Void | |
typealias RemoveHomeObservingCallback = () -> Void | |
typealias UpdateHomeObservingCallback = () -> Void | |
typealias AddRoomObservingCallback = (Room: HMRoom!) -> Void | |
typealias RemoveRoomObservingCallback = () -> Void | |
typealias UpdateRoomObservingCallback = () -> Void | |
typealias AddSceneObservingCallback = (scene: HMActionSet!) -> Void | |
typealias RemoveSceneObservingCallback = () -> Void | |
typealias UpdateSceneObservingCallback = () -> Void | |
typealias AddAccessoriesObservingCallback = (accessory: HMAccessory!) -> Void | |
typealias RemoveAccessoriesObservingCallback = () -> Void | |
typealias UpdateAccessoriesObservingCallback = () -> Void | |
class AppleHomeKitUtilities: NSObject, HMHomeManagerDelegate, HMHomeDelegate, HMAccessoryBrowserDelegate, HMAccessoryDelegate, GeofenceViewControllerDelegate { | |
var homeManager = HMHomeManager(); | |
var accessoryBrowser: HMAccessoryBrowser = HMAccessoryBrowser(); | |
var phHueSDK:PHHueSDK?; | |
var phNotificationManager:PHNotificationManager = PHNotificationManager.defaultManager(); | |
var bridgeSearch:PHBridgeSearching? | |
var phResourcesCache:PHBridgeResourcesCache?; | |
var bridgesFound:Dictionary<String, String>?; | |
var homes:Array<HMHome> = []; | |
var accessories:Array<HMAccessory> = []; | |
var phAccessories:Array<PHLight> = []; | |
var selectedPhAccessories:Array<PHLight> = []; | |
var selectedHome:HMHome?; | |
var selectedRoom:HMRoom?; | |
var selectedAccessory:HMAccessory?; | |
var selectedPhAccessory:PHLight?; | |
var selectedService:HMService?; | |
var selectedScene:HMActionSet?; | |
var addHomeCallback: AddHomeObservingCallback? | |
var removeHomeCallback: RemoveHomeObservingCallback? | |
var updateHomeCallback: UpdateHomeObservingCallback? | |
var addRoomCallback: AddRoomObservingCallback? | |
var removeRoomCallback: RemoveRoomObservingCallback? | |
var updateRoomCallback: UpdateRoomObservingCallback? | |
var addSceneCallback: AddSceneObservingCallback? | |
var removeSceneCallback: RemoveSceneObservingCallback? | |
var updateSceneCallback: UpdateSceneObservingCallback? | |
var addAccessoriesCallback: AddAccessoriesObservingCallback? | |
var removeAccessoriesCallback: RemoveAccessoriesObservingCallback? | |
var updateAccessoriesCallback: UpdateAccessoriesObservingCallback? | |
var geoFenceController:GeofenceViewController?; | |
// singleton | |
class var sharedInstance: AppleHomeKitUtilities { | |
struct Static { | |
static var instance: AppleHomeKitUtilities? | |
static var token: dispatch_once_t = 0 | |
} | |
dispatch_once(&Static.token) { | |
Static.instance = AppleHomeKitUtilities() | |
} | |
return Static.instance! | |
} | |
func initializeHomeKit(){ | |
var timer = NSTimer(timeInterval: 10, target: self, selector: Selector("loadConnectedBridgeValues"), userInfo: nil, repeats: true); | |
timer.fire(); | |
println("initializeHomeKit"); | |
self.homeManager.delegate = self; | |
self.homes.removeAll(keepCapacity: false); | |
for home in homeManager.homes{ | |
self.homes.append(home as! HMHome); | |
} | |
self.accessoryBrowser.delegate = self; | |
self.accessoryBrowser.startSearchingForNewAccessories(); | |
geoFenceController = GeofenceViewController.sharedInstance; | |
geoFenceController?.geofenceDelegate = self; | |
geoFenceController!.initializeGeoFenceKit(); | |
self.initializePHHueSDK(); | |
} | |
func livingRoomAction(){ | |
self.loadConnectedBridgeValues(); | |
if(self.phAccessories.count > 0){ | |
var bridgeSendAPI = PHBridgeSendAPI(); | |
var light:PHLight = self.phAccessories[0] as PHLight; | |
var lightState:PHLightState = light.lightState; | |
lightState.on = NSNumber(bool: true); | |
lightState.x = NSNumber(float: NSUserDefaults.standardUserDefaults().floatForKey("xValue")) | |
lightState.y = NSNumber(float: NSUserDefaults.standardUserDefaults().floatForKey("yValue")) | |
// lightState.x = NSNumber(float: Float(0.167)); | |
// lightState.x = NSNumber(float: Float(0.400)); | |
bridgeSendAPI.updateLightStateForId(light.identifier, withLightState: lightState, completionHandler: { (errors:[AnyObject]!) -> Void in | |
println(errors); | |
if(errors != nil){ | |
println("error -> \(errors)"); | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "Please check Philips Hue Light for living room" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
else{ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "Philips Hue Light is executed for living room" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
}) | |
} | |
} | |
func didEnterBeaconRegion() { | |
self.loadConnectedBridgeValues(); | |
if(self.phAccessories.count > 0){ | |
var bridgeSendAPI = PHBridgeSendAPI(); | |
var light:PHLight = self.phAccessories[0] as PHLight; | |
var lightState:PHLightState = light.lightState; | |
lightState.on = NSNumber(bool: true); | |
bridgeSendAPI.updateLightStateForId(light.identifier, withLightState: lightState, completionHandler: { (errors:[AnyObject]!) -> Void in | |
println(errors); | |
if(errors != nil){ | |
println("error -> \(errors)"); | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "Please check Philips Hue Light for enter zone" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
else{ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "Philips Hue Light is executed for enter zone" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
}) | |
} | |
if(AppleHomeKitUtilities.sharedInstance.homeManager.homes.count > 0){ | |
var scenes = AppleHomeKitUtilities.sharedInstance.homeManager.primaryHome!.actionSets as! Array<HMActionSet>; | |
var isSceneExecuted = false; | |
for scene in scenes{ | |
if(scene.name == "Entry Scene"){ | |
isSceneExecuted = true; | |
AppleHomeKitUtilities.sharedInstance.homeManager.primaryHome!.executeActionSet(scene, completionHandler: { (error:NSError!) -> Void in | |
if(error != nil){ | |
println("error -> \(error)"); | |
var alertView:UIAlertView = UIAlertView(title: "", message:error?.localizedDescription, delegate: nil, cancelButtonTitle: "Ok"); | |
alertView.show(); | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = error?.localizedDescription | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
else{ | |
var alertView:UIAlertView = UIAlertView(title: "", message:"'Entry Scene' is successfully executed", delegate: nil, cancelButtonTitle: "Ok"); | |
alertView.show(); | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "'Entry Scene' is successfully executed" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
}); | |
break; | |
} | |
} | |
if(isSceneExecuted == false){ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "'Entry Scene' is not set" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
var alertView:UIAlertView = UIAlertView(title: "", message:"'Entry Scene' is not set", delegate: nil, cancelButtonTitle: "Ok"); | |
// alertView.show(); | |
} | |
} | |
else{ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "No Homes are available" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
} | |
func didExitBeaconRegion() { | |
self.loadConnectedBridgeValues(); | |
if(self.phAccessories.count > 0){ | |
var bridgeSendAPI = PHBridgeSendAPI(); | |
var light:PHLight = self.phAccessories[0] as PHLight; | |
var lightState:PHLightState = light.lightState; | |
lightState.on = NSNumber(bool: false); | |
bridgeSendAPI.updateLightStateForId(light.identifier, withLightState: lightState, completionHandler: { (errors:[AnyObject]!) -> Void in | |
println(errors); | |
if(errors != nil){ | |
println("error -> \(errors)"); | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "Please check Philips Hue Light for exit zone" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
else{ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "Philips Hue Light is executed for exit zone" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
}) | |
} | |
if(AppleHomeKitUtilities.sharedInstance.homeManager.homes.count > 0){ | |
var scenes = AppleHomeKitUtilities.sharedInstance.homeManager.primaryHome!.actionSets as! Array<HMActionSet>; | |
var isSceneExecuted = false; | |
for scene in scenes{ | |
if(scene.name == "Elicia's Exit Scene"){ | |
isSceneExecuted = true; | |
AppleHomeKitUtilities.sharedInstance.homeManager.primaryHome!.executeActionSet(scene, completionHandler: { (error:NSError!) -> Void in | |
if(error != nil){ | |
println("error -> \(error)"); | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = error?.localizedDescription | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
else{ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "'Exit Scene' is successfully executed" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
}); | |
break; | |
} | |
} | |
if(isSceneExecuted == false){ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "'Exit Scene' is not set" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
} | |
else{ | |
let notification: UILocalNotification = UILocalNotification() | |
notification.timeZone = NSTimeZone.defaultTimeZone() | |
let dateTime = NSDate() | |
notification.fireDate = dateTime | |
notification.alertBody = "No Homes are available" | |
UIApplication.sharedApplication().scheduleLocalNotification(notification) | |
} | |
} | |
func addHome(homeName:String!, completionHandler completion: ((Bool, NSError?) -> Void)!){ | |
println("ADD HOME"); | |
homeManager.addHomeWithName(homeName, completionHandler: { (home:HMHome!, error:NSError!) -> Void in | |
if(error != nil){ | |
println(error); | |
completion(false, error); | |
} | |
else{ | |
var filteredHomes = self.homes.filter { (_home) -> Bool in | |
_home.name == home.name; | |
}; | |
if(filteredHomes.count > 0){ | |
var index:Int? = self.homes.indexOf(filteredHomes.last!); | |
if(index == nil){ | |
self.homes.append(home); | |
} | |
else{ | |
self.homes[index!] = home; | |
} | |
} | |
else{ | |
self.homes.append(home); | |
} | |
completion(true, nil); | |
} | |
}) | |
} | |
func addRoom(roomName:String!, completionHandler completion: ((Bool, NSError?) -> Void)!){ | |
println("ADD ROOM"); | |
self.selectedHome!.addRoomWithName(roomName, completionHandler: { (room:HMRoom!, error:NSError!) -> Void in | |
if(error != nil){ | |
completion(false, error); | |
} | |
else{ | |
completion(true, nil); | |
} | |
}); | |
} | |
func addAccessoryInCurrentHomeWithCompletion(completion: ((Bool, NSError?) -> Void)!) { | |
println("ADD ACCESSORY"); | |
self.selectedHome?.addAccessory(self.selectedAccessory, completionHandler: { (error:NSError!) -> Void in | |
if(error != nil){ | |
completion(false, error); | |
println(error); | |
} | |
else{ | |
println("success"); | |
completion(true, nil); | |
} | |
}) | |
} | |
func addScene(sceneName:String!, withAccessories sceneCharacteristics:Array<HMCharacteristic>, completionHandler completion: ((Bool, NSError?) -> Void)!){ | |
self.selectedHome?.addActionSetWithName(sceneName, completionHandler: { (actionSet:HMActionSet!, sceneError:NSError!) -> Void in | |
if(sceneError != nil){ | |
completion(false, sceneError); | |
} | |
else{ | |
var scene = actionSet; | |
var totalCharacteristicsCount = 0; | |
var errorMessage:String = ""; | |
for characteristic in sceneCharacteristics { | |
println(characteristic); | |
var characteristicAction:HMCharacteristicWriteAction? | |
switch(characteristic.metadata.format as NSString){ | |
case HMCharacteristicMetadataFormatBool: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:characteristic.value.boolValue); | |
break; | |
case HMCharacteristicMetadataFormatString: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:characteristic.value); | |
break; | |
case HMCharacteristicMetadataFormatInt: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:NSNumber(integer: characteristic.value.integerValue)); | |
break; | |
case HMCharacteristicMetadataFormatUInt8: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:NSNumber(unsignedChar: characteristic.value.unsignedCharValue)); | |
break; | |
case HMCharacteristicMetadataFormatUInt16: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:NSNumber(unsignedShort: characteristic.value.unsignedShortValue)); | |
break; | |
case HMCharacteristicMetadataFormatUInt32: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:NSNumber(unsignedInt: characteristic.value.unsignedIntValue)); | |
break; | |
case HMCharacteristicMetadataFormatUInt64: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:NSNumber(unsignedLongLong: characteristic.value.unsignedLongLongValue)); | |
break; | |
case HMCharacteristicMetadataFormatFloat: | |
characteristicAction = HMCharacteristicWriteAction(characteristic: characteristic, targetValue:NSNumber(float: characteristic.value.floatValue)); | |
break; | |
default: | |
println("invalid format:\(characteristic.metadata.format)"); | |
break; | |
} | |
println("format:\(characteristic.metadata.format) -> \(HomeKitCharacteristicTypes[characteristic.characteristicType]) -> \(characteristicAction) -> \(characteristic.value)"); | |
if(characteristicAction != nil){ | |
totalCharacteristicsCount++; | |
scene.addAction(characteristicAction, completionHandler: { (error:NSError!) -> Void in | |
if(error != nil){ | |
println("\(HomeKitCharacteristicTypes[characteristic.characteristicType]) -> \(error.localizedDescription)"); | |
errorMessage = errorMessage + "\n \(HomeKitCharacteristicTypes[characteristic.characteristicType]) -> \(error.localizedDescription)"; | |
} | |
else{ | |
println("\(HomeKitCharacteristicTypes[characteristic.characteristicType]) -> success"); | |
} | |
totalCharacteristicsCount--; | |
if(totalCharacteristicsCount == 0){ | |
if(errorMessage.isEmpty){ | |
completion(true, nil); | |
} | |
else{ | |
var errorInfo:Dictionary = Dictionary(dictionaryLiteral:("localizedDescription", errorMessage)); | |
var sError = NSError(domain: "Add Scene Error", code: 111, userInfo: errorInfo); | |
completion(false, sError); | |
} | |
} | |
}) | |
} | |
} | |
} | |
}) | |
} | |
func isPrimaryHomeExist(homeName:String!) -> Bool{ | |
var isPrimaryHomeExist:Bool = false; | |
if(homeManager.primaryHome != nil){ | |
if(homeManager.primaryHome.name == homeName){ | |
isPrimaryHomeExist = true; | |
} | |
} | |
else{ | |
isPrimaryHomeExist = false; | |
} | |
return isPrimaryHomeExist; | |
} | |
func homeManagerDidUpdateHomes(manager: HMHomeManager){ | |
self.homes.removeAll(); | |
for home in manager.homes{ | |
self.homes.append(home as! HMHome); | |
} | |
self.homes.sort { (home1: HMHome, home2: HMHome) -> Bool in | |
return (home1.name < home1.name) | |
}; | |
if(self.updateHomeCallback != nil){ | |
self.updateHomeCallback!(); | |
} | |
} | |
func homeManager(manager: HMHomeManager, didAddHome home: HMHome!){ | |
var filteredHomes = self.homes.filter { (_home) -> Bool in | |
_home.name == home.name; | |
}; | |
if(filteredHomes.count > 0){ | |
var index:Int? = self.homes.indexOf(filteredHomes.last!); | |
if(index == nil){ | |
self.homes.append(home); | |
} | |
else{ | |
self.homes[index!] = home; | |
} | |
} | |
else{ | |
self.homes.append(home); | |
} | |
if(self.addHomeCallback != nil){ | |
self.addHomeCallback!(home: home); | |
} | |
println("manager didAddHome : \(self.homes)"); | |
} | |
func homeManager(manager: HMHomeManager, didRemoveHome home: HMHome!){ | |
self.homes.removeObject(home); | |
if(self.removeHomeCallback != nil){ | |
self.removeHomeCallback!(); | |
} | |
println("manager didRemoveHome : \(self.homes)"); | |
} | |
// accessory browser delegates | |
func accessoryBrowser(browser: HMAccessoryBrowser, didFindNewAccessory accessory: HMAccessory!){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
if(accessory.reachable == true){ | |
accessory.delegate = self; | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
} | |
} | |
func accessoryBrowser(browser: HMAccessoryBrowser, didRemoveNewAccessory accessory: HMAccessory!){ | |
println("didRemoveNewAccessory -> ", accessory.services); | |
accessory.delegate = nil; | |
self.accessories.removeObject(accessory); | |
if(self.updateAccessoriesCallback != nil){ | |
self.updateAccessoriesCallback!(); | |
} | |
println("browser didRemoveNewAccessory : \(self.accessories)"); | |
} | |
// accessory delegates | |
func accessoryDidUpdateName(accessory: HMAccessory){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
println("accessoryDidUpdateName : \(self.accessories)"); | |
} | |
func accessory(accessory: HMAccessory, didUpdateNameForService service: HMService!){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
println("accessory didUpdateNameForService : \(self.accessories)"); | |
} | |
func accessory(accessory: HMAccessory, didUpdateAssociatedServiceTypeForService service: HMService!){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
println("accessory didUpdateAssociatedServiceTypeForService : \(self.accessories)"); | |
} | |
func accessoryDidUpdateServices(accessory: HMAccessory){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
if(accessory.reachable == true){ | |
accessory.delegate = self; | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
} | |
} | |
func accessoryDidUpdateReachability(accessory: HMAccessory){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
if(accessory.reachable == true){ | |
accessory.delegate = self; | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
} | |
} | |
func accessory(accessory: HMAccessory, service: HMService!, didUpdateValueForCharacteristic characteristic: HMCharacteristic!){ | |
self.accessories.removeAll(); | |
for discoveredAccessory in self.accessoryBrowser.discoveredAccessories{ | |
if(accessory.reachable == true){ | |
accessory.delegate = self; | |
self.accessories.append(discoveredAccessory as! HMAccessory); | |
} | |
} | |
} | |
////////////////////////////////////////////////////////////// | |
///////////// Philips Hue Light SDK ///////////////////////// | |
////////////////////////////////////////////////////////////// | |
func initializePHHueSDK(){ | |
self.phHueSDK = PHHueSDK(); | |
self.phHueSDK!.startUpSDK(); | |
self.phHueSDK!.enableLogging(true); | |
self.registerPHHueSDKNotifications(); | |
self.enableLocalHeartbeat(); | |
} | |
func registerPHHueSDKNotifications(){ | |
self.phNotificationManager.registerObject(self, withSelector: Selector("checkConnectionState"), forNotification: LOCAL_CONNECTION_NOTIFICATION); | |
self.phNotificationManager.registerObject(self, withSelector: Selector("noLocalConnection"), forNotification: NO_LOCAL_CONNECTION_NOTIFICATION); | |
self.phNotificationManager.registerObject(self, withSelector: Selector("notAuthenticated"), forNotification: NO_LOCAL_AUTHENTICATION_NOTIFICATION); | |
self.phNotificationManager.registerObject(self, withSelector: Selector("authenticationSuccess"), forNotification: PUSHLINK_LOCAL_AUTHENTICATION_SUCCESS_NOTIFICATION); | |
self.phNotificationManager.registerObject(self, withSelector: Selector("authenticationFailed"), forNotification: PUSHLINK_LOCAL_AUTHENTICATION_FAILED_NOTIFICATION); | |
self.phNotificationManager.registerObject(self, withSelector: Selector("noLocalBridge"), forNotification: PUSHLINK_NO_LOCAL_BRIDGE_KNOWN_NOTIFICATION); | |
self.phNotificationManager.registerObject(self, withSelector: Selector("buttonNotPressed:"), forNotification: PUSHLINK_BUTTON_NOT_PRESSED_NOTIFICATION); | |
} | |
func checkConnectionState() { | |
if (self.phHueSDK!.localConnected() == false) { | |
// Dismiss modal views when connection is lost | |
println ("No connection at all"); | |
// No connection at all, show connection popup | |
} | |
else { | |
println ("One of the connections is made"); | |
// One of the connections is made, remove popups and loading views | |
} | |
} | |
/** | |
Starts the local heartbeat with a 10 second interval | |
*/ | |
func enableLocalHeartbeat() { | |
/*************************************************** | |
The heartbeat processing collects data from the bridge | |
so now try to see if we have a bridge already connected | |
*****************************************************/ | |
self.phResourcesCache = PHBridgeResourcesReader.readBridgeResourcesCache(); | |
if self.phResourcesCache == nil { | |
// Automaticly start searching for bridges | |
self.searchForBridgeLocal(); | |
} | |
else{ | |
if self.phResourcesCache!.bridgeConfiguration != nil && self.phResourcesCache!.bridgeConfiguration.ipaddress != nil { | |
println("connecting"); | |
// Enable heartbeat with interval of 10 seconds | |
self.phHueSDK?.enableLocalConnection(); | |
} | |
else{ | |
// Automaticly start searching for bridges | |
self.searchForBridgeLocal(); | |
} | |
} | |
} | |
func disableLocalHeartbeat() { | |
self.phHueSDK?.disableLocalConnection(); | |
} | |
func searchForBridgeLocal(){ | |
self.disableLocalHeartbeat(); | |
self.bridgeSearch = PHBridgeSearching(upnpSearch: true, andPortalSearch: true, andIpAdressSearch: true); | |
self.bridgeSearch!.startSearchWithCompletionHandler({ bridgesFound -> Void in | |
println(bridgesFound); | |
if bridgesFound.count > 0 { | |
// Get mac address and ip address of selected bridge | |
self.bridgesFound = bridgesFound as? Dictionary<String, String>; | |
var macAddress:String = self.bridgesFound!.keys.first!; | |
var ipAddress:String = self.bridgesFound![macAddress]!; | |
self.phHueSDK?.setBridgeToUseWithIpAddress(ipAddress, macAddress: macAddress); | |
self.startBridgeAuthentication(); | |
println(self.bridgesFound); | |
} | |
else { | |
// No bridges were found | |
self.bridgesFound = nil; | |
self.searchForBridgeLocal(); | |
} | |
}) | |
} | |
func loadConnectedBridgeValues(){ | |
/*************************************************** | |
The heartbeat processing collects data from the bridge | |
so now try to see if we have a bridge already connected | |
*****************************************************/ | |
if(self.phHueSDK != nil){ | |
self.phResourcesCache = PHBridgeResourcesReader.readBridgeResourcesCache(); | |
if self.phResourcesCache == nil { | |
// Automaticly start searching for bridges | |
self.searchForBridgeLocal(); | |
} | |
else{ | |
if self.phResourcesCache!.bridgeConfiguration != nil && self.phResourcesCache!.bridgeConfiguration.ipaddress != nil { | |
self.phAccessories.removeAll(keepCapacity: false); | |
if(self.phResourcesCache!.lights != nil){ | |
for object in self.phResourcesCache!.lights { | |
var light:PHLight = object.1 as! PHLight; | |
if(light.lightState.reachable.boolValue){ | |
println(light); | |
self.phAccessories.append(light); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
// Check if we have connected to a bridge before | |
// bridge authentication | |
func startBridgeAuthentication(){ | |
var alertView:UIAlertView = UIAlertView(title: "", message:"Please click Bridge Button for authentication", delegate: nil, cancelButtonTitle: "Ok"); | |
alertView.show(); | |
self.phHueSDK?.startPushlinkAuthentication(); | |
} | |
/** | |
Notification receiver which is called when the pushlinking was successful | |
*/ | |
func authenticationSuccess() { | |
/*************************************************** | |
The notification PUSHLINK_LOCAL_AUTHENTICATION_SUCCESS_NOTIFICATION | |
was received. We have confirmed the bridge. | |
De-register for notifications and call | |
pushLinkSuccess on the delegate | |
*****************************************************/ | |
var alertView:UIAlertView = UIAlertView(title: "", message:"Authentication is successful", delegate: nil, cancelButtonTitle: "Ok"); | |
alertView.show(); | |
// Deregister for all notifications | |
self.phNotificationManager.deregisterObjectForAllNotifications(self); | |
self.phResourcesCache = PHBridgeResourcesReader.readBridgeResourcesCache(); | |
if self.phResourcesCache == nil { | |
// Automaticly start searching for bridges | |
self.searchForBridgeLocal(); | |
} | |
else{ | |
println(self.phResourcesCache?.lights); | |
} | |
// Inform delegate | |
// [self.delegate pushlinkSuccess]; | |
} | |
/** | |
Notification receiver which is called when the pushlinking failed because the time limit was reached | |
*/ | |
func authenticationFailed() { | |
var alertView:UIAlertView = UIAlertView(title: "", message:"Authentication failed", delegate: nil, cancelButtonTitle: "Ok"); | |
alertView.show(); | |
// Inform delegate | |
// [self.delegate pushlinkFailed:[PHError errorWithDomain:SDK_ERROR_DOMAIN | |
// code:PUSHLINK_TIME_LIMIT_REACHED | |
// userInfo:[NSDictionary dictionaryWithObject:@"Authentication failed: time limit reached." forKey:NSLocalizedDescriptionKey]]]; | |
} | |
/** | |
Notification receiver which is called when the pushlinking failed because the local connection to the bridge was lost | |
*/ | |
func noLocalConnection() { | |
// Deregister for all notifications | |
// [[PHNotificationManager defaultManager] deregisterObjectForAllNotifications:self]; | |
// | |
// // Inform delegate | |
// [self.delegate pushlinkFailed:[PHError errorWithDomain:SDK_ERROR_DOMAIN | |
// code:PUSHLINK_NO_CONNECTION | |
// userInfo:[NSDictionary dictionaryWithObject:@"Authentication failed: No local connection to bridge." forKey:NSLocalizedDescriptionKey]]]; | |
} | |
/** | |
Notification receiver which is called when the pushlinking failed because we do not know the address of the local bridge | |
*/ | |
func noLocalBridge() { | |
// Deregister for all notifications | |
// [[PHNotificationManager defaultManager] deregisterObjectForAllNotifications:self]; | |
// | |
// // Inform delegate | |
// [self.delegate pushlinkFailed:[PHError errorWithDomain:SDK_ERROR_DOMAIN code:PUSHLINK_NO_LOCAL_BRIDGE userInfo:[NSDictionary dictionaryWithObject:@"Authentication failed: No local bridge found." forKey:NSLocalizedDescriptionKey]]]; | |
} | |
/** | |
This method is called when the pushlinking is still ongoing but no button was pressed yet. | |
@param notification The notification which contains the pushlinking percentage which has passed. | |
*/ | |
func buttonNotPressed(notification:NSNotification) { | |
// Update status bar with percentage from notification | |
// var dict:Dictionary<String, AnyObject> = notification.userInfo; | |
// var progressPercentage: AnyObject? = dict["progressPercentage"]; | |
} | |
// Converts RGB values into normalized [x, y] coordinates for the hue | |
func rgbtoXYZ(red:Float, green:Float, blue:Float) -> (Float, Float){ | |
if(red == 0 && green == 0 && blue == 0) | |
{ | |
NSUserDefaults.standardUserDefaults().setFloat(0.0, forKey: "xValue") | |
NSUserDefaults.standardUserDefaults().setFloat(0.0, forKey: "yValue") | |
// NSUserDefaults.standardUserDefaults().setValue(AppleHomeKitUtilities.sharedInstance.selectedHome?.name, forKey: "home") | |
NSUserDefaults.standardUserDefaults().synchronize() | |
return (Float(0), Float(0)); | |
} | |
var rgb = [ red , green , blue ]; | |
for(var i = 0; i < 3; i++) { | |
if (rgb[i] > 0.04045) { | |
rgb[i] = pow(((rgb[i] + 0.055) / 1.055), 2.4); | |
} else { | |
rgb[i] /= 12.92; | |
} | |
rgb[i] = rgb[i] * 100; | |
} | |
var xyz = [ | |
rgb[0] * 0.4124 + rgb[1] * 0.3576 + rgb[2] * 0.1805, | |
rgb[0] * 0.2126 + rgb[1] * 0.7152 + rgb[2] * 0.0722, | |
rgb[0] * 0.0193 + rgb[1] * 0.1192 + rgb[2] * 0.9505 | |
]; | |
NSUserDefaults.standardUserDefaults().setFloat(xyz[0] / (xyz[0] + xyz[1] + xyz[2]), forKey: "xValue") | |
NSUserDefaults.standardUserDefaults().setFloat(xyz[1] / (xyz[0] + xyz[1] + xyz[2]), forKey: "yValue") | |
// NSUserDefaults.standardUserDefaults().setValue(AppleHomeKitUtilities.sharedInstance.selectedHome?.name, forKey: "home") | |
NSUserDefaults.standardUserDefaults().synchronize() | |
return ( | |
xyz[0] / (xyz[0] + xyz[1] + xyz[2]), | |
xyz[1] / (xyz[0] + xyz[1] + xyz[2]) | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment