Dino Lupo     About     Archive     Feed

Rest Service With Intel Galileo and XDK from Start to Finish

In this tutorial I’m going to build a node.js rest web service server and client in the IoT platform Intel Galileo gen 2. I realized that I needed a “physical” way to check if some services are performing good or bad in the network. This is a little but working example that could be useful if you want to see real physical alerts based on some good or bad service behaviours. Some examples are: a software factory want to see green or red lights in a room when an integration test has failed or not, or a devops guy wants to know if some important services (e.g. service discovery service in a microservice architecture) are up or down, and so on…

Preliminary Steps:

I’ll use a basic service template from the Dropwizard tutorial. I updated the demo template to use gradle instead of maven. You can clone or fork it from this repo: https://github.com/dinolupo/dropwizard-gradle-onejar-template.git

In this tutorial I’m going to use Intel XDK IoT Edition IDE installed on OSX Yosemite. I’ll be very fast on the XDK download and setup with the board, so, if you want to go slow on that, follow the articles in the reference section at the bottom.

Download XDK from Intel

Register inside a tool for an XDK account if you don’t have any.

This tutorial needs an updated Yocto Linux meta distribution running from a microSD card that must be plugged into the board.

You need to download the latest version of the Yocto boot image iot-devkit-latest-mmcblkp0.direct.bz2, decompress the downloaded image file, and write the extracted image iot-devkit-latest-mmcblkp0.direct to the microSD card. Latest compressed boot image

Pay attention to this procedure, because otherwise you’ll risk to delete all of your content on another drive.

Once you have inserted your micro SD card into your host with a USB or SD adapter (I’m using an SD adapter here), take note of the name of your partition using Disk Utility. My previous micro SD was formatted with GALILEO label as shown in the following image:

Disk Utility shows GALILEO partition

Opening a terminal, you can see the same information plus the crucial one: what’s the block device associated to the SD, using the mount command as follows:

img1

Note that the command will output the mounted partitions, so for example in my case the SD card has 1 partition “s1” with composite device name disk5s1. So cutting the partition from the mounted device name gives you the device (disk) name disk5.

Complete command list:

1) Executing mount

$ mount
/dev/disk0s2 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
/dev/disk0s4 on /Volumes/BOOTCAMP (ntfs, local, read-only, noowners)
/dev/disk2s2 on /Volumes/OXS-Download (hfs, local, nodev, nosuid, journaled, noowners)
/dev/disk1s2 on /Volumes/Volume (ntfs, local, nodev, nosuid, read-only, noowners)
/dev/disk3s1 on /Volumes/TimeMachine3TB (hfs, local, nodev, nosuid, journaled)
/dev/disk5s1 on /Volumes/GALILEO (msdos, local, nodev, nosuid, noowners)

2) Take note of your mounted partition on SD card, in my example is /dev/disk5s1 so the device name is /dev/disk5

3) Unmount the partition /dev/disk5s1:

% sudo diskutil umount /dev/disk5s1
Volume GALILEO on disk5s1 unmounted

4) Be careful with the commands to avoid erasing the wrong device (such as your hard drive!):

[08:34:07]$ sudo dd if=iot-devkit-latest-mmcblkp0.direct of=/dev/disk5 bs=8m
131+1 records in
131+1 records out
1103102976 bytes transferred in 3914.000749 secs (281835 bytes/sec)
[09:40:06]$

As you can see it takes very long to write the image on the microSD card (more than an hour on my 32GB microSD card). So wait until the command finishes and the terminal displays the prompt again, before closing the terminal window.

Put the SD card into Galileo, then plug the Ethernet cable and power on the device. Wait about a minute, until the SD led stops blinking:

img4

Open XDK IDE and select your device:

img3

Set the following options on the IDE:

img6

Node.js code and explanation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Require the HTTP library
var http = require("http");
// Require the MRAA library
var mraa = require('mraa');

// Print the MRAA library version to the IDE console
console.log('MRAA Library Version: ' + mraa.getVersion());

// GREEN LED
var serviceUpLed = new mraa.Gpio(13);
serviceUpLed.dir(mraa.DIR_OUT);

// RED LED
var serviceDownLed = new mraa.Gpio(8);
serviceDownLed.dir(mraa.DIR_OUT);

// YELLOW LED
var serviceHealthWarning = new mraa.Gpio(12);
serviceHealthWarning.dir(mraa.DIR_OUT);

// initialize all led
serviceUpLed.write(0);
serviceDownLed.write(0);
serviceHealthWarningLed.write(0);

// set your service hostname, port and path
var options = {
    hostname: '192.168.5.131',
    port: 8080,
    path: '/hello-world',
    headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            /*'charset':'UTF-8'*/
    },
    //method: 'GET'
};

// request callback, open GREEN led if HTTP 200 - OK
var callback = function(res) {
    res.on('data', function (data) {
        console.log("Got response: " + res.statusCode);
        console.log(data);
        if (res.statusCode==200) {
            serviceUpLed.write(1);
            serviceDownLed.write(0);
        }
    });
}

// call the request every 5 seconds. Set timeout with callback to 1 second to open YELLOW led in case of slow response.
var interval = setInterval(function() {
    serviceHealthWarningLed.write(0);
    var req = http.get(options, callback);

    // if there is an error, open the RED led
    req.on('error', function (err) {
        console.log("Got ERROR: " + err.message);
            serviceUpLed.write(0);
            serviceDownLed.write(1);
    });

    // if request timeout is passed, open the YELLOW led
    req.setTimeout(1000, function() {
        console.log("---> Request Timeout");
            serviceHealthWarningLed.write(1);
    });
}, 5000);

// if you want to run a server, uncomment the following. It could be useful to adjust timeouts or to switch watched services on the fly
//var server = http.createServer(function(request, response) {
//
//    if ((request.method == 'GET') && (request.url = '/someservice')) {
// 		// do something useful
//    }
// });
// Start listening at port 1337
// server.listen(1337);
// console.log("Server is listening at port 1337");

Remember to save, compile and upload every time you do a change to the code:

img5

Now start the Dropwizard service with gradle run and run the node.js program from the IDE, you will see the following:

IDE Console service calls: IDE Console service calls

OSX Terminal calls coming from Galileo: OSX Terminal calls coming from Galileo

Green Led On: Green Led On

From the OSX Terminal where Dropwizard is running, close it pressing <CTRL>-C without closing the running node.js program on XDK (Galileo), you will see:

IDE Console failed calls: IDE Console failed calls

Red Led On: Red Led On

Service Performance Test

Modify the Java service adding a Thread.sleep(2000) instruction, just the necessary time to trigger the configured timeout on the Galileo, here is the full code sample:

package info.dinolupo.resource;

import info.dinolupo.core.Saying;

import com.google.common.base.Optional;
import com.codahale.metrics.annotation.Timed;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import java.util.concurrent.atomic.AtomicLong;

@Path("/hello-world")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
    private final String template;
    private final String defaultName;
    private final AtomicLong counter;

    public HelloWorldResource(String template, String defaultName) {
        this.template = template;
        this.defaultName = defaultName;
        this.counter = new AtomicLong();
    }

    @GET
    @Timed
    public Saying sayHello(@QueryParam("name") Optional<String> name) {
        final String value = String.format(template, name.or(defaultName));
        try {
		Thread.sleep(2000);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
        return new Saying(counter.incrementAndGet(), value);
    }
}

Save the file and run again gradle run, you will see the following:

IDE Console Timeout logs: IDE Console Timeout logs

Green and Yellow leds are on: Green and Yellow leds are on

This is only an example, you’ll need electrical skills to connect high voltage lamps. Thanks for reading.

Resources:

IoT project with Intel Galileo

Add Rest based services to IoT devices

comments powered by Disqus