When a Chatbot Meets Arduino

If you have worked with IOT projects that integrate with other web apps or any other types of system you probably must be dealing with 10 different languages and frameworks, it’s painful. It also gets chaotic to maintain the code base in different language and repository. In such areas of troubles, Nodejs/javascript gives out some ray of hope. In this post, we will create a chat bot that will be able to communicate with Arduino board and its connected sensor and this entire project will be in Nodejs just one language javascript. Nodejs is chosen because it excels at handles I/O operations.

#Motivation

I have done a couple of chat bot projects, the amazing thing about chat bots is their ease of availability. You don’t have to install another app/plugin on your phone/computer it’s available right in your messenger app just like a jinni waiting to fulfill your wish. And I have also done some side projects on Arduino board, integrating Arduino projects with other systems can be a little tricky, you can have a sensor reading been displayed on a 16x2 LCD, that is cool but it’s can be super cool if it could be delivered in you Messenger app with so suggestions on what action could we do next like if light sensor show reading of 10% or below and its evening then turn on the light or if temperature drops below 10 C the turn on the heater etc. In this post, I have tried to mix the concept of chat bots and Arduino interacting physical world.

#Software required

  1. Messager platform - Telegram bot API’s are simple to use and there are nice npm modules available which can help us to do quick prototyping.
  2. Nodejs IOT framework - there are several frameworks available like breakoutjs, firmatajs and johnny-five, but I am going to use johnny-five no specific reason.
  3. Arduino IDE - Arduino Standard firmware is not going to work with the johnny-five library, we need StardardFirmataPlus Arduino firmware to communicate with the johnny-five library. johnny-five uses Firmata protocol to communicate with the microcontroller, I will get back to this in the later part of the post.

#Hardware required

  1. Arduino Uno
  2. Light dependent resistor
  3. Breadboard
  4. Jumper wires

Plan of the post is not to create some sophisticated hardware application but just to illustrate the concept, so one sensor is enough for that.

#Basic project setup

We are going to use a couple of Nodejs packages which are :

  1. johnny-five - IOT framework as discussed before.
  2. node-telegram-bot-api - High-level wrapper for Telegram bot API’s that takes care of message polling etc, and give nice callback function just to deal with the incoming messages.

To setup the project execute the commands below

1
2
3
4
mkdir iot-bot && cd iot-bot;
npm init -y
npm install --save johnny-five
npm install --save node-telegram-bot-api

#Setting up Arduino for johnny-five

To use johnny-five with Arduino we have to upload StandardFirmataPlus firmware to Arduino. So what exactly is StandardFirmataPlus again? In simple terms it’s a general purpose sketch which you don’t program the explicitly sketch to read/write data for particular pins instead, the sketch is programmed to read commands from the host computer to which Arduino is connected and execute it. The command could be writing/reading data to/from Arduino pins. All this is done with a Firmata protocol. It is contrary to the traditional Arduino sketch we write that has all the logic on how to deal with sensor data. Logic is moved to the host computer instead, and a general purpose sketch is uploaded to Arduino that just knows how to deal with I/O pins.

To install StandardFirmataPlus firmware go to File > Examples > Firmata > StandardFirmataPlus it will open up Arduino sketch upload the sketch to Arduino board. To test if everything went right execute the below javascript code on your host computer to which Arduino board is connected and you should get Board is ready printed on your terminal.

1
2
3
4
5
6
var five = require("johnny-five");
var board = new five.Board();

board.on("ready", function() {
console.log("Board is ready")
});

Arduino Schematic diagram

Getting console greeting is not enough, follow the below schematic to connect a light dependent resistor with Arduino board, javascript code below we will read the value of light sensor data from pin A0 and print it on the console.

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
var five = require("johnny-five");
var board = new five.Board();

board.on("ready", function () {
console.log('Board is ready')
// read the sensor data from analog pin 0
var light = new five.Light("A0");

// change event is fired when there is a change in
// value of the pin
light.on("change", function () {
console.log(this.level);
});

/**
* if the pin reading is between 10% to 30%
* then there is definitely some strong light
* source in the room.
* the callback function is called if the pin
* value is between range specifed below
* late we will laverage this function for
* chatbot notification
*/
light.within([0.10, 0.30], function () {
console.log('Lights are on')
});
});

#Setting up Telegram Bot

Till now we have handled the Arduino side of the project, we have to manage to pull the sensor data from Arduino into our Nodejs code, next we have to send it to Telegram messenger. But first, we have to setup Telegram bot. You need Bot token to use Telegram bot API’s you can follow this official post on how to create a bot and get bot token.

Once you have the bot token lets verify that you got things right, execute the javascript code below and fill the token variable with the bot token which you bot from @BotFather.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var TelegramBot = require('node-telegram-bot-api');

// paste the bot token you receive from @BotFather
var token = 'YOUR_TELEGRAM_BOT_TOKEN';

var bot = new TelegramBot(token, {polling: true});

// Listen for any kind of message.
bot.on('message', function(msg) {
// we will need chat id if we want to push the message
var chatId = msg.chat.id;
console.log('Chat id of user : ', chatId);
// echo back the message
bot.sendMessage(chatId, 'Got it chief!');
});

#Hooking up Arduino with Chat Bot

Now that we are through with different components of the project it time that we hook everything together. The bot will send a notification to you if the value of the light dependent resistor is between 10% to 30 %. This range value (10-30%) was the reading of the sensor when the light was on in my room, so that’s what I am using, you can change it to any other value that suits your environment, threshold value depends lots of factor like the distance between the light source and the sensor so the value might differ for your settings. Another functionality will be reading light sensor value on when asked for, this can be done simply by storing the value of the sensor in the variable when a change event is fired this way we have the last changed value of light sensor, and when user ask’s for sensor reading send the value of the variable.

To receive notifications you have to subscribe by sending /subscribe command to the bot, if you interested to know the value of the sensor right away then type /light command and if you don’t want to receive the notification then type /unsubscribe. Telegram bot platform has commands functionality inbuilt so UI dropdown list shows up so you don’t have to type the whole word. And as you might have noticed commands starts with / which is also part of bot platform. The bot will send push message when the sensor value is within range.

Bot commands summary :

  1. /light - Read the current value of light sensor
  2. /subscribe - Subscribe to list of user getting notifications.
  3. /unsubscribe - Unsubscribe to notifications if not interested.

Below is the code for what we have discussed so far

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
var five = require("johnny-five");
var TelegramBot = require('node-telegram-bot-api');

var token = 'YOUR_TELEGRAM_BOT_TOKEN';
// fill this variable with the chatId of the use you want
// to send the message to
var chatIds = [];
var lightSensorValue = 0;

var board = new five.Board();
var bot = new TelegramBot(token, {
polling: true
});

// send message to who so every ask for the value
bot.onText(/\/light/, (msg, match) => {
var chatId = msg.chat.id;
bot.sendMessage(chatId, 'Light is at ' + (lightSensorValue * 100) + '%');
});

// subscribe to the list of users who wish to recieve light notifications
bot.onText(/\/subscribe/, (msg, match) => {
var chatId = msg.chat.id;
var index = chatIds.indexOf(chatId);
if(index == -1){
chatIds.push(chatId);
bot.sendMessage(chatId, 'You will recieve light notifications ;)');
} else {
bot.sendMessage(chatId, 'You are already subscribed!');
}
});

// unsubscribe the notifications
bot.onText(/\/unsubscribe/, (msg, match) => {
var chatId = msg.chat.id;
var index = chatIds.indexOf(chatId);
if(index != -1){
chatIds.splice(index, 1);
bot.sendMessage(chatId, 'You have successfully unsubcribed.');
} else {
bot.sendMessage(chatId, 'You are are not subscribed.');
}
});

/**
* if the value of sensor is within range then
* too many messages might get pushed in short span
* of time to avoid this below logic has been included
* to make sure that there is at least 10 min interval between
* two notifications
*/
var spamControlOn = true;
setInterval(function () {
spamControlOn = true;
}, 1000 * 60 * 10)

board.on("ready", function () {
console.log('Board is ready')
var light = new five.Light("A0");

light.on("change", function () {
lightSensorValue = this.level;
if (five.Fn.inRange(this.level, 0.10, 0.30)) {
if (spamControlOn && chatIds.length > 0) {
chatIds.forEach(function (chatId) {
bot.sendMessage(chatId, 'Light is : ' + (lightSensorValue * 100) + '%');
});
spamControlOn = false;
}
}
});
});

This small project we did it too simple but it was just to illustrate the concept nothing serious project was intended. But now that you have tools you could develop something more sophisticated by mashing up many sensors like temperature sensor, relay circuit etc. You could display Telegram message send by the user to 16x2 LCD display connected to Arduino sitting in your kitchen possibilities are limitless.

#Conclusion

As you saw we implemented chat bot interacting with Arduino in few lines of code. All though the project is very simple, it’s clear that you don’t need to learn another language to program Arduino javascript is enough. Our entire project was in Nodejs but you could use any language of your choice, as there are Firmata protocol client libraries for many languages and also it’s not difficult to make Telegram bot REST API calls from the language of your choice you might even find a GitHub library for that as well. Happy Hacking!

#Useful links

  1. Link to the source code used in this post
  2. List of Firmata client libraries
  3. Firmata protocol documentation
  4. Creating telegram bot
  5. Node telegram library documentation
  6. johnny-five library documentation
Share