Skip to content

Instantly share code, notes, and snippets.

@ankitthakur
Last active February 9, 2017 23:35
Show Gist options
  • Save ankitthakur/7a5d7ea85d398fba3d33 to your computer and use it in GitHub Desktop.
Save ankitthakur/7a5d7ea85d398fba3d33 to your computer and use it in GitHub Desktop.
Apple HomeKit Utilities
//
// 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