Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Displaying Metrics From IoT Devices With Kendo UI Builder

DZone's Guide to

Displaying Metrics From IoT Devices With Kendo UI Builder

In this post on the Kendo UI Builder, we look at displaying metrics from an IoT device. Read more to learn how!

· IoT Zone ·
Free Resource

In my next post for the Kendo UI Builder how-to series, we are going to study a sample custom component that interacts with another component on the page via the model property. Specifically, the component will display a metric from an IoT device in a room. The data from the various rooms and devices is obtained via a REST data provider.

We will use two instances of this component on a blank view to show the temperature and the humidity in the room. The room is selected from a ComboBox component on the same view.

The view containing the ComboBox and the two custom components looks like this:

Room metrics

This sample component builds up from the basic component sample that I introduced earlier in the series. If you are not familiar with it, you can read more about it here.

To follow along, download the template samples zip from GitHub or clone the repository. Then, open the folder components/custom-device-metrics-comp and follow the same steps outlined in this post to install this template in your target application.

Prerequisites

We need to set up a couple of items:

  1. A test REST server that serves device metrics for several rooms
  2. A Data Provider to the REST service
  3. A blank view containing a ComboBox to select which room we want information from

We will leverage the REST server and data provider in several other samples in this series. So, please take the two minutes it takes to set it up. It will be time well spent.

Setting Up the REST Server (2 Minutes)

The device metrics will be provided by a test REST server. Setting it up is straightforward, thanks to the JSON-server, a zero coding REST server:

  1. Install with the command:  npm install -g json-server  (click here for more info)
  2. Start the server:  json-server --watch dbIoT.json --port 3004  (this starts the server with the data set in file dbIoT.json, which is available on this GitHub repo)
  3. You can verify access by trying this URL http://localhost:3004/devices

You should get a full list of about 20 records that look similar to this example record:

"id": 1,
 "room": "Schrödinger",
 "currentTemp": 21,
 "setTemp": 20,
 "hum": 65,
 "co2": 200,
 "voc": 4


Setting Up the Data Provider to the REST Service

  1. Create a Kendo UI Builder application, save it, and exit from the Kendo UI Builder
  2. Copy the sample Data Provider file from: https://github.com/thierryciot/kendoui-builder-template-samples/blob/master/DataProviders/IoT.json to: [your application name]\meta\dataProviders\IoT.json
    This will save you from having to configure the REST data provider to the Devices REST service installed in the previous step.

Now, you will need to restart the Kendo UI Builder and verify that the IoT data provider is listed. When you edit the Devices data source, you should see this:
data

Setting Up the Blank View

The blank view is set up with a data source to our Devices REST service and with a drop-down list showing the list of rooms. Follow these steps:

  • In your application, create a blank view.
  • In the right panel, click on the Edit button of the View’s Data Source property and create a data source like this:View data source
  • On the blank view, in one column of your choice, add a ComboBox component with the following properties:data source

Once that’s done, we are ready to create instances of our device metric component and bind these instances to a specific field from the REST record (a room with device metrics) via the model “DevicesModel.”

How do we define a component that can be bound to a field in this model? Let’s take a look at how we do that by programming the component definition file.

Component Definition

Open the file components/custom-device-metrics-comp/custom-device-metrics-comp.json

It contains the same properties as the basic component sample, so these should be familiar to you. If not, please refer to this blog post.

There are two new properties:

"valuePrimitive": {
 "type": "boolean",
 "default": true,
 "hidden": true,
 "order": 3
},
 "model": {
 "type": "string",
 "title": "Model",
 "default": "",
 "editorType": "modelName",
 "order": 4
}


In this post, we're focusing on the model. We will go into the details of the valuePrimitive in the next blog when we write a multi-values component.

The model property, and more specifically the modelName editor (property editorType), provides a way to select the data source and the field to bind it to the EJS model variable.

Here is how the model property renders at design-time in the property panel:

device metrics

For the first instance of my device metric custom component, I selected the model corresponding to my IoT Devices data source (DevicesModel). Then, I selected, the field currentTemp   to indicate that I wanted the Metric component to display the current temperature from the selected room.

For the second instance, I simply selected the “hum” field (Humidity):

humidity

Now would be an appropriate time to try this for yourself. Go to the blank view you created earlier and drag two instances of the custom component in two separate columns. For each one, select the model and any of the metric you like (like VOC, CO2, etc.).

Design-Time

As we did in this previous post, in the sample custom-hello-world-comp, we define an icon used in the component palette (left panel).

We also define a template:

<div>
    <%- metric %>: 12
</div>


This templates simply shows the label of the metric and a hard-coded value.

Run-Time

The run-time templates are also relatively simple.

There are two main things we need to take care of:

  1. We need to ensure that we display the label for the proper instance, so we use the EJS <%-id%> string to refer to the specific instance.
  2. We also need to reference the proper field from the data model using the EJS <%- model %> string (the value of this will be, for the component instances, DevicesModel.currentTemp   and  DevicesModel.hum  respectively)

The generated code for these depends on the target framework. So, let’s explore each one a bit more.

Angular

The template looks like this:

<div class="deviceMetric">
  <span class="deviceMetricLabel">{{$config.components.<%-id%>.metric}}</span>
  <span class="deviceMetricSeparator"></span>
  <span class="deviceMetricValue">{{$dataModels.<%- model %>}}</span>
</div>


Refer to file components/custom-device-metrics-comp/angular/template.html.ejs

The generated code base component typescript file, for example,  devices.view.base.component.ts , has an object literal  $dataModels  with a reference to an object containing the field values we want to render in component instances.

public $dataModels: any = {
  DevicesModel: new IoTDevice()
};


And, here is the definition for IoTDevice:

export class IoTDevice
{
   public id: number;
   public room: string;
   public setTemp: number;
   public currentTemp: number;
   public hum: number;
   public co2: number;
   public voc: number;
}


The expression {{$dataModels.<%- model %>}} will be translated by the EJS compiler to {{$dataModels.DevicesModel.currentTemp>}}. For the first instance of the custom component and to {{$dataModels.DevicesModel.hum>}} for the second instance, this provides access to the values for the currently selected device (room).

Note: The code generator uses the data provider and data source names to generate the IoTDevice class name. If you used a different data provider than the one provided in the GitHub repository, the names will be different.

How is the model updated?

The model is updated each time the ComboBox is changed. This is happening because of this change handler registered within the ComboBox component (See file: generators/angular/generators/shared-module/templates/components/combo-box/combo-box.component.html in your generated project):

(valueChange)= "changeHandler($event)"


AngularJS

Refer to file components/custom-device-metrics-comp/angularjs/directive.html.ejs:

<div class="deviceMetric">
    <span class="deviceMetricLabel">{{vm.$components.<%-id%>.metric}}</span>
    <span class="deviceMetricSeparator"></span>
    <span class="deviceMetricValue">{{vm.$viewModels.<%-model%>}}</span>
</div>


The generated code (controller.js) defines $viewModels as an array of data source models. The expression {{vm.$viewModels.<%-model%>}} will be translated by EJS compiler to {{ vm.$viewModels.DevicesModel.currentTemp>}} for the first instance of the custom component and to {{ vm.$viewModels.DevicesModel.hum>}} for the second instance, this provides access to the values for the currently selected device (room).

CSS Classes

Notice that for both the Angular and AngularJS frameworks, we provide a set of CSS classes to further customize the appearance and content. Here is an example of CSS definitions to put in view styles:

.deviceMetric{
    font-size: 120%;
    margin: 1rem;
}

.deviceMetricLabel {
    font-weight: normal;
}

.deviceMetricSeparator:before {
    content: ":";
    margin-right: 0.6rem;
}

.deviceMetricValue {
    font-weight: bold;
}


Conclusion

A component typically needs to interact with data source items. This blog and its associated sample show you how:

  1. You can define a custom component that interacts with the data source model (a property with an editor of type modelEditor).
  2. You can leverage the model property in the component template.

The component we studied is rendering a single value. In an upcoming post, we will study a component that renders multiple values, so stay tuned!

Topics:
iot ,tutorial ,kendo ui builder ,rest api ,metrics

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}