Getting a working AJAX example.

Hello Fluksonians,

My name is Roan and I'm a newcommer to the community.
We are using a Fluksometer for our school project and don't have it employed yet.
However, we do want to start developing our mobile wepapplication.
Using the information of this post: https://www.flukso.net/content/jsonrest-api-released (it seems a bit outdated to me) we are trying to create a working AJAX example.

This is our code:
// Create request
var xhr = new XMLHttpRequest();
var interval = 'interval=hour';
var unit = '&unit=watt'
var url = 'https://api.flukso.net/sensor/c1411c6b4f9910bbbab09f145f8533b9?' + interval + unit;
xhr.open('GET',url,true);

//Set headers
xhr.setRequestHeader('Accept','application/json');
xhr.setRequestHeader('X-Version','1.0');
xhr.setRequestHeader('X-Token','d8a8ab8893ea73f768b66b45234b5c3a');

//Send request
xhr.send();

The error I am recieving in my console is: "NetworkError: 405 Method Not Allowed - https://api.flukso.net/sensor/c1411c6b4f9910bbbab09f145f8533b9?interval=hour&unit=watt"
Also the URL visited at https://api.flukso.net/sensor/c1411c6b4f9910bbbab09f145f8533b9?interval=... is perfectly blank. Shouldn't I get data? I Googled the error and it says 'Method not allowed' is only ever seen when using a POST where POST is not alllowed.

The token and sensor id are directly copied from the 'working' example. The headers seem okay too. Is the working example still valid? Is there any other test server I can connect to trough the API? To be clear again: I do not currently have acces to a own Fluksometer yet, so There is no way for me to get my own sensor id or token.

Is there anybody that can help me further setting up my AJAX example on a Flukso test server?

Have a great day,
Roan.

fusionpower's picture

Haven't done much of this json and api stuff but i believe you need to include the api version in the URL and also the unit should probably be watt not wat.
Try https://api.flukso.net/sensor/c1411c6b4f9910bbbab09f145f8533b9?version=1...
it seems to return data even if the values are nan.
Maybe that sensor has no data? I tried the URL i mentioned above with one of my sensors and it returns valid data.
Hope this helps.

rzuman's picture

The url now indeed returns sensor data (Even if it is NAN)
I still can't acces the API with my AJAX code however.

Setting just the header: xhr.setRequestHeader('Accept','application/json');
Returns a 400 Bad Request.
Setting the headers:
xhr.setRequestHeader('X-Version','1.0');
xhr.setRequestHeader('X-Token','d8a8ab8893ea73f768b66b45234b5c3a');
Return a 405 Method Not Allowed.

After doing a little inspecting I found that when setting any other header then Accept, my browser (FF)
sends out a OPTIONS method first before sending the GET method. The OPTIONS method is to see which headers the server accepts. However, according to this article: http://stackoverflow.com/questions/11300874/backbone-fetch-request-is-op...
The server of Flukso doesn't know how to correctly handle the OPTIONS method. I can see that connecting to the Flukso API from the server-side goes fine, but client-side using AJAX it fails.

Is there any way I could get more information from a API developer or submit a Bug Report?

Roan.

gebhardm's picture

For a PHP class to access the FLM's API see https://www.flukso.net/content/flukso-api-php-class - this may help as an example to gather data. You may switch to local API access on testing to not bother the flukso website with too many requests... The FLM manual on the Install menu also provides evidence for allowed parameter values. I must admit that I switched over to the local MQTT broker... (see https://www.flukso.net/content/mqtt-mq-telemetry-transport) as this is, at least for local access, much more stable than the REST interface that sometimes sees dropouts...

rzuman's picture

Thank you for your response Gebhardm,

For our project - local acces (or even local testing) is not really an option since we have to develop
a Javascript driven interface to connect to external Fluksometers at home of our users.
PHP can be an option, since the API is accesible by the server-side. This would however mean
we have to use Javascript to connect to PHP (essentially creating our own API) and PHP in return connects to the Flukso API. Which doesn't really make sense since you can in theory acces the API with just a XMLhttpRequest in Javascript.

Because of the default way browsers work, they first send a OPTIONS method to the API, followed by a GET method. The OPTIONS method is not recognized by the server and trows an error. So basicly, the JSON/REST API from Flukso can not be used in Javascript.

I'm still trying to find a way to bypass this, and otherwise I will indeed use PHP and cURL.
Thanks for all your suggestions so far,

Roan.

icarus75's picture

1/ Please consult the Fluksometer Manual, chapter 3 to see how a REST call to api.flukso.net should be formatted.
2/ I do think the API can be accessed from Javascript since it's used for fetching the dash page's data points. So every time you look at a dash chart a successful REST call from within JS was made. To see how the call is set up, have a look at the relevant code on github. Start with line 534.

rzuman's picture

The dashboard works because it reqeusts from the same origin. (flukso.net/api).
When requested from an other origin (read domain) a safety mechanism triggers.
If you add additional headers (like x-token and x-version) the browser sends a preflighted request using
the OPTIONS method. The response I get form the Flukso server is simply telling me that it only accepts GET and POST, and then aborts..

-- Server response --
Allow POST, GET
Connection keep-alive
Content-Length 0
Date Fri, 08 Nov 2013 15:26:38 GMT
Server nginx/1.4.1

-- Server request -- (not that this is the forced, preflighted request with OPTIONS method)
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language nl,en-us;q=0.7,en;q=0.3
Access-Control-Request-He... x-token,x-version
Access-Control-Request-Me... GET
Cache-Control no-cache
Connection keep-alive
DNT 1
Host flukso.net
Origin null
Pragma no-cache
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0

-- Read more about the OPTIONS method here --
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redire...
( Applies to all browsers, not just Mozilla's)

As we speak, I still find myself unable to connect using Javascript.
I will try other solutions this weekend..

jonne's picture

@rzuman: did you manage to solve this issue? I'm facing the exact same problem. Thanks for sharing the solution if you did!

rzuman's picture

The Flukso API is NOT directly accesible by AJAX methods. This is caused by not accepting the OPTIONS method that a browser (client) always sends first. Only Flukso can acces the API trough AJAX because it runs on the same domain. Alternativly, it is still posible to acces a LOCAL Flukso sensor which is on the same WIFI network as where the browser is running.

My solution: I've written my own API in PHP using Curl (should be standard most of the time)
//Get Flukso data
function getFlukso($sensor_id,$sensor_token,$sensor_interval,$sensor_unit) {
//Flukso URL
$api_url='https://api.flukso.net/sensor/';

//Which headers we send to Flukso?
$header=array();
$header[]="Accept: application/json";
$header[]="X-Version: 1.0";
$header[]='X-Token: '.$sensor_token;

//Construct the request
$request = $api_url.$sensor_id;
$request.='?interval='.$sensor_interval.'&unit='.$sensor_unit;

//Initiate cURL
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$request);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$data = curl_exec($ch);
curl_close($ch);

$array = json_decode($data);

for($i = 0; $i < count($array);$i++){
$array[$i][0] = date('d-m-Y h:i:s', $array[$i][0]);
}

$data = json_encode($array);
echo $data;

}

And then Request this PHP file trough AJAX from the same domain.

To summerize: Javascript (AJAX) > PHP (Curl) > Flukso API
Javascript (AJAX) > Flukso API Does NOT work!

icarus75's picture

@rzuman The current Flukso API doesn't support CORS. I will look into that. But you can extract data out of the Flukso API from another origin by by using JSONP. In JQuery you can use the getJSON() method and append the "callback=?" string to the query params. The Flukso dash uses JSONP by default, see the github code line 534. You can also search for jsonp in the Fluksometer Manual.