LPWAN IoT applications

Many IoT scenarios, such as smart city applications, involve multiple autonomous devices that fulfill specific tasks, such as monitoring noise levels, air quality, light, traffic, etc. These devices typically operate in LPWAN configurations (Low Power Wide Area Networks) with limited capabilities, and no access to power sources. As a consequence, the life-time of their battery, their power consumption as well as the network coverage and capabilities are main criteria to consider in the technical choices made when designing the related IoT applications; starting with the choice of an adequate network protocol and infrastructure.

LoRaWAN is one of the network communication protocols and architectures that address the above requirements. LoRaWAN adopts a star deployment model, where nodes communicate with gateways that forward data packets to cloud network servers, which add some intelligence to the process, notably by filtering messages, conveying them to third party APIs and enabling back and forth communication between the latter and the devices.

Network servers solve the communication problems between devices and the rest of the world and as such, they are major components of the implementation of IoT solutions/applications. They do not however cover this implementation from end to end and more particularly, they do not usually deal with the implementation of (business) processes, data integration and/or transformation, or bespoke integration with third parties. This latter part is usually handled by other cloud-based IoT platforms such a scriptr.io.

Smart city sample application

In order to illustrate the collaboration between network servers such as Orbiwise and scriptr.io, we will describe a sample smart city application we implemented using: (1) loRaWAN-enabled devices, (2) an Orbiwise server, (3) scriptr.io and (4) our connector to Orbiwise.

About Orbiwise

Orbiwise offers a full network software solution for LoRaWAN-based networks, which can scale to support millions of devices. They notably provide a network server to interconnect loRaWAN devices to the outside world, either through API exposed by the server or through packet propagation (invocation of callbacks registered at the server).

Scenario

lora-scenario

In our sample smart city application, two loRaWAN enabled devices push temperature and light measures to an Orbiwise server. Using our Orbiwise connector, we register a callback to the Orbiwise server, which will automatically be invoked whenever new data is sent by one of the two devices. Temperature and light measures that are received as part of the devices’ payload are passed to a decision table that will decide if city lights should be turned on (in case light percentage is below 25%) and/or if an icy road alert should be sent (in case temperature in below 4 Celsius degrees) or if a heat alert should be sent whenever temperature rises above 33 Celsius degrees. Alerts will actually be sent through push notifications to all subscribers. Administrators will be able to follow-up on the status of their devices using a dashboard built by assembling scriptr.io’s UI components.

Registering a callback

First step is to require the orbiwise server script into your application (a script in your workspace), then create an instance of the OrbiwiseServer class:

var orbiwise = require("../modules/orbiwise/orbiwiseserver");
var orbiwiseServer = new orbiwise.OrbiwiseServer(); 

To register a callback, simply invoke the registerCallback() method. We will use the default callback endpoint that is provided by the connector, and thus won’t pass any parameters to the method (of course, you can override this behavior and pass your own callback configuration):

orbiwiseServer.registerCallback();

After registering the callback, the application will automatically receive any updated data sent by the devices through the Orbiwise server to the callback’s endpoint.

Taking decisions based on the received data

Next step is to retrieve the temperature and light values from the body of the HTTP request that is received by the callback script and pass it to our decision table:

var payload = atob(request.body); // payload is a base64 encoded JSON {"temp":xx, "light":yy}
var decision = decisionTable.executeDecisionTable("./decisiontable", payload); // decision is similar to [{lights:"on"}, {alert:"icy roads"}]  

Our decision table is as follows:

smart_city_decision

As you can notice, rules are non mutually exclusive and therefore, multiple decisions can be driven from the values of the payload sent to the table.

Control city lights and send alerts to mobile phones

From the decisions returned by the decision table, the last step of our process is to send instructions to the devices that control the city lights and send alerts through push notifications to the citizen who subscribed to the “smart city service”.

In the below, we loop through the decisions: whenever a decision key is “lights”, we publish the corresponding value (“on” or “off”) to the “citylights” channel. This latter has already been created in scriptr.io and it broadcasts any published message through a web socket connection to the devices that are subscribed to it (city light controllers). Whenever a decision key is “alert”, we use the native “pushToGroup” function to push a notification to the “citizen” group. This group has also been created and contains device tokens obtained from the citizen who have subscribed to the service.

for (var i = 0; i < decision.length; i++) {
  
  var key = Object.keys(decision[i])[0];
  var value = Object.keys(decision[i])[1]
  switch(key) {
     
    case "lights": publish("citylights", value);break;
    case "alerts": pushToGroup("citizen", value);break;
  }  
}

Simple dashboard

Last step in implementing the application is to provide a very simple dashboard where the devices’ status (temperature and light %) is displayed. Our dashboard is built simply by assembling a configuring a few scriptr.io UI components, as shown in the code snippet below.

We just need to add a few lines of code to the callback script, in order to publish the temperature and light values to a scriptr.io channel (“lorawan_sub”, already created), to which our widgets (gauges) are subscribed:

// from the device payload received by the callback script, build a message with 
// the value of the temperature, 
var tempMsg = {
   "id": "temperature", // this allows the dashboard to determine which UI component is targeted
   "result": payload.temp
};

// publish the temperature on the "lorawan_sub" channel, to which the temperature 
// gauge in subscribed
publish("lorawan_sub", tempMsg);

// from the device payload received by the callback script, build a message with 
// the value of the light %, 
var lightMsg = {
   "id": "light", // this allows the dashboard to determine which UI component is targeted
   "result": payload.light
};

publish("lorawan_sub", lightMsg);

The dashboard itself is built by assembling two gauges components:

<scriptr-gauge 
	transport='wss' 
	msg-tag="light" 
	api='/dashboard/light/getLight'
	on-format-data="vm.callback">
</scriptr-gauge>
<scriptr-gauge 
	transport='wss' 
	msg-tag="temperature" 
	api='/dashboard/light/getTemperature'
	on-format-data="vm.callback">
</scriptr-gauge>

orbiwise-dashboard

Conclusion

Smart city applications – and many IoT applications – adopt a quite stable architectural pattern: devices push data on a network, data reaches network servers and is forwarded to other IoT platforms where business logic resides. While this pattern is rather simple and stable indeed, deriving it into an actual implementation will usually lead you to dealing with too many low-level tasks with no added value, such as protocol management, integration, messaging, UI, etc. Using Orbiwise and scriptr.io’s out-of-the-box capabilities, you can actually avoid falling into handling these low-level tasks, as we’ve tried to demonstrate it in this blog post.