Connecting to Google App Engine

Posted on
  • Hi all,

    I am very often using Google App Engine to host APIs and I have an API up here

    http://hybrisiot.appspot.com/shelves/def­ault

    If you call this with a browser or curl, it will respond with a bunch of JSON. It will take longer upon the first request because GAE just fires up the app, but then from the second request it is pretty fast.

    Now, with the CC3000 connected, I try to get that JSON response. But I get this in the console:

    ERROR: Unable to locate host
    ERROR: Timeout in CC3000 driver (4107)
    Looks like CC3000 has died again. Power cycling...

    Below is the espruino js code.

    require("http").get("http://hybrisiot.appspot.com/shelves/def­ault", function(res) {

      res.on('data', function(data) {
        console.log(data);
      });
    });
    

    I also tried to use the raw request method - could someone maybe also post an example for a POST with url-encoded body? That woudl be awesome.

  • This is strange, but using the "raw" request method it does work. I am posting this here so others can have an example of how to use the request method:

        var options = {
          host: 'hybrisiot.appspot.com', 
          port: '80',
          path:'/shelves/default/status/' + getButtonStatus(), 
          method:'post'
        };
    
        var req = require("http").request(options, function(res)
        {
    		res.on('data', function(data) {
              if (debug) {
    			console.log('> ' + data);
              }
            lights(data);
            setTimeout(postData, 5000); //repeat every 5 sec
    		digitalWrite(LED1,0);
          });
        });
        req.end();
    

    Unfortunately I have a new problem - will create a new thread for that.

  • Great! glad you got it working! It looks like there's some kind of issue with url.parse:

    >url.parse("hybrisiot.appspot.com/shelve­s/default");  
    ={"method":"GET","host":"hybrisiot.appsp­ot.com/shelves","path":"/default","pathn­ame":"/default","search":null,"port":80,­"query":null}
    

    I'll look into that - should be an easy fix which will be in 1v52.

  • Thx Gordon, very cool. BTW would there be a way to extendn the request function to be able to include Request Headers - and potentially access teh response headers?

    In general I am super super super happy not to have to deal with the parsing of the raw response, e.g. data in the on('data') even contains the pure body of the response, not the raw headers around it (that's so painful on Arduino).

    But I assume sometimes it woudl be nice to access headers. e..g. res.body woudl be the body, by res.headers a map with the headers.

    In another post I mentioned that I have issues with the stability. I get erros from the CC3000 but once these happens I have no way to restart the device, other than pressing reset. And especially here in an office environment, the likelihood to get the CC3000 connected and a few requests sent out is very low. The max. number of consecutive post requests I was able to send is two :-) then the CC3000 crashed and all stopped.

    Any idea?

  • Are you using 1v51 of Espruino? That had some changes that really improved stability. I've also done a few more tweaks that'll appear in 1v52 and that should improve matters fuirther.

    Also are you sure you're connecting to VBat and not 3.3v, as the 3.3v regulator won't supply enough power for the CC3000...

    As far as the request headers, they're pre-parsed in req.headers / res.headers:

    >require("http").createServer(function (req, res) {
    :  console.log(req.headers);   
    :  res.writeHead(200, {'Content-Type': 'text/plain'});
    :  res.end();
    :}).listen(8081);  
    ...
    {"Host":"localhost:8081",
     "Connection":"keep-alive",
     "Accept":"text/html,application/xhtml+xm­l,application/xml;q=0.9,image/webp,*/*;q­=0.8",
     "User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36",
     "Accept-Encoding":"gzip,deflate,sdch",
     "Accept-Language":"en-GB,en-US;q=0.8,en;­q=0.6"}
    

    and

    >require("http").get("http://www.pur3.co­.uk/time.php", function(res) {
    :  console.log(res.headers);   
    :});                                                  
    ...
    {"Date":"Thu, 20 Feb 2014 16:25:35 GMT",
     "Server":"Apache/2.2.14 (Ubuntu)",
     "X-Powered-By":"PHP/5.3.2-1ubuntu4.18",
     "Vary":"Accept-Encoding",
     "Content-Length":"8",
     "Connection":"close",
     "Content-Type":"text/html"
    }
    

    The only thing you can't do currently is easily get the 'body' of the HTTP server request.

  • Hi @Gordon, yes 1.51. THX for vbat, i had 3.3 To 3.3 and VIN in cc3000 to vbat. Removed the one cable now, I'll see if that makes it better.

    For headers I was thinking outgoing requests, e.g. setting the headers to a request for a remote server call.

    Will report later once I am home.

  • For headers I was thinking outgoing requests

    Looks like you can do that too, just like node.js - not that I remember implementing it :)

    Untested, but:

    var options = {
          host: 'hybrisiot.appspot.com', 
          port: '80',
          path:'/shelves/default/status/' + getButtonStatus(), 
          method:'post',
          headers: { "A":"B", "C":"D"} // <----------------- Here
        };
        var req = require("http").request(options, function(res) { ... });
    
  • Hi @Gordon, the "hidden" headers feature is cool, thx!

    I am now at home, e.g. a "nice" WiFi environment with only a few devices. I just implemented a tiny counter in the request calls and the maximum requests before it somehow stalled is 22. I have a 2 second delay between the requests right now. The espruino is still working btw, I have a toggle on an LED (interval) and the LED is still flashing. But the 23 request now does not seem to be able to complete.

  • Try the new firmware suggestion from the other post - it might help...

    Otherwise, are you only initiating another setTimeout when the request completes successfully, or are you using setInterval? setInterval would be better, as a request may well fail at some point because of the connection (but hopefully the next one will succeed).

  • I seem to be not successful with the Xively - I used a REST client which gave me the info that it works with HTTP, too, so I gave it a try:

    PUT http://api.xively.com/v2/feeds/184885797­4
    header: X-Api-Key: RMspyWqYIq1m9vEyuF9Q9BLpngLf4Tr1MlEhmDnH­TbAjQvG8
    body: counter,2

    in JS it looks like this - but was not able to get a request through:

    function putXively() {
    	digitalWrite(LED1,1);
    
        var options = {
          host: 'api.xively.com', 
          port: '80',
          path:'/v2/feeds/1848857974', 
          method:'put',
          headers: { "X-ApiKey":"RMspyWqYIq1m9vEyuF9Q9BLpngLf­4Tr1MlEhmDnHTbAjQvG8" }
        };
    
        var req = require("http").request(options, function(res)
        {
    		res.on('data', function(data) {
            setTimeout(putXively, 2000);
    		digitalWrite(LED1,0);
          });
        });
        req.end("counter," + counter++);
    }
    

    Yes, I posted my API key. Don't care, this is for testing. Feel free to use exactly the same key. The feed is also public, e.g. can be accessed via https://xively.com/feeds/1848857974

    I made a few test calls via RESTclient, so some data is there. But unfortunately did not get a request through via the Espruino+CC3000.

  • The main issue was that you wrote put, not PUT - but otherwise it looks like by default it uses the JSON API. You might be able to append .csv to the URL to fix that though? https://xively.com/dev/docs/api/data/wri­te/multiple_datapoints_to_single_datastr­eam/

    counter = 1;
    function putXively() {
        content = JSON.stringify({
         version : "1.0.0",
         datastreams : [ { id:"counter", current_value:counter++ } ]
        });
        var options = {
          host: 'api.xively.com',
          port: '80',
          path:'/v2/feeds/1848857974',
          method:'PUT',
          headers: { "X-ApiKey":"RMspyWqYIq1m9vEyuF9Q9BLpngLf­4Tr1MlEhmDnHTbAjQvG8", "Content-Length":content.length }
        };
        var req = require("http").request(options, function(res)  {
            res.on('data', function(data) {
            print("->"+data);
            setTimeout(putXively, 2000);
          });
        });
        req.end(content);
    }
    
  • Also, just to point out that it wanted a content-length too.

    It seems to work well. I'll have to get something set up now ;)

  • I just added something here, using a DHT11 sensor: http://www.espruino.com/wifi_humidity

  • Thx @Gordon. I took that tutorial as a base. I added a LDR to track the light intensity and also a super simple soil sensor (could be done with two nails). After experimenting with Solar-powered, I burnt a CC3000 or it was just time for that one to die... and I am still fighting the stability. It runs a few hours sometimes, but then I am unlucky and it will stop just after I left (like today). A nicely resetting CC3000 without removing all timers in case of an error would be awesome. It is still great now, I just have to hit the reset button from time to time.

  • Yes, I'll look at that. This is the failure you get when it gives error code 1? It'll be a pretty easy fix I hope.

  • Not quite sure what you mean with error code 1 - it is the CC3000 issue that happens when connect (most likely) is called. It seems to drop all watches and intervals then, which means the device does not run the "sendToXively" function any more.

    Thx again!

  • Yes, that's what I found - as in another post, this should be fixed in 1v56...

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Connecting to Google App Engine

Posted by Avatar for hansamann @hansamann

Actions