Languages: English简体中文繁體中文

SensorThings API - 數據驅動樣式設計

第一部分中, 我們:

  • 使用Leaflet製作了一個簡單地圖
  • 使用多倫多自行車共享站點的位置信息Locations填充了這張地圖
在這一部分中,我們會介紹如何基於SensorThings服務器取回的真實數據來設計地圖。 而且,我們會向您展示如何在地圖上製作不同顏色標記,來指示在特定位置可用的自行車數量。

首先,調整地圖

在我們深入了解數據驅動樣式設計的細節之前,讓我們對地圖進行一些微調。

  • 把標記改成圓圈
  • 為了使用戶了解數據來源,增加一行代碼來註明地圖中所提供的開放數據屬於自於多倫多市

在 SensorThings Share 上查看代碼
pointToLayer現在引入了一個函數,它回傳了圓形標記(circleMarker)來替代預設的標記圖案。

var geoJsonLayerGroup = L.geoJSON(geoJsonFeatures, {

  // Change the default marker to a circle
  pointToLayer: function(geoJsonPoint, latlng) {
    return L.circleMarker(latlng);
  }

});
這行代碼註明了地圖中所提供的開放數據屬於自於多倫多市。

map.attributionControl.addAttribution("Contains information licensed under the Open Government Licence – Toronto.");

自行車的去向?

現在,我們已經在地圖上放置了很多點,它們看起來還不錯,但不夠特別。因為雖然我們知道了自行車共享站點的位置,但如果能進一步知道每個共享站點有多少自行車將會更好。現在我們就來做這件事。

在SensorThings中,例如“可用的自行車(available bikes)”這樣的信息,可稱為觀測屬性ObservedProperty。 此次教程中的使用的SensorThings服務器包含了兩個觀測屬性ObservedProperties

  • 可用的自行車(Available bikes)
  • 可用的站點(Available docks)

請參考以下代碼

GET {{staBaseUrl}}/ObservedProperties

雖然對我們而言,可用的自行車和可用的站點都是重要的信息。但依需要,這部分教程將只關注可用的自行車數量。

現在我們要做的,是找到在特定的Location中可用自行車的數量。在SensorThings中,這類的信息被存儲在觀測值Observation中。我們必須通過SensorThings中多個其他的實體(entities)來獲取觀測值Observation。具體來說,我們需要先獲取在這個位置LocationThings,以及Things對應的數據流Datastreams (因為只有Datastream包含可用自行車的信息),然後我們再獲取每個數據流Datastream中的觀測值Observations(我們只要最新的一份數據)。這些雖然看起來繁瑣,但這些實體可支持您進行複雜特定的查詢。

GET {{staBaseUrl}}/Locations?$expand=Things/Datastreams($filter=ObservedProperty/name eq 'available_bikes'),Things/Datastreams/Observations($orderby=phenomenonTime desc;$top=1)

以上這個查詢看起來似乎有些難度,但實際上並不複雜。

  • /Locations: 對Locations的端點進行請求,與之前的請求相同。

  • $expand=Things/Datastreams($filter=ObservedProperty/name eq 'available_bikes'): 通過擴展這個Location來獲取Things以及它對應的多個Datastreams,然後在結果中過濾其他Datastreams,僅保留ObservedProperty中屬性名為'available_bikes'的結果。

  • Things/Datastreams/Observations($orderby=phenomenonTime desc;$top=1): 這是擴展$expand參數的第二部分。這部分對於剩下未被過濾的Datastreams擴展獲得觀測值Observations,並且獲取根據phenomenonTime排序後的最新一份數據。因此只會傳回最新的觀測值Observation

這些響應包括:

  • Location的經度和緯度座標(之前取回過)

  • Location最新一些的可用自行車數量(本次新增)

這裏的結果我們將不會帶您逐行閱讀,但您可以自行閱讀以加深理解,包括哪些數據是有用的以及結構如何。畢竟數據是建立用戶界面的原始材料!

整合到地圖

現在我們知道如何從每個站點取回可用自行車的數量,接下來就準備建立我們的地圖了。

在 SensorThings Share 上查看代碼
我們在GeoJSON Features裡增加了一行properties: location,以便LeaFlet來訪問SensorThings響應中的Things,Datastreams, 和Observations

var geoJsonFeatures = success.data.value.map(function(location) {
  return {
    type: 'Feature',
    geometry: location.location,
    properties: location
  };
});
最後,我們改變了標記的顏色,用於區分"足夠的"自行車(顯示為藍色, 或十六進制顏色#38f)和"不足的"的自行車(顯示為紅色)。我們姑且設定了一個值(5),超過五輛自行車即為“足夠的”,小於則為“不足的”。

pointToLayer: function(geoJsonPoint, latlng) {
  var enoughBikeColor = "#38f";
  var fewBikesColor = "red";
  var availableBikes = geoJsonPoint.properties.Things[0].Datastreams[0].Observations[0].result;
  return L.circleMarker(latlng, {
    color: availableBikes > 5 ? enoughBikeColor : fewBikesColor
  });
}

下一步?

您是那種會告訴老師他們錯了的學生嗎?如果您是,此刻您肯定會舉手,事實上,也許此刻您會瘋狂地揮舞手臂引起老師注意。 那是因為您可能發現了,/Locations的響應中"@iot.count": 199,但其實只有100個 Locations被傳回來。您也許還會注意到這裏暗藏了一個@iot.nextLink屬性。

我們還沒有顯示所有的自行車分享站點。

所以,接下來請繼續第三部分。

第三部分 - 可視化更多的位置(Location)