This past few months have been heavily focused on SAP HANA and Internet of Things (IoT) for me and the SAP Developer Relations team. The result from Las Vegas, Berlin and just last week at the ThingMonk 2014 event in London is a nice little collection of code making up a new example application that will be present in the next version of the SAP HANA Developer Edition (SPS9) in the next weeks. Ideally this project will be embedded in the next HANA Dev Edition but also available on GitHub in the next weeks.
The goal of this example is to show how easily one can read data from an external hardware device with a sensor such as temperature sensor and store, visualize and access the data via a SAP HANA XS application.
This example application also allows for display of the values entered via those devices.
No example is complete without showing the complete "round trip", this example also provides the ability to retrieve values from SAP HANA and use them in the hardware side.
Below you will find example code for posting to this application from different hardware devices. 3 That we have focused on are:
Creating the circuit on the breadboard is extremely simply.
Basically any type of hardware device that can do a JSON based HTTP post can submit data to the server using Content-Type": "application/json".
var jsonData = {
"ID": 1,
"SNAME": "Tessel",
"STYPE": "Temp",
"SVALUE": ""+temp+"",
"TDATE": "/Date("+timeStamp+")/"
}
import os
import glob
import json
import urllib2
import time
import RPi.GPIO as GPIO
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
hanaposts = 0
hanaposts2 = 0
# to use Raspberry Pi board pin numbers
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
# set up GPIO output channel
GPIO.setup(18, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
def blink(pin):
GPIO.output(pin,GPIO.HIGH)
time.sleep(1)
GPIO.output(pin,GPIO.LOW)
time.sleep(1)
return
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c
while True:
hanaposts += 1
txtTemp = read_temp()
txtDate = '/Date(' + str(int(time.time())) + ')/'
url = 'http://[SERVER IP]:[SERVER PORT]/sap/devs/iot/services/iot_input.xsodata/sensor'
params = {"ID": "1", "TDATE": txtDate, "SVALUE": str(txtTemp), "SNAME": "Craig", "STYPE": "Temp" }
req = urllib2.Request(url,
headers = {
"Authorization": basic_authorization('[USER]', '[PASSWORD]'),
"Content-Type": "application/json",
"Accept": "*/*",
}, data = json.dumps(params))
f = urllib2.urlopen(req)
# LED
if hanaposts == 25:
hanaposts = 0
hanaposts2 += 1
blink(22)
if hanaposts2 == 50:
hanaposts2 = 0
blink(18)
time.sleep(1)
var b = require('bonescript');
var temperatureSensor = "P9_40"
setInterval(readTemperature, 1000);
function readTemperature() {
b.analogRead(temperatureSensor, writeTemperature);
}
// The MCP9700A provides 500mV at 0C and 10mV/C change.
function writeTemperature(x) {
//console.log("temp value: "+x.value);
var millivolts = x.value * 3300; // Only outputs 1.8v, so must adjust accordingly
var temp_c = (millivolts - 500) / 100;
var temp_f = (temp_c * 9 / 5) + 32;
//console.log("Millivolts: " + millivolts + ", temp_c: " + temp_c + ", temp_f: " + temp_f);
var timeStamp = new Date().getTime();
//console.log(new Date());
writeToScreen(temp_c);
writeToHana(temp_c,timeStamp);
}
function writeToHana(temp, timeStamp) {
var http = require('http');
var options = {
host: '[SERVER IP]',
port: [SERVER PORT],
path: '/sap/devs/iot/services/iot_input.xsodata/sensor',
method: 'POST',
headers: {
'Authorization': '[AUTH STRING]' ,
'Content-Type':'application/json'
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf-8');
var responseString = '';
res.on('data', function(data) {
responseString += data;
// Do something when a value is there
//console.log("Response: " + responseString);
});
res.on('end', function() {
//var resultObject = JSON.parse(responseString);
});
});
req.on('error', function(e) {
console.log("error found");
console.error(e);
});
var jsonData = {
"ID": 1,
"SNAME": "Craig",
"STYPE": "Temp",
"SVALUE": ""+temp+"",
"TDATE": "/Date("+timeStamp+")/"
}
var strData = JSON.stringify(jsonData);
//console.log(strData);
req.write(strData);
req.end();
}
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
/*********************************************
This basic climate example logs a stream
of temperature and humidity to the console.
*********************************************/
var tessel = require('tessel');
// if you're using a si7020 replace this lib with climate-si7020
var climatelib = require('climate-si7020');
var climate = climatelib.use(tessel.port['A']);
climate.on('ready', function () {
console.log('Connected to si7020');
// Loop forever
setImmediate(function loop () {
climate.readTemperature('c', function (err, temp) {
climate.readHumidity(function (err, humid) {
console.log('Degrees:', temp.toFixed(4) + 'C', 'Humidity:', humid.toFixed(4) + '%RH');
var timeStamp = new Date().getTime();
writeToHana(temp.toFixed(4),timeStamp);
setTimeout(loop, 1000);
});
});
});
});
climate.on('error', function(err) {
console.log('error connecting module', err);
});
function writeToHana(temp, timeStamp) {
var http = require('http');
var options = {
host: '[SERVER IP]',
port: [SERVER PORT],
path: '/sap/devs/iot/services/iot_input.xsodata/sensor',
method: 'POST',
headers: {
'Authorization': '[AUTH STRING]' ,
'Content-Type':'application/json'
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf-8');
var responseString = '';
res.on('data', function(data) {
responseString += data;
// Do something when a value is there
//console.log("Response: " + responseString);
});
res.on('end', function() {
//var resultObject = JSON.parse(responseString);
});
});
req.on('error', function(e) {
console.log("error found");
console.error(e);
});
var jsonData = {
"ID": 1,
"SNAME": "Tessel",
"STYPE": "Temp",
"SVALUE": ""+temp+"",
"TDATE": "/Date("+timeStamp+")/"
}
var strData = JSON.stringify(jsonData);
//console.log(strData);
req.write(strData);
req.end();
}
Using an HTTP GET using Content-Type": "application/json" we can retrieve values from our "control" table.
import RPi.GPIO as GPIO
import time
import urllib2
import json
# convert string to number
def num(s):
try:
return int(s)
except ValueError:
return float(s)
# blinking function
def blink(pin):
GPIO.output(pin,GPIO.HIGH)
time.sleep(1)
GPIO.output(pin,GPIO.LOW)
time.sleep(1)
return
# Get values from server
def getServerResponse(url):
req = urllib2.Request(url)
opener = urllib2.build_opener()
f = opener.open(req)
return json.loads(f.read())
###### Initialize Program ######
# surpress warnings
GPIO.setwarnings(False)
# to use Raspberry Pi board pin numbers
GPIO.setmode(GPIO.BOARD)
# set up GPIO output channel
GPIO.setup(18, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
# fetch control variables
jsonStr = getServerResponse("http://[SERVER IP]/sap/devs/iot/services/iot_control.xsodata/control?$format=json&$filter=SCONTROL%20eq%20%27HOT%27")
hotTemp = jsonStr['d']['results'][0]['SVALUE']
jsonStr = getServerResponse("http://[SERVER IP]/sap/devs/iot/services/iot_control.xsodata/control?$format=json&$filter=SCONTROL%20eq%20%27COLD%27")
coldTemp = jsonStr['d']['results'][0]['SVALUE']
# Now loop and check for action
while True:
jsonStr = getServerResponse("http://[SERVER IP]/sap/devs/iot/services/iot.xsodata/IOT?$orderby=ID%20desc&$top=1&$select=SVALUE&$filter=SNAME%20eq%20%27Ian%27&$format=json")
currentTemp = jsonStr['d']['results'][0]['SVALUE']
if num(currentTemp) < num(coldTemp):
print "Under, " + currentTemp + " is less than " + coldTemp
for i in range(0,50):
blink(18)
else:
if num(currentTemp) > num(hotTemp):
print "Over, " + currentTemp + " is more than " + hotTemp
for i in range(0,50):
blink(22)
else:
print "Within range"
time.sleep(5)
GPIO.cleanup()
Using an HTTP GET using Content-Type": "application/json" we can retrieve values from our "control" table.
This round trip uses a fan, fan and "led" as a heater. The fan is a small 4V fan using the 5V power and a transistor on board. The idea here is that when the fan reaches the "HOT" value from the control table the program would start the fan to cool it back down and when it reaches the "COLD" value the "heater" would start to heat of the environment.
import os
import glob
import json
import urllib2
import time
import RPi.GPIO as GPIO
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
maxtemp = 0
mintemp = 0
# to use Raspberry Pi board pin numbers
GPIO.setmode(GPIO.BOARD)
# set up GPIO output channel
GPIO.setup(12, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
def blink(pin):
GPIO.output(pin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(pin, GPIO.LOW)
time.sleep(0.5)
return
def temp_low():
GPIO.output(12, GPIO.HIGH)
GPIO.output(13, GPIO.LOW)
GPIO.output(15, GPIO.HIGH)
GPIO.output(16, GPIO.LOW)
return
def temp_high():
GPIO.output(12, GPIO.LOW)
GPIO.output(13, GPIO.HIGH)
GPIO.output(15, GPIO.HIGH)
GPIO.output(16, GPIO.LOW)
return
def temp_ok():
GPIO.output(12, GPIO.LOW)
GPIO.output(13, GPIO.LOW)
GPIO.output(15, GPIO.LOW)
GPIO.output(16, GPIO.HIGH)
return
# Get values from server
def getServerResponse(url):
req = urllib2.Request(url)
opener = urllib2.build_opener()
f = opener.open(req)
return json.loads(f.read())
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c
jsonStr = getServerResponse("http://[SERVER IP]/sap/devs/iot/services/iot_control.xsodata/control?$format=json&$filter=SCONTROL%20eq%20%27COLD%27")
mintemp = jsonStr['d']['results'][0]['SVALUE']
print ('MIN Temp is set at ' + mintemp + 'c')
jsonStr = getServerResponse("http://[SERVER IP]/sap/devs/iot/services/iot_control.xsodata/control?$format=json&$filter=SCONTROL%20eq%20%27HOT%27")
maxtemp = jsonStr['d']['results'][0]['SVALUE']
print ('MAX Temp is set at ' + maxtemp + 'c')
while True:
# Value of Sensor
txtTemp = read_temp()
# Timestamp
txtDate = '/Date(' + str(int(time.time())) + ')/'
# HTTP Post to HANA
url = 'http://[SERVER IP]/sap/devs/iot/services/iot_input.xsodata/sensor'
params = {"ID": "1", "TDATE": txtDate, "SVALUE": str(txtTemp), "SNAME": "Ian", "STYPE": "Temp" }
# print(params)
req = urllib2.Request(url,
headers = {
"Authorization": basic_authorization('[USER]', '[PASSWORD]'),
"Content-Type": "application/json",
"Accept": "*/*",
}, data = json.dumps(params))
f = urllib2.urlopen(req)
blink(18)
# fetch the url
# url2 = "http://[SERVER IP]/sap/devs/iot/services/iot.xsodata/IOT?$orderby=ID%20desc&$top=1&$select=SVALUE&$filter=SNAME%20eq%20%27Ian%27&$format=json"
# req2 = urllib2.Request(url2)
# opener2 = urllib2.build_opener()
# f2 = opener2.open(req2)
# json2 = json.loads(f2.read())
# currtemp = json2['d']['results'][0]['SVALUE']
jsonStr = getServerResponse("http://[SERVER IP]/sap/devs/iot/services/iot.xsodata/IOT?$orderby=ID%20desc&$top=1&$select=SVALUE&$filter=SNAME%20eq%20%27Ian%27&$format=json")
currtemp = jsonStr['d']['results'][0]['SVALUE']
#print currtemp
if (float(currtemp) <= float(maxtemp)):
if (float(currtemp) < float(mintemp)):
print ('>>> HEATER ON ' + currtemp + "c lower than MIN temp of " + str(mintemp) + "c")
temp_low()
else:
print ('HEATER/FAN OFF ' + currtemp + "c within bounds")
temp_ok()
else:
print ('>>> FAN ON ' + currtemp + "c exceeds MAX temp of " + str(maxtemp) + "c")
temp_high()
# Loop to next reading
time.sleep(3)
** Be sure on your spacing for your code, for some reason formatting here is horrid!!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
23 | |
12 | |
12 | |
9 | |
9 | |
9 | |
8 | |
8 | |
6 | |
6 |