diff --git a/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy b/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy new file mode 100644 index 0000000..3f89262 --- /dev/null +++ b/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy @@ -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() +} diff --git a/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy b/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy index afa767d..26dd7e5 100644 --- a/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy +++ b/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy @@ -18,7 +18,6 @@ definition( ) { appSetting "clientId" appSetting "clientSecret" - appSetting "serverUrl" } preferences { @@ -29,16 +28,13 @@ mappings { path("/receivedToken") { action: [ POST: "receivedToken", GET: "receivedToken"] } path("/receiveToken") { action: [ POST: "receiveToken", GET: "receiveToken"] } path("/hookCallback") { action: [ POST: "hookEventHandler", GET: "hookEventHandler"] } + path("/oauth/initialize") {action: [GET: "oauthInitUrl"]} path("/oauth/callback") { action: [ GET: "callback" ] } } -def getSmartThingsClientId() { - return appSettings.clientId -} - -def getSmartThingsClientSecret() { - return appSettings.clientSecret -} +def getServerUrl() { return "https://graph.api.smartthings.com" } +def getBuildRedirectUrl() { "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${state.accessToken}&apiServerUrl=${apiServerUrl}" } +def buildRedirectUrl(page) { return buildActionUrl(page) } def callback() { def redirectUrl = null @@ -64,9 +60,8 @@ def callback() { // SmartThings code, which we ignore, as we don't need to exchange for an access token. // Instead, go initiate the Jawbone OAuth flow. log.debug "Executing callback redirect to auth page" - def stcid = getSmartThingsClientId() state.oauthInitState = UUID.randomUUID().toString() - def oauthParams = [response_type: "code", client_id: stcid, scope: "move_read sleep_read", redirect_uri: "${serverUrl}/oauth/callback"] + def oauthParams = [response_type: "code", client_id: appSettings.clientId, scope: "move_read sleep_read", redirect_uri: "${serverUrl}/oauth/callback"] redirect(location: "https://jawbone.com/auth/oauth2/auth?${toQueryString(oauthParams)}") } } else { @@ -85,10 +80,11 @@ def authPage() { createAccessToken() } description = "Click to enter Jawbone Credentials" - def redirectUrl = oauthInitUrl() - // log.debug "RedirectURL = ${redirectUrl}" - return dynamicPage(name: "Credentials", title: "Jawbone UP", nextPage: null, uninstall: true, install:false) { - section { href url:redirectUrl, style:"embedded", required:true, title:"Jawbone UP", description:description } + def redirectUrl = buildRedirectUrl + log.debug "RedirectURL = ${redirectUrl}" + def donebutton= state.JawboneAccessToken != null + return dynamicPage(name: "Credentials", title: "Jawbone UP", nextPage: null, uninstall: true, install: donebutton) { + section { href url:redirectUrl, style:"embedded", required:true, title:"Jawbone UP", state: hast ,description:description } } } else { description = "Jawbone Credentials Already Entered." @@ -100,17 +96,14 @@ def authPage() { def oauthInitUrl() { log.debug "oauthInitUrl" - def stcid = getSmartThingsClientId() state.oauthInitState = UUID.randomUUID().toString() - def oauthParams = [ response_type: "code", client_id: stcid, scope: "move_read sleep_read", redirect_uri: buildRedirectUrl("receiveToken") ] - return "https://jawbone.com/auth/oauth2/auth?${toQueryString(oauthParams)}" + def oauthParams = [ response_type: "code", client_id: appSettings.clientId, scope: "move_read sleep_read", redirect_uri: "${serverUrl}/oauth/callback" ] + redirect(location: "https://jawbone.com/auth/oauth2/auth?${toQueryString(oauthParams)}") } def receiveToken(redirectUrl = null) { log.debug "receiveToken" - def stcid = getSmartThingsClientId() - def oauthClientSecret = getSmartThingsClientSecret() - def oauthParams = [ client_id: stcid, client_secret: oauthClientSecret, grant_type: "authorization_code", code: params.code ] + def oauthParams = [ client_id: appSettings.clientId, client_secret: appSettings.clientSecret, grant_type: "authorization_code", code: params.code ] def params = [ uri: "https://jawbone.com/auth/oauth2/token?${toQueryString(oauthParams)}", ] @@ -232,18 +225,10 @@ String toQueryString(Map m) { return m.collect { k, v -> "${k}=${URLEncoder.encode(v.toString())}" }.sort().join("&") } -def getServerUrl() { return appSettings.serverUrl ?: "https://graph.api.smartthings.com" } - -def buildRedirectUrl(page) { - // log.debug "buildRedirectUrl" - // /api/token/:st_token/smartapps/installations/:id/something - return "${serverUrl}/api/token/${state.accessToken}/smartapps/installations/${app.id}/${page}" -} - def validateCurrentToken() { log.debug "validateCurrentToken" def url = "https://jawbone.com/nudge/api/v.1.1/users/@me/refreshToken" - def requestBody = "secret=${getSmartThingsClientSecret()}" + def requestBody = "secret=${appSettings.clientSecret}" try { httpPost(uri: url, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ], body: requestBody) {response -> @@ -257,9 +242,7 @@ def validateCurrentToken() { if (e.statusCode == 401) { // token is expired log.debug "Access token is expired" if (state.refreshToken) { // if we have this we are okay - def stcid = getSmartThingsClientId() - def oauthClientSecret = getSmartThingsClientSecret() - def oauthParams = [client_id: stcid, client_secret: oauthClientSecret, grant_type: "refresh_token", refresh_token: state.refreshToken] + def oauthParams = [client_id: appSettings.clientId, client_secret: appSettings.clientSecret, grant_type: "refresh_token", refresh_token: state.refreshToken] def tokenUrl = "https://jawbone.com/auth/oauth2/token?${toQueryString(oauthParams)}" def params = [ uri: tokenUrl @@ -288,9 +271,10 @@ def validateCurrentToken() { } def initialize() { - def hookUrl = "${serverUrl}/api/token/${state.accessToken}/smartapps/installations/${app.id}/hookCallback" - def webhook = "https://jawbone.com/nudge/api/v.1.1/users/@me/pubsub?webhook=$hookUrl" - log.debug "Callback URL: $webhook" + log.debug "Callback URL - Webhook" + def localServerUrl = getApiServerUrl() + def hookUrl = "${localServerUrl}/api/token/${state.accessToken}/smartapps/installations/${app.id}/hookCallback" + def webhook = "https://jawbone.com/nudge/api/v.1.1/users/@me/pubsub?webhook=$hookUrl" httpPost(uri: webhook, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) } @@ -328,7 +312,6 @@ def setup() { } def installed() { - enableCallback() if (!state.accessToken) { log.debug "About to create access token" @@ -341,7 +324,6 @@ def installed() { } def updated() { - enableCallback() if (!state.accessToken) { log.debug "About to create access token" @@ -500,4 +482,4 @@ def hookEventHandler() { def html = """{"code":200,"message":"OK"}""" render contentType: 'application/json', data: html -} \ No newline at end of file +} diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 14dfd95..7d81c41 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -724,8 +724,11 @@ private getBridgeIP() { host = d.latestState('networkAddress').stringValue } if (host == null || host == "") { - def macAddress = selectedHue - def bridge = getHueBridges().find { it?.value?.mac?.equalsIgnoreCase(macAddress) }?.value + def serialNumber = selectedHue + def bridge = getHueBridges().find { it?.value?.serialNumber?.equalsIgnoreCase(serialNumber) }?.value + if (!bridge) { + bridge = getHueBridges().find { it?.value?.mac?.equalsIgnoreCase(serialNumber) }?.value + } if (bridge?.ip && bridge?.port) { if (bridge?.ip.contains(".")) host = "${bridge?.ip}:${bridge?.port}" diff --git a/smartapps/smartthings/ifttt.src/ifttt.groovy b/smartapps/smartthings/ifttt.src/ifttt.groovy index 0bc3b20..cad83d2 100644 --- a/smartapps/smartthings/ifttt.src/ifttt.groovy +++ b/smartapps/smartthings/ifttt.src/ifttt.groovy @@ -98,6 +98,15 @@ def installed() { } def updated() { + def currentDeviceIds = settings.collect { k, devices -> devices }.flatten().collect { it.id }.unique() + def subscriptionDevicesToRemove = app.subscriptions*.device.findAll { device -> + !currentDeviceIds.contains(device.id) + } + subscriptionDevicesToRemove.each { device -> + log.debug "Removing $device.displayName subscription" + state.remove(device.id) + unsubscribe(device) + } log.debug settings } diff --git a/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy b/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy index 0816d03..03c5ccc 100644 --- a/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy +++ b/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy @@ -34,7 +34,7 @@ * locks | lock | lock, unlock | locked, unlocked * ---------------------+-------------------+-----------------------------+------------------------------------ */ - + definition( name: "Logitech Harmony (Connect)", namespace: "smartthings", @@ -48,7 +48,6 @@ definition( ){ appSetting "clientId" appSetting "clientSecret" - appSetting "callbackUrl" } preferences(oauthPage: "deviceAuthorization") { @@ -90,16 +89,18 @@ mappings { } 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=${state.accessToken}&apiServerUrl=${apiServerUrl}" } def authPage() { - def description = null + def description = null if (!state.HarmonyAccessToken) { if (!state.accessToken) { log.debug "About to create access token" createAccessToken() } 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) { section { href url:redirectUrl, style:"embedded", required:true, title:"Harmony", description:description } } @@ -111,7 +112,7 @@ def authPage() { def huboptions = state.HarmonyHubs ?: [] def actoptions = state.HarmonyActivities ?: [] - + def numFoundHub = huboptions.size() ?: 0 def numFoundAct = actoptions.size() ?: 0 if((deviceRefreshCount % 5) == 0) { @@ -121,13 +122,14 @@ 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.") { 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") { input "selectedactivities", "enum", required:false, title:"Select Harmony Activities (${numFoundAct} found)", multiple:true, options:actoptions - } + } if (state.resethub) - section("Connection to the hub timed out. Please restart the hub and try again.") {} - } + section("Connection to the hub timed out. Please restart the hub and try again.") {} + } } } @@ -139,7 +141,7 @@ def callback() { } else { log.warn "No authQueryString" } - + if (state.HarmonyAccessToken) { log.debug "Access token already exists" discovery() @@ -164,8 +166,8 @@ def callback() { def init() { log.debug "Requesting Code" - def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote", response_type: "code", redirect_uri: "${appSettings.callbackUrl}" ] - redirect(location: "https://home.myharmony.com/oauth2/authorize?${toQueryString(oauthParams)}") + def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote", response_type: "code", redirect_uri: "${callbackUrl}" ] + redirect(location: "https://home.myharmony.com/oauth2/authorize?${toQueryString(oauthParams)}") } def receiveToken(redirectUrl = null) { @@ -175,7 +177,7 @@ def receiveToken(redirectUrl = null) { uri: "https://home.myharmony.com/oauth2/token?${toQueryString(oauthParams)}", ] try { - httpPost(params) { response -> + httpPost(params) { response -> state.HarmonyAccessToken = response.data.access_token } } catch (java.util.concurrent.TimeoutException e) { @@ -222,7 +224,7 @@ def connectionStatus(message, redirectUrl = null) { """ } - + def html = """ @@ -303,30 +305,28 @@ def buildRedirectUrl(page) { } def installed() { - enableCallback() if (!state.accessToken) { log.debug "About to create access token" createAccessToken() - } else { + } else { initialize() } } def updated() { unsubscribe() - unschedule() - enableCallback() + unschedule() if (!state.accessToken) { log.debug "About to create access token" createAccessToken() - } else { + } else { initialize() - } + } } def uninstalled() { if (state.HarmonyAccessToken) { - try { + try { state.HarmonyAccessToken = "" log.debug "Success disconnecting Harmony from SmartThings" } catch (groovyx.net.http.HttpResponseException e) { @@ -340,7 +340,7 @@ def initialize() { if (selectedhubs || selectedactivities) { addDevice() runEvery5Minutes("discovery") - } + } } def getHarmonydevices() { @@ -360,20 +360,20 @@ Map discoverDevices() { def hubname = getHubName(it.key) def hubvalue = "${hubname}" hubs["harmony-${hubkey}"] = hubvalue - it.value.response.data.activities.each { + it.value.response.data.activities.each { def value = "${it.value.name}" def key = "harmony-${hubkey}-${it.key}" activities["${key}"] = value - } + } } state.HarmonyHubs = hubs - state.HarmonyActivities = activities - } + state.HarmonyActivities = activities + } } //CHILD DEVICE METHODS def discovery() { - def Params = [auth: state.HarmonyAccessToken] + def Params = [auth: state.HarmonyAccessToken] def url = "https://home.myharmony.com/cloudapi/activity/all?${toQueryString(Params)}" try { httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> @@ -385,11 +385,11 @@ def discovery() { poll() } else { log.debug "Error: $response.status" - } + } } } catch (groovyx.net.http.HttpResponseException e) { if (e.statusCode == 401) { // token is expired - state.remove("HarmonyAccessToken") + state.remove("HarmonyAccessToken") log.warn "Harmony Access token has expired" } } catch (java.net.SocketTimeoutException e) { @@ -397,12 +397,12 @@ def discovery() { state.resethub = true } catch (e) { log.warn "Hostname in certificate didn't match. Please try again later." - } + } return null } def addDevice() { - log.trace "Adding Hubs" + log.trace "Adding Hubs" selectedhubs.each { dni -> def d = getChildDevice(dni) if(!d) { @@ -413,8 +413,8 @@ def addDevice() { } else { log.trace "found ${d.displayName} with id $dni already exists" } - } - log.trace "Adding Activities" + } + log.trace "Adding Activities" selectedactivities.each { dni -> def d = getChildDevice(dni) if(!d) { @@ -425,7 +425,7 @@ def addDevice() { } else { log.trace "found ${d.displayName} with id $dni already exists" } - } + } } def activity(dni,mode) { @@ -433,26 +433,26 @@ def activity(dni,mode) { def msg = "Command failed" def url = '' if (dni == "all") { - url = "https://home.myharmony.com/cloudapi/activity/off?${toQueryString(Params)}" - } else { + url = "https://home.myharmony.com/cloudapi/activity/off?${toQueryString(Params)}" + } else { def aux = dni.split('-') def hubId = aux[1] - if (mode == "hub" || (aux.size() <= 2) || (aux[2] == "off")){ - url = "https://home.myharmony.com/cloudapi/hub/${hubId}/activity/off?${toQueryString(Params)}" + if (mode == "hub" || (aux.size() <= 2) || (aux[2] == "off")){ + url = "https://home.myharmony.com/cloudapi/hub/${hubId}/activity/off?${toQueryString(Params)}" } else { def activityId = aux[2] url = "https://home.myharmony.com/cloudapi/hub/${hubId}/activity/${activityId}/${mode}?${toQueryString(Params)}" } - } + } try { - httpPostJson(uri: url) { response -> + httpPostJson(uri: url) { response -> if (response.data.code == 200 || dni == "all") { msg = "Command sent succesfully" - state.aux = 0 + state.aux = 0 } else { msg = "Command failed. Error: $response.data.code" } - } + } } catch (groovyx.net.http.HttpResponseException ex) { log.error ex if (state.aux == 0) { @@ -460,7 +460,7 @@ def activity(dni,mode) { activity(dni,mode) } else { msg = ex - state.aux = 0 + state.aux = 0 } } catch(Exception ex) { msg = ex @@ -473,10 +473,10 @@ def poll() { // GET THE LIST OF ACTIVITIES if (state.HarmonyAccessToken) { getActivityList() - def Params = [auth: state.HarmonyAccessToken] + def Params = [auth: state.HarmonyAccessToken] def url = "https://home.myharmony.com/cloudapi/state?${toQueryString(Params)}" try { - httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> + httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> def map = [:] response.data.hubs.each { if (it.value.message == "OK") { @@ -489,20 +489,20 @@ def poll() { def currentActivity = getActivityName(it.value.response.data.currentAvActivity,it.key) hub.sendEvent(name: "currentActivity", value: currentActivity, descriptionText: "Current activity is ${currentActivity}", display: false) } - } + } } else { log.trace it.value.message - } + } } - def activities = getChildDevices() + def activities = getChildDevices() def activitynotrunning = true activities.each { activity -> - def act = activity.deviceNetworkId.split('-') + def act = activity.deviceNetworkId.split('-') if (act.size() > 2) { def aux = map.find { it.key == act[1] } if (aux) { def aux2 = aux.value.split(',') - def childDevice = getChildDevice(activity.deviceNetworkId) + def childDevice = getChildDevice(activity.deviceNetworkId) if ((act[2] == aux2[0]) && (aux2[1] == "1" || aux2[1] == "2")) { childDevice?.sendEvent(name: "switch", value: "on") if (aux2[1] == "1") @@ -512,30 +512,30 @@ def poll() { if (aux2[1] == "3") runIn(5, "poll", [overwrite: true]) } - } - } + } + } } return "Poll completed $map - $state.hubs" } } catch (groovyx.net.http.HttpResponseException e) { if (e.statusCode == 401) { // token is expired - state.remove("HarmonyAccessToken") + state.remove("HarmonyAccessToken") return "Harmony Access token has expired" - } + } } catch(Exception e) { log.trace e } - } + } } def getActivityList() { // GET ACTIVITY'S NAME if (state.HarmonyAccessToken) { - def Params = [auth: state.HarmonyAccessToken] + def Params = [auth: state.HarmonyAccessToken] def url = "https://home.myharmony.com/cloudapi/activity/all?${toQueryString(Params)}" try { - httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> + httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> response.data.hubs.each { def hub = getChildDevice("harmony-${it.key}") if (hub) { @@ -548,10 +548,10 @@ def getActivityList() { } activities += [id: "off", name: "Activity OFF", type: "0"] log.trace activities - } - hub.sendEvent(name: "activities", value: new groovy.json.JsonBuilder(activities).toString(), descriptionText: "Activities are ${activities.collect { it.name }?.join(', ')}", display: false) + } + hub.sendEvent(name: "activities", value: new groovy.json.JsonBuilder(activities).toString(), descriptionText: "Activities are ${activities.collect { it.name }?.join(', ')}", display: false) } - } + } } } catch (groovyx.net.http.HttpResponseException e) { log.trace e @@ -560,7 +560,7 @@ def getActivityList() { } catch(Exception e) { log.trace e } - } + } return activity } @@ -568,16 +568,16 @@ def getActivityName(activity,hubId) { // GET ACTIVITY'S NAME def actname = activity if (state.HarmonyAccessToken) { - def Params = [auth: state.HarmonyAccessToken] + def Params = [auth: state.HarmonyAccessToken] def url = "https://home.myharmony.com/cloudapi/hub/${hubId}/activity/all?${toQueryString(Params)}" try { - httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> + httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> actname = response.data.data.activities[activity].name } } catch(Exception e) { log.trace e } - } + } return actname } @@ -585,19 +585,19 @@ def getActivityId(activity,hubId) { // GET ACTIVITY'S NAME def actid = activity if (state.HarmonyAccessToken) { - def Params = [auth: state.HarmonyAccessToken] + def Params = [auth: state.HarmonyAccessToken] def url = "https://home.myharmony.com/cloudapi/hub/${hubId}/activity/all?${toQueryString(Params)}" try { - httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> + httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> response.data.data.activities.each { if (it.value.name == activity) actid = it.key - } + } } } catch(Exception e) { log.trace e } - } + } return actid } @@ -605,16 +605,16 @@ def getHubName(hubId) { // GET HUB'S NAME def hubname = hubId if (state.HarmonyAccessToken) { - def Params = [auth: state.HarmonyAccessToken] + def Params = [auth: state.HarmonyAccessToken] def url = "https://home.myharmony.com/cloudapi/hub/${hubId}/discover?${toQueryString(Params)}" try { - httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> + httpGet(uri: url, headers: ["Accept": "application/json"]) {response -> hubname = response.data.data.name } } catch(Exception e) { log.trace e - } - } + } + } return hubname } @@ -625,8 +625,8 @@ def sendNotification(msg) { def hookEventHandler() { // log.debug "In hookEventHandler method." log.debug "request = ${request}" - - def json = request.JSON + + def json = request.JSON def html = """{"code":200,"message":"OK"}""" render contentType: 'application/json', data: html @@ -660,12 +660,16 @@ def updateDevice() { } else { def device = allDevices.find { it.id == params.id } if (device) { - if (arguments) { - device."$command"(*arguments) - } else { - device."$command"() + if (device.hasCommand("$command")) { + if (arguments) { + device."$command"(*arguments) + } else { + device."$command"() + } + render status: 204, data: "{}" + } else { + render status: 404, data: '{"msg": "Command not supported by this Device"}' } - render status: 204, data: "{}" } else { render status: 404, data: '{"msg": "Device not found"}' }