Languages: English简体中文繁體中文

SensorThings API - Getting Started with Representing Observations

This is of a four-part series on representing Observations with SensorThings.

The SensorThings API handles a wide variety of data necessary for creating a geospatial-enabled Internet of Things (IoT) solution. One of the entities in SensorThings is the Observation, which is used to store Sensor Observations/readings. The very first step in analysing the IoT data is to visualize the different Observations from different Things. In this tutorial, we're going to focus on how we can retrieve Observations from SensorThings, and display them in a chart.

Toronto Bike Sharing Dataset

SensorThings allows you to share data using open standards, which is a good thing. The city of Toronto has a bike sharing program, which is also a good thing. This program shares bike availability and docking availability information via an open data feed, which is, you guessed it, a good thing. We've put these good things to good use by taking the Bike Share Toronto data and putting it in a SensorUp Cloud instance. We'll be using that instance as the data source for this tutorial.

Prerequisite

In this tutorial we'll be using Highcharts library, which is a JavaScript library for creating interactive charts. Let's start by showing a basic chart. We are also using jQuery library for retrieving data from SensorThings server. Also, Moment.js library is used for parsing Dates in Observations.

Here is the code for adding jQuery, Moment.js, and Highcharts libraries.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highstock/4.2.6/highstock.js"></script>

First Learning Step:
How to retrieve Observations from a SensorThings Service

In this step we will retrieve Observations from Bike Share data.

In SensorThings API each Things has multiple Datastreams and each Datastreams has Observation. We can look at Datastream as the grouping for Observations of a Sensor. What we need to do is representing the Observations of one Datastream as they are coming from the same Sensor. So, what we do is first we retrieve the Datastream and then we retrieve the Observations of that Datastream to show on a chart.

We can retrieve the Datastream by sending an HTTP GET request.

GET https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)

Here is the code for retrieving a Datastream using jQuery library:

var datastreamURI = "https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)";
$.getJSON(datastreamURI, function(datastream) {});

Then, in the callback function we can follow Observations @iot.navigationLink to retrieve the Observations of that Datastream. Again it can be done with HTTP GET Request.

GET https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)/Observations

Here is the code for retrieving a Observations:

var datastreamURI = "https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)";
$.getJSON(datastreamURI, function(datastream) {
  $.getJSON(datastream["Observations@iot.navigationLink"], function(observations) {});
});

Now we have the Observations data needed for plotting on a chart. However, the data format that Highcharts is accepting is different.

  • First, data needs to be sorted by time in ascending order.
  • Second, the data format is array of [timestamp, value], like [[phenomneonTime1, result1],...]

So lets correct the data format before start preparing chart.

Here is the code for re-formatting and sorting Observations data:

var datastreamURI = "https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)";
$.getJSON(datastreamURI, function(datastream) {
  $.getJSON(datastream["Observations@iot.navigationLink"], function(observations) {
    var data = $.map(observations.value, function(observation) {
        var timestamp = moment(observation.phenomenonTime).valueOf();
        return [[timestamp, parseFloat(observation.result)]];
    });
    data.sort(function(a, b) {
      return a[0] - b[0];
    });
  });
});

Now that we have the data ready and in the correct format, lets start preparing the chart.

Second Step:
How to represent on Chart

We start with creating the container for the chart. Here is the code for a 500 pixel tall div tag. Later, we will tell Highcharts to show the chart in this div.

<div id="chart" style="height: 500px"></div>

Now we create a Highcharts chart in the chart div we created earlier, and set the title as "Loading chart data". We will update this title as we load the data into the chart.

var chart = new Highcharts.StockChart("chart", {
  title: { text: "Loading Chart Data..." },
  series: []
});

We can enable the chart to display that it is loading until we load it with data. Highcharts library handles it and the code for that is as simple as following code.

chart.showLoading();

First we want to update chart title with the information we retrieved from Datastream. Here is the code for that.

vchart.setTitle({ text: datastream.description });

Now we want to load our prepared data to the chart. We just need to use "addSeries" function from the Highcharts library and load our data. We also set the tooltip text for the chart points so that it will show unitOfMeasurement on mouse over.

Here is the code for that.

var series = chart.addSeries({
  data: data,
  tooltip: {
    valueSuffix: " " + datastream.unitOfMeasurement.symbol
  }
});

The last thing we want to do is to update the Y axis and add unitOfMeasurement to that. Then we can remove loading from the chart.

series.yAxis.update({
  title: {
    text: datastream.unitOfMeasurement.name + " (" + datastream.unitOfMeasurement.symbol + ")"
  }
});
chart.hideLoading();

Lets check the result

It is time to check the result of our work. Here is how it looks.

See the code on SensorThings Share

How to make it better?

Instead of sending two HTTP GET request to the Datastream and its Observations, we can use SensorThings API query capabilities to retrieve all we need in one request. To this end, we can use $expand query to embed the Observations in our Datastream query.

GET https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)?$exapnd=Observations

We need to make a slight change in the retrieving data part and the rest of code is exactly the same.

Here is how we need to change the code for using $expand:

var datastreamURI = "https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)?$expand=Observations";
$.getJSON(datastreamURI, function(datastream) {
  var data = $.map(datastream.Oservations, function(observation) {
      var timestamp = moment(observation.phenomenonTime).valueOf();
      return [[timestamp, parseFloat(observation.result)]];
  });
  data.sort(function(a, b) {
    return a[0] - b[0];
  });
});

Here is the code uses $expand that you can also try:

See the code on SensorThings Share

What's Next?

Our next tutorial will show you how to show multiple Datastreams on the same chart. This type of visualization can be more useful for comparing the trend of changing between multiple Datastreams.

Proceed to Part 2 - Multiple Datastreams on a Chart