Overview
IoT is one of the most talked about domains and probably the biggest techno-buzz of the year. As the core of IoT is essentially an embedded system, it is being perceived as a maker's domain and has been drawing the attention of the makers and DiY community. Many a people has a misconception that IoT is all about some hardware hooking up to some internet services and therefore a complex hardware (or even a hack) is the heart of IoT system. However, IoT is a framework that provides a suite for connecting physical devices with computational entities (both at the edge as well as at the core). Industrial IoT is little undertalked because historically makers have never been interested in industrial automation as much as say something like robotics and home automation.
An industrial automation or monitoring system goes much beyond the hobby projects. The entire principle depends upon a robust and fundamentally scalable architecture of monitoring devices. The heart of any industria. system is the ability to overcome data leakage, providing a high accuracy connection and more importantly a robust framework of APIs and analytical engine. Data analysis in real time is of as much importance as data collection.
So how is an industrial IoT (sometime referred as IIoT) different from home IoT? As an example, if we consider the water management system, a home water tank probably will have a single unit and the tank capacity will vary say between 1000 liters to 3000 liters with water filling at most 2-3 times a day. Now consider a stell plant with units like foundry, molding, rolling, milling, churning, flattening, plating. Each of these units needs their own water management. Millions of gallons of water is supplied across to these units several times in a minute. The flow of the water is directly interlinked with the production objective. So an industrial IoT architecture must be able to handle such a large volume of data exchange over such large number of devices spread across a large geography (water supplying uinit, pump house and distribution centers are often located at different geographic locations). Therefore industrial IoT needs to be perceived with the aim of scalability, maintainability and of course, analytical possibility.
You can imagine the effort needed when a firmware needs to be updated across different machines, manufactured by different vendors, located at different places without breaking the current monitoring process. That is significantly different from a consumer IoT device (say a smart relay).
In this article, I would introduce you to one of the most trusted and promising IIoT boards called Samsung Artik and explain to you the process of working with Artik with Tembo. We shall take a case study of water resource management. As deploying the solution in an industry is out of the scope of this article, I would take you through the working process of the system and elaborate how the current simulation level prototype can be used in industrial context.
Introduction
This has been a high level of experiment that I was doing with Samsung Artik 10. We got this device for Samsung Makers against drought challenge. We got the Samsung Artik 10 so this is a tribute to what I had done with the board. We will work on building a simple IoT app and get started with it.
You can take a look at the video of the solution.
Background
The starting point arises as a surprise as we had real trouble going through the board as this was completely so this is my experience which we had going through the IoT app.
The way we started...
First of all, it was just unboxing my Artik 10 and figuring out what it had to offer. Hence, we opened the box.The Artik 10 board was robust.
The box:
The Board:
First Things First
We didn't update the image because one of the libraries that we were hoping to use was best possibly working with the older image and we kept it as it is till now after the project after the project was completed.
Accessing Wifi
We were using a Windows system so the first thing was how to get the device talking to wifi or the internet. First of all, the OS installed in Artik was Linus, hence one solution had to interact with putty only installed putty.Connected the Artik 10 board with USB powered on with the power supply provided and went inside the Artik 10 device using putty.
Configuration of Wifi in Artik 10
We need to follow the setup guide as mentioned by Samsung.
Now after we login to the Artik 10 board, we will use dir
command to check the listing in the Artik 10 board.
We will have three files:
- llvm-arm.conf
- mariadb-ar.conf
- temboo.conf
Checking the wifi status:
ifconfig
It will give all the details:
Now we are good to go with the WiFi.
Temboo: The Word for Magic
As we had a plan for using a cloud platform that was easy and robust for Artik 10, we found that Temboo was the obvious answer as it is a cloud platform which can make production ready IoT code in minutes. There are lot of APIs that we can use for our purposes.
API's ==Choreos
Every API you access in Temboo is named as Choreos. There are different Choreos that you can take advantage of. The usage is easy as the learning curve for mastering is just few steps to follow.
Platforms for Temboo
If we want to work on Temboo hardware capability, we found that we have had three options:
- Texas Instruments Board
- Arduino board
- Samsung Artik 10 (Arduino certified)
We can choose any one of the platforms to work with. As we had a Artik 10 board handy, we choose Samsung.
SDKs for Temboo
We have variety of options to start with using the SDK. We will show it on Processing.
Firstly, we need to download the processing library for Temboo.
Just click on run your first Choreo for processing. In the next page, it will show the SDKs and the download option.
When we click on processing, we have the steps mentioned in the next step on getting started with it.
Let's download the Processing library for Temboo first.
Unzip the library, copy it to the processing library folder.
Copy the code generated to the processing IDE
import com.temboo.core.*;
import com.temboo.Library.Google.Geocoding.*;
TembooSession session = new TembooSession
("abhigeek81", "myFirstApp", "XvaH06Qhpq9zAqDedc9UqsjMljvvu47b");
void setup() {
runGeocodeByAddressChoreo();
}
void runGeocodeByAddressChoreo() {
GeocodeByAddress geocodeByAddressChoreo = new GeocodeByAddress(session);
geocodeByAddressChoreo.setAddress("1600 Amphitheatre Parkway, Mountain View, CA");
GeocodeByAddressResultSet geocodeByAddressResults = geocodeByAddressChoreo.run();
println(geocodeByAddressResults.getLatitude());
println(geocodeByAddressResults.getLongitude());
println(geocodeByAddressResults.getResponse());
}
Now the output:
So we have seen how easy it is to use a Choreo and run it on Processing.
Prebuilt IoT Apps that You Can Deploy Readily
We have a large chunk of pre-bulit IoT apps that are production ready and easy to use.We can use any of those to deploy in our Samsung Artik.
These are the options for pre-built IoT app available in Temboo.
The options are:
- Building Management
- Energy
- Environment
- Farming
- Logistics
- Manufacturing
- Smart Cities
- Water Management
The Workflow for Artik 10
Let's break the flow:
- We need to power up the board attach the USB Cable and follow the steps mentioned in the Samsung Artik 10 to configure the board.
- As we are working on Windows machine and Artik 10 is running in Fedora Core, we have to communicate using putty.
- Create a Temboo account. Follow the prebuilt IoT apps to run the code.
A catch: There is a great option in Temboo as after visual informations and following the steps, the entire code is converted to C language so we can add a combination of Choreos for our liking. - Now there will be a zip file that we need to push to the Artik 10 board using putty.
- You are ready to go with your IoT app.
Let's Create a Choreo for Artik 10
When we go to dashboard, we will have to choose Samsung.
When we click on Get started, it will take us to the page where we copy the library config file for our usage.
In the next step, we put in our address so that Yahoo weather gives the weather condition and we will be ready with the code that we can deploy on Artik 10.
The code as generated it's a C language code.
The header file and the c file:
#ifndef TEMBOOACCOUNT_H_
#define TEMBOOACCOUNT_H_
#define TEMBOO_ACCOUNT "abhigeek81" // Your Temboo account name
#define TEMBOO_APP_KEY_NAME "myFirstApp" // Your Temboo app name
#define TEMBOO_APP_KEY "XvaH06Qhpq9zAqDedc9UqsjMljvvu47b" // Your Temboo app key
#endif /* TEMBOOACCOUNT_H_ */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <temboo.h>
#include <temboosession.h>
#include <temboonetworkclient.h>
#include "TembooAccount.h"
SocketConnection theSocket;
TembooSession theSession;
int currentRun = 0;
const int MAX_RUNS = 10;
const int CHOREO_TIMEOUT = 300;
const uint32_t choreoInterval = 30;
uint32_t lastChoreoRunTime = 0;
TembooError setup() {
TembooError returnCode = TEMBOO_SUCCESS;
#ifndef USE_SSL
returnCode = initTembooSession(
&theSession,
TEMBOO_ACCOUNT,
TEMBOO_APP_KEY_NAME,
TEMBOO_APP_KEY,
&theSocket);
#else
printf("Enabling TLS...\n");
returnCode = initTembooSessionSSL(
&theSession,
TEMBOO_ACCOUNT,
TEMBOO_APP_KEY_NAME,
TEMBOO_APP_KEY,
&theSocket,
"/opt/iothub/artik/temboo/temboo_artik_library/lib/temboo.pem",
NULL);
#endif
return returnCode;
}
void runGetWeatherByAddress(TembooSession* session) {
printf("\nRunning GetWeatherByAddress\n");
TembooChoreo choreo;
const char choreoName[] = "/Library/Yahoo/Weather/GetWeatherByAddress";
initChoreo(&choreo, choreoName);
ChoreoInput AddressIn;
AddressIn.name = "Address";
AddressIn.value = "kolkata";
addChoreoInput(&choreo, &AddressIn);
int returnCode = runChoreo(&choreo, session, CHOREO_TIMEOUT);
if (returnCode != 0) {
printf("runChoreo failed. Error: %d\n", returnCode);
}
while (tembooClientAvailable(session->connectionData)) {
printf("%c", readChoreoResult(&choreo, session));
}
tembooClientStop(session->connectionData);
}
int main(void) {
if (setup() != TEMBOO_SUCCESS) {
return EXIT_FAILURE;
}
uint32_t now = time(NULL);
lastChoreoRunTime = now - choreoInterval;
while(currentRun < MAX_RUNS){
now = time(NULL);
if ((now - lastChoreoRunTime >= choreoInterval)){
lastChoreoRunTime = now;
currentRun++;
runGetWeatherByAddress(&theSession);
}
usleep(1000);
}
#ifdef USE_SSL
endTembooSessionSSL(&theSession);
#endif
return EXIT_SUCCESS;
}
Pushing the Code to Artik 10
Here, I prefered a VM/I created a Ubuntu VM 14.10 and downloaded the code on that os. We open a terminal to see where the download is as we have downloaded the code in the downloads folder.
Now we have to do a secure copy of the file we have downloaded in Ubuntu os to the Artik 10 board. We get the IP of the Artik 10 board using ifconfig
now we need to use scp
command.
scp getweatheraddress.zip root@192.168.0.3:/hostname
Put in the password root one and start copying the file. After success, you will see the file gets copied.
We unzip the file:
[root@localhost ~]$ unzip getweatherbyaddress.zip
We compile the code at first.
[root@localhost ~]$ gcc -L/opt/iothub/artik/temboo/temboo_artik_library/lib
-ltemboo -I/opt/iothub/artik/temboo/temboo_artik_library/include getweatherbyaddress.c
-o getweatherbyaddress
Now we run it.
[root@localhost ~]$ ./getweatherbyaddress
The output from the board.
We will now recreate the water management system for industrial IoT.
Water Management System for Industrial IoT
Water management in big production houses or industry as it helps in saving lots and lot of water with proper usage. Water is very precious as it is very difficult to use and we need to do proper channelizing of water. At places, we see water is wasted and in some places, it is less. The basic problem is how we properly utilize the water resources. Proper planning of how to use water is essential. Using water as when it is required and don't waste it. IoT plays an important role in managing water resources and this Industrial IoT project is the replica of water management system as mentioned in Temboo.
The header file is as follows:
#ifndef TEMBOOACCOUNT_H_
#define TEMBOOACCOUNT_H_
#define TEMBOO_ACCOUNT "abhigeek81" // Your Temboo account name
#define TEMBOO_APP_KEY_NAME "WaterManagementApp" // Your Temboo app name
#define TEMBOO_APP_KEY "9Vj52NWvhrMPWFsOA2UYUlpamVyPyqKf" // Your Temboo app key
#endif /* TEMBOOACCOUNT_H_ */
The main C file is as given below:
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <temboo.h>
#include <temboosession.h>
#include <temboonetworkclient.h>
#include "TembooAccount.h"
#define HIGH 1
#define LOW 0
#define INPUT 1
#define OUTPUT 0
SocketConnection theSocket;
TembooSession theSession;
const int CHOREO_TIMEOUT = 300;
bool pumpStatus = false;
const int triggerAlertThreshold = 2100;
const int pumpOffThreshold = 2030;
const int waterLevelSensor = 2;
const int motorPin = 22;
int waterLevel = 0;
bool digitalPinMode(int pin, int dir) {
FILE * fd;
char fName[32];
if(( fd = fopen("/sys/class/gpio/export", "w")) == NULL) {
printf("Error: unable to export pin\n");
return false;
}
fprintf(fd, "%d\n", pin);
fclose(fd);
sprintf(fName, "/sys/class/gpio/gpio%d/direction", pin);
if((fd = fopen(fName, "w")) == NULL) {
printf("Error: can't open pin direction\n");
return false;
}
if(dir == OUTPUT) {
fprintf(fd, "out\n");
} else {
fprintf(fd, "in\n");
}
fclose(fd);
return true;
}
int digitalRead(int pin) {
FILE * fd;
char fName[32];
char val[2];
sprintf(fName, "/sys/class/gpio/gpio%d/value", pin);
if((fd = fopen(fName, "r")) == NULL) {
printf("Error: can't open pin value\n");
return false;
}
fgets(val, 2, fd);
fclose(fd);
return atoi(val);
}
bool digitalWrite(int pin, int val) {
FILE * fd;
char fName[32];
sprintf(fName, "/sys/class/gpio/gpio%d/value", pin);
if((fd = fopen(fName, "w")) == NULL) {
printf("Error: can't open pin value\n");
return false;
}
if(val == HIGH) {
fprintf(fd, "1\n");
} else {
fprintf(fd, "0\n");
}
fclose(fd);
return true;
}
int analogRead(int pin) {
FILE * fd;
char fName[64];
char val[8];
sprintf(fName, "/sys/devices/12d10000.adc/iio:device0/in_voltage%d_raw", pin);
if((fd = fopen(fName, "r")) == NULL) {
printf("Error: can't open analog voltage value\n");
return 0;
}
fgets(val, 8, fd);
fclose(fd);
return atoi(val);
}
TembooError setup() {
TembooError returnCode = TEMBOO_SUCCESS;
#ifndef USE_SSL
returnCode = initTembooSession(
&theSession,
TEMBOO_ACCOUNT,
TEMBOO_APP_KEY_NAME,
TEMBOO_APP_KEY,
&theSocket);
#else
printf("Enabling TLS...\n");
returnCode = initTembooSessionSSL(
&theSession,
TEMBOO_ACCOUNT,
TEMBOO_APP_KEY_NAME,
TEMBOO_APP_KEY,
&theSocket,
"/opt/iothub/artik/temboo/temboo_artik_library/
lib/temboo.pem",
NULL);
#endif
digitalPinMode(motorPin, OUTPUT);
return returnCode;
}
void runGetWeatherByAddress(TembooSession* session, char* msg) {
TembooChoreo choreo;
const char choreoName[] = "/Library/Yahoo/Weather/GetWeatherByAddress";
initChoreo(&choreo, choreoName);
const char profileName[] = "ser";
setChoreoProfile(&choreo, profileName);
ChoreoInput TmbAppSrcIn;
TmbAppSrcIn.name = "TmbAppSrc";
TmbAppSrcIn.value = "WaterManagementApp";
addChoreoInput(&choreo, &TmbAppSrcIn);
ChoreoOutput filterTomorrow;
filterTomorrow.name = "tomorrow";
filterTomorrow.xpath = "/rss/channel/item/yweather:forecast[2]/@text";
filterTomorrow.variable = "Response";
ChoreoOutput filterToday;
filterToday.name = "today";
filterToday.xpath = "/rss/channel/item/yweather:forecast[1]/@text";
filterToday.variable = "Response";
addChoreoOutput(&choreo, &filterTomorrow);
addChoreoOutput(&choreo, &filterToday);
int returnCode = runChoreo(&choreo, session, CHOREO_TIMEOUT);
if (returnCode == 0) {
while (tembooClientAvailable(session->connectionData)) {
char name[64];
char value[64];
memset(name, 0, sizeof(name));
memset(value, 0, sizeof(value));
choreoResultReadStringUntil(session->connectionData, name, sizeof(name), '\x1F');
if (0 == strcmp(name, "tomorrow")) {
if (choreoResultReadStringUntil(session->connectionData, value, sizeof(value), '\x1E') == -1) {
printf("Error: char array is not large enough to store the string\n");
} else {
strcat(msg, "Tomorrow's forecast is ");
strcat(msg, value);
strcat(msg,". ");
}
} else if (0 == strcmp(name, "today")) {
if (choreoResultReadStringUntil(session->connectionData,
value, sizeof(value), '\x1E') == -1) {
printf("Error: char array is not large enough to store the string\n");
} else {
strcat(msg, "Today's forecast is ");
strcat(msg, value);
strcat(msg, ". ");
}
}
else {
choreoResultFind(session->connectionData, "\x1E");
}
}
}
tembooClientStop(session->connectionData);
}
void runCaptureTextToSpeechPromptChoreo(TembooSession* session) {
char msg[256] = "Alert, your tank is running low.";
runGetWeatherByAddress(session, msg);
strcat(msg, "Press 1 to turn on the pump.");
TembooChoreo choreo;
const char choreoName[] = "/Library/Nexmo/Voice/CaptureTextToSpeechPrompt";
initChoreo(&choreo, choreoName);
ChoreoInput TextIn;
TextIn.name = "Text";
TextIn.value = msg;
addChoreoInput(&choreo, &TextIn);
ChoreoInput TmbAppSrcIn;
TmbAppSrcIn.name = "TmbAppSrc";
TmbAppSrcIn.value = "WaterManagementApp";
addChoreoInput(&choreo, &TmbAppSrcIn);
const char profileName[] = "abhishek22";
setChoreoProfile(&choreo, profileName);
int returnCode = runChoreo(&choreo, session, CHOREO_TIMEOUT);
if (returnCode == 0) {
while(tembooClientAvailable(session->connectionData)) {
char nameString[64];
char dataString[32];
memset(nameString,0,sizeof(nameString));
memset(dataString,0,sizeof(dataString));
choreoResultReadStringUntil(session->connectionData,
nameString, sizeof(nameString), '\x1F');
if(!strcmp(nameString, "Digits")) {
if(choreoResultReadStringUntil(session->connectionData,
dataString, sizeof(dataString), '\x1E') == -1) {
printf("Error: char array is not large enough to store the string\n");
} else {
if(!strcmp(dataString, "1")){
digitalWrite(motorPin, HIGH);
pumpStatus = true;
}
}
} else {
choreoResultFind(session->connectionData, "\x1E");
}
}
}
tembooClientStop(session->connectionData);
}
int main(void) {
if (setup() != TEMBOO_SUCCESS) {
return EXIT_FAILURE;
}
while(1){
int i = 0;
waterLevel = 0;
for(i = 0; i <10; i++) {
waterLevel = waterLevel + analogRead(waterLevelSensor);
}
waterLevel *= .1;
printf("The water level is %i\n", waterLevel);
if (waterLevel > triggerAlertThreshold && !pumpStatus){
runCaptureTextToSpeechPromptChoreo(&theSession);
}
if(waterLevel < pumpOffThreshold && pumpStatus) {
digitalWrite(motorPin, LOW);
pumpStatus = false;
}
usleep(5000);
}
#ifdef USE_SSL
endTembooSessionSSL(&theSession);
#endif
return EXIT_SUCCESS;
}
The Water Resource Management Case Study
Let's start the process.
We did the experiment based on most water deficit places in California. Our Use case was for Bakersfield, California.
Now we had a scenario that we had to figure out when the water level is low and when the water pump will start.
The IoT system works this way it uses Yahoo weather Choreo and when the threshold value is less triggers an alert for checking the water level (which is done by water level indicator).
We have used Nexmo Chroreo to automatically generate the toggle switch from phone where 1 triggers the water pump one and 0 triggers it off.
Hardware required:
- Water level Sensor
- Water pump
- TP120 transistor
- Breadboard
- Samsung ARtik 10 Device
- Water Reservoir
- Water Tank
The setup:
The water reservoir with water level sensor.
After running the code in Artik 10 as the water level is empty reflects the values.
Now with the help of Nexmo service will generate a phone call which triggers the option to switch on the water pump.
As the water level changes, the level indicator also changes.
The pump starts working.
The complete solution in action.
Conclusion
We have seen how Artik 10 can be used as a solution for industrial IoT solution (though the simulation was basic). We have used the power of Temboo to full effect. The powerful capabilities of the Temboo Choreos and automatic generation of code in it helps us to do the solution very fast. We have also used Yahoo weather Choreo to full effect. Nexmo is used to make a phone call. You can play around with other choreos and select the ones ideal for your plant.
Points of Interest
Getting hold of Artik 10 board and using it was so fun and a good learning experience.
History
- 4th August, 2016: Initial version