Microsoft StreamInsight

Erstellen des „Internets der Dinge“

Torsten Grabs, Colin Miller

 

In letzter Zeit herrscht ein großer Hype um das „Internet der Dinge“ (Internet of Things, IoT). Und das aus gutem Grund. Hans Vestberg, CEO bei Ericsson, schätzt, dass im Jahre 2020 50 Milliarden Geräte mit dem Web verbunden sein werden (bit.ly/yciS7r [PDF-Download]). Zur Verdeutlichung: Derzeit gibt es etwa 1,5 Milliarden PCs und annähernd eine Milliarde Telefone, die mit dem Web verbunden sind. Bei 50 Milliarden Geräten sind das sieben pro Person! Das Marktforschungsunternehmen IDC wiederum schätzt, dass es im Jahre 2015 mehr als 16 Milliarden vernetzte Geräte sein werden (siehe Abbildung 1). Zugegebenermaßen gibt es auch konservativere Einschätzungen. Insgesamt weisen jedoch alle auf eine große Veränderung der Rolle des Internets hin. Weg vom reinen Informations- und Unterhaltungsmedium und hin zum Verbindungspunkt für eine neue Generation moderner, gerätefähiger Anwendungen.

Estimating the “Embedded Internet,” from IDC
Abbildung 1: Schätzung „Embedded Internet“, IDC

Diese hohen Zahlen sind plausibel, denn die vorhandenen Möglichkeiten und Notwendigkeiten sorgen für eine starke Zunahme solcher Lösungen. In der letzten Ausgabe von The Economist (economist.com/node/17388368) stand „… von dem Trend profitieren nicht nur Technologiefirmen und ehrgeizige Politiker. Das Ganze hat eine Eigendynamik entwickelt, denn der Bedarf an solchen Systemen ist da.“ Abbildung 2 zeigt die Zunahme dieser Lösungen aufgeteilt nach den jeweiligen Anwendungsbereichen. So wurde beispielsweise der vorgeschriebene Einsatz effizienter Energiesysteme in Europa aus der Notwendigkeit heraus geboren. Das Entwickeln von erforderlichen Technologien zur Energiegewinnung muss Hand in Hand gehen mit einer Regelung des Verbrauchs. Der einfache, weitverbreitete Warenautomat ist ein gutes Beispiel für die Palette der Möglichkeiten. Sobald das Gerät angeschlossen ist, kann das Servicepersonal je nach Bedarf und nicht stur nach Plan eingesetzt werden. Preise können sogar dynamisch geändert werden, wenn der Bedarf vor Ort steigt oder der Inhalt das Verfallsdatum erreicht. Stromausfälle können gemeldet werden, sodass verderbliche Waren schnell ausgetauscht werden können. Mit anderen Worten: Durch die Vernetzung ist ein neues und effizienteres Geschäftsmodell möglich.

Application Growth by Segment
Abbildung 2: Anwendungszunahme pro Segment

Der Verweis auf die Anzahl der vernetzten Geräte untermauert die These der Veränderung drastisch. Er ist aber auch etwas missverständlich, denn es geht hier nicht um die Vollbeschäftigung hunderttausender traditioneller Embedded-Programmierer. Diese Geräte sind nur der Endpunkt für komplexe Lösungen, die andere Geräte in alle Aspekte des Internets integrieren. Dazu zählen Analysen, die Cloud, Webanwendungen, PC- und mobile Schnittstellen und vieles mehr.

Jeder, der derzeit webbasierte Anwendungen erstellt, muss sich mit der Integration von Geräten und der Entwicklung neuer Geschäfte und Geschäftsmodelle auseinandersetzen. Mit anderen Worten: Selbst, wenn Sie kein Embedded-Entwickler sind und nicht in einer Firma arbeiten, die Embedded-Geräte herstellt, ist dies eine Chance, über die es sich nachzudenken lohnt. Mit Ihren Microsoft-Kenntnissen können Sie eine erfolgreiche Rolle im IoT spielen.

Analysieren von Gerätedaten

„Daten sind die neue Währung“, so Kevin Dallas, General Manager des Windows Embedded-Teams, kürzlich in einem Interview (bit.ly/wb1Td8). Im Unterschied zu aktuellen Internetanwendungen geht es beim IoT um die Informationserstellung und -verwaltung sowie den Zugriff auf Informationen. Lassen Sie uns die Daten einer typischen Internetanwendung mit einer IoT-Anwendung vergleichen. Sie und vermutlich Millionen andere zahlen Ihre Rechnungen online über einen weitverbreiteten Mechanismus, der von vielen Kreditinstituten eingesetzt wird. Sie melden sich mehrmals pro Monat an, sehen sich einige Seiten an und übermitteln Ihre Zahlungsinformationen. Das Verfahren beruht auf einer herkömmlichen Datenbank, bei der Abfragen ausgeführt werden, sobald Sie mit dem System interagieren. Mögen die heruntergeladenen Seiten groß sein, die Interaktionen sind es nicht, auch wenn sie wertvolle Informationen wie Zahlungsdaten und Updates persönlicher Informationen enthalten, die auf unbestimmte Zeit aufbewahrt werden müssen.

Sie können dies mit einem Energiemanagementsystem vergleichen, das Daten von 50 Millionen Gebäuden (Geschäfts- und Wohngebäuden) erhält. Die Einspeisung der Daten erfolgt über mehrere lokale Endpunkte, beispielsweise einem Haus, mit einer einzelnen aggregierten Ansicht, die an das Backend übermittelt wird. Die Daten enthalten aktuelle Nutzungsinformationen. Diese bilden die Grundlage für die Preisgestaltung und Abrechnung und möglicherweise auch für obligatorische Kontrollen, die im Gebäude erforderlich sind. Bei diesem System kommt es zu häufigen Interaktionen mit Daten, die nicht mehr unbedingt wichtig sind, wenn Sie den aktuellen Systemstatus und möglicherweise Trenddaten für diesen Endpunkt errechnen. In jedem Fall muss das System sofort auf gefährliche Situationen reagieren können, beispielsweise auf Nachfrageschübe, die eine Überlastung des Netzes oder Stromausfälle verursachen können. Hier kann dann durch die Übertragung der entsprechenden Informationen eine sofortige Senkung des Energieverbrauchs erfolgen. Ein solches System muss die eingehenden Daten permanent analysieren und Trends vergleichen, um Muster zu identifizieren, die auf ein erhöhtes Risiko für einen Stromausfall hinweisen.

Abbildung 3 zeigt die typische Architektur von IoT-Anwendungen. Der untere Bereich enthält verschiedene Anlagen oder Geräte, die je nach Anwendung mit unterschiedlichen Sensoren ausgestattet sind. Die Sensoren erzeugen permanente Datenströme, die von der Anwendung schnell verarbeitet und analysiert werden müssen. Je nach Ausstattung kann das Gerät selbst einen Teil der Verarbeitung lokal durchführen. Dies wird als lokale Analyse bezeichnet. Tools wie .NET Micro Framework unterstützen Sie bei der lokalen Verarbeitung, ehe die Daten vom Gerät weitergegeben werden. IoT-Anwendungen nutzen Internetprotokolle für die Weitergabe der Gerätedaten, sodass eine globale Analyse der Daten durchgeführt werden kann. Die Ergebnisse der globalen Analyse, beispielsweise der Gesamtzustand des Energieversorgungsnetzes, sind für Endnutzer interessant, die Vorgänge durchführen, oder für Personen, die Geschäftsentscheidungen treffen. Über die Analysen können auch geschlossene Systeme gesteuert werden, die automatisch anhand der eingehenden Daten bestimmte Aktionen durchführen. Diese Ansätze kommen insbesondere dort zum Tragen, wo Anlagen Schlüsse aus der globalen Analyse ziehen können, um beispielsweise eine Änderung im Verhalten zu erreichen oder um Vorgänge zu verbessern. Die globalen Analysen, die zu diesen Prozessen führen, müssen permanent erstellt werden, und die Ergebnisse müssen so schnell wie möglich verfügbar sein. Die Analysen basieren häufig auf Zeiten und Zeitstempeln, die mit den Sensordaten bereitgestellt werden. Deshalb ist das reine Speichern solcher Daten in einer Datenbank und das Ausführen periodischer Abfragen nicht die geeignete Vorgehensweise. Glücklicherweise gibt es den Microsoft StreamInsight-Ansatz.

Typical Architecture for Internet of Things Applications
Abbildung 3: Typische Architektur von IoT-Anwendungen

Microsoft StreamInsight

Microsoft StreamInsight wurde entwickelt, um rechtzeitige Reaktionen auf einen permanenten Datenstrom zu liefern, ohne dass die Daten für Analysen und Abfragen auf einem Datenträger gespeichert werden müssen. Viele IoT-Anwendungen müssen eingehende Daten nahezu in Echtzeit verarbeiten, also direkt nach dem diese aus den Datenquellen abgerufen wurden. Denken Sie an die bereits erwähnte intelligente Versorgungsnetzanwendung, die schnell auf einen Anstieg des Energiebedarfs reagieren muss, damit das Netz nicht überlastet wird. Die Anforderungen der meisten IoT-Anwendungen ähneln sich: benötigt wird eine Datenverarbeitung mit kontinuierlicher Analyse und stringenter Latenzzeit. Eine permanente Analyse ist erforderlich, da stetig neue Daten von den Datenquellen generiert werden. Zudem ist oftmals eine schnelle Identifikation von und Reaktion auf Bedingungen vonnöten, die nur aus der Analyse der eingehenden Daten ersichtlich werden. Deshalb werden Analysen mit kurzer Latenzzeit gebraucht, die nahezu sofort Ergebnisse liefern. Aufgrund dieser Anforderungen macht das Speichern solcher Daten in relationalen Datenbanken vor der Durchführung der Analyse relativ wenig Sinn.

Wir bezeichnen solche Anwendungen als ereignisgesteuerte Anwendungen. Das IoT ist nur ein Szenario, in dem solche Funktionen sehr nützlich sind. StreamInsight ist eine leistungsstarke Plattform zum Erstellen hochskalierbarer, ereignisgesteuerter Anwendungen mit kurzen Latenzzeiten. Ab Version 2008 R2 ist StreamInsight Bestandteil von Microsoft SQL Server. StreamInsight ergänzt SQL Server durch eine ereignisgesteuerte Verarbeitung und komplexe, zeitbasierte Analysen. Mit StreamInsight erhalten Sie genauso schnell Einblicke in Geschäftsabläufe wie Daten produziert werden. Also viel schneller als bei herkömmlichen Datenbankberichten.

Analyseergebnisse, die sofort für die menschliche Auswertung zur Verfügung stehen oder die es Anwendungen ermöglichen, automatisch auf Ereignisse zu reagieren, ermöglichen Unternehmen einen zeitgerechteren und relevanteren Einblick in Vorgänge und können diese sogar teilweise automatisieren. Zudem können Sie viel schneller auf kritische Situationen, Möglichkeiten und Trends reagieren, die sich aus den Sensor- oder Gerätedaten ergeben.

Zum Erstellen von StreamInsight-Anwendungen können Entwickler vertraute Tools wie Microsoft .NET Framework, LINQ und Microsoft Visual Studio einsetzen. Abbildung 4 zeigt die Entwickler- und Laufzeiterfahrung einer StreamInsight-Anwendung und stellt einige der wichtigsten Konzepte vor.

StreamInsight Application Development and Runtime
Abbildung 4: StreamInsight, Anwendungsentwicklung und Laufzeit

Eine einfache IoT-Anwendung

Werfen wir zunächst einmal einen genaueren Blick auf eine IoT-Anwendung, die wir anschließend erstellen werden. Wir konzentrieren uns bei diesem End-to-End-Beispiel auf ein einfaches Szenario, bei dem Bewegungssensoren für die Überwachung drehender Elemente, wie sie bei Turbinen oder Windmühlen Anwendung finden, eingesetzt werden. Die Überwachung ist erforderlich, da zu viele Vibrationen auf eine kritische Situation hindeuten können, bei der beispielsweise Rotorblätter durchbrechen und einen erheblichen Schaden verursachen können, wenn die Anlage nicht sofort gestoppt wird. Um eine solche Situation zuverlässig identifizieren zu können, werden die Bewegungen von mehreren Sensoren erfasst. Misst nur ein Sensor eine Bewegungszunahme, weist dies möglicherweise nur auf eine fehlerhafte Datenauswertung des Sensors hin. Wird die Zunahme jedoch gleichzeitig von mehreren Sensoren gemessen, ist dies ein Hinweis auf eine kritische Situation. Bei einer großen Turbine beispielsweise wäre in einem solchen Fall das automatische Auslösen eines Alarms oder das Herunterfahren der Anlage eine Option. Neben dem permanenten Aufspüren solche Situationen möchten wir die Betreiber mit einem Dashboard ausstatten, das den Status der Anlage nahezu in Echtzeit anzeigt.

Für dieses Szenario sind folgende Fragen zu klären:

  • Welche Daten sollen vom Gerät erfasst werden?
  • Welche Sensoren werden für die Messungen eingesetzt?
  • Wie überträgt das Gerät die Sensordaten an das Internet?
  • Wie werden die Daten zentral für die Analysen gesammelt?
  • Wie können die eingehenden Daten permanent analysiert werden, und wie kann schnell auf kritische Situationen reagiert werden?
  • Wie können die Sensordaten verschiedener Geräte rechtzeitig zueinander in Beziehung gesetzt werden, damit globale Bedingungen richtig eingeschätzt werden?

Beschäftigen wir uns nun mit der Beantwortung der Fragen und dem Implementieren des End-to-End-Szenarios.

Die IoT-Anwendung: Das Wichtigste bei der Implementierung

Nachfolgend einige der wichtigsten Schritte bei der Implementierung der im vorherigen Abschnitt vorgestellten IoT-Anwendung. Wir beginnen mit Informationen zum Gerät, wechseln dann zur Visualisierung der Ausgabe und gehen dann über zu den Analysen mit mehreren Geräten, die auf dem Dashboard angezeigt werden.

Zum Erstellen des Sensorgeräts verwendeten wir ein Netduino Plus, eine bekannte kleine Platine mit 128 K SRAM, auf der .NET Micro Framework ausgeführt wird. Dann haben wir ein herkömmliches WiFi-Radio namens WiFly GSX Breakout hinzugefügt und die eigentlichen Sensoren einschließlich eines dreiachsigen Beschleunigungsmessers auf einer Leiterplatte montiert. Wir haben das Gerät so programmiert, dass es jede Sekunde ein Update der Sensordaten an einen Webdienst überträgt. Dieser wird als Hub eingesetzt und sammelt und verarbeitet die Daten aller Geräte.

Für die Anbindung an den Webdienst verwenden wir eine RESTful-Verbindung. Dies ist ein HTTP POST, der durch Komma getrennte Name/Wert-Paare enthält. Sie können dies mit jedem Gerät durchführen, das HTTP unterstützt. Wir haben uns für .NET Micro Framework entschieden, sodass die gesamte Anwendung, einschließlich der Geräte und StreamInsight-Adapter sowie des Webdiensts und des Silverlight-Dashboards, mit einem einzigen Programmiermodell (.NET) und einer einzigen Toolkette (Visual Studio) geschrieben werden konnte. Klarer Fall, wenn Sie über .NET-Kenntnisse verfügen, müssen Sie kein Personal anheuern oder einen Teil des IoT-Projekts nach außen vergeben. Für das Einrichten des Beschleunigungsmessers sind beispielsweise nur wenige Codezeilen nötig, um auf die AnalogInput-Klasse und die Read-Methode zuzugreifen:

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

Nach dem Lesen der Sensoreingaben und dem Formatierten der HTTP-Nachricht müssen die Daten nur noch gesendet werden. Die Voraussetzungen hierfür werden in Abbildung 5 gezeigt.

Abbildung 5: Übermitteln von Sensordaten

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
  {
    ...
  }
}

Auf dem Server implementieren wir die SaveDeviceData-Methode, an die die Geräte ihre Nachrichten ÜBERMITTELN. Wir teilen die Nachrichtenzeichenfolge und parsen die MAC-Adresse, den Zeitstempel und die Nutzlastdaten, beispielsweise die Bewegungsdaten vom Beschleunigungsmesser. Mit diesen Daten füllen wir ein DeviceData-Objekt (siehe Abbildung 6), das wir zur Analyse an StreamInsight übergeben.

Abbildung 6: Füllen des DeviceData-Objekts

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

Das Dashboard: Wir möchten nun ein Dashboard erstellen, mit dem der Geräteführer den aktuellen Sensorstatus anzeigen kann. Zur einfachen Veranschaulichung konzentrieren wir uns auf eine einzelne Ausstattungskomponente. Abbildung 7 zeigt ein Beispiel eines solchen Dashboards. Schauen wir uns einmal die unterschiedlichen Anzeigen der Sensordaten an. Wir beginnen links.

Dashboard for Equipment Monitoring
Abbildung 7: Dashboard zur Ausstattungsüberwachung

Gleitender Durchschnitt – Ansicht: Das Datenraster unten links zeigt die Sensordaten des Geräts. Aufgeführt werden die Werte für Licht, Temperatur und Bewegung sowie die Gerätekennung und der Zeitstempel. Anhand des Zeitstempels können Sie sehen, dass diese Werte sekündlich aktualisiert werden. Anstatt aber die reinen Sensorwerte anzuzeigen, gibt das Dashboard den gleitenden Durchschnitt für je 10 Sekunden an. Das heißt, dass die Werte pro Sekunde einmal mit dem Durchschnittswert der letzen 10 Sekunden aktualisiert werden. Die Verwendung eines gleitenden Durchschnitts ist eine allgemein übliche und einfache Technik, um Ausreißer und falsche Messwerte zu vermeiden, wie sie bei kostengünstigen Sensoren auftreten können.

Trendlinie – Ansicht: Unten rechts zeigt das Dashboard die Trendlinien für die Sensoren. Die Anzeige erfolgt in Abhängigkeit vom gleitenden Durchschnitt, der im Datenraster auf der linken Seite dargestellt wird.

Alarm – Ansicht: Diese Ansicht zeigt oben rechts ein Datenraster für Alarmmeldungen. Wird eine kritische Situation entdeckt, wird ein Alarm ausgelöst, der die Uhrzeit sowie weitere Informationen wie den Schweregrad und den Status wiedergibt.

Analyse: Lassen Sie uns nun einen Blick hinter die Kulissen werfen. Beschäftigen wir uns mit den Analysen, bei denen die eingehenden Sensordaten verarbeitet und die Ergebnisse berechnet werden, die dann auf dem Dashboard angezeigt werden. Für die Analysen verwenden wir StreamInsight. Die folgende Klasse stellt die Gerätedaten einschließlich MAC-Adresse, Zeitstempel und Sensorwerte dar:

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

Diese Klasse definiert die Form eines einzelnen Ereignisses. Lassen Sie uns trotzdem über mehrere Ereignisse nachdenken. Zu diesem Zweck definieren wir eine Observable-Datenquelle für StreamInsight. Dies ist eine einfache Datenquelle, die die System.IObservable-Schnittstelle implementiert:

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

Sobald Sie über eine .NET Framework-Sequenz wie Enumerable oder Observable verfügen, können Sie StreamInsight-Abfragen für diese Sammlungen schreiben. Werfen wir nun einen kurzen Blick auf einige der wichtigsten Abfragen. Bei der ersten wird die Oberservable als Eingabe verwendet und generiert eine Reihe von StreamInsight-Punktereignissen, bei denen das Feld für Datum und Zeit in den Gerätedaten als Zeitstempel für das StreamInsight-Ereignis genutzt wird. Wir übergeben diesen Datenstrom an die nächste LINQ-Anweisung und gruppieren die Daten nach der MAC-Adresse. Anschließend wenden wir auf jede Gruppe ein springendes Fenster (eine zeitbasierte Teilmenge von Ereignissen) an. Die Fenstergröße beträgt 10 Sekunden und die Neuberechnung erfolgt sekündlich. Innerhalb eines jeden Fensters errechnen wir die Durchschnittswerte für Temperatur, Licht und Bewegung. Dadurch erhalten wir einen gleitenden Durchschnitt pro Gerät, der sekündlich neu berechnet wird. Abbildung 8 zeigt den entsprechenden Code, eingeschlossen in eine Funktion, die das Ergebnis als Datenstrom der StreamInsight-Ereignisse zurückgibt.

Abbildung 8: Errechnen der gleitenden Durchschnittswerte

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

Wir sind jetzt an einem Punkt, an dem wir über die Implementierung einer Alarmabfrage nachdenken sollten. Wir erinnern uns, dass der Alarm dann ausgelöst werden soll, wenn mehrere Bewegungswerte gleichzeitig den Schwellenwert überschreiten. Für unseren Zweck eignen sich eine Reihe von StreamInsight-LINQ-Anweisungen für die gerade berechneten, gruppierten Durchschnittswerte. Die erste Abfrage, q3, wendet einen Trick an. Dabei werden die Änderungen der Alarmschwelle als Ereignisstrom mit der Bezeichnung AlarmThresholdSignal dargestellt. Die Abfrage verbindet die Schwellenwerte mit dem Datenstrom der Durchschnittswerte der vorherigen Abfrage und filtert dann die Ereignisse aus, die den Schwellenwert überschreiten.

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",
         };

Die nächste Abfrage identifiziert dann mit dem Momentaufnahmefenster von StreamInsight die Punkte, an denen sich der Ereignisstatus ändert. Ein neues Ereignis, dass sich aus der vorherigen Filterabfrage ergibt, ist eine neue Momentaufnahme. Durch die Momentaufnahme wird ein neues Fenster mit den Ereignissen erzeugt, die mit dem Ereignis zusammenfallen oder sich mit diesem überschneiden, das das Momentaufnahmefenster ausgelöst hat. Der folgende Code zählt die Ereignisse über der Alarmschwelle, wenn das Momentaufnahmefenster erstellt wird:

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

Im letzten Schritt wird geprüft, ob mehrere Geräte einen Alarm anzeigen:

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

Nun müssen wir nur noch die Ausgabedatenströme mit den durchschnittlichen Sensorwerten und Alarmen von StreamInsight auf die Benutzeroberfläche übertragen.

Anzeigen des Datenstroms auf der Benutzeroberfläche

Da StreamInsight die Ergebnisströme auf dem Server generiert, müssen wir einen Weg finden, diese Datenströme den Anwendern zu präsentieren. In der Regel möchten Anwender nicht in Serverprozesse eingreifen und nutzen meist einfache Webanwendungen zur Darstellung der Ergebnisse. Arbeiten Sie mit Silverlight, eignet sich das Duplex-Protokoll, da dieses eine permanente Push-basierte Lieferung vom Server an den Client unterstützt. Alternativ können auch HTML5-WebSockets eingesetzt werden. Ziel ist in jedem Fall ein einfaches Hinzufügen neuer Analysen auf der Serverseite und eine Möglichkeit, diese mit der Benutzeroberfläche zu verknüpfen. Und das ohne ein Auseinanderreißen der Client-Server-Schnittstellen zwischen der Benutzeroberfläche und dem Prozess, der StreamInsight hostet. Ist die Auslastung zwischen Benutzeroberfläche und Server eher gering, können Sie die Ergebnisse auf dem Server in XML serialisieren und auf dem Client wieder deserialisieren. So müssen Sie sich hinsichtlich der Übertragung und der Client-Server-Schnittstellen nur um XML sorgen. Darüber hinaus gibt es einen weiteren Cookie, der anzeigt, welche Arten für die Deserialisierung erwartet werden. Im Folgenden sehen Sie einige wichtige Codeausschnitte.

Der erste Codeausschnitt zeigt den Windows Communication Foundation-Vertrag für das Fließen der Ereignisdaten als XML-serialisierte Zeichenfolge zusammen mit einer GUID zum Anzeigen des Typs:

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

Wir können nun unsere Ergebnisereignisstrukturen mit einem Datenvertrag versehen, damit diese serialisiert werden können, siehe Abbildung 9.

Abbildung 9: Anmerkungen für Ereignisstrukturen

[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; }
}

Wir können nun die Ergebnisereignisse auf der Serverseite serialisieren und an den Client übermitteln, siehe Abbildung 10.

Abbildung 10: Senden der Ergebnisereignisse vom Server

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

Auf der Clientseite deserialisieren wir das Ereignis in der Callback-Methode für den Duplex-Dienst und verzweigen dann je nach erhaltenem Ereignistyp in verschiedene Methoden, siehe Abbildung 11.

Abbildung 11: Empfangen und Deserialisieren des Ereignisses auf dem Client

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

Mit diesen Abfragen und der bestehenden Webanwendungskommunikation können Sie nun verschiedene Geräte nehmen und so lange schütteln, bis einige die Alarmschwelle erreichen. Auf der Benutzeroberfläche werden dann rote Alarmmeldungen angezeigt, siehe Abbildung 12.

Equipment Dashboard with Alarms
Abbildung 12: Ausstattungs-Dashboard mit Alarm

Bei einem Dashboard mit einer Anzeige in nahezu Echtzeit gehen ständig neue Daten ein, deshalb sind ObservableCollections für die Aktualisierung der Benutzeroberfläche sehr nützlich. Basieren Ihre Datenraster und Trendlinien auf diesen Observable-Sammlungen, müssen Sie sich über das Aktualisieren des Codes keine Sorgen machen. Bei diesen Sammlungen geschieht dies automatisch im Hintergrund.

Ausblick

Bei der vorgestellten Implementierung kommunizieren die Geräte mit einem herkömmlichen Webdienst, der auf einem einfachen PC mit Internetanschluss ausgeführt werden kann. Cloud Computing stellt eine attraktive Alternative dar, da Sie die Hardware nicht selbst besitzen und die Software für Ihren eigenen Webserver ausführen müssen. Stattdessen wird ein Dienst in der Cloud als Hub eingesetzt, um alle Gerätedaten für Ihre Anwendung zu sammeln. So können Sie Ihre Verarbeitungsleistung flexibel skalieren, wenn die Anzahl der Geräte zunimmt oder Sie zusätzliche Analysen der Gerätedaten durchführen. Microsoft plant die StreamInsight-Funktionen als Dienst in Windows Azure (StreamInsight-Projekt, Codename „Austin“) bereitzustellen. Durch das Bereitstellen von vordefinierten Kommunikationsendpunkten und -protokollen ermöglicht Ihnen Austin eine einfache Anbindung Ihrer Geräte an komplexe, analytische Verarbeitungsfunktionen in der Microsoft-Cloud. Wenn Sie Ihre IoT-Anwendungen in Windows Azure bereitstellen, erhalten Sie automatisch die Cloud-Vorteile einer flexiblen Skalierung und eines nutzungsbasierten Modells zum Verwalten von Geräteverbindungen und zum Ausführen komplexer Gerätedatenanalysen.

Hinsichtlich des W3C-Standardisierungsbestrebens kündigt sich ebenfalls eine Veränderung an. Die wichtigsten Komponenten für IoT-Anwendungen sind HTML5 und WebSockets. HTML5 stellt die Plattform für komplexe Webanwendungen wie dem von uns implementierten Dashboard zur Verfügung. WebSocket dagegen vereinfacht die Vollduplex-Kommunikation zwischen dem Browser und dem Webserver über TCP. Dies gilt insbesondere für das Push-Modell der Ergebnislieferung, das durch die ständige Verarbeitung von Sensordaten erforderlich ist.

Verbundene Geräte eröffnen eine neue aufregende Welt der Anwendungen. Die Tools zum Erstellen dieser IoT-Anwendungen sind bereits heute über Microsoft erhältlich. In diesem Artikel haben wir Ihnen gezeigt, wie Sie Ihre .NET Framework-Kenntnisse auf Geräteebene über bekannte Schnittstellen einsetzen können und wie Sie Daten über Webdienste an leistungsstarke StreamInsight-Analysefunktionen übergeben. Fangen Sie doch gleich mit dem Erstellen eigener IoT-Anwendungen mithilfe verbundener Geräte an!

Torsten Grabs ist führender Program Manager der Microsoft SQL Server-Abteilung. Er verfügt über eine mehr als zehnjährige Erfahrung in der Arbeit mit Microsoft SQL Server-Produkten. Er ist diplomierter Computerwissenschaftler und hat am Swiss Federal Institute of Technology in Zürich studiert.

Colin Miller arbeitet seit 25 Jahren (davon 15 bei Microsoft) mit PC-Software, darunter Datenbanken, DTP, Konsumgüter, Word, Internet Explorer, Passport (LiveID) und Onlinedienste. Er ist Product Unit Manager für das NET Micro Framework.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Rafael Fernandez Moctezuma und Lorenzo Tessiore