Skip to Content

PS: Live demo of the prototype in the end.

Motivation for the blog

I have been quite fascinated by IoT and the endless number of opportunities which it brings to the table. So far I have managed to broadcast my mobile GPS data to the SAP cloud platform IoT here, but that itch of getting the bidirectional communication in place was still pending to be explored. I wanted to make something where we don’t need to buy any hardware such as Rasperry Pi etc. , only use the most common hardware and come up with something.

So this blog talks about not only sending data from a device but also interacting with the device  based on the data received. In addition to this some new learnings which we got while setting up the POC.

So What are we making?

We will be making a Realtime Laptop RAM usage monitor which will  send data to cloud as well as receive alerts/messages from the UI5 app. So the major steps involved are as follow.

  • Sending RAM usage data from Laptop to SAP Cloud IoT
  • SAPUI5 App to monitor the RAM usage
  • SAPUI5 App interaction with the Laptop

Sending data from Laptop to SAP Cloud IoT Neo

Sending data from Laptop to SAP Cloud IoT involve two steps. First is the configuration on SAP Cloud side which was done using the configuration guide as seen below.

Second part was to send data from Laptop to the cloud where we have used below mentioned Python script. This script read RAM usage of laptop and then sends data via API

import psutil
import time
import requests
import json
import ast
# Get Authorization token
URL = 'https://iotmms<userid>.hanatrial.ondemand.com/com.sap.iotservices.mms/v1/api/http/data/<device id>'
headers = {
    "Authorization": "Bearer <token>"    ,
    "Content-Type":"application/json;charset=utf-8"
}
count = 0
while count < 1000:
	count += 1
	p = psutil.virtual_memory()
	print(p.percent)
	body={"mode":"async", "messageType":"<messageid>", "messages":[{ "RAMValue":str(p.percent), "timestamp":"1468991773"}]}
	responsePost = requests.post(URL,data=json.dumps(body),headers=headers) 
	print(body)
	print(responsePost)

Looks easy right  no, the first trouble which started was the data not being received on the cloud side. So as a first step what i did was to use SAP Cloud IoT local data posting tool like Postman to see if it is working locally.  But sadly it did not work. Neither i see a new table with data nor a blank one created for my new message format.

Then on searching further found this blog from Murali where he has highlighted how to configure the mapping for the custom table name for our messages format but it still did not help.

On digging further found out it was message id which needs to be passed not the name. So actually i ended up learning how to configure custom table name which i did not know previously.

SAPUI5 app for data monitoring

So now we have received data next step was to get a UI5 app up to display the data. The sample app is already provided here and followed the steps mentioned in the guide. As always the first try failed, meaning another learning to be discovered.If you remember we have used custom table name in previous section for our custom table but the the app was constructing the table name with message id. This needs to be changed. I was hoping it will work  but no again it did not work.

On digging further i found out it was using the timestamp field which we replaced  with G_ CREATED as we were sending the same timestamp each time why not use default one. I thought now my changes will work but things are not that easy.

There was still one thing which needs to be fixed which was ,the template app was converting the field name to Uppercase by default which was not needed in our case.

So finally all issues resolved, we have the app up and running

Extending SAPUI5 app for interact with our Device.

First step before extending the app was to make an API which will interact with my laptop when called. This API will inturn call a python script which will trigger actions on our laptop.  For time being we have kept simple alerts messages like shown below. You can do anything for example stop some processes, restart whatever crazy you want to do.

As i am a big fan of NodeJS so i got my localhost server up and running using Express which will provide an endpoint to execute local python script. This worked fine when tested locally.

Node JS app

const express = require('express')
const app = express()
const port = 3000
app.get('/endpoint', (request, response) => {
  var spawn = require("child_process").spawn;
  var process = spawn("python.exe", ["./pop.py"]);
  process.stdout.on('data', function (data) {
    response.send('High RAM usage Alert received - '+data.toString('utf8'));
  });
  var child_process = require('child_process');
  child_process.exec('python pop.py', function (err){
    if (err) {
    console.log("child processes failed with error code: " + err);
  }
});
})
app.listen(port, (err) => {
  if (err) {
    return console.log('something bad happened', err)
  }
  console.log(`server is listening on ${port}`)
})

Python Script

from win10toast import ToastNotifier
toaster = ToastNotifier()
toaster.show_toast("High RAM Usage",
                   "Necessary steps taken ",
                   icon_path=None,
                   duration=10)
print('High RAM usage reset done!')

Next challenge was to get this localhost API exposed to the internet that is where i learnt about Ngrok. Setting Ngrock is quite simple and you can have your localhost api now being exposed over the internet in just 2 minutes as can be seen below.

Our localhost now exposed to internet

Next step was simple to add a button to the existing view and add the xhr call which will call the Ngrok endpoint.

<Button text="Send Signal to Laptop" press="onSendsignalToLaptop" class="sapUiTinyMarginBegin" tooltip="Send signal to Laptop"/>

Ajax call to endpoint.

var url = "https://<num>.ngrok.io/endpoint";
 $.ajax({
                    url : url,
                    type : "GET",
                    contentType : "text/xml; charset=\"utf-8\"",
                    success : function(data, textStatus, jqXHR) {
                          response = data;
                    },
                    error: function(xhr, status)
                    {
                          console.log("ERROR");
                    }
});

Live Demo

Please bear with the video quality will try to find out a way to record better videos:)

Whats is Next?

Now we have live working demo of an IoT device, next important thing i would like to deep dive into predicting when to raise the automatic alert by using Machine learning. I plan to pass more information or features such as number of processes running etc. to make our predicting algorithm more realistic, will share the experience in coming days.

Feel free to try out or provide your feedback open to all ears.

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply