Languages: English简体中文繁體中文

SensorThings API - 展示观测值(Observations)

SensorThings API可以处理各类创建地理空间相关的物联网(Internet of Things, IoT)解决方案的必备数据。SensorThings中有多个实体(entity),其中一个实体是观测值Observation,它是用于存储传感器(Sensor)观察值(observations)/读数。分析IoT数据的第一步就是可视化物体(thing)中的不同Observation。本教程将关注如何从SensorThings取回Observations并且显示在图表上。

多伦多自行车共享资料集

SensorThings允许您透过开放标准来共享数据。现在,多伦多市有一个自行车共享计划,这个计划通过开放数据源(open data feed)共享了可用自行车以及可用站点的数据。我们获取了一些多伦多的自行车数据,并且把这些数据上传到了SensoUp云平台。这个系列教程中将使用这些数据。

先决条件

在这次教程,我们使用Highcharts函式库来创建互动式图表。同时,使用jQuery函式库从SensorThings取回数据。此外,还将使用Moment.js解析观测值的数据。

引入jQuery, Moment.js 和 Highcharts 函式库:

<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>

第一步: 从SensorThings服务器取回观测值(Observations)

在这一步中,我们会取回自行车共享数据的Observations。 SensorThings API中,每个Thing可以有多个数据流(Datastream),每个数据流Datastreams含有观测值Observation。我们可以将Datastreams看作是一个传感器sensor所有Observations的集合。

现在我们要做的就是将一个Datastreams(同属一个sensor)的所有Datastreams展现出来。所以接下来,首先是取回Datastream,然后取回这个DatastreamObservations,最后显示在图表上。

我们可以使用HTTP GET请求取得Datastream

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

这是使用jQuery来取得一个Datastream的代码:

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

然后,在这个回调函数中,我们可以跟随Observations@iot.navigationLink取回这个DatastreamObservations,可继续用HTTP GET请求来实现。

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

这是取回一个Observations的代码:

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

现在我们已经得到了绘制图表所需的Observations数据。 然而,Highcharts接受的数据格式是不同的:

  • 首先,数据需要按时间增序排列;
  • 第二,数据格式须为数组[timestamp,value],比如[[phenomneonTime1, result1],...]

因此,在开始准备图表之前,先调整数据格式。这是重新编排格式和排序后的观测值(Observations)数据的代码:

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];
    });
  });
});

现在我们的数据已经准备好了,让我们开始准备图表吧!

第二步: 显示图表

首先建立了一个div容器。接着,告诉Highcharts在这个div显示图表。

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

现在我们已经在chart div建立了Highcharts图表,并且设定标题为"Loading chart data"。当我们将数据加载到图表中时,我们将更新此标题。

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

我们可以让图表在加载数据的过程中显示“正在加载(loading)”,直至数据加载完毕再显示图表。Highcharts可以处理这个功能,而且代码很简单。

chart.showLoading();

首先,依据Datastream取回到的数据来更新图表标题,代码如下:

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

然后,将准备好的数据加载到图表上,只需要使用Highcharts中的"addSeries"函数来加载数据。再通过给图表上的点设定数据点提示框,当鼠标滑过图表时,它将会提示unitOfMeasurement的讯息,代码如下:

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

最后,更新Y轴并加入unitOfMeasurement,然后从图表中删除"正在加载"。

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

确认结果

现在是时候确认结果了,它应该看起来像下方的图表的样子
在 SensorThings Share 上查看代码

如何提升?

之前我们向Datastream以及它的Observations发送了两次HTTP GET请求。但其实,如果在Datastream中中扩展$expand它的Observations来进行查询,就只需要发送一次请求。

GET https://toronto-bike-snapshot.sensorup.com/v1.0/Datastreams(1504)?$exapnd=Observations
只在取回数据的部分修改一点点代码,其他保持不变即可做到。

在代码中加入$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];
  });
});
使用$expand后的结果如下:
在 SensorThings Share 上查看代码

下一步?

我们的下一部分教程将向您展示,如何在同一图表上显示多个Datastream。这种类型的图表对于比较多个Datastreams之间的变化可能更有用。

第二部分 - 同一图表多个数据流(datastreams)