Languages: English简体中文繁體中文

SensorThings API - Multiple Datastreams on a Chart

In Part 1 of this series, we saw how to display Observations of one Datastream on a chart. In this part, we'll be representing multiple Datastreams on a chart. It can make comparison easier.

What we will do is retrieving a Thing and its Datastreams and then Observations of each Datastream. We, then, add each of Datastreams' Observations as a new series to the chart.

Let's start with retriveing the Thing. As we saw on previous tutorial retrieving an entity in SensorThings API is as easy as sending an HTTP GET request.

GET http://toronto-bike-snapshot-snapshot.sensorup.com/v1.0/Things(1501)

We retrieve the Thing and then follow the @iot.navigationLink to retrieve its Datastreams.

Then for each of those Datastreams we follow, again, the @iot.navigationLink to retrieve Observations.

Here is the code for that:

var thingURI = "https://toronto-bike-snapshot.sensorup.com/v1.0/Things(1501)";
$.getJSON(thingURI , function(thing) {
  $.getJSON(thing["Datastreams@iot.navigationLink"] , function(datastreams) {
    $.each(datastreams.value, function(i, datastream) {
      $.getJSON(datastream["Observations@iot.navigationLink"] , function(observations) {});
    });
  });
});

After we retrieve Observations of one Datastream, we prepare the data and add it to the chart.

We can do it in the latest callback function, exactly as we did in the previous tutorial, and because we call the "addSeries" function each time in the "$.each" loop, multiple series will be added to the chart.

The only difference is that, since we have different set of data on the chart, we want to add a Y axis for each of them so that the chart will be more readable. For that, we use "addAxis" function of Highcharts library. Also to make the chart look more organized we can put Y axis to different side of chart every time.

Here is the code for that:

//Change position of YAxis every time we go to "$.each" loop
flag = !flag;
chart.addAxis({
  id: datastream.unitOfMeasurement.name,
  title: {
     text: datastream.unitOfMeasurement.name + " (" + datastream.unitOfMeasurement.symbol + ")"
  },
  opposite: flag
});

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

The rest of the code is exactly like previous tutorial. Here is the result:

See the code on SensorThings Share

How to make it better?

Again instead of multiple HTTP GET requests, we can get all the Thing, Datastreams, and Observations in one request using $expand query. One of the great capabilities of SensorThings API is that not only you can embed the immediate related entities in the response, but also you can embed the entities from next level of relation using multilevel $expand. For example, in this tutorial what we need is /Thing(<id>)?$expand=Datastreams/Observations

GET https://toronto-bike-snapshot.sensorup.com/v1.0/Things(1504)?$exapnd=Datastreams/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 thingURI = "https://toronto-bike-snapshot.sensorup.com/v1.0/Things(1501)?$expand=Datastreams/Observations";
$.getJSON(thingURI , function(thing) {
  $.each(thing.Datastreams, function(i, datastream) {
    var data = $.map(datastream.Observations, 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 retrieve Observations of a Datastream for a specified day. This tutorial will help you learn more about filtering capabilities of SensorThings API. Also, in case that the SensorThings server supports pagination, it shows how to follow @iot.nextLink to retrieve the next page of Observations.

Proceed to Part 3 - Filter Observations and Display on Chart