Harmony Global Oauth

This commit is contained in:
juano2310
2015-11-05 14:11:38 -05:00
parent c62fd52a26
commit dec9ff20b0
2 changed files with 165 additions and 80 deletions

View File

@@ -0,0 +1,81 @@
/**
* Logitech Harmony Activity
*
* Copyright 2015 Juan Risso
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "Logitech Harmony Activity", namespace: "smartthings", author: "Juan Risso") {
capability "Switch"
capability "Actuator"
capability "Refresh"
command "huboff"
command "alloff"
command "refresh"
}
// simulator metadata
simulator {
}
// UI tile definitions
tiles {
standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: 'Off', action: "switch.on", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#ffffff", nextState: "on"
state "on", label: 'On', action: "switch.off", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#79b821", nextState: "off"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("forceoff", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'Force End', action:"switch.off", icon:"st.secondary.off"
}
standardTile("huboff", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'End Hub Action', action:"huboff", icon:"st.harmony.harmony-hub-icon"
}
standardTile("alloff", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'All Actions', action:"alloff", icon:"st.secondary.off"
}
main "button"
details(["button", "refresh", "forceoff", "huboff", "alloff"])
}
}
def parse(String description) {
}
def on() {
sendEvent(name: "switch", value: "on")
log.trace parent.activity(device.deviceNetworkId,"start")
}
def off() {
sendEvent(name: "switch", value: "off")
log.trace parent.activity(device.deviceNetworkId,"end")
}
def huboff() {
sendEvent(name: "switch", value: "off")
log.trace parent.activity(device.deviceNetworkId,"hub")
}
def alloff() {
sendEvent(name: "switch", value: "off")
log.trace parent.activity("all","end")
}
def refresh() {
log.debug "Executing 'refresh'"
log.trace parent.poll()
}

View File

@@ -43,12 +43,10 @@ definition(
category: "SmartThings Labs", category: "SmartThings Labs",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony.png", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony%402x.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony%402x.png",
oauth: [displayName: "Logitech Harmony", displayLink: "http://www.logitech.com/en-us/harmony-remotes"], oauth: [displayName: "Logitech Harmony", displayLink: "http://www.logitech.com/en-us/harmony-remotes"]
singleInstance: true
){ ){
appSetting "clientId" appSetting "clientId"
appSetting "clientSecret" appSetting "clientSecret"
appSetting "callbackUrl"
} }
preferences(oauthPage: "deviceAuthorization") { preferences(oauthPage: "deviceAuthorization") {
@@ -89,7 +87,10 @@ mappings {
path("/oauth/initialize") { action: [ GET: "init"] } path("/oauth/initialize") { action: [ GET: "init"] }
} }
def getShardUrl() { return getApiServerUrl() }
def getServerUrl() { return "https://graph.api.smartthings.com" } def getServerUrl() { return "https://graph.api.smartthings.com" }
def getCallbackUrl() { "https://graph.api.smartthings.com/oauth/callback" }
def getBuildRedirectUrl() { "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${atomicState.accessToken}&apiServerUrl=${shardUrl}" }
def authPage() { def authPage() {
def description = null def description = null
@@ -99,7 +100,7 @@ def authPage() {
createAccessToken() createAccessToken()
} }
description = "Click to enter Harmony Credentials" description = "Click to enter Harmony Credentials"
def redirectUrl = "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${state.accessToken}" def redirectUrl = buildRedirectUrl
return dynamicPage(name: "Credentials", title: "Harmony", nextPage: null, uninstall: true, install:false) { return dynamicPage(name: "Credentials", title: "Harmony", nextPage: null, uninstall: true, install:false) {
section { href url:redirectUrl, style:"embedded", required:true, title:"Harmony", description:description } section { href url:redirectUrl, style:"embedded", required:true, title:"Harmony", description:description }
} }
@@ -121,7 +122,8 @@ def authPage() {
section("Please wait while we discover your Harmony Hubs and Activities. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { section("Please wait while we discover your Harmony Hubs and Activities. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") {
input "selectedhubs", "enum", required:false, title:"Select Harmony Hubs (${numFoundHub} found)", multiple:true, options:huboptions input "selectedhubs", "enum", required:false, title:"Select Harmony Hubs (${numFoundHub} found)", multiple:true, options:huboptions
} }
if (numFoundHub > 0 && numFoundAct > 0 && false) // Virtual activity flag
if (numFoundHub > 0 && numFoundAct > 0 && true)
section("You can also add activities as virtual switches for other convenient integrations") { section("You can also add activities as virtual switches for other convenient integrations") {
input "selectedactivities", "enum", required:false, title:"Select Harmony Activities (${numFoundAct} found)", multiple:true, options:actoptions input "selectedactivities", "enum", required:false, title:"Select Harmony Activities (${numFoundAct} found)", multiple:true, options:actoptions
} }
@@ -164,7 +166,7 @@ def callback() {
def init() { def init() {
log.debug "Requesting Code" log.debug "Requesting Code"
def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote", response_type: "code", redirect_uri: "${appSettings.callbackUrl}" ] def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote", response_type: "code", redirect_uri: "${callbackUrl}" ]
redirect(location: "https://home.myharmony.com/oauth2/authorize?${toQueryString(oauthParams)}") redirect(location: "https://home.myharmony.com/oauth2/authorize?${toQueryString(oauthParams)}")
} }
@@ -303,7 +305,6 @@ def buildRedirectUrl(page) {
} }
def installed() { def installed() {
enableCallback()
if (!state.accessToken) { if (!state.accessToken) {
log.debug "About to create access token" log.debug "About to create access token"
createAccessToken() createAccessToken()
@@ -314,8 +315,7 @@ def installed() {
def updated() { def updated() {
unsubscribe() unsubscribe()
unschedule() unschedule()
enableCallback()
if (!state.accessToken) { if (!state.accessToken) {
log.debug "About to create access token" log.debug "About to create access token"
createAccessToken() createAccessToken()
@@ -660,12 +660,16 @@ def updateDevice() {
} else { } else {
def device = allDevices.find { it.id == params.id } def device = allDevices.find { it.id == params.id }
if (device) { if (device) {
if (arguments) { if (device.hasCommand("$command")) {
device."$command"(*arguments) if (arguments) {
} else { device."$command"(*arguments)
device."$command"() } else {
device."$command"()
}
render status: 204, data: "{}"
} else {
render status: 404, data: '{"msg": "Command not supported by this Device"}'
} }
render status: 204, data: "{}"
} else { } else {
render status: 404, data: '{"msg": "Device not found"}' render status: 404, data: '{"msg": "Device not found"}'
} }