Microsoft StreamInsight

建置物聯網

Torsten Grabs
Colin Miller

 

最近關於“物聯網”(IoT) 的爭論有很多,而且理由都很充分。Ericsson 的 CEO Hans Vestberg 預測到 2020 年將有 500 億台設備連接到 Web(bit.ly/yciS7r [PDF 下載])。目前約有 15 億台 PC 以及不足 10 億台電話連接到 Web — 500 億相當於全球每個人約 7 台設備,這可以説明您直觀理解這一數位!市場研究機構 IDC 則預測到 2015 年將有超過 160 億台設備連接到 Internet(參見圖 1)。不可否認,也存在一些較保守的預測,但通過每個人提供的數位,我們看到 Internet 的角色正在發生巨大轉變 — 從為人們提供資訊和娛樂內容到為支援設備的新興應用程式提供連接服務。


圖 1 IDC 預測會出現“嵌入式 Internet”

這些龐大數位看似可信的理由是強大的驅動因素(商機和必然性)正在推動此類解決方案的快速增加。《經濟學家》(economist.com/node/17388368) 最近的一期雜誌指出,“…經濟大潮的向前滾動不僅僅是為了符合技術公司和雄心勃勃的政治家的利益。It has gained momentum because there is a real need for such systems.” Figure 2 shows the growth of this type of solution by application area.例如,在歐洲強制實施智慧能源系統是一個必然結果。如果我們還不能管理能源消耗,則無法構建所需的能源產生功能。在商機方面,簡單的、無所不在的自動售貨機就是一個很好的示例。在連接該設備之後,可以根據需要而不是某項並非最理想的計畫來指派服務人員。如果本地需求增加或商品接近到期日,甚至還可以動態更改價格。可以報告停電情況以便督促立即更換易腐商品。換句話說,連接實現了更高效的全新業務模型。


圖 2 按行業劃分的應用增長態勢

通過引用連接設備的數量來描述此轉變肯定很形象,但它也會讓人產生一些誤解 — 此種轉變並不表明幾十萬傳統嵌入式程式師將充分就業。這些設備僅是將其他設備集成到 Internet 的所有方面(包括分析、雲、Web 應用程式、PC 和移動介面等)的複雜解決方案的終結點。

因此,看待此問題的方法是當前構建基於 Web 的應用程式的每個人將需要集成設備並説明開發新業務和新業務模型。換句話說,即使您不是嵌入式開發者,也不在構建嵌入式設備的商店中工作,這也是一個值得您評估的非常誘人的商機。您當前具備的 Microsoft 技能將使您能夠在 IoT 方面取得成功。

對設備資料進行分析

“資料已成為新的貨幣”,Windows Embedded 團隊的總經理 Kevin Dallas 在最近的採訪中說道 (bit.ly/wb1Td8)。與當前 Internet 應用程式相比,IoT 涉及資訊生成、管理和訪問。讓我們比較一下當今典型 Internet 應用與 IoT 應用的資料特徵。您或許和其他幾百萬人均使用多家金融機構共用的流行機制連線支付帳單。您每月登錄多次,查看一些頁面並提交付款資訊。所有這些資料都是使用當您開始與系統互動時所運行的查詢從傳統資料庫中提取的。您下載的頁面量可能很大,但交互非常少,即使它們生成的有價值的資訊(付款資訊、個人資訊更新等)需要長時間保存也是如此。

將此應用與能源管理系統進行對比,該系統中可能有 5000 萬座大樓(商業樓和住宅樓)正在提供輸入。輸入由內部的多個本地終結點(例如,房子)使用發佈到後端的單個聚合視圖生成。該資料包括返回給大樓的成為定價和記帳基礎的即時使用資訊和強制性控制。此系統將與價值相對較低的資料進行非常頻繁的交互,這些資料在您計算系統的當前狀態和該終結點的趨勢資料時不一定有意義。不過,該系統需要能夠立即對可能威脅其運行的情況(例如需求劇增引發網格超載和停電)做出回應。在這種情況下,廣播資訊可以立即減少能源消耗。此類系統需要連續分析傳入資料並比較發展趨勢,以識別指示較高停電風險的模式。

圖 3 演示 IoT 應用的典型體系結構。堆疊底部顯示了各種資產或設備,它們根據不同應用領域配備了不同種類的感測器。這些感測器通常生成應用領域快速處理和分析所需的連續資料來源。根據設備的功能,設備本身或許能夠在本地執行一些處理。這稱為本地分析,並且 .NET Micro Framework 之類的工具可説明您在設備傳遞資料之前執行該本地處理。IoT 應用使用 Internet 協定傳遞設備資料,以便可以對資料進行全域分析。而全域分析的結果(例如電網的整體運行狀況)是管理運營的最終使用者或業務決策者關注的內容。分析還可以驅動根據傳入資料中呈現的情況自動採取操作的封閉系統。如果資產可接收來自全域分析的回饋(例如,影響行為更改或改進操作),則這些方法將非常有用。需要連續計算推動這些過程的全域分析並儘快提供結果。另外,分析頻繁參考隨感測器資料一起提供的時間和時間戳記。因此,僅將此類資料放入資料庫中並對其運行定期查詢不是適當的方法。幸運的是,Microsoft StreamInsight 支援不同的方法。


圖 3 物聯網應用的典型體系結構

Microsoft StreamInsight

Microsoft StreamInsight 旨在對連續到達的資料提供及時反應,而不將資料寫入磁片中以進行分析和查詢。許多 IoT 應用領域需要在從源獲取資料後幾乎即時地分析傳入資料。考慮我們提到的智慧電網應用,它需要對劇增的電力需求快速做出反應以重新平衡電網的運營能力。許多 IoT 應用具有相同的需求:需要連續分析的資料處理和引人注目的延遲。分析必須連續,因為資料來源不斷地生成新資料。許多方案需要識別只能通過分析傳入資料而呈現的情況並對其快速做出反應,因此它們需要低延遲分析和幾乎立即提供的結果。這些要求使在執行分析之前將資料存儲在關聯式資料庫中變得不切實際。

我們將這些應用稱為事件驅動應用,而 IoT 正是此類功能發揮作用的一個方案。StreamInsight 是一個用於構建這些高度可伸縮、低延遲的事件驅動應用的強大平臺。它是自 2008 R2 版本發佈以後的 Microsoft SQL Server 的一部分。在事件驅動處理和基於豐富表達時間的分析方面,StreamInsight 為 SQL Server 提供了補充。使用 StreamInsight,將以生成資料的速度,而不是處理傳統資料庫報告的速度提供業務見解。

可供人們立即使用或使應用程式能夠自動對事件做出反應的分析結果可説明企業更及時且更好地瞭解其相關運營情況,甚至可以自動執行部分運營工作。它們也可以對感測器或設備資料中出現的重要情況、商機或趨勢更快地做出反應。

要編寫 StreamInsight 應用程式,開發者可使用 Microsoft .NET Framework、LINQ 和 Microsoft Visual Studio 等熟悉的工具。圖 4 描述了 StreamInsight 應用程式的開發者和運行時體驗並介紹了一些關鍵概念。


圖 4 StreamInsight 應用程式開發和運行時

簡單的 IoT 應用

讓我們更深入地瞭解可能的 IoT 應用方案;然後我們將構建它。在我們的端到端示例中,我們將關注一個簡單方案,該方案使用運動感測器監視旋轉設備,例如渦輪或風車。這很重要,因為振動過大會導致出現緊急情況,在這種情況下,設備可能出現故障,並且如不立即停止,則會出現嚴重損壞。為可靠地檢測此情況,每台設備均配備多個跟蹤運動的感測器。單個感測器中的運動激增可能僅指示該感測器的資料讀數不可靠,但多個感測器中同時出現異常劇烈的運動則表明出現緊急情況。例如對於大型渦輪,您可能希望引發警報,甚至自動關閉設備。除了持續檢查此類情況外,我們還希望為操作員提供一個儀錶板,它提供了設備狀態的近即時視圖。

若要構建此方案,我們需要滿足以下要求和解決以下技術難題:

  • 設備需要捕獲哪些資料?
  • 我們使用哪些感測器來測量資料?
  • 設備如何將其感測器讀數傳送到 Internet?
  • 我們如何將設備資料收集到一個位置以進行分析?
  • 我們如何可以連續分析傳入資料並對緊急情況快速做出反應?
  • 我們如何跨多台設備及時關聯感測器讀數,以便可以檢查全域情況?

讓我們看一下滿足這些要求並實現端到端方案的方式。

IoT 應用:實現要點

下麵是實現上一節中所述的 IoT 應用的一些關鍵步驟。我們將首先討論設備,再轉到輸出的視覺化,然後轉到填充儀錶板的跨設備分析。

設備。為構建感測器設備,我們首先從 Netduino Plus 著手,它是運行 .NET Micro Framework、具有 128K SRAM 的受歡迎的小型開發板。我們添加了名為 WiFly GSX Breakout 的常見愛好者 Wi-Fi 無線電,並在自訂 PCB 板上安裝了實際感測器,包括三軸加速計。我們對設備進行程式設計,以將感測器讀數的每秒更新發送給 Web 服務,該服務充當從所有設備收集資料並進行處理的中心。

我們對 Web 服務使用 RESTful 連接 — 它只是包含逗號分隔名稱-值對的 HTTP POST。當然,您可以從支援 HTTP 的任何種類的設備執行此操作。我們選擇使用 .NET Micro Framework,以便整個應用程式(包括設備、Web 服務、StreamInsight 適配器、Silverlight 儀錶板等)全部可以使用單個程式設計模型 (.NET) 和工具鏈 (Visual Studio) 進行編寫。很明顯,如果您具有 .NET 技能,則無需招聘新員工或將您的 IoT 專案的一部分外包給外部嵌入式商店;您具有完全執行它的技能。例如,設置加速計時只需幾行代碼即可訪問 AnalogInput 類並調用 Read 方法:

this.analogInputX = new AnalogInput(pinX);
this.analogInputY = new AnalogInput(pinY);
this.analogInputZ = new AnalogInput(pinZ);
...
rawZ = analogInputZ.Read();
rawY = analogInputY.Read();
rawX = analogInputX.Read();

在讀取感測器輸入並設置 HTTP 消息內容格式後,發送資料所需的一切都包括在圖 5 中。

圖 5 提交感測器資料

protected void submitSensorData(string uri, string payload)
{
  // Message format
  StringBuilder sb = new StringBuilder(256);
  sb.Append(
    "POST /Website/Services/DataService.aspx?method=SaveDeviceData HTTP/1.1\n");
  sb.Append("User-Agent: NetduinoPlus\n");
  sb.Append("Host: 192.168.1.101\n");
  sb.Append("Connection: Keep-Alive\n");
  sb.Append("Content-Length: ");
  sb.Append(payload.Length.ToString());
  sb.Append("\n");
  sb.Append(payload);
  sb.Append("\n");
  try
  {
    HttpResponse response = webServer.SendRequest(uri, 80, request);
  }
  catch
  {
    ...
}
}

在伺服器端,我們實現方法 SaveDeviceData,設備要將其消息發佈給該方法。 我們拆分消息字串並分析 MAC 位址、時間戳記和負載資料,例如來自加速計的運動讀數。 我們使用所有這些資訊來填充傳遞給 StreamInsight 以進行後續分析的 DeviceData 物件(請參見圖 6)。

圖 6 填充 DeviceData 物件

private int SaveDeviceData()
{
...
List<string> data = record.Split(',').ToList();
  DeviceData deviceData = new DeviceData();
  deviceData.MAC = NormalizeMAC(data[0].Trim());
  deviceData.DateTime = DateTime.UtcNow;
...
deviceData.Motion = Convert.ToDecimal(data[2].Substring(data[2].IndexOf(":") + 1));
...
// Communicate each new device data record to StreamInsight           
  DeviceDataStreaming streaming = (DeviceDataStreaming)
    HttpContext.Current.Application[Global.StreamingIdentifier];
    streaming.TrackDeviceData(deviceData);
...
}

儀錶板。現在我們要構建允許設備操作員查看設備上感測器的當前狀態的儀錶板。為便於演示,我們將僅關注一台設備。圖 7 顯示了一個此類儀錶板的示例。讓我們從左側開始,查看感測器資料的不同視圖。


圖 7 用於設備監視的儀錶板

移動平均數視圖:左下角的資料網格顯示裝置的感測器讀數,其中包括光線、溫度和運動值以及設備 ID 和時間戳記。正如您可以從時間戳記中看到的,這些值每秒更新一次。但儀錶板不顯示原始感測器值,而是顯示 10 秒內感測器資料的移動平均數。這意味著會使用最近 10 秒內資料的平均數每秒更新一次值。使用移動平均數是一種常見的簡單技術,可防止出現使用低成本感測器時偶爾出現的異常值和不良資料。

趨勢線視圖:在右下角,儀錶板顯示感測器的趨勢線。趨勢線視圖的走勢由左側資料網格中顯示的移動平均數決定。

警報視圖:右上角的視圖顯示警報的資料網格。如果檢測到臨界情況,則會引發顯示時間和其他資訊(例如嚴重性和狀態)的警報。

分析。現在讓我們瞭解幕後操作並討論處理傳入感測器資料並計算儀錶板視覺化的結果的分析。我們使用 StreamInsight 執行分析。以下類表示設備資料,其中包括 MAC 位址、時間戳記和感測器值:

public class DeviceData
{
  public string MAC { get; set; }
  public DateTime DateTime { get; set; }
  public decimal?
Light { get; set; }
  public decimal?
Temperature { get; set; }
  public decimal?
Motion { get; set; }
}

此類定義單個事件的形狀,但我們想要開始討論許多事件。 為此,我們為 StreamInsight 定義了 Observable 資料來源。 這僅是實現 System.IObservable 介面的資料來源:

public class DeviceDataObservable : IObservable<DeviceData>
  {
    ...
}

在定義 .NET Framework 序列(例如 Enumerable 或類似的 Observable)後,即可開始編寫對這些集合的 StreamInsight 查詢。 讓我們快速瞭解一下其中某些關鍵查詢。 第一個查詢獲取 Observable 作為輸入並生成 StreamInsight 點事件流,以使用設備資料中的“DateTime”欄位作為 StreamInsight 事件的時間戳記。 在下一個 LINQ 語句中,我們獲取此流作為輸入,並按 MAC 位址對資料進行分組。 對於每個組,我們然後應用視窗大小為 10 秒的跳躍視窗(基於時間的一部分事件),並讓視窗每秒重新計算一次。 在每個視窗中,我們計算溫度、光線和運動的平均數。 這為我們提供了每秒重新計算一次的每台設備的移動平均數。 圖 8 顯示了用於返回 StreamInsight 事件流形式的結果的函數實現此過程的代碼。

圖 8 獲取移動平均數

public static CepStream<AverageSensorValues> GroupedAverages(
              Application application,
              DeviceDataObservable source)
  {
    var q1 = from e1 in source.ToPointStream(application,
      e => PointEvent.CreateInsert(
        new DateTimeOffset(
          e.DateTime.ToUniversalTime()),e),
      AdvanceTimeSettings.StrictlyIncreasingStartTime,
      "Device Data Input Stream")
             select e1;
    var q2 = from e2 in q1
             group e2 by e2.MAC into groups
             from w in groups.HoppingWindow(
               TimeSpan.FromSeconds(10),
               TimeSpan.FromSeconds(1))
             select new AverageSensorValues
             {
               DeviceId = groups.Key,
               Timestamp = null,
               AvgTemperature = w.Avg(t => t.Temperature),
               AvgLight = w.Avg(t => t.Light),
               AvgMotion = w.Avg(t => t.Motion)
             };
    return q2;
  }

這是考慮實現警報查詢的最佳位置。 請記住,當有多個運動感測器的讀數同時高於運動閾值時,將觸發警報。 只需對剛計算的分組平均數使用幾個 StreamInsight LINQ 語句便可處理此問題。 通過將警報閾值的更改表示為名為 AlarmThresholdSignal 的事件流,第一個查詢 q3 應用了一個極佳的技巧。 此查詢將閾值與來自前一個查詢的平均數流聯接,然後僅篩選高於閾值的事件:

var q3 = from sensor in GroupedAverages(application, source)
         from refdata in AlarmThresholdSignal(application, alarmsthresholds)
         where (sensor.AvgMotion !=
           null && (double) sensor.AvgMotion > refdata.Threshold)
         select new
         {
           AlarmDevice = sensor.DeviceId,
           AlarmInfo = "This is a test alarm for a single device",
         };

下一個查詢使用 StreamInsight 快照視窗來識別事件狀態更改的時間點。 如果從前一個篩選查詢產生了一個新事件,則這是新快照,並且該快照操作生成一個新視窗,其中包含與觸發快照視窗的事件一致或重疊的所有事件。 下麵的代碼對創建快照視窗時高於警報閾值的事件進行計數:

var alarmcount = from win in q3.SnapshotWindow()
                 select new
                 {
                   AlarmCount = win.Count()
                 };

最後一步檢查計數是否顯示有多台設備將發出警報指示:

var filteralarms = from f in alarmcount
                   where f.AlarmCount >= 2
                   select new AlarmEvent
                   {
                     AlarmTime = null,
                     AlarmInfo = "Now we have an alarm across multiple devices",
                     AlarmKind = 0,
                     AlarmSeverity = 10,
                     AlarmStatus = 1
                   };

現在,我們只需將包含平均感測器值和警報的輸出流從 StreamInsight 傳送到 UI。

使輸出流傳送到 UI

使用在伺服器端生成結果流的 StreamInsight,我們需要一種方法來將這些流傳送給使用者。 使用者可能不在伺服器進程中運行,並可能使用輕型 Web 應用程式來視覺化結果。 如果您使用 Silverlight,則雙工協定很方便,因為它支援從伺服器到用戶端的連續的基於推送的傳送。 HTML5 Web 通訊端也是引人注目的替代方法。 無論如何,您都希望輕鬆地在伺服器端添加新分析並能夠輕鬆地將它們與 UI 連接,而無需拆分 UI 和承載 StreamInsight 的進程之間的用戶端-伺服器介面。 如果 UI 和伺服器之間的負載適中,則您可以將伺服器端的結果序列化為 XML 並在用戶端對其進行反序列化。 這樣,您只需關注線路上和您的用戶端-伺服器介面中的 XML,以及指示要反序列化的類型的附加 Cookie。 下麵是幾段關鍵代碼。

第一個程式碼片段是 Windows Communication Foundation 協定,它用於傳送 XML 序列化字串形式的事件資料以及指示類型的 GUID:

[ServiceContract]
public interface IDuplexClient
{
  [OperationContract(IsOneWay = true)]
  void Receive(string eventData, Guid guid);
}

現在,我們可以使用資料協定為結果事件結構添加批註以使其可序列化,如圖 9 所示。

圖 9 為事件結構添加批註

[DataContract]
public class AverageSensorValues : BaseEvent
{
  [DataMember]
  public new static Guid TypeGuid =
    Guid.Parse("{F67ECF8B-489F-418F-A01A-43B606C623AC}");
  public override Guid GetTypeGuid() { return TypeGuid; }
  [DataMember]
  public string DeviceId { get; set; }
  [DataMember]
  public DateTime?
Timestamp { get; set; }
  [DataMember]
  public decimal?
AvgLight { get; set; }
  [DataMember]
  public decimal?
AvgTemperature { get; set; }
  [DataMember]
  public decimal?
AvgMotion { get; set; }
}

現在,我們可以輕鬆地序列化伺服器端的結果事件並將其傳送到用戶端,如圖 10 所示。

圖 10 從伺服器發送結果事件

static public void CallClient<T>(T eventData) where T : BaseEvent
  {
    if (null != client)
    {
      var xmlSerializer = new XmlSerializer(typeof(T));
      var stringBuilder = new StringBuilder();
      var stringWriter = new StringWriter(stringBuilder);
      xmlSerializer.Serialize(stringWriter, eventData);
      client.Receive(stringBuilder.ToString(), eventData.GetTypeGuid());
    }
  }

在用戶端上,我們反序列化雙工服務的回檔方法中的事件,然後根據接收到的事件的類型將其分支到不同的方法中,如圖 11 所示。

圖 11 在用戶端上接收和反序列化事件

void proxy_ReceiveReceived(object sender, ReceiveReceivedEventArgs e)
{
  if (e.Error == null)
  {
    if (AverageSensorValues.TypeGuid == e.guid)
    {
      ProcessAverageSensorValues(Deserialize<AverageSensorValues>(e.eventData));
    }
    else if (AlarmEvent.TypeGuid == e.guid)
    {
      ProcessAlarms(Deserialize<AlarmEvent>(e.eventData));
    }
    else
    {
      ProcessUnknown();
    }
  }
}

使用這些查詢並傳送到相應的 Web 應用程式,您現在可以選取幾台設備並搖動它們,直到一些設備讀數高於警報閾值。然後,UI 將生成這些紅色警報之一,如圖 12 所示。


圖 12 包含警報的設備儀錶板

因為新資料會不斷進入幾乎即時的儀錶板,所以 ObservableCollections 對更新 UI 極其有用。如果您使資料網格和趨勢線基於這些 Observable 集合,則無需擔心代碼中的更新部分。這些集合將在後臺為您自動執行此操作。

The Outlook

在此實現中,設備與常規 Web 服務通信,該服務可以運行在連接到 Internet 的普通 PC 上。但雲計算是一個吸引人的替代方法;您不一定需要為自己的 Web 伺服器擁有硬體並運行軟體。雲中的服務可以充當為您的應用程式收集所有設備資料的中心。這還使您能夠在設備數量增加或部署針對設備資料的其他分析時,非常輕鬆且靈活地擴展您的處理能力。Microsoft 計畫將 StreamInsight 功能作為 Windows Azure 中的一項服務(StreamInsight 專案代碼名稱“Austin”)提供。通過提供預定義的通信終結點和協定,Austin 將使您能夠輕鬆地將設備連接到 Microsoft 雲中豐富的分析處理功能。如果您將 IoT 應用程式部署到 Windows Azure 中,則將自動獲得靈活擴展和即付即用等雲好處,以便管理設備連接和對設備資料執行豐富的分析。

另一個重大轉變涉及最近進行的 W3C 標準化工作。IoT 應用程式的最重要計畫是 HTML5 和 Web 通訊端。HTML5 為豐富的 Web 應用程式(例如我們實現的儀錶板)提供平臺。而 WebSocket 又簡化了流覽器和 Web 伺服器之間基於 TCP 的全雙工通信,尤其是針對連續處理感測器資料時所要求的結果傳送的推送模型。

連接的設備開創了一個令人興奮的新應用領域,並且 Microsoft 現在提供用於構建這些 IoT 應用程式的工具。我們在這裡介紹了如何在設備級別通過熟悉的介面利用您的 .NET Framework 技能,以及如何通過 Web 服務為 StreamInsight 的強大分析功能提供資料。立即開始使用連接設備構建您的 IoT 應用程式!

Torsten Grabs 是 Microsoft SQL Server 部門的首席專案經理。他具有 10 餘年 Microsoft SQL Server 產品的使用經驗,並獲得瑞士蘇黎世的瑞士聯邦理工學院的電腦科學博士學位。

Colin Miller 在 PC 軟體領域工作了 25 年(其中有 15 年效力于 Microsoft),研究方向涉及資料庫、桌面發佈、消費類產品、Word、Internet Explorer、Passport (LiveID) 及聯機服務。他是 .NET Micro Framework 的產品部經理。

衷心感謝以下技術專家對本文的審閱:Rafael Fernandez MoctezumaLorenzo Tessiore