Control lights using HTTP GET without switch ID

Using the REST API I’ve successfully been able to control on, off, and setlevel of all the lights in my house. However what I want to do is instead of using the unique switch ID to tell smartthings which light/lights to turn on I want to use the API to run a smartapp that I can setup using the smartthings app. This would allow me to easily create scenes and control them via HTTP GET commands without having to lookup switch IDs of each light associated with that scene (which could be a dozen lights that need set to execute a single scene). I feel there are two options to accomplish this:

  1. Pass the Smartapp name via the HTTP GET command and execute the smartapp directly inside my endpoint smartapp. However to turn on a single light it doesn’t make sense to set up a smartapp so i would want to be able to pass the switch name and execute an on, off, or setlevel command.

  2. If I can’t run a smartapp from another smartapp (and I haven’t found a way to do this) I can turn a switch on and tie a smartapp to execute when that switch turns on. I know I can do this. However to accomplish this I need to be able to pass the switch name through the HTTP GET command and execute an on command. When I try to do this I get an error telling me I can’t execute a command on a string. Can I convert that string that gets defined via my HTTP GET to have the capability of a switch?

an example of the HTTP GET url is below. I’m actually creating a remote via tasker for quick access to control all my lights so I don’t have to launch the smartthings app. I will also be able to use voice commands using autovoice and now that autovoice can grab commands directly from google now it becomes very useful for handsfree control. I’m definitely not a coder and have fumbled through what I have created so far. Any help to accomplish this would be greatly appreciated.

https://graph.api.smartthings.com/api/smartapps/installations/xxxxxxxxxx/remote/KitchenMain/OFF?access_token=xxxxxxxxxxxxxxxxxxxx

/remote - tells the endpoint my command is coming from my tasker remote
/KitchenMain - switch name I currently have setup in the preferences section. I created a separate input for each light in my house that I just select the correct switch from the drop down menu. This could be replaced with a smartapp name too if executing a smartapp is possible.
/OFF - command that needs executed on the switch name

You cannot run an app from another app, but solution #2 is doable. You’ll just need to look up your switches by names instead of IDs, which is tricky for two reasons:

  1. Names can contain spaces and other reserved characters, so you’ll need to URL-encode them, for example “Living Room” becomes “Living%20Room”.
  2. Names are not unique, so you’ll have to resolve duplicate names somehow.

This makes me feel better about going down the road I went down (I’ve already created quite a few virtual switches using the on/off button tile device and created some controls and scenes based on these getting switched on.

I’ve used names without any spaces or special characters to avoid any issues. At least the variable name assigned to the switch I select I did this with as you can see below. So if I pass “KitchenMain” from my HTTP GET command I want this switch to be triggered.

section("Allow Endpoint to Control These Things...") {
}
section("Kitchen Main"){
	input "KitchenMain", "capability.switch", title: "Where?"
}

Further my path inside my endpoint looks like this:

path("/remote/:id/:command") {
action: [
GET: “remotecontrol”
]
}

So if I pass /remote/KitchenMain/ON I want to turn on the light I have tied to KitchenMain in my preference section. However the variable I define by “def location = params.id” is a string so when I attempt to run “location.on()” I get an error.

any ideas why this doesnt work or how I can turn my variable “location” into something I can turn on?

Right. That won’t work.

input "KitchenMain", "capability.switch", title: "Where?"

This code creates a variable KitchenMain in your app. You cannot convert a string you get from the REST endpoint to a variable name. What you need to do is to match that string with the device name, not variable name. I.e.

if (KitchenMain.name == params.id) {
    KitchenMain.on()
}

This is exactly how I began doing this however I quickly realized how many if statements I would end up with. I’ll need to have a separate section for every switches ON and OFF as well as setLevel for each dimmer. That’s when i decided to try to tackle it a different way by having a single ON, OFF, and setLevel section and pass the actual switch name through the API. This would greatly reduce my code.

This really isn’t possible? Even though my string value is identical to my switch variable name? How does the below work when using the switch ID? Regardless of which ID I pass (which would be a string) the app uses the same command to control it (“device.on()” for example). I don’t understand the declaration line (def device = devices.find { it.id == params.id }) but this somehow allows this all to work. It isn’t possible to do a similar thing using the switch name?

def command = params.command
def level = params.level
//let’s create a toggle option here
if (command)
{
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, “Device not found”)
} else {
if(command == “toggle”)
{
if(device.currentValue(‘switch’) == “on”)
device.off();
else
device.on();
}
else if(command == “level”)
{
device.setLevel(level.toInteger())
}
else
{
device."$command"()
}

Thanks for all the help so far!

You need to brush up your Groovy skills. :smile:
This is called ‘closure’. The code in {} is executed for each element of the list. Sort of like foreach() in other languages. ‘It’ is an implied variable referring to the current element (iterator). So the code finds an element in a list with id equal to params.id.

I have no Groovy skills. I don’t have any skills in any language. But this is what i suspected that did. What list is it looking at? Why can’t I do something like this?

def device = devices.find {it.name == params.id}

wouldn’t this search the list for the name? Is the name not the variable I set in my preferences section? do I need to compare to the actual switch name?

Anyone know why

def device = devices.find { it.name == params.id}

doesnt work? I’ve confirmed that the name of the switch I’m looking for is in fact the name given to it in the devices settings. The string I pass to the endpoint matches exactly with the name of the switch but it doesn’t set device equal to anything.

I’m following this thread with interest. The you guys are doing sounds awesome.

What I’m hoping this will provide is an ability to control ST devices from a regular browser and custom html page?

First off, is that a correct assumption, the code being worked here is a smart app that could respond to external IP requests and in turn control ST devices?

Secondly, if that’s correct, is there any working examples made available at this stage.

Cheers.

It’s over two years old.

Yes, noted. Was hoping someone had conclusion to the topic. It kinda just ended.