Call REST API from JavaScript

Posted on
Fri Feb 20, 2015 1:36 pm
davinci offline
Posts: 362
Joined: Feb 14, 2015

Call REST API from JavaScript

Code: Select all
    $.ajax({
  url: 'http://127.0.0.1:8176/devices/light%20upstairs',
  type: 'PUT',
  data: "isOn=0&_method=put",
  success: function(data) {
    alert('Load was performed.');
  }
});
   


I'm getting this error:
WebServer 405 Method Not Allowed "http://127.0.0.1:8176/devices/light upstairs" from 127.0.0.1


Why doesn't this work?

Posted on
Fri Feb 20, 2015 6:44 pm
jay (support) offline
Site Admin
User avatar
Posts: 16815
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Call REST API from JavaScript

Do you have authentication turned on? If so, then you need to authenticate using digest authentication (not sure how you do that in JavaScript).

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Sat Feb 21, 2015 1:06 am
davinci offline
Posts: 362
Joined: Feb 14, 2015

Re: Call REST API from JavaScript

I disabled it for testing but get the same error.

Posted on
Sat Feb 21, 2015 5:43 am
davinci offline
Posts: 362
Joined: Feb 14, 2015

Re: Call REST API from JavaScript

TWO PROBLEMS

Problem with the 405 error is on PHP Server side.

I can't login automatically. If I enter it manually it works until cache is removed. Anyone has an idea?

Code: Select all
    $.ajax({ url: 'http://127.0.0.1:8176/devices/Licht%20B%FCro',
    type: 'PUT', data: "isOn=1&_method=put", beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic d2lraTpwZWRpYQ0K==") }
           
 

Posted on
Mon Feb 23, 2015 11:57 am
davinci offline
Posts: 362
Joined: Feb 14, 2015

Re: Call REST API from JavaScript

So how can I login properly over a website?

Also why is my command rejected completely if I do it over my local PHP?

Posted on
Mon Feb 23, 2015 8:37 pm
matt (support) offline
Site Admin
User avatar
Posts: 20568
Joined: Jan 27, 2003
Location: Texas

Re: Call REST API from JavaScript

Indigo doesn't use PHP (it uses a python based Web server). The 405 is probably because you are doing HTTP Basic authentication instead of HTTP Digest. I'm not sure how to do that via JavaScript. You can disable Indigo's Digest authentication in favor of Basic authentication but it is less secure. Search in the forum for "HTTP Digest Basic authentication" and you should find the thread with the details. If you don't then I can find it.

Image

Posted on
Tue Feb 24, 2015 4:56 am
davinci offline
Posts: 362
Joined: Feb 14, 2015

Re: Call REST API from JavaScript

Finally it works!

I can use this to call REST API in a secure way. Maybe someone can benefit from this code as well:

Code: Select all
<?php
$service_url = 'http://127.0.0.1:8176/devices/light';
$ch = curl_init($service_url);
 
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, 'user:pass');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
$data = array("toggle" => '1');
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));
$response = curl_exec($ch);
if ($response === false) {
    $info = curl_getinfo($ch);
    curl_close($ch);
    die('Error: ' . var_export($info));
}
curl_close($ch);
$decoded = json_decode($response);
if (isset($decoded->response->status) && $decoded->response->status == 'ERROR') {
    die('error occured: ' . $decoded->response->errormessage);
}
echo 'OK!';
var_export($decoded->response);
?>

Posted on
Tue Feb 24, 2015 7:13 am
davinci offline
Posts: 362
Joined: Feb 14, 2015

Re: Call REST API from JavaScript

Example use of curl and virtual HTTP execute call to execute action group “party scene”:

curl -X EXECUTE http://127.0.0.1:8176/actions/party%20scene
http://127.0.0.1:8176/actions/party%20s ... od=execute


translates to

Code: Select all
<?php
$service_url = 'http://127.0.0.1:8176/actions/action';
$ch = curl_init($service_url);
 
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, 'user:pass');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "EXECUTE");
$data = array("_method" => 'execute');
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));
$response = curl_exec($ch);
if ($response === false) {
    $info = curl_getinfo($ch);
    curl_close($ch);
    die('Error: ' . var_export($info));
}
curl_close($ch);
$decoded = json_decode($response);
if (isset($decoded->response->status) && $decoded->response->status == 'ERROR') {
    die('Error: ' . $decoded->response->errormessage);
}
echo 'response ok!';
var_export($decoded->response);
?>



However all of the sudden indigo refused the calls and I had to restart the server.

Posted on
Tue Feb 24, 2015 8:05 am
RogueProeliator offline
User avatar
Posts: 2437
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: Call REST API from JavaScript

However all of the sudden indigo refused the calls and I had to restart the server.

No idea on that, but one thing it looks like you changed was an HTTP Method from PUT to EXECUTE... You should probably stick with a PUT (though I think a GET will work on the RESTful API) in case the non-standard method is confusing the server.

Adam

Posted on
Sat Feb 28, 2015 8:44 am
OnnoH offline
Posts: 26
Joined: Nov 05, 2014
Location: The Netherlands

Re: Call REST API from JavaScript

I'm trying to accomplish kind of the same thing using Python.

Code: Select all
import requests
import time
from requests.auth import HTTPDigestAuth

print "Switching ON to 50%"
site = "http://indigo.local:8176/devices/DiningRoom%20-%20OverheadLight"
cmd = "brightness=50"
response = requests.put(url=site, data=cmd, auth=HTTPDigestAuth('admin', 'admin'))
print response
time.sleep(5)
print "Switching OFF"
cmd = "isOn=0"
response = requests.put(url=site, data=cmd, auth=HTTPDigestAuth('admin', 'admin'))
print response
Resulting in the following output
Code: Select all
Switching ON to 50%
<Response [200]>
Switching OFF
<Response [200]>
but no light :(

Using curl
Code: Select all
curl --digest -u admin:admin -X PUT -d brightness=50 http://indigo.local:8176/devices/DiningRoom%20-%20OverheadLight
I achieve the proper result.

What am I missing?

Posted on
Sat Feb 28, 2015 1:13 pm
davinci offline
Posts: 362
Joined: Feb 14, 2015

Re: Call REST API from JavaScript

In your case you could try to use this:

Code: Select all
import subprocess
resp= subprocess.Popen("/usr/bin/curl --digest -u admin:admin -X PUT -d brightness=50 http://indigo.local:8176/devices/DiningRoom%20-%20OverheadLight",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0]

Posted on
Sun Mar 01, 2015 9:18 am
OnnoH offline
Posts: 26
Joined: Nov 05, 2014
Location: The Netherlands

Re: Call REST API from JavaScript

Thanks, but spawning an OS task is a last resort IMHO. Although we're on a Mac, cross platform scripting is always something to consider.

Using a Google Chrome REST Client App didn't bring me much further, so I took your approach of using a curl library: pycurl and here's what I've come up with:
Code: Select all
import pycurl

c = pycurl.Curl()
c.setopt(pycurl.URL, "http://indigo.local:8176/devices/DiningRoom%20-%20OverheadLight")
c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_DIGEST)
c.setopt(pycurl.USERPWD, "admin:admin")
c.setopt(pycurl.CUSTOMREQUEST, "PUT")
c.setopt(pycurl.POSTFIELDS, "isOn=1")
c.perform()
c.close()

As I suspected the way the payload is sent across probably does the trick. A mix and match of PUT and POST. The Indigo REST API expects a PUT (POST gets a 405), but then POSTs form data. I guess the curl command is doing that by default.

Since I've been sniffing around an application with an AngularJS frontend and a RESTeasy Java backend using JSON, I would love Indigo to head in that direction. I thought I've read somewhere that Matt and Jay are considering refactoring their REST API (or having done so already with the TouchApp 2.0). Any light on this guys? :roll:

Posted on
Sun Mar 01, 2015 10:06 am
OnnoH offline
Posts: 26
Joined: Nov 05, 2014
Location: The Netherlands

Re: Call REST API from JavaScript

Having said that, I did some further reading and reverted back to my original code with the requests lib. Changed
Code: Select all
cmd="brightness=100"
to
Code: Select all
cmd = { "brightness":100 }
and I'm in business. Did I mention I just love JSON? Well actually it's a Python dictionary but they look alike 8)

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 1 guest

cron