/** * LIFX * * Copyright 2015 LIFX * */ definition( name: "LIFX (Connect)", namespace: "smartthings", author: "LIFX", description: "Allows you to use LIFX smart light bulbs with SmartThings.", category: "Convenience", iconUrl: "https://cloud.lifx.com/images/lifx.png", iconX2Url: "https://cloud.lifx.com/images/lifx.png", iconX3Url: "https://cloud.lifx.com/images/lifx.png", oauth: true, singleInstance: true) { appSetting "clientId" appSetting "clientSecret" } preferences { page(name: "Credentials", title: "LIFX", content: "authPage", install: false) } mappings { path("/receivedToken") { action: [ POST: "oauthReceivedToken", GET: "oauthReceivedToken"] } path("/receiveToken") { action: [ POST: "oauthReceiveToken", GET: "oauthReceiveToken"] } path("/hookCallback") { action: [ POST: "hookEventHandler", GET: "hookEventHandler"] } path("/oauth/callback") { action: [ GET: "oauthCallback" ] } path("/oauth/initialize") { action: [ GET: "oauthInit"] } path("/test") { action: [ GET: "oauthSuccess" ] } } def getServerUrl() { return "https://graph.api.smartthings.com" } def apiURL(path = '/') { return "https://api.lifx.com/v1beta1${path}" } def buildRedirectUrl(page) { return "${serverUrl}/api/token/${state.accessToken}/smartapps/installations/${app.id}/${page}" } def authPage() { log.debug "authPage" if (!state.lifxAccessToken) { log.debug "no LIFX access token" // This is the SmartThings access token if (!state.accessToken) { log.debug "no access token, create access token" createAccessToken() // predefined method } def description = "Tap to enter LIFX credentials" def redirectUrl = "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${state.accessToken}" // this triggers oauthInit() below log.debug "app id: ${app.id}" log.debug "redirect url: ${redirectUrl}" return dynamicPage(name: "Credentials", title: "Connect to LIFX", nextPage: null, uninstall: true, install:false) { section { href(url:redirectUrl, required:true, title:"Connect to LIFX", description:"Tap here to connect your LIFX account") // href(url:buildRedirectUrl("test"), title: "Message test") } } } else { log.debug "have LIFX access token" def options = locationOptions() ?: [] def count = options.size() def refreshInterval = 3 return dynamicPage(name:"Credentials", title:"Select devices...", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) { section("Select your location") { input "selectedLocationId", "enum", required:true, title:"Select location (${count} found)", multiple:false, options:options } } } } // OAuth def oauthInit() { def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote_control:all", response_type: "code" ] log.info("Redirecting user to OAuth setup") redirect(location: "https://cloud.lifx.com/oauth/authorize?${toQueryString(oauthParams)}") } def oauthCallback() { def redirectUrl = null if (params.authQueryString) { redirectUrl = URLDecoder.decode(params.authQueryString.replaceAll(".+&redirect_url=", "")) } else { log.warn "No authQueryString" } if (state.lifxAccessToken) { log.debug "Access token already exists" success() } else { def code = params.code if (code) { if (code.size() > 6) { // LIFX code log.debug "Exchanging code for access token" oauthReceiveToken(redirectUrl) } else { // Initiate the LIFX OAuth flow. oauthInit() } } else { log.debug "This code should be unreachable" success() } } } def oauthReceiveToken(redirectUrl = null) { log.debug "receiveToken - params: ${params}" def oauthParams = [ client_id: "${appSettings.clientId}", client_secret: "${appSettings.clientSecret}", grant_type: "authorization_code", code: params.code, scope: params.scope ] // how is params.code valid here? def params = [ uri: "https://cloud.lifx.com/oauth/token", body: oauthParams, headers: [ "User-Agent": "SmartThings Integration" ] ] httpPost(params) { response -> state.lifxAccessToken = response.data.access_token } if (state.lifxAccessToken) { oauthSuccess() } else { oauthFailure() } } def oauthSuccess() { def message = """
Your LIFX Account is now connected to SmartThings!
Click 'Done' to finish setup.
""" oauthConnectionStatus(message) } def oauthFailure() { def message = """The connection could not be established!
Click 'Done' to return to the menu.
""" oauthConnectionStatus(message) } def oauthReceivedToken() { def message = """Your LIFX Account is already connected to SmartThings!
Click 'Done' to finish setup.
""" oauthConnectionStatus(message) } def oauthConnectionStatus(message, redirectUrl = null) { def redirectHtml = "" if (redirectUrl) { redirectHtml = """ """ } def html = """
${message}