Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
craigcmehil
Community Manager
Community Manager

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.

  • Hardware such as Raspberry Pi, Beagle Bone, and Tessel
  • Circuit
  • Some code for hardware devices using Bonescript, Python and Javascript

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.

Hardware

Below you will find example code for posting to this application from different hardware devices. 3 That we have focused on are:

  • Raspberry Pi Model B

  • Beagle Bone Black

  • Tessel

Circuit


Creating the circuit on the breadboard is extremely simply.

  • Connect a black jumper wire to the GND
  • Connect a red jumper wire to the 3.3 V
  • Place an LED in the breadboard
  • Place a 220 Ohm Resister from GND to the short leg of the LED
  • Place a jumper wire from the long leg of the LED to the GPIO pin 18
  • Repeat the process for the second LED and connect to GPIO pin 22
  • Place the digital temperature sensor on the bread board, we are using DS18B20
  • From the "left" leg of the sensor we run a black jumper wire to GND
  • From the "right" leg of the sensor we run a red jumper wire to 3.3v
  • From the "center" leg of the sensor we run a jumper wire to the GPIO pin 16
  • Between the "right" and "center" legs we place a 4.7K Ohm resistor

Coding


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+")/"
         
              }
    

Python for the Raspberry Pi

        

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)





Bonescript for the Beagle Bone

          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();
          }
    

Javascript for the Tessel


// 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();


}


    





Control Values

Using an HTTP GET using Content-Type": "application/json" we can retrieve values from our "control" table.

Python for the Raspberry Pi


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()





Round Trip

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.

Python for the Raspberry Pi


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!!

6 Comments