Skip to content

Instantly share code, notes, and snippets.

@manchan
Created December 17, 2015 07:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manchan/106f4b6108c737df15dc to your computer and use it in GitHub Desktop.
Save manchan/106f4b6108c737df15dc to your computer and use it in GitHub Desktop.
PhilipsHueSwift
//
// AppDelegate.swift
// PhilipsHueSwift
//
// Created by matz on 2015/11/27.
// Copyright © 2015年 matz. All rights reserved.
//
import UIKit
@objc(AppDelegate)
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UIAlertViewDelegate,
PHBridgeSelectionViewControllerDelegate, PHBridgePushLinkViewControllerDelegate{
var window: UIWindow?
// The Hue SDK is created as a property
var phHueSDK:PHHueSDK?
var loadingView:PHLoadingViewController?
var bridgeSearch:PHBridgeSearching?
var noConnectionAlert:UIAlertView?
var noBridgeFoundAlert:UIAlertView?
var authenticationFailedAlert:UIAlertView?
var pushLinkViewController:PHBridgePushLinkViewController?
var bridgeSelectionViewController:PHBridgeSelectionViewController?
var controlLightsViewController:ViewController?
var navigationController:UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
// Create sdk instance
self.phHueSDK = PHHueSDK()
// next, the startUpSDK call will initialize the SDK and kick off its regular heartbeat timer:
self.phHueSDK?.startUpSDK()
self.phHueSDK?.enableLogging(true)
// Create the main view controller in a navigation controller and make the navigation controller the rootviewcontroller of the app
self.navigationController = UIStoryboard(name: "Main", bundle:nil).instantiateViewControllerWithIdentifier("firstNav") as? UINavigationController
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
let notificationManager:PHNotificationManager = PHNotificationManager.defaultManager()
/***************************************************
The SDK will send the following notifications in response to events:
- LOCAL_CONNECTION_NOTIFICATION
This notification will notify that the bridge heartbeat occurred and the bridge resources cache data has been updated
- NO_LOCAL_CONNECTION_NOTIFICATION
This notification will notify that there is no connection with the bridge
- NO_LOCAL_AUTHENTICATION_NOTIFICATION
This notification will notify that there is no authentication against the bridge
*****************************************************/
notificationManager.registerObject(self, withSelector: Selector("localConnection"), forNotification: LOCAL_CONNECTION_NOTIFICATION)
notificationManager.registerObject(self, withSelector: Selector("noLocalConnection"), forNotification: NO_LOCAL_CONNECTION_NOTIFICATION)
notificationManager.registerObject(self, withSelector: Selector("notAuthenticated"), forNotification: NO_LOCAL_AUTHENTICATION_NOTIFICATION)
/***************************************************
The local heartbeat is a regular timer event in the SDK. Once enabled the SDK regular collects the current state of resources managed
by the bridge into the Bridge Resources Cache
*****************************************************/
self.enableLocalHeartbeat()
// JINS MEME
MEMELib.setAppClientId("********", clientSecret: "********")
NSLog("Please set AppClientId / ClientScecret at developer site");
NSLog("More info at https://developers.jins.com/ja/apps/create/");
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
// Start heartbeat
self.enableLocalHeartbeat()
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
/**
Notification receiver for successful local connection
*/
func localConnection(){
self.checkConnectionState()
}
/**
Notification receiver for failed local connection
*/
func noLocalConnection(){
self.checkConnectionState()
}
/**
Notification receiver for failed local authentication
*/
func notAuthenticated() {
/***************************************************
We are not authenticated so we start the authentication process
*****************************************************/
self.navigationController?.popToRootViewControllerAnimated(true)
// Dismiss modal views when connection is lost
if (self.navigationController?.presentedViewController != nil) {
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
// Remove no connection alert
if self.noConnectionAlert != nil {
self.noConnectionAlert?.dismissWithClickedButtonIndex((self.noConnectionAlert?.cancelButtonIndex)!, animated: true)
self.noConnectionAlert = nil
}
/***************************************************
doAuthentication will start the push linking
*****************************************************/
self.performSelector("doAuthentication", withObject: nil, afterDelay: 0.5)
}
/**
Checks if we are currently connected to the bridge locally and if not, it will show an error when the error is not already shown.
*/
func checkConnectionState(){
if self.phHueSDK?.localConnected() == false {
// Dismiss modal views when connection is lost
if (self.navigationController?.presentedViewController != nil) {
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
// No Connection at all, show connection popup
if self.noConnectionAlert == nil {
self.navigationController?.popToRootViewControllerAnimated(true)
// showing popup, so remove this view
self.removeLoadingView()
self.showNoConnectionDialog()
}
}
else {
// One of the connections is made, remove popups and loading views
if (self.noConnectionAlert != nil) {
self.noConnectionAlert?.dismissWithClickedButtonIndex((self.noConnectionAlert?.cancelButtonIndex)!, animated: true)
self.noConnectionAlert = nil
}
self.removeLoadingView()
}
}
/**
Shows the first no connection alert with more connection options
*/
func showNoConnectionDialog() {
self.noConnectionAlert = UIAlertView(title: "No connection", message: "Connection to bridge is lost", delegate: self, cancelButtonTitle: nil, otherButtonTitles: "Reconnect", "Find new bridge", "Cancel")
self.noConnectionAlert?.tag = 1
self.noConnectionAlert?.show()
}
/**
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
*****************************************************/
let cache:PHBridgeResourcesCache = PHBridgeResourcesReader.readBridgeResourcesCache()
if (cache != false && cache.bridgeConfiguration != nil && cache.bridgeConfiguration.ipaddress != nil) {
self.showLoadingViewWithText("Connecting...")
// Enable heartbeat with interval of 10 seconds
self.phHueSDK?.enableLocalConnection()
}
else{
// Automaticaly start searching for bridges
self.searchForBridgeLocal()
}
}
/**
Stops the local heartbeat
*/
func disableLocalHeartbeat() {
self.phHueSDK?.disableLocalConnection()
}
/**
Search for bridges using UPnP and portal discovery, shows results to user or gives error when none found.
*/
func searchForBridgeLocal(){
// Stop heartbeats
self.disableLocalHeartbeat()
// Show search screen
self.showLoadingViewWithText("Searching...")
/***************************************************
A bridge search is started using UPnP to find local bridges
*****************************************************/
// Start search
self.bridgeSearch = PHBridgeSearching(upnpSearch: true, andPortalSearch: true, andIpAdressSearch: true)
self.bridgeSearch?.startSearchWithCompletionHandler({ (bridgesFound: [NSObject: AnyObject]!) -> Void in
// Done with search, remove loading view
self.removeLoadingView()
/***************************************************
The search is complete, check whether we found a bridge
*****************************************************/
// Check for results
if (bridgesFound.count > 0) {
// Results were found, show options to user (from a user point of view, you should select automatically when there is only one bridge found)
print("bridgesFound:: \(bridgesFound)")
// (UIApplication.sharedApplication().delegate as! AppDelegate).phHueSDK?.setBridgeToUseWithIpAddress("192.168.24.63", macAddress: "00:17:88:11:0d:bf")
self.bridgeSelectionViewController = PHBridgeSelectionViewController(nibName: "PHBridgeSelectionViewController", bundle: NSBundle.mainBundle(), bridges: bridgesFound, delegate: self)
/***************************************************
Use the list of bridges, present them to the user, so one can be selected.
*****************************************************/
let navController:UINavigationController = UINavigationController(rootViewController: self.bridgeSelectionViewController!)
navController.modalPresentationStyle = UIModalPresentationStyle.FormSheet
self.navigationController?.presentViewController(navController, animated: true, completion: nil)
}
else{
/***************************************************
No bridge was found was found. Tell the user and offer to retry..
*****************************************************/
// No bridges were found, show this to the user
self.noBridgeFoundAlert = UIAlertView(title: "No bridges", message: "No bridge found alert title", delegate: self, cancelButtonTitle: nil, otherButtonTitles: "Retry", "Cancel", "No bridge found alert cancel button")
self.noBridgeFoundAlert?.tag = 1
self.noBridgeFoundAlert?.show()
}
})
}
/**
Delegate method for PHbridgeSelectionViewController which is invoked when a bridge is selected
*/
func bridgeSelectedWithIpAddress(ipAddress: String!, andBridgeId bridgeId: String!) {
/***************************************************
Removing the selection view controller takes us to
the 'normal' UI view
*****************************************************/
// Remove the selection view controller
self.bridgeSelectionViewController = nil
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
// Show a connecting view while we try to connect to the bridge
self.showLoadingViewWithText("Connecting...")
// Set SDK to use bridge and our default username (which should be the same across all apps, so pushlinking is only required once)
//NSString *username = [PHUtilities whitelistIdentifier];
/***************************************************
Set the ipaddress and bridge id,
as the bridge properties that the SDK framework will use
*****************************************************/
print("bridgeId です: \(bridgeId)")
print("ipAddress です: \(ipAddress)")
self.phHueSDK?.setBridgeToUseWithId(bridgeId, ipAddress:ipAddress)
// self.phHueSDK?.setBridgeToUseWithIpAddress(bridgeId, macAddress: ipAddress)
/***************************************************
Setting the hearbeat running will cause the SDK
to regularly update the cache with the status of the
bridge resources
*****************************************************/
// Start local heartbeat again
self.performSelector(Selector("enableLocalHeartbeat"), withObject: nil, afterDelay: 1)
}
/**
Start the local authentication process
*/
func doAuthentication(){
// Disable heartbeats
self.disableLocalHeartbeat()
/***************************************************
To be certain that we own this bridge we must manually
push link it. Here we display the view to do this.
*****************************************************/
// Create an interface for the pushlinking
self.pushLinkViewController = PHBridgePushLinkViewController(nibName: "PHBridgePushLinkViewController", bundle: NSBundle.mainBundle(), hueSDK: (UIApplication.sharedApplication().delegate as! AppDelegate).phHueSDK, delegate: self)
self.navigationController?.presentViewController(self.pushLinkViewController!, animated: true, completion: { () -> Void in
/***************************************************
Start the push linking process.
*****************************************************/
// Start pushlinking when the interface is shown
self.pushLinkViewController?.startPushLinking()
})
}
/**
Delegate method for PHBridgePushLinkViewController which is invoked if the pushlinking was successfull
*/
func pushlinkSuccess() {
/***************************************************
Push linking succeeded we are authenticated against
the chosen bridge.
*****************************************************/
// Remove pushlink view controller
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
self.pushLinkViewController = nil
// Start local heartbeat
self.performSelector("enableLocalHeartbeat", withObject: self, afterDelay: 1)
}
/**
Delegate method for PHBridgePushLinkViewController which is invoked if the pushlinking was not successfull
*/
func pushlinkFailed(error: PHError!) {
// Remove pushlink view controller
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
self.pushLinkViewController = nil
// Check which error occured
if (error.code ) == PUSHLINK_NO_CONNECTION as! Int{
// No local connection to bridge
self.noLocalConnection()
// Start local heartbeat (to see when connection comes back)
self.performSelector(Selector("enableLocalHeartbeat"), withObject: nil, afterDelay: 1)
}
else {
// Bridge button not pressed in time
self.authenticationFailedAlert = UIAlertView(title: "Authenticationfailed", message: "Make sure you press the button within 30 seconds", delegate: self, cancelButtonTitle: nil, otherButtonTitles: "Retry", "Cancel")
self.authenticationFailedAlert?.show()
}
}
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
if alertView == self.noConnectionAlert && alertView.tag == 1 {
// this is no conection alert with option to reconnect or more options
self.noConnectionAlert = nil
if buttonIndex == 0 {
// Retry, just wait for the hearbeat to finish
self.showLoadingViewWithText("Connecting...")
}
else if buttonIndex == 1 {
// Find new bridge button
self.searchForBridgeLocal()
}
else if buttonIndex == 2 {
// Cancel and disable local heartbeat unit started manually again
self.disableLocalHeartbeat()
}
}
else if alertView == self.noBridgeFoundAlert && alertView.tag == 1 {
// This is the alert which is shown when no bridges are found locally
self.noBridgeFoundAlert = nil
if buttonIndex == 0 {
// Retry
self.searchForBridgeLocal()
}
else if buttonIndex == 1 {
// Cancel and disable local hearbeat unit started manually again
self.disableLocalHeartbeat()
}
}
else if alertView == self.authenticationFailedAlert {
// This is the alert which is shown when local pushlinking authentication has failed
self.authenticationFailedAlert = nil
if (buttonIndex == 0) {
// Retry authentication
self.doAuthentication()
} else if (buttonIndex == 1) {
// Remove connecting loading message
self.removeLoadingView()
// Cancel authentication and disable local heartbeat unit started manually again
self.disableLocalHeartbeat()
}
}
}
/**
Shows an overlay over the whole screen with a black box with spinner and loading text in the middle
@param text The text to display under the spinner
*/
func showLoadingViewWithText(text:NSString) {
// First Remove
self.removeLoadingView()
// Then add new
self.loadingView = PHLoadingViewController(nibName: "PHLoadingViewController", bundle: NSBundle.mainBundle())
self.loadingView!.view.frame = (self.navigationController?.view.bounds)!
self.navigationController?.view.addSubview((self.loadingView?.view)!)
self.loadingView?.loadingLabel?.text = text as String
}
/**
Removes the full screen loading overlay.
*/
func removeLoadingView() {
if self.loadingView != nil {
self.loadingView?.view.removeFromSuperview()
self.loadingView = nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment