Tracking Environmental Data With LTPS and Keen.IO

DZone 's Guide to

Tracking Environmental Data With LTPS and Keen.IO

Temperature and humidity measurements are common, useful projects. In this case, collect and analyze data with Keen.IO's cloud and Tibbo's hardware.

· IoT Zone ·
Free Resource

Keen.IO is a cloud platform that provides data collection and analysis services via REST API. Keen offers SDKs for many programming languages, including browser-side JavaScript and Node.js. In this tutorial, we used Tibbit #30 (ambient humidity and temperature meter) for collecting environmental data and storing it on the Keen.IO server.

A very simple in-browser application is used for fetching data from Keen.IO and displaying charts in the browser window (the charts below have been received from Keen.IO, they are not static). Data collection and representation are separated into device.js and server.js applications.

Temperature, C Humidity, %

What You Need


  Proposed Tibbit configuration

Onboard Software

  • Node.js V6.x.x (pre-installed during production).

External Services

  • Keen.IO (you should create an account).

GitHub Repository

Setting Up External Services

  • Create a Keen.IO account (free for up to 50,000 events per month).

  • Add your project.

  • Click on the title of the project to open an overview tab:

Image title

  • Receive your projectID and API keys (you need read and write keys):

    Store the keys securely, especially the master one:

Image title

Node.js Application

Configuration and Installation

git clone https://github.com/tibbotech/keenio-tutorial.git
cd keenio-tutorial
npm install .
  • Launch the app:

node device

Note the comments in the code – they explain how it works:

// requires Keen.IO client module
const Keen = require('keen.io');

// requires Tibbo's humidity/temperature meter and sets it up to work with I2C line 4
const humTempMeter = require('@tibbo-tps/tibbit-30').init("S5");

// Binds the client to your account
const client = Keen.configure({
    projectId: "57066...........fe6a1279",
    writeKey: "0d2b95d4aa686e8274aa40604109d59c5..............4501378b3c193c3286608"

// Every minute..
    // ..reads the environmental data from the meter..
    var data = humTempMeter.getData();

    // ..checks out if everything's correct..
    if(data.status === 1){
        var payload = {
            hum: data.humidity,
            temp: data.temperature

        // ..and submits them to your event collection.
        client.addEvent("humtemp",  payload, function(err){
            if(err !== null){

Web Interface


  • The web interface application can be installed on your PC, a remote server, or executed on the same LTPS device (as a separate process).

  • Install the application (skip if running on the same LTPS):

git clone https://github.com/tibbotech/keenio-tutorial.git
cd keenio-tutorial
npm install .
  • Launch:
node server

Note the comments in the code – they explain how it works:


        var client = new Keen({
            projectId: "5706............fe6a1279",
            readKey: "29ec96c5e..........746871b0923"

        // Configures NVD3 charting engine
        $scope.options = {
            chart: {
                type: 'lineChart',
                height: 300,
                margin: {
                    top: 20,
                    right: 20,
                    bottom: 40,
                    left: 55
                x: function (d) {
                    return d.x;
                y: function (d) {
                    return d.y;
                useInteractiveGuideline: true,
                xAxis: {
                    axisLabel: 'Time',
                    tickFormat: function (d) {
                        return d3.time.format("%X")(new Date(d));

        $scope.temperature = [
                values: [],
                key: 'Temperature',
                color: 'red'

        $scope.humidity = [
                values: [],
                key: 'Humidity',
                color: 'blue'

        // Defines Keen.IO query
        var query = new Keen.Query("multi_analysis", {
            event_collection: "humtemp",
            timeframe: {
                start : "2016-04-09T00:00:00.000Z",
                end : "2016-04-11T00:00:00.000Z"
            interval: "hourly",
            analyses: {
                temp : {
                    analysis_type : "average",
                    target_property: "temp"
                hum : {
                    analysis_type : "average",
                    target_property: "hum"

            // Executes the query..
            client.run(query, function(err, res){

                // ..transforms the received data to be accepted by NVD3..
                    var timestamp = new Date(record.timeframe.end);
                        x: timestamp,
                        y: record.value.temp.toFixed(2)
                        x: timestamp,
                        y: record.value.hum.toFixed(2)

                // ..and does rendering


        <link href="http://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.2/nv.d3.min.css" rel="stylesheet" type="text/css">

        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"/>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-nvd3/1.0.6/angular-nvd3.min.js" type="text/javascript"/>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/keen-js/3.4.0/keen.min.js" type="text/javascript"/>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js" type="text/javascript"/>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.2/nv.d3.min.js" type="text/javascript"/>

        <script src="browser.js" type="text/javascript"/>

    <body ng-app="chart" ng-controller="nodejs-keen">
        <h3>Temperature, C</h3>
        <nvd3 options="options" data="temperature">

        <h3>Humidity, %</h3>
        <nvd3 options="options" data="humidity">

node js ,sensors ,ltps ,iot ,temperature ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}