IoT and “Industrie 4.0” for SharePoint–Part II

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives


In the Part I of this article series I described how to build the System on Module application in .NET Micro Framework which publishes (ingress) events from sensor to the Service Bus. Additionally I also described how to implement the listener on the sensor which is receiving remotely sent commands.

In this post I will describe how to build a SharePoint App which listens to events sent from sensor and how to build the SharePoint app which sends commands to the sensor.

SharePoint App

To create a SharePoint-App I used standard Visual Studio template and created a Provider Hosted App. The template created the solution with required SharePoint artifacts and a MVC WebProject called GasSensorEventPartWeb.
image_thumb[3]

In general there are two possibilities to create the IoT capable app in this project.

- First possibility would be to implement all code on the server side in the appropriate controller. In this case I would use .NET Service Bus SDK for connectivity.

- However in this post I decided to do it a harder way (Second Possibility). I will rather create the JavaScript HTML5 app with angular and Service Bus Java Script SDK.
By using of this approach I want to show how Service Bus capabilities can be leveraged in any kind of JavaScript application. In other words you could use the same code in cordova application to build app which runs on any other platform.
As described in previous topic this app will also implement bidirectional communication via broker.

1. Listening for Events from device.
2. Sending of Commands to device.

Booth scenarios are implemented in GasSensorEvents.aspx and GasSensorCommands.aspx. respectively. The file app.js implements the angular based controller and model (MVC) and servicebussdk-1.0.js provides the Service Bus connectivity.

After the SharePoint App project is created I implemented two AppParts, one for each scenario. To add an AppPart in the solution right mouse click on GasSensorEventPart (the SP artifact project) and add add the item template Client Web Part (Host Web).

image_thumb12

I did this twice to create create GasSensorCommandsWebPart and GasSensorEventsCLientWebPart (Picture below on left). Be sure that Content element in Elements.xml file points to the right ASPX file.

<Content Type="html"  Src="~remoteAppUrl/IoT/GasSensorEvents.aspx" />

This will make two AppParts appear in the list of AppParts in the SharePoint portal (picture below on right)

Devil" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image_thumbDevil" src="http://developers.de/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/damir_5F00_dobric/image_5F00_thumb6_5F00_thumb_5F00_46ED17F0.png" width="316" height="462" />         Music" style="border-left-width:0px;border-right-width:0px;background-image:none;border-bottom-width:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;border-top-width:0px;" border="0" alt="image_thumbMusic" src="http://developers.de/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/damir_5F00_dobric/image_5F00_thumb8_5F00_thumb_5F00_08F38732.png" width="424" height="440" />

In fact I didn’t want to use ASPX for implementation of my app. I wanted rather to use HTML pages.
Because the project template is based on MVC all request to all HTML pages as routed (allowed) as HTT-GET verbs.This would be perfectly fine for cordova based app or similar. Unfortunately , SharePoint will typically stream down the SharePoint-App content by HTTP-POST request, because the body of request will hold serialized SharePoint context data. Sending this request to a HTML page would cause 405 error (method not allowed). It is possible to workaround this with few tweaks. To simplify it I just renamed HTML page in ASPX page. My both ASPX-pages starts with typical HTML code.

<!DOCTYPE html>

<html ng-app="gassensormodule" xmlns="http://www.w3.org/1999/xhtml">
. . .

Receiving Events from Device with Java Script

Let’s take a look now how to implement receiving of events from device. To do this I will use Service Bus JavaScript SDK. First of all we need to initialize the QueueClient object.

var ingressQueueClient = new QueueClient(
        {
           
'name'
: ingressQueuePath,
           
'namespace': "YOURNAMESPACE"
,
           
'sasKey': "*****"
,
           
'sasKeyName': "send_listen_policy"
,
           
'timeOut'
: 10,
        });


Then we can use initialized client to receive the message. Following code will send the HTTP request to Service Bus endpoint and wait 10 seconds for message. If there is a message we will read properties and apply them as event object (new list element) on the view model list ‘events

 

this.sendCommand = function () {

           
var
msgBody = {};
           
var props = [{ 'Name': 'command', 'Value'
: $scope.CC.viewModel.command.name },
                       
{ 'Name': 'param', 'Value'
: $scope.CC.viewModel.command.param },
                        {
'Name': 'owner', 'Value'
: $scope.CC.viewModel.command.owner },
                        {
'Name': 'observed', 'Value': new
Date() }, ]

           
var msg = new
BrokeredMessage(msgBody, props);

            gasCmdQueueClient.sendMessage(msg,
function
(messagingResult) {
               
var
r = 1;
            },
"application/json"
);
        };
    });



The code shown above is a part of angularJS based controller. This controller is used for both EventReceiving and Command Sending pages.


(function () {

   
var app = angular.module('gassensormodule'
, []);

    app.controller(
'GasSensorController', function
($scope, $http) {

       
var m_SvcUri = "http://localhost:17742/api/Contact"
;

       
this
.viewModel = {};

        $scope.CC.viewModel.command =
        {
'name': 'stop', 'owner': "damir dobric - daenet GmbH", 'param': '-'
};

        $scope.CC.viewModel.events = [{
           
'gaslevel': 'gas'
,
           
'owner': 'owner'
,
           
'observed': 'observed'
,
           
'received': 'received'
,
        }];

       
var ingressQueuePath = "gasingressqueue"
;
       
var egressQueuePath = "gascommandqueue"
;

       
var ingressQueueClient = new
QueueClient(
        {
           
'name'
: ingressQueuePath,
           
'namespace': "YOURNAMESPACE"
,
           
'sasKey': "*****"
,
           
'sasKeyName': "send_listen_policy"
,
           
'timeOut'
: 10,
        });

       
var gasCommandQueuePath = "gascommandqueue"
;

       
var gasCmdQueueClient = new
QueueClient(
        {
           
'name'
: egressQueuePath,
           
'namespace': "YOURNAMESPACE"
,
           
'sasKey': "OBFUSCATED"
,
           
'sasKeyName': "send_listen_policy"
,
           
'timeOut'
: 10,
        });


       
var getSensorData = function
() {. . . }

       
this.readSensorState = function
() {
            getSensorData();
        },

       
this.sendCommand = function () {. . .
}

());



In HTML I used angular to render the UI on top of events stored in the view model. This is the whole required HTML code, which will render events as they arrive from Service Bus.


<!DOCTYPE html>
<html ng-app="gassensormodule" xmlns="http://www.w3.org/1999/xhtml">

<head>
   
<link href="css/bootstrap.min.css" rel="stylesheet" />
   
<title>Receiving of events</title>
</head>
<body ng-controller="GasSensorController as CC">

   
<script src="Scripts/servicebussdk-1.0.js"></script>
   
<script type="text/javascript"  src="Scripts/angular.js"></script>
   
<script type="text/javascript"  src="Scripts/app.js"></script>

   
<h2>Events received from device:</h2>

  
<button ng-click="CC.readSensorState()">Start reading</button>
  
   
<div ng-repeat="event in CC.viewModel.events">
       
<div style="border: thin outset #4cff00">
           
<p>Observed:{{event.observed}}</p>
           
<p>Gas Level: {{event.gaslevel}} V </p>
           
<p>Sent by: {{event.owner}}</p>
           
<br />
       
</div>
   
</div>
</body>
</html>


Sending Commands from JavaScript to Device

Sending of commands is almost identical approach. First we need to create the client instance, which will send commands to device. Note that we use different queues for sending of events and receiving of commands.

var gasCmdQueueClient = new QueueClient(
        {
           
'name'
: egressQueuePath,
           
'namespace': "YOURNAMESPACE"
,
           
'sasKey': "OBFUSCATED"
,
           
'sasKeyName': "send_listen_policy"
,
           
'timeOut'
: 10,
        });

Then we will use following code to send commands:

  this.sendCommand = function () {

           
var
msgBody = {};
           
var props = [
            {
'Name': 'command', 'Value'

            $scope.CC.viewModel.command.name },
            {
'Name': 'param', 'Value':
           
$scope.CC.viewModel.command.param },
            {
'Name': 'owner', 'Value'
: $scope.CC.viewModel.command.owner },
            {
'Name': 'observed', 'Value': new
Date() },
            ]

           
var msg = new
BrokeredMessage(msgBody, props);

            gasCmdQueueClient.sendMessage(msg,
function
(messagingResult) {
               
var
r = 1;
            },
"application/json"
);
        };
    });



Corresponding HTML code is this one. This code will read entered command related values and invoke sendCommand() when the button is clicked.

<!DOCTYPE html>
<html ng-app="gassensormodule" xmlns="http://www.w3.org/1999/xhtml">

<head>
   
<link href="css/bootstrap.min.css" rel="stylesheet" />
   
<title>Sending of Commands</title>
</head>
<body ng-controller="GasSensorController as CC">

   
<script src="Scripts/servicebussdk-1.0.js"></script>
   
<script type="text/javascript" src="Scripts/angular.js"></script>
   
<script type="text/javascript" src="Scripts/app.js"></script>

   
<h2>Command to be sent to device:</h2>
   
<div>
       
<p>
           
<h3>Enter Command ('stop', 'start', 'threshold')</h3>
       
</p>
       
<p>
           
<input type="text" ng-model="CC.viewModel.command.name"
               
ng-model-options="{ getterSetter: true }">
       
</p>

       
<p>
           
<h3>Enter the command parameter:</h3>
       
</p>
       
<p>
           
<input type="text" ng-model="CC.viewModel.command.param"
               
ng-model-options="{ getterSetter: true }">
       
</p>
       
<p>
           
<h3>Enter the owner:</h3>
       
</p>
       
<p>
           
<input type="text" ng-model="CC.viewModel.command.owner"
               
ng-model-options="{ getterSetter: true }">
       
</p>
       
<button ng-click="CC.sendCommand()">Send command</button>
   
</div>
</body>
</html>


Recap

In these two articles I shown how to implement highly scalable bidirectional communication between small devices and SharePoint by using Service Bus as broker and Service Assisted Communication introduced by Clemens. The power of this approach is that neither SharePoint Apps nor Sensor are acting as server. All acts as clients and do not have  a public IP address. Moreover, participants in the system can talk different protocols. This all makes system more secure and dramatically simplifies infrastructure requirements. I do not know how fast we are going to adopt such scenarios, but I’m sure that this approach opens a gate to many new scenarios.


Posted Dec 16 2014, 08:00 PM by Damir Dobric
developers.de is a .Net Community Blog powered by daenet GmbH.