Showing posts with label BoneScript. Show all posts
Showing posts with label BoneScript. Show all posts

Sunday, August 24, 2014

Creating REST based Web Service using Javascript on the BeagleBone Black

Right after I published the Taking the Temperature with theBeagleBone Black and Javascript, I started thinking about creating a REST based Web Service using Javascript that I could use to read the temperature from a remote device.  For this project I will be using the node.js restify module to create the REST service. 

The TMP36GZ temperature sensor is wired to the Beaglebone Black as show in this diagram.



I always hate running services from within an IDE so I will not use Cloud 9 for this project and instead I will be running the service from the command line using node.js.  So the first thing we need to do is to setup a directory structure that contains the node.js modules needed to run the service.  I used the following steps to get the structure/modules set up (this is based off of the latest Debian image 2014-05-14):

1.  Start off within our home directory.  In Linux the ~ directory is the users home directory.
cd ~

2.  Create a work directory and change to that directory
mkdir temperature
cd temperature

3.  Install the restify module
npm install restify

4.  Copy the bonescript module to our working structure
mkdir node_modules/bonescript
cp /var/lib/cloud9/static/bonescript.js node_modules/bonescript/

At this point you should still be in the temperature directory and both the restify and bonescript modules should be located in the ~/temperature/node_modules directory.   This will let our application use these two modules.

From the ~/temperature directory, create a file called tempServer.js and put the following code in it.

var b = require('bonescript');
var rest = require('restify');

var ip = '0.0.0.0'
var port = '18080'
var path = 'temperature'
var tempPin = 'P9_40';
var currentTemp = 0.0;

b.analogRead(tempPin, readTemperature);
setInterval(function() {b.analogRead(tempPin, readTemperature)},30000);

var server = rest.createServer({
     name : "Temperature"
});

server.get({path : path , version : '0.1'}, getTemperature);

server.listen(port,ip, function() {
     console.log('%s listening at %s ',server.name, server.url);
});

function getTemperature(req, res, next) {
     var tempResponse = {"temperature":currentTemp};
     res.send(200, tempResponse);
}

function readTemperature (aRead) {
     console.log("Geting Temp");
    var x = (aRead.value * 1800/1024);
    var cel = 100*x -50;
    var fah = (cel *9/5)+32;
     currentTemp = fah;
}

This code begins by loading both the bonescript and restify modules that are needed for this application.  We then set the following variables:

ip:  The IP address of the interface to bind too.  By using 0.0.0.0 the server will bind to all available interfaces (this is what we want).
port:  The port to bind too.  Typically web servers bind to port 80 but we do not want to take up that privileged port (and it also requires root access to bind to ports below 1024) so we will use 18080 for our service.
path:  The URL path for our service. 
tempPin:  The pin that will be connected to the TMP36GZ temperature sensor.
CurrentTemp:  Will contain the current temperature.  This will be updated every 30 seconds.

After we set the variables, we then read the temperature using the analogRead function from the bonescript module.  This function will read the voltage from the tempPin and then call the readTemperature function when it has the voltage.  The readTemperature function calculates the current temperature based on the voltage of the pin and stores that temperature into the currentTemp variable.

We use the Javascript setInterval function to call the readTemperature function every 30 seconds to update the currentTemp variable.

Now that we have the temperature and updating it every 30 seconds, we need to create our web service that will respond to our requests.  We start off by creating a server object using restify’s createServer function. 

Next we define what services we wish to offer though this server object.  In this case we only have one service.  This service will respond to HTTP GET requests so the get function from our server object is used to define the service.  This service will listen on the path defined in our path variable and when a request comes in it will call the getTemperature function.

Finally we till the server to listen on the port and interface that we defined in the variables earlier.

The getTemperature function simply creates a JSON object that contains the current temperature and uses the send function from the res response object to send the object back to the client that requested it. 

You can run this application using the following command:

Node tempServer.js

Once it is running you can test it from the Beaglebone black command line using curl like this:

curl localhost:18080/temperature

You can also access the service from a remote machine by using the external IP address of your Beaglebone Black like this (remember to change the IP address to the IP address of your Beaglebone Black):




Taking the Temperature with the BeagleBone Black and Javascript

Where I live the temperature this weekend is into the triple digits so there is no way we are going outside to do anything which means we had time for another project with the BeagleBone.  With the temperatures being so high, we decided to figure out how to take the temperature with the BeagleboneBlack.  To take the temperature we will use a TMP36GZ temperature sensor and will develop the application to read the sensor in Javascript.

The first thing we need to do is to wire the temperature sensor. Here is the wiring diagram for this project:



You will notice that we connected the center pin of the TMP36GZ sensor to pin P9_40, which is an analog pin that can be used with the analogRead and analogWrite functions.

Once we had the sensor wired, we needed to developed an application to read the sensor and print out the temperature.  Here is the code that I wrote:

var b = require('bonescript');

console.log("Started");
var tempPin = 'P9_40';

b.analogRead(tempPin, printTemp);

function printTemp(aRead) {
    console.log("Geting temp");
    var x = (aRead.value * 1800/1024);
    console.log("value " + aRead.value);
    console.log("x:  " + x);

    var cel = 100*x -50;
    var fah = (cel *9/5)+32;
    console.log("Fah:  " + fah);
    console.log("Cel:  " + cel);
}

We begin by loading in the bonescript module using node.js require function.  Next we set the tempPin variable to the pin connected to the TMP36GZ temperature sensor.  In our case, we connected the sensor to pin 40 of the P9 expansion header.

We set the pin mode of the tempPin to ANALOG_OUTPUT so we can read the pin and then called the analogRead function to read the pin.  In the printTemp function we converted the voltage to a Celsius temperature and then the Celsius temperature to Fahrenheit and printed the temperature to the console.


If you recall from my earlier post (http://myroboticadventure.blogspot.com/2014/06/using-javascript-with-bonescript-to.html) that I was not really a fan of the Cloud 9 IDE that came with the Angstrom image however I had not tried the latest version that came with the Debian image.  Since I have the latest Debian image on my test Beaglebone Black, I decided to give the new Cloud 9 IDE a try.  I do like the latest version a lot more and I think I will with hold my judgment on it until I use it a bit more.  I would recommend that if you did not like Cloud 9 before that you should give it a second chance. 

Sunday, July 27, 2014

Comparing the BeagleBone Black and the Spark Core: Remotely turning on an LED



After writing the Spark Core iOS library I started thinking more about being able to control the BeagleBone Black from my iOS devices.  The BeagleBone Black does not have built in Wi-Fi but I normally have my spare BeagleBone Black (non-robot one) connected to my Wi-Fi router with a network cable.  So I started asking myself; how could I control my spare BeagleBone Black from my iOS device with it connected directly to my router?  The answer came in the form of socket.io and bonescript.  

Lets look at how we can use socket.io with bonescript to control one of the user LEDs on the BeagleBone Black.  I used the Cloud9 IDE to write this application so the first thing that I needed to do was to install socket.io where Cloud9 can use it.  To install socket.io run the following commands (Note: I am using Agnstrom Linux, you may need to adjust the paths depending our you flavor of Linux):

cd /var/lib/cloud9
npm install socket.io

Once socket.io is installed, we can open the Cloud9 IDE in our favorite web browser by going to port 3000 of our BeagleBone.  You can do this by opening your favorite browser and entering the IP Address of your BeagleBone followed by colon and 3000 IE:  10.0.1.18:3000. 

Now that we have everything setup, lets write the application to control one of the user LEDs on the BeagleBone black.  In the Cloud9 IDE, create a folder called “RemoteLED”.  We will be creating two files within this folder called toggleled.js and index.html.  Lets look at the toggleled.js file first:

var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
var fs = require('fs');
var b = require('bonescript');

//Set socket.io to listen on port 2080
app.listen(3080);

//my constants
var ledPin = "USR3";
var STATEON = b.HIGH;
var STATEOFF = b.LOW;

//called to initilize the device
setup = function() {
    b.pinMode(ledPin, b.OUTPUT);
    b.digitalWrite(ledPin, STATEOFF);
};

//function called to setup our page
function handler (req, res) {
  //load our index.html page
  fs.readFile('RemoteLED/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading page');
    }

    res.writeHead(200);
    res.end(data);
  });
}

//on method listener
io.sockets.on('connection', function (socket) {
  socket.on('led', function (command) {
    console.log(command);
    if (command == 'on'){
        b.digitalWrite(ledPin, STATEON);
        socket.emit('ledstatus', 'LED is on');
    }else{
        b.digitalWrite(ledPin, STATEOFF);
        socket.emit('ledstatus', 'LED is off');
    }
  });
});

We begin by adding the external modules needed using the require function that comes with node.js.  Next we set socket.io to listen for requests on port 3080 and define three constants.

The setup function is called when the application starts up.  It initializes the LED pin and also turns the LED off so the LED will begin in the OFF state.   The handler function is called when a HTTP request comes in and sends the index.html page, which we will look at shortly, to the client. 

Finally we add an “on” method listener that listens for incoming actions.  In this example, we listen for the ‘led’ action and when a ‘led’ action is received it runs the inner function.  This inner function will turn the LED on if it receives the “on” command otherwise it will turn the LED off.  It also uses the emit function to send a ‘ledstatus’ action back to the client with the current status of the LED.

Now lets look at the index.html file. 

<html>
<head>
    <style>
        .button {height:100px;width:140px;font-size:34px;margin-left:30px;margin-top:50px;}
        .status {font-size:34px;margin-top:50px;margin-left:30px;}
    </style>
    <script src = "/socket.io/socket.io.js" > </script>
    <script>
        var socket = io.connect();
            socket.on('ledstatus', function (data) {
                console.log(data);
                var statusDiv = document.getElementById("status");
                statusDiv.innerHTML = data;
            });
    </script>
    <script>
        function ledOn(){
            socket.emit('led', 'on');  
        }
        function ledOff(){
            socket.emit('led', 'off');
        }
    </script>
</head>

<body>
    <input type="button" name="on" id="onButton" class="button" value="ON" onClick="ledOn();">
    <input type="button" name="off" id="offButton" class="button" value="OFF" onClick="ledOff();">
    <div id="status" class="status">LED is off</div>
</body>
</html>

The interesting parts of this page are between the two “script” tags.  In the first “script” tag we set up a listener that listens for an ‘ledstatus’ action and when it is received it will call the inner function that sets the status label to the message that was received.  This action is sent from the toggleled.js script with the following command:  socket.emit('ledstatus', 'LED is on'); 

The second ”script” tag contains two functions.  These functions are called when the on and off buttons are pressed and uses the emit function to send a ‘led’ action back to the listener in the toggleled.js script that turns the LED on or off.

If you run this code within the Cloud9 IDE you should be able to control User LED from any computer or mobile device that can connect to the BeagleBone Black.  The web page should look like this: 



Now lets look at how we would control the User LED on the Spark Core. I will use Spark’s standard tools and then write an iOS app using my Spark Core – iOS Library that will control the User LED on the Spark Core.  If you do not know how to use Spark’s IDE or flash the Spark Core, please refer to Spark’s getting started page.

Lets begin by looking at the code that we will flash to the Spark Core:

int userLed = D7;
int ledStatus = 0;

void setup()
{
   Spark.function("led", ledController);
   pinMode(userLed, OUTPUT);
   Spark.variable("ledStatus", &ledStatus, INT);
}

void loop()
{
   //doing nothing
}

int ledController(String param)
{
    if (param == "on")
   {
        digitalWrite(userLed, HIGH);
        ledStatus = 1;
        return 1;
   }

    if (param == "off")
    {
        digitalWrite(userLed, LOW);
        ledStatus = 0;
        return 1;
    }
    return -1;
}

In the setup function we begin by making the ledController function available through the Spark cloud by using the Spark.function.  We can send information to the ledController function using a POST request from our client. We also define a variable that can be read using the Spark.variable function using a GET request.  We will turn the LED On or Off with the ledController function and read the LED status from the ledStatus variable.

The ledController function looks at the parameter that was sent in the POST request.  If the parameter is “on”, the function turns the LED on and sets the ledStatus variable to 1.  If the parameter is “off”, the function turns the LED off and sets the ledStatus variable to 0.  If something besides “on” or “off” was sent, the function returns -1.  Once you have the code in Spark’s IDE, you should flash it to your Spark Core.

Now lets look at the iOS application to see how it works.  If you are not familiar with my iOS library for the Spark Core, you can read my blog post about it.  You can download the code from the GitHub repository.  The full source for the iOS application is in the Spark Core GitHub repository under the “SparkComparisonApp” directory.

I do not want to go over the full ViewController class here but I do want to highlight two methods.  

-(void)getStatus {
    SparkTransactionGet *getTransaction = [[SparkTransactionGet alloc] initWithAccessToken:ACCESS_TOKEN deviceId:DEVICE_ID andProperty:STATUS_VAR];
   
    [SparkCoreConnector connectToSparkAPIWithTransaction:getTransaction andHandler:^(NSURLResponse *response, NSDictionary *responseDictionary, NSError *error){
        if(error == nil) {
            NSLog(@"Response: %@",responseDictionary);
            int status = [[responseDictionary objectForKey:@"result"] intValue];
       
            NSString *statusStr = @"off";
            if (status == 1)
                statusStr = @"on";
            _statusLabel.text = [NSString stringWithFormat:@"LED is  %@", statusStr];
        } else {
            NSLog(@"Error: %@",error);
            _statusLabel.text = @"Error Getting Status";
        }
    }];
}

The getStatus method makes a GET request to Sparks Cloud API and retrieves the current status of the LED.  When the status is returned it sets the statusLabel UILabel with the status of the LED.  If an error is returned it sets the statusLabel UILabel to an error message.

-(void)sendRequestWithParameter:(NSString *)parameter {
    NSLog(@"Params: %@",parameter);
    SparkTransactionPost *postTransaction = [[SparkTransactionPost alloc] initWithAccessToken:ACCESS_TOKEN deviceId:DEVICE_ID functionName:FUNCTION andParameters:parameter];
   
    [SparkCoreConnector connectToSparkAPIWithTransaction:postTransaction andHandler:^(NSURLResponse *response, NSDictionary *responseDictionary, NSError *error){
        if(error == nil) {
            NSLog(@"Response: %@",responseDictionary);
        } else {
            NSLog(@"Error: %@",error);
        }
         [self getStatus];
    }];
   
    NSLog(@"Continueing with app");
   
}

@end


The sendRequestWithParameter: method sends a POST request to Sparks Cloud API telling it to turn the LED either on or off depending on what the parameter is.  The parameter should be either “on” or “off” to match the commands on the Spark.  When the response comes back from Spark’s API, acknowledging that the on/off command was received, we then call the getStatus function to retrieve the current state of the LED.

One thing I did notice with the Spark Core is there is a noticeable delay from the time I pressed the on or off button to when the status label was updated.  The delay was less then a second but it was pretty obvious.  I would imagine this delay would not be a problem for most applications but you would just need to account for it.  The response from the BeagleBone Black was all but instantaneous which is what I expected from socket.io. 

Spark’s IDE is all right.  I would definitely rate the Cloud9 IDE above Spark’s mainly because the error messages from Spark’s IDE are really unhelpful.  I wasted a lot of time trying to track down a simple typo.

The architecture of the BeagleBone Black’s application is a lot nicer because the client and server components are contained in one application making it easier to update.  However if you plan on making a commercial product, being able to upload the client application to Apple’s app store would be really nice.

The big advantage that the Spark Core has over the BeagleBone Black is the built in Wi-Fi and it was designed/built to communicate with remote devices.  Spark’s Cloud API is also very easy to use with the REST based API.  Both the BeagleBone Black and the Spark Core have advantages and disadvantages; you will need to see which one fits best with your project.  I will say that I wish the BeagleBone Black had built in Wi-Fi but it does not.