├── LICENSE ├── README.md └── rest-api.groovy /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Brady Holt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [SmartThings](https://www.smartthings.com/) REST API 2 | 3 | ## Setup 4 | 5 | ### Installation 6 | 7 | 1. Login at https://graph.api.smartthings.com/ 8 | 2. Navigate: My SmartApps > New SmartApp > From Code (tab) 9 | 3. Paste contents of rest-api.groovy 10 | 4. Click: Create, Publish > For Me 11 | 6. Navigate: App Settings > OAuth 12 | 7. Click: Enable OAuth in Smart App 13 | 8. Note the Client ID (i.e. `abc123`) and Client Secret (i.e. `def321`) 14 | 15 | ### Get Access Token via OAuth 16 | 17 | 1. Replace the client_id value and open this URL in a browser: https://graph.api.smartthings.com/oauth/confirm_access?response_type=code&scope=app&redirect_uri=http%3A%2F%2Flocalhost&client_id=abc123 18 | 2. Login and Click "Authorize". 19 | 3. You will be redirected to http://localhost; note the code query value (i.e. aD4kF5 in http://localhost/?code=aD4kF5) 20 | 4. Run `curl -v -H "Content-Type: application/x-www-form-urlencoded" -X POST --data 'grant_type=authorization_code&code=aD4kF5&client_id=abc123&client_secret=def321&redirect_uri=http%3A%2F%2Flocalhost' https://graph.api.smartthings.com/oauth/token` 21 | 5. Note access_token in response (i.e. `xyz123`). **This will be the access token used to authenticate to the REST API.** 22 | 6. Run `curl -v -H "Authorization: Bearer xyz123" https://graph.api.smartthings.com/api/smartapps/endpoints` 23 | 7. Note the `uri` value (i.e. https://graph1.smartthings.com/api/smartapps/installations/123987). **This will be the Endpoint URL used to access the REST API.** 24 | 25 | ## Usage 26 | 27 | _(Assumming Access Token: `xyz123` and Endpoint URL: `https://graph1.smartthings.com/api/smartapps/installations/123987`)_ 28 | 29 | 30 | #### List Devices 31 | ``` 32 | curl -v -H "Authorization: Bearer xyz123" \ 33 | https://graph1.smartthings.com/api/smartapps/installations/123987/devices 34 | ``` 35 | 36 | #### Get Device Attribute (i.e. on/off for a switch) 37 | ``` 38 | curl -v -H "Authorization: Bearer xyz123" \ 39 | https://graph1.smartthings.com/api/smartapps/installations/123987/device/123/attribute/switch 40 | ``` 41 | 42 | #### Turn Device On 43 | ``` 44 | curl -H "Authorization: Bearer xyz123" -X POST \ 45 | https://graph1.smartthings.com/api/smartapps/installations/123987/device/123/command/on 46 | ``` 47 | 48 | #### Turn Device Off 49 | ``` 50 | curl -H "Authorization: Bearer xyz123" -X POST \ 51 | https://graph1.smartthings.com/api/smartapps/installations/123987/device/123/command/off 52 | ``` 53 | 54 | #### Adjust Brightness to 50% 55 | ``` 56 | curl -H "Authorization: Bearer xyz123" -X POST \ 57 | https://graph1.smartthings.com/api/smartapps/installations/123987/device/123/command/setLevel?arg=50 58 | ``` 59 | -------------------------------------------------------------------------------- /rest-api.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * SmartThings REST API 3 | * 4 | * Copyright 2017 Brady Holt 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 7 | * in compliance with the License. You may obtain a copy of the License at: 8 | * 9 | * https://opensource.org/licenses/MIT 10 | * 11 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 12 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing permissions and limitations under the License. 14 | * 15 | */ 16 | definition( 17 | name: "REST API", 18 | namespace: "bradymholt", 19 | author: "Brady Holt", 20 | description: "SmartThings REST API", 21 | category: "SmartThings Labs", 22 | iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", 23 | iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", 24 | iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", 25 | oauth: [displayName: "SmartThings REST API", displayLink: ""] 26 | ) 27 | 28 | mappings { 29 | path("/devices") { 30 | action: [ 31 | GET: "listDevices" 32 | ] 33 | } 34 | path("/device/:id") { 35 | action: [ 36 | GET: "deviceDetails" 37 | ] 38 | } 39 | path("/device/:id/attribute/:name") { 40 | action: [ 41 | GET: "deviceGetAttributeValue" 42 | ] 43 | } 44 | path("/device/:id/command/:name") { 45 | action: [ 46 | POST: "deviceCommand" 47 | ] 48 | } 49 | } 50 | 51 | preferences { 52 | section() { 53 | input "devices", "capability.actuator", title: "Devices", multiple: true 54 | } 55 | } 56 | 57 | def installed() { 58 | log.debug "Installed with settings: ${settings}" 59 | initialize() 60 | } 61 | 62 | def updated() { 63 | log.debug "Updated with settings: ${settings}" 64 | unsubscribe() 65 | initialize() 66 | } 67 | 68 | def initialize() { 69 | } 70 | 71 | def listDevices() { 72 | def resp = [] 73 | devices.each { 74 | resp << [ 75 | id: it.id, 76 | label: it.label, 77 | manufacturerName: it.manufacturerName, 78 | modelName: it.modelName, 79 | name: it.name, 80 | displayName: it.displayName 81 | ] 82 | } 83 | return resp 84 | } 85 | 86 | def deviceDetails() { 87 | def device = getDeviceById(params.id) 88 | 89 | def supportedAttributes = [] 90 | device.supportedAttributes.each { 91 | supportedAttributes << it.name 92 | } 93 | 94 | def supportedCommands = [] 95 | device.supportedCommands.each { 96 | def arguments = [] 97 | it.arguments.each { arg -> 98 | arguments << "" + arg 99 | } 100 | supportedCommands << [ 101 | name: it.name, 102 | arguments: arguments 103 | ] 104 | } 105 | 106 | return [ 107 | id: device.id, 108 | label: device.label, 109 | manufacturerName: device.manufacturerName, 110 | modelName: device.modelName, 111 | name: device.name, 112 | displayName: device.displayName, 113 | supportedAttributes: supportedAttributes, 114 | supportedCommands: supportedCommands 115 | ] 116 | } 117 | 118 | def deviceGetAttributeValue() { 119 | def device = getDeviceById(params.id) 120 | def name = params.name 121 | def value = device.currentValue(name); 122 | return [ 123 | value: value 124 | ] 125 | } 126 | 127 | def deviceCommand() { 128 | def device = getDeviceById(params.id) 129 | def name = params.name 130 | def args = params.arg 131 | if (args == null) { 132 | args = [] 133 | } else if (args instanceof String) { 134 | args = [args] 135 | } 136 | log.debug "device command: ${name} ${args}" 137 | switch(args.size) { 138 | case 0: 139 | device."$name"() 140 | break; 141 | case 1: 142 | device."$name"(args[0]) 143 | break; 144 | case 2: 145 | device."$name"(args[0], args[1]) 146 | break; 147 | default: 148 | throw new Exception("Unhandled number of args") 149 | } 150 | } 151 | 152 | def getDeviceById(id) { 153 | return devices.find { it.id == id } 154 | } 155 | --------------------------------------------------------------------------------