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)