Make Your Own IoT Twitter Bot

Internet of Things (IoT) is one of the big buzzwords making the rounds these days.

The basic concept is to have lightweight computing platforms integrated with everyday devices turning them into ‘smart’ devices. For example take your good old electricity meter embed a computing platform on it and connect it to the Internet – you get a Smart Meter!

Basic ingredients of an IoT ‘device’ include:

  • A data source, usually a sensor (e.g. temperature sensor, electricity meter, camera)
  • A lightweight computing platform with:
    • low power requirements
    • network connectivity (wireless and/or wired)
    • OS to run apps
  • Power connection
  • Data connection (mobile data, ethernet or WiFi)

In this post I wanted to build a basic IoT sensor using an off-the-shelf computing platform to show how easy it is!

This is also to encourage people to do their own IoT projects!

Raspberry Pi and Tessel2 platforms are two obvious choices for the computing platform.

I decided to use Tessel2 which is lot less powerful than Pi (sort of like comparing a Ford Focus with a Ferrari F40).

Tessel2 has a 580MHz processor, 64MB RAM and 32MB flash (just for comparison Pi3B has a Quad Core 1.2GHz processor, 1GB RAM) – both have Wifi and Ethernet built in.

Pi comes with a Debian based OS with full desktop-class capabilities (GUI, Applications etc.) where as Tessel2 just supports Node.JS based apps (it is running Open WRT) and has no GUI capabilities. Therefore it is lot closer to a IoT platform in terms of capabilities, power requirements and form factor.

Temperature Tweeter Architecture

Temperature Tweeter Architecture

Architecture

Computing Platform: Tessel2

Tessel2 has a set of basic hardware features which includes USB2.0 ports, sensor sockets (where you can plug in different modules such as temperature, GPS, bluetooth) and one Ethernet socket.

Since there is no UI for the Tessel2 OS you have to install the ‘t2’ command line tool to interact with your tessel.

The Tessel2 website has an excellent ‘first steps’ section here.

If you are blessed with a Windows 10 based system you might have some issues with detecting the Tessel2. One solution is to install ‘generic USB drivers’ here. But Google is your friend in case you run into the dreaded: ‘Detected a Tessel that is booting’ message.

Data Source: Climate Sensor Module

The sensor module we use as a data source for this example is the climate sensor which gives the ambient temperature and the relative humidity. The sensor module can be purchased separately and you can connect up to two modules at a time.

Power and Data:

As the sensor is based indoors we use a standard micro-USB power supply. For external use we can use a power bank. The data connection is provided through a wired connection (Ethernet) – again as we are indoors.

The Node.JS Application

Start by creating a folder for your Tessel2 app and initialise the project by using the ‘t2 init’ command within that folder.

Create the node.js app to read data from the sensor and then use the ‘twitter’ api to create a tweet with the data. The application is really simple but shows off the power of Node.JS and the large ecosystem of libraries available for it.

One good thing about the Tessel2 is that because it is such a lightweight platform you really cannot run fulll sized Node.JS apps on it. As a comparison, a single Node.JS instance can use up to 1.8GB of RAM on a 64-bit machine where as Tessel2 has only 64MB RAM in total for everything that is running on it!

Most common type of applications that you will find yourself writing, in the IoT space, will involve reading some value from a sensor or attached device then either exposing it via a REST server running on Tessel2 itself (pull) or by calling a remote server to write the data (push).

In other words you will just end up writing pipelines to run on Tessel2 which read from a source and write to a destination. You can also provide support for cross cutting concerns such as logging, authentication and remote access.

If you want to Tweet the data then you will need to register a Twitter account and create a ‘Twitter app’ from your account settings. All the keys and secrets are then generated for you. The Twitter API for Node.JS is really easy to use as well. All the info is here.

The implementation can be found here: https://twitter.com/machwe_bot

Few Pointers

Don’t put any complex calculations, data processing or analytics functionality in the pipeline if possible. The idea is also that IoT devices should be deploy and forget.

Be careful of the libraries you use. Certain objects such as ‘clients’ and ‘responses’ can be quite large considering the fact that you only have less than 64MB of RAM to play around with. So you might want to run the program locally and profile the memory use just to be sure.

‘t2 run’ command allows you to test your program on the tessel2 while getting console output to your terminal. This is an excellent way of testing your programs. Once you are ready to ‘deploy and forget’ your Tessel2 just use the ‘t2 push’ command to load your Node.JS app on the device. Thereafter every time the device restarts it will launch your app.

Code

This is the code for the ‘Climate Tweeter’:

‘npm install’ will get you all the imports.

var Twitter = require('twitter');
 
var tessel = require('tessel');
var climatelib = require('climate-si7020');
 
// Init Climate Module
var climate = climatelib.use(tessel.port['B']);
 
var data = {
  consumer_key: 'your consumer key',
  consumer_secret: 'your consumer secret',
  access_token_key: 'your access token key',
  access_token_secret: 'your access token secret'
};
 
var client = (new Twitter(data));
 
setInterval(function(){
    if (climate_status) {
        // Read the Temperature and Humidity
        climate.readTemperature('c', function (err, temp) {
          climate.readHumidity(function (err, humid) {
 
            // Output Tweet
            var output = (new Date())+',Bristol UK,Home,Temp(C):'+ (temp.toFixed(2)-5) + ', Humidity(%RH):'+ humid.toFixed(2);
 
            //Tweet to Twitter
            client.post('statuses/update', {status : output}, function(error, tweet, response) {
                    if (error) {												
                        console.error("Error: ",error);
                    }                                                                                                                         
            });     
        });
    });
}},600000);
 
climate.on('ready', function () {
  console.log('Connected to climate module');
  // Climate module on and working - we can start reading data from it
  climate_status = true;
});

What next?

The interesting thing is that I did not need anything external to the Tessel2 to make this work. I did not have to setup any servers etc. I can very easily convert the device to work outdoors as well. I could hook up a camera (via USB) to make this a ‘live’ webcam, attach a GPS and mobile data module with a power pack (for backup) and connect it to your car (via the power port or lighter) – you have a car tracking device.

Enjoy!

 

Time-Series Dashboards with Grafana and Influx DB

I have been collecting currency data (once every hour) over the last couple of years, using a Node.JS retriever. The data goes in to a Mongo DB instance. We store the timestamp and all the currency pairings against the US Dollar (e.g. how may GBPs get you 1 USD).

Some other features we may need:

  • What if we want different pairings? Say we wanted to have pairings against Gold or Euros?
  • We may need to normalise the data if we want to compare the movement of different currencies?
  • We may also need ways of visualising the data (as time series etc.)

To cater to this I decided to bring in Grafana (I did not want to use the ELK stack because I believe if you don’t need text search don’t use elasticSEARCH!). Grafana does not support Mongo out of the box so I had to bring in Influx DB.

Bringing in Influx DB allowed me to integrate painlessly with Grafana (sort of). But as we all know – when you are integrating systems there is a certain minimum amount of pain you have to experience. Juggling around just shifts that pain to hopefully a location where you can deal with it efficiently. I my case I moved the pain to the integration between Mongo and Influx.

I had to create a component that pulls out the raw data from Mongo DB, pumps it through a pipeline to filter (to get the pairings of interest – the full data set has 168 currencies in it!), normalise and inject into Influx DB.

A side note: I used the Influx DB Java API which was REALLY easy to use, this encouraged me to go ahead with the Influx – Mongo integration in Java.

Grifana Influx

Grafana – Influx

I also wanted the Influx – Mongo integration to be ‘on-demand’ so that we can create different pairings against different targets – such as the big 3 against Gold, major currencies against SDR (International Monetary Fund – Special Drawing Rights) etc. and populate different time-series databases in Influx. So I gave the integration a REST interface using Spark-Java.

I did encounter one problem with Grafana – InfluxDB integration was the ‘easy’ query system did not work – I had to create one manually – which is pretty straight forward as the InfluxDB documentation is decent.

Results

I was able to get the dashboards to work with normalised time-series of 6 currencies against Gold (XAU): US Dollar (USD), Indian Rupee (INR), Nigerian Naira (NGN), Euro (EUR), British Pound (GBP) and Chinese Yuan (CNY). I discovered something interesting when I was looking at the data around the ‘Brexit’ vote (23/24 June 2016).

Brexit

The screenshot above is from Grafana. Filtered to show EUR-XAU, GBP-XAU, USD-XAU and NGN-XAU. We see a massive dip in Nigerian Naira before the actual Brexit vote. I was surprised so I googled and it seems that few days before Brexit vote the Naira was allowed to float against USD (earlier it was pegged to it) which led to a massive devaluation.

Then on Brexit day we see a general trend for the selected currencies to fall against Gold as it suddenly became the asset of choice once the ‘unthinkable’ had happened, with the GBP-XAU registering the largest fall. As you can see the Naira also registers a dip against Gold (XAU).

This also shows how universal Gold is. At one time all currencies were pegged against Gold, now unofficially USD is the currency of trade, but this shows when something unthinkable or truly ‘world-changing’ happens people run back to the safety of Gold.

Bots using Microsoft Bot Platform and Heroku: Customer Life-cycle Management

This post is about using the Microsoft Bot Platform with Heroku to build a bot!

The demo scenario is very simple:

  1. User starts the conversation
  2. Bot asks for an account number
  3. Customer provides an account number or indicates they are not a customer
  4. Bot retrieves details if available for a personalised greeting and asks how can it be of help today
  5. Customer states the problem/reason for contact
  6. Bot uses sentiment analysis to provide the appropriate response

Bots

Bots are nothing but automated programs that carry out some well defined set of tasks. They are old technology (think web-crawlers).

Recent developments such as Facebook/Skype platform APIs being made available for free, easy availability of cloud-computing platforms and relative sophistication of machine learning as a service  has renewed interest in this technology especially for customer life-cycle management applications.

Three main components of a modern, customer facing bot app are:

  • Communication Platform (e.g. Facebook Messenger, Web-portal,  Skype etc.): the eyes, ears and mouth of the bot
  • Machine Learning Platform: the brain of the bot
  • Back end APIs for integration with other systems (e.g. order management): the hands of the bot

Other aspects include giving a proper face to the bot in terms of branding but from a technical perspective above three are complete.

Heroku Setup

Heroku provides various flavours of virtual containers (including a ‘free’ and ‘hobby’ ones) for different types of applications. To be clear: a ‘dyno’ is a lightweight Linux container which runs a single command that you specify.

Another important reason to use Heroku is that it provides a ‘https’ endpoint for your app which makes it more secure. This is very important as most platforms will not allow you to use a plain ‘http’ endpoint (e.g. Facebook Messenger). So unless you are ready to fork out big bucks for proper web-hosting and SSL certificates start out with something like Heroku.

Therefore for a Node.JS dyno you will run something like node <js file name>.

The cool thing about Heroku (in my view) is that it integrates with Git so deploying your code is as simple as ‘git push heroku <branch name to push from>’.

You will need to follow a step by step process to make yourself comfortable with Heroku (including installing the Heroku CLI) here: https://devcenter.heroku.com/start

We will be using a Node.JS flavour of Heroku ‘dynos’.

Heroku has an excellent ‘hello world’ guide here: https://devcenter.heroku.com/articles/getting-started-with-nodejs#introduction

 

Microsoft Bot Platform

The Microsoft Bot Platform allows you to create, test and publish bots easily. It also provides connectivity to a large number of communication platforms (such as Facebook Messenger). Registration and publishing is FREE at the time of writing.

You can find more information on the Node.js base framework here: http://docs.botframework.com/builder/node/overview/

The dialog framework in the MS Bot Platform is based on REST paths. This is a very important concept to master before you can start building bots.

Architecture

Microsoft provide a publishing platform to register your bot.

Once you have the bot correctly published on a channel (e.g. Web, Skype etc.) messages will be passed on to it via the web-hook.

You need to provide an endpoint (i.e. the web-hook) to a web app in Node.JS which implements the bot dialog framework to publish your bot. This web app is in essence the front door to your ‘bot’.

You can test the bot locally by downloading the Microsoft Bot Framework simulator.

The demo architecture is outlined below:

Bot Demo Architecture

Bot Demo Architecture

Detailed Architecture for the Demo

There are three main components to the above architecture as used for the demo:

  1. Publish the bot in the Bot Registry (Microsoft) for a channel – you will need your Custom Bot application endpoint to complete this step,in the demo I am publishing only to a web-channel which is the easiest to work with in my opinion. Once registered you will get an application id and secret which you will need to add to the bot app to ‘authorise’ it.
  2. Custom Bot Application (Node.JS) with the embedded bot dialog – the endpoint where the app is deployed needs to be public, a HTTPS endpoint is always better! I have used Heroku to deploy my app which gives me a public HTTPS endpoint to use in the above step.
  3. Machine Learning Services – to provide functionality to make the Bot intelligent, we can have a statically scripted bot with just the embedded dialog but where is the fun in that? For the demo I am using Watson Sentiment Analysis API to detect the users sentiment during the chat.

*One item that I have purposely left out within the Custom Bot app, in the architecture, is the service that provides access to the data which drives the dialog (i.e. Customer Information based on the Account Number). In the demo a dummy service is used that returns hard coded values for Customer Name when queried using an Account Number.

The main custom bot app Javascript file is available below, right click and save-as to download.

Microsoft Bot Demo App

Enjoy!!

Javascript: Playing with Prototypes – II

Let us continue the discussion about Prototypes in Javascript and show the different ways in which inheritance can work. Inheritance is very important because whether you are trying to extend the JQuery framework or trying to add custom event sources in Node.JS you will need to extend an existing JS object.

Let us remember the most important mantra in JS – “nearly everything interesting is an object, even functions”

Objects are mutable, primitives (e.g. strings) are NOT!

Let us first introduce the example. There is a base object: Person which has two properties ‘id’ and ‘age’ and getter/setter methods for these. We want to create a child object: Student, which should inherit the id and age properties from Person and add its own read-only ‘student id’ property.

/*
Base object: Person
*/
function Person(id)
{
  this.id = 0;
  this.age = 0;
}
 
/*
Add set/get methods for Age and Id
*/
Person.prototype.setId = function(id)
{
 
  this.id = id;
};
 
Person.prototype.getId = function()
{
  return this.id;
};
 
Person.prototype.setAge = function(age)
{
 
  this.age = age;
};
 
Person.prototype.getAge = function()
{
  return this.age;
};
 
 
/*
Child object Student which should extend properties and methods from Person
*/
function Student(sid)
{
  this.sid = sid;
 
  /*
  Constructor for Person (to be safe)
  */
  Person.call(this);
  /*
  Student Id getter
  */
  Student.prototype.getSid = function()
  {
    return this.sid;
  }
}

 

There are different ways (patterns) of implementing ‘inheritance’ based (Inheritance Methods):

  • Pattern 1: Student.prototype = Object.create(Student);
  • Pattern 2: Student.prototype = Object.create(Person.prototype);
  • Pattern 3: Student.prototype = new Person;

Below is the snippet of code we use to probe what happens in each of the three cases. Two instances of Student are created (s1 and s2). Then we examine the prototypes and assign values to some of the properties.

<Inheritance Method: one of the three options above>
 
var s1 = new Student(101);
var s2 = new Student(102);
 
console.log("S1",s1);
console.log("S2",s2);
console.log("Proto S1",Object.getPrototypeOf(s1));
console.log("Proto S2",Object.getPrototypeOf(s2));
if (Object.getPrototypeOf(s1) == Object.getPrototypeOf(s2)) {
  console.log("Compare prototypes:",true);
}
 
console.log("\n\n");
 
s1.setId(1);
s1.setAge(30);
console.log("S1",s1.getAge());
 
s2.setId(2);
 
console.log("Compare Id S1:S2",s1.getId(),s2.getId());
 
s2.setAge(20);
console.log("S2 set age 20");
 
console.log("S1 age",s1.getAge());
console.log("S2 age",s2.getAge());

 

Let us look at what happens in each case:

1) Student.prototype = Object.create(Student);

Output:

S1: { sid: 101, id: 0, age: 0 }
S2: { sid: 102, id: 0, age: 0 }
Proto S1: { getSid: [Function] }
Proto S2: { getSid: [Function] }
Compare prototypes: true
 
 
/Users/azaharmachwe/node_code/NodeTest/thisTest.js:73
s1.setId(1);
^
TypeError: Object object has no method 'setId'
at Object.<anonymous> (/Users/azaharmachwe/node_code/NodeTest/thisTest.js:73:4)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3

 

The surprising result is that an exception is thrown. It seems there is no method ‘setId’ on the Student instance. This means that inheritance did not work. We can confirm this by looking at the prototype of S1 and S2 instance. Only the getter for student id defined in the Student object is present. We have not inherited any of the methods from Person.

But if we look at the list of attributes we see ‘id’ and ‘age’ present. So it seems the attributes were acquired somehow.

If we look at the way we define the Person object we actually add the ‘id’ and ‘age’ attributes to the instance (i.e. we use this.id) where as the accessor methods are added on the prototype. When we create an instance of Student as Student.prototype = Object.create(Student) we correctly set the attributes as they are defined at the instance level.

If the line in bold is removed then you will only see the Student level attribute (‘sid’).

 

2) Student.prototype = Object.create(Person.prototype);

Output:

S1: { sid: 101, id: 0, age: 0 }
S2: { sid: 102, id: 0, age: 0 }
Proto S1: { getSid: [Function] }
Proto S2: { getSid: [Function] }
Compare prototypes: true
 
 
 
S1 30
Compare Id S1:S2 1 2
S2 set age 20
S1 age 30
S2 age 20

No errors this time.

So we see both S1 and S2 instances have the correct attributes (Person + Student) prototypes for both contain the getter defined in Student and both have the same prototype. Something more interesting is the fact that we can set ‘age’ and ‘id’ on them as well showing us that the attribute setters/getters have been inherited from Person.

But why can’t we see the get/set methods for ‘age’ and ‘id’ on the Student prototype? The reason is that with the call to Object.create with the Person.prototype parameter we chain the prototype of Person with that of Student. To see the get/set methods for ‘age’ and ‘id’ that the Student instance is using add the following line to the probe commands:

console.log(“>>”,Student.prototype.__proto__);

This proves that the object is inheriting these methods at the prototype level and not at the object level. This is the recommended pattern for inheritance.

3) Student.prototype = new Person;

This is a method you may see in some examples out there. But this is not the recommended style. The reason is that in this case you are linking the prototype of Student with an instance of Person. Therefore you get all the instance variables of the super-type included in the sub-type.

Output:

S1: { sid: 101 }
S2: { sid: 102 }
Proto S1: { id: 0, age: 0, getSid: [Function] }
Proto S2: { id: 0, age: 0, getSid: [Function] }
Compare prototypes: true
 
 
 
S1 30
Compare Id S1:S2 1 2
S2 set age 20
S1 age 30
S2 age 20

Note the presence of ‘id’ and ‘age’ attributes with default values in the prototypes of S1 and S2. If the attributes are array or object type (instead of a primitive type as in this case), we can get all kinds of weird, difficult to debug behaviours. This is the case with frameworks where a base object needs to be extended to add custom functionality. I came across this issue while trying to create a custom Node.JS event source.

Wrong way to extend: A Node.JS example

I have seen many Node.JS custom event emitter examples that use pattern number (3). The correct pattern to use is pattern (2). Let us see why.

The code below extends the Node.JS EventEmitter (in ‘events’ module) to create a custom event emitter. Then two instance of this custom event emitter are created. Different event handling callback functions for the two instances are also defined. This will allow us to clearly identify which instance handled the event.

In the end we cause the custom event to fire on both the instances.

var ev = require("events");
 
/*
Create a custom event emitter by extending the Node.JS event emitter
*/
function myeventemitter(id)
{
  this.id = id;
  ev.EventEmitter.call(this);
}
/*
Try different ways of extending
*/
 
myeventemitter.prototype = new ev.EventEmitter;
 
myeventemitter.prototype.fire = function()
{
  console.log('\nFire',this.id);
  this.emit('go',this.id);
}
 
/*
Initialise two instances of the custom event emitter
*/
var myee1 = new myeventemitter("A");
var myee2 = new myeventemitter("B");
 
/*
Define callbacks on the custom event ('go')
*/
myee1.on('go',function(id)
{
  console.log("My EE1: Go event received from",id);
});
 
myee2.on('go',function(id)
{
  console.log("My EE2: Go event received from",id);
});
 
/*
Cause the custom event to fire on both the custom event emitters
*/
myee1.fire();
myee2.fire();
 
/*
Dump the prototype of our custom event emitter
*/
console.log(myeventemitter.prototype);

Note we are using pattern (3) to extend the EventEmitter:

myeventemitter.prototype = new ev.EventEmitter;

We expect that custom events fired on instance 1 will result in the event handling function on instance 1 being called. The same thing should happen for instance 2. Let us look at the actual output:

Fire A
My EE1: Go event received from A
My EE2: Go event received from A
 
Fire B
My EE1: Go event received from B
My EE2: Go event received from B
{ domain: null,
_events: { go: [ [Function], [Function] ] },
_maxListeners: 10,
fire: [Function] }

This looks wrong! When we cause instance 1 to fire its custom event it actually triggers the event handling functions in both the instances! Same happens when we try with instance 2.

The reason as you may have already guessed is that when we use pattern (3) we actually attach the JSON object that holds the individual event handling functions to the prototype (variable name: _events). This can be seen in the above output.

Therefore both instances of the custom event emitter will have the same set of event handling functions registered because there is only one such set.

To correct this just switch the extension patter to (2):

Fire A
My EE1: Go event received from A
 
Fire B
My EE2: Go event received from B
 
{ fire: [Function] }

The output now looks correct. Only the instance specific callback function is called and the prototype does not store the event handling functions. Therefore each instance of the custom event emitter has its own set for storing event handling functions.