Make an ARTIK Weather Station with libcurl and Node.js

This blog is the third article in our Weather Station series. In this post, we are going to introduce a few other ways to develop an IoT weather station for both native and web developers. You will want to read the previous two articles in the series Make an IoT Weather Station with SAMI and Make an IoT Weather Station with ARTIK, Temboo and SAMI – they provide background and information on how to set up the hardware and get a SAMI device ID and token.

Hardware components

ARTIK 10 development board with a network connection • Temperature sensor (TMP36) • Breadboard with wiring

SAMI device ID and token

Follow the “Connect to SAMI” section in the Make an IoT Weather Station with SAMI post to create a temperature sensor entry in SAMI. Keep a copy your device ID and device token.

For native developers…

Generic GPIO functions

We will start with the WeatherStation.c generated in our second Weather Station blog post. The generic GPIO functions meet our basic requirements for GPIO operations. We will continue using them.

bool  digitalPinMode(int pin, int dir)
int   analogRead(int pin)
int   digitalRead(int pin)
bool  digitalWrite(int pin, int val)

Post temperature data to SAMI by using libcurl

Posting temperature data to SAMI is a simple HTTP POST operation, which we implemented in the runPost() function. This time, we will use cURL to post our temperature data. cURL is used to transfer data to or from a server. It supports HTTP, FTP, SCP, and other protocols. cURL has two parts: the libcurl library and a command-line tool, cURL. Both libcurl and cURL are pre-installed in our ARTIK 10 binary. The libcurl client-side library is thread-safe, fast, and IPv6 portable. We can use its “easy” interface to make ARTIK communicate with SAMI programmatically. You can replace runPost() with the httpPostToSAMI() function below. As with runPost(), we pass the temperature as part of the request body.

char* samiUrl = "https://api.samsungsami.io/v1.1/messages";
char* device_id="INSERT_YOUR_DEVICE_ID_HERE";
char* device_token="INSERT_YOUR_DEVICE_TOKEN_HERE";
void httpPostToSAMI(float temperature) {
  CURL *curl;
  CURLcode res;
  printf("Running Http Post...n");
  curl = curl_easy_init();
  if (curl) {
	/* construct http header */
	struct curl_slist *requestHeader = NULL;
	char bearer[60]=;
	requestHeader = curl_slist_append(requestHeader, "Content-Type: application/json");
	sprintf(bearer, "Authorization: Bearer %s", device_token);
	requestHeader = curl_slist_append(requestHeader, bearer);
	char requestBody[256]=;
	sprintf(requestBody,"{n  "sdid": "%s",n  "type": "message",n  "data": {n        "temperature": %f                                  n    }n}", device_id, temperature);
	curl_easy_setopt(curl, CURLOPT_URL, samiUrl);
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, requestHeader);     
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestBody);     
	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
	res = curl_easy_perform(curl);
	if (res != CURLE_OK)
		fprintf(stderr, "curl_easy_perform() failed: %sn",
			curl_easy_strerror(res));
	curl_slist_free_all(requestHeader);
	curl_easy_cleanup(curl);  
}  return;
}

Compile with libcurl

The final WeatherStationLibcurl.c can be found here. If you are developing on the host machine, you can copy WeatherStationLibcurl.c to your ARTIK board using scp. Run scp from your computer. Make sure you use the IP address of your board in the command below: $ scp WeatherStationLibcurl.c root@xxx.xxx.xxx.xxx:/home On the ARTIK board, compile with the built-in gcc compiler, then run it. # gcc WeatherStationLibcurl.c -o WeatherStationLibcurl –lcurl # ./WeatherStationLibcurl Your weather station will post temperature data to SAMI every 10 seconds. Log into the SAMI User Portal to view your collected data in real-time.

For web developers…

Now let’s switch gears and talk about implementing Weather Station on ARTIK 10 using JavaScript and Node.js. Node.js is an open source, cross-platform runtime environment for developing web applications that has become wildly popular over the past few years. Best of all, we’ve preloaded Node.js for ARM in the ARTIK 10 binary! You can build this app from scratch, but if you already built it on the Raspberry Pi from the earlier tutorial, you’ll be able to port it to ARTIK with minimal changes. You will need to manually install the Node Package Manager on ARTIK 10 by running this command: #curl –L https://www.npmjs.com/install.sh | sh

Access GPIO pins from web application

Voltage values for the analog pins are accessible from /sys/devices/12d10000.adc/iio:device0/in_voltageX_raw. Since we are reading temperature sensor voltage from Pin 7, the file we use should be /sys/devices/12d10000.adc/iio:device0/in_voltage7_raw. We only need to read from this file and convert its voltage data into temperature value. To implement this, we will use the Node.js fs module.

var fs = require('fs');
fs.readFile("/sys/devices/12d10000.adc/iio:device0/in_voltage7_raw", 'utf8',function(error, sensorVal) {
   var voltage = sensorVal;
   voltage /= 1024.0;
   temperatureC = (voltage - 0.5) * 100;
   temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
   console.log(temperatureF);
});

Post temperature data to SAMI by using Node.js

To post temperature data to SAMI, we can use either SAMI’s REST API or WebSockets.

REST API

If you choose to use SAMI’s REST API, you will need to add the node-rest-client package to your ARTIK via npm first: #npm intall node-rest-client Here is the code snippet to build your REST call and send it to the server.

var samiURL = "https://api.samsungsami.io/v1.1/messages";
var bearer = "Bearer INSERT_YOUR_DEVICE_TOKEN_HERE";
var device_id = "INSERT_YOUR_DEVICE_ID_HERE";
var fs = require('fs');
var Client = require('node-rest-client').Client;
var c = new Client();
function build_args (temp, ts) {
    var args = {
		headers: {
			"Content-Type": "application/json",
            "Authorization": bearer            
			},
            data: {
				"sdid": device_id,
                "ts": ts,
                "type": "message",
                "data": {
					"temperature": temp
					}
				}
			};
	return args;
}function sendData(temperature){
  var args = build_args(temperature, new Date().valueOf());
  c.post(samiURL, args, function(data, response) {
  console.log(data);
  });
}

We then collect temperature sensor data every 10 seconds, and invoke sendData() to upload our data to SAMI. The final code can be found here. Finally, fire it up by calling: #node WeatherStation_restclient.js

WebSockets

In the REST call above, a connection to SAMI is initiated for each HTTP request and terminated after the response is received. A new connection thus needs to be established for each subsequent HTTP request/response. With WebSockets, the same TCP connection is maintained for the lifecycle of the WebSocket. To use WebSockets, install the ws module on your ARTIK: #npm install ws Please refer to the SAMI WebSockets API documentation to learn how to register your device with SAMI and send bi-directional data between your ARTIK and SAMI. Here is the code to create a WebSocket, register your device, and send messages.

var webSocketURL = "wss://api.samsungsami.io/v1.1/websocket?ack=true";
var device_token = "INSERT_YOUR_DEVICE_TOKEN_HERE";
var device_id = "INSERT_YOUR_DEVICE_ID_HERE";
var fs = require('fs');
var WebSocket = require('ws');
var isWebSocketReady = false;
var ws = null;/**
 * Create a websocket bi-directional connection
 */
 function start() {
	//Create the websocket connection
	isWebSocketReady = false;
	ws = new WebSocket(webSocketURL);
	ws.on('open', function() {
		console.log("Websocket connection is open ....");
		register();     });
		ws.on('message', function(data, flags) {
			console.log("Received message: " + data + 'n');
		});
		ws.on('close', function() {
			console.log("Websocket connection is closed ....");
		});
}
/**  
* Sends a register message to the websocket and starts the message flooder
*/
function register(){
  console.log("Registering device on the websocket connection");
  try {
	var registerMessage = '{"sdid":"'+ device_id + '"' + ', "type": ' + ' "register"' + ', "Authorization": "bearer ' + device_token + '"' + '}';
    console.log('Sending register message ' + registerMessage + 'n');
    ws.send(registerMessage, {mask: true});
    isWebSocketReady = true;
	}  catch (e) {
	console.error('Failed to register messages. Error in registering message: ' + e.toString());
	} 
}
/** 
* Send temperature data to SAMI 
*/
function sendData(temperature){
  try{
	ts = ', "ts": '+ new Date().valueOf();
    var data = {
		"temperature": temperature,
	};
    var payload = '{"sdid":"'+ device_id + '"' + ts + ', "type": ' + ' "message" ' +', "data": '+ JSON.stringify(data) + '}';
	console.log('Sending payload ' + payload);
	ws.send(payload, {mask: true});
    } catch (e) {
		console.error('Error in sending a message: ' + e.toString());
	}
}

The rest of the implementation is identical to the REST implementation above. We read temperature data every 10 seconds and call sendData() to post the data to SAMI. You can find the source code here. Run the app: #node WeatherStation_websocket.js We hope this series has given you a feel for ARTIK’s development options. ARTIK packs a lot of power in a very small package, and gives you the flexibility to develop your way!