Juli 2015

Band 30, Nummer 7

Azurblaue Insider - Veranstaltung Hubs für Analysen und Visualisierung, Teil 3

Von Bruno Terkaly | Juli 2015

Wenn Sie diese Serie verfolgt haben, sehen Sie schließlich die Realisierung das Hauptziel der vorherigen Arbeit in diese letzte Rate — aus Raspberry Pi-Geräte im Feld Daten visualisieren. Dies ist die letzte Rate einer dreiteiligen Serie um ein Internet der Dinge (IoT)-Szenario. Die vorherigen zwei Artikel überprüfen die April-Ausgabe (msdn.microsoft.com/magazine/dn948106) und Juni-Ausgabe (msdn.microsoft.com/magazine/mt147243).

Die abstrakte Ziele dieses Monats sind recht einfach. Ich werde eine Node.js-Anwendung erstellen, die fungiert als Website und stellt Daten auf das mobile Gerät, das dann ein Balkendiagramm des Niederschlagsmenge Daten anzeigt. Ich brauche den Webserver Node.js, denn es ist im Allgemeinen nicht ratsam für ein mobiles Gerät Datenspeichern direkt zugreifen.

Andere Technologien konnte haben diese Funktion, z. B. ASP.NET Web API oder Microsoft Azure API Apps durchgeführt. Die meisten Architekten empfehlen Ihnen zum Filtern, Sortieren und Daten in der mittleren Ebene auf einem Server, nicht auf dem mobilen Gerät selbst analysieren. Das ist da Mobilgeräte haben weniger Rechenleistung und nicht große Mengen an Informationen über das Kabel an das Gerät senden möchten. Kurz gesagt, lassen Sie den Server, die die Schwerarbeit zu tun und lassen Sie das Gerät Bilder anzuzeigen.

Erste Schritte

Um die Beispiele im Artikel dieses Monats auszuführen, müssen Sie die vorherigen zwei vom April und Juni Fragen abgeschlossen haben. Wenn Sie noch nicht, bekommen wahrscheinlich Sie durch mit der manuellen Erstellung von heraus Ihre eigenen DocumentDB-Datenspeicher.

Vorausgesetzt, dass Sie einen DocumentDB-Datenspeicher erstellt haben, starten Sie indem das Azure Portal und die DocumentDB-Datenbank anzeigen. Es gibt einige nette Werkzeuge auf dem Portal, mit das Sie Ihre Daten anzeigen und Ausführen von verschiedenen Queries kann. Sobald Sie validieren die Daten ist da und seine Grundstruktur verstehen, können Sie den Webserver Node.js zu bauen beginnen.

Entwickler, wie generell um Software zu überprüfen, wenn sie es heraus aufbauen. Viele Entwickler beginnen mit Unit-Tests, z. B. mit Tools wie Mokka oder Jasmine. Zum Beispiel vor dem Erstellen der mobilen Clients, ist es sinnvoll, sicherzustellen, dass der Webserver Node.js funktioniert wie erwartet. Ein Ansatz ist eine Web-Proxy-Tool wie Fiddler verwenden. Das erleichtert die ausstellen Webanforderungen (z. B. HTTP-GET) und die Antwort im nativen JSON-Format anzuzeigen. Dies kann nützlich sein, da beim Erstellen der mobilen Clients Sie können sicher sein, dass irgendwelche Probleme mit dem mobilen Client nicht den Webdienst zusammenhängen.

Um Dinge einfach zu halten, verwenden Sie ein Windows Phone Gerät als Client, obwohl iOS und Android-Geräte stärker verbreitet sind. Vielleicht wäre der beste Ansatz eine Web-basierte Technologie. Dies ließ Sie verbrauchen oder die Daten von jedem Gerät, daher nicht beschränken sich auf mobile Geräte zu visualisieren. Ein anderer Ansatz ist native Cross-Plattform-Produkte, wie Xamarin verwenden.

Es gibt mehrere Quellen von Informationen, die Sie verwenden können, zu bauen, eine Web-basierte mobile Client, nicht zuletzt mit der W3C-Normen-Körper ist. Lesen Sie mehr über sie in der Standard-Unterlagen bei bit.ly/1PQ6uOt. Der Apache Software Foundation hat auch eine Menge Arbeit in diesem Bereich getan. Hier erfahren Sie, dass bei cordova.apache.org. Ich konzentrierte mich auf Windows Phone hier weil der Code einfach, einfach, zu Debuggen und einfach zu erklären ist.

DocumentDB auf dem Portal

In diesem nächsten Abschnitt werde ich auf die bisherige Arbeit aufbauen, worin ich einen DocumentDB-Datenspeicher für die Stadt und Temperatur-Daten erstellt. Um Ihre DocumentDB-Datenbank (TemperatureDB) zu finden, einfach klicken Sie auf das Menüelement, durchsuchen, und wählen Sie dann DocumentDB Konten. Sie könnten auch Ihre Datenbank als Kachel auf der Hauptseite mit der rechten Maustaste, anheften, machen das Azure-Hauptportal ein Dashboard-Seite. Finden Sie eine schöne Zusammenfassung der Verwendung von Portal Werkzeuge zur Interaktion mit Ihren DocumentDB-Datenspeicher auf bit.ly/112L4X1.

Eines der wirklich nützliche Features auf dem neuen Portal ist die Möglichkeit zum Abfragen und die tatsächlichen Daten in DocumentDB, so dass Sie die Stadt und Temperatur-Daten im systemeigenen JSON Format finden Sie unter anzeigen. Dies vereinfacht Ihre Fähigkeit, den Webserver Node.js leicht zu verändern und zu bauen, Fragen notwendigen.

Der Webserver Node.js zu bauen

Eines der ersten Dinge, die Sie benötigen, zu tun, wenn das Erstellen von Ihrem Webservers Node.js ist verbinden Sie mit dem DocumentDB-Datenspeicher. Die benötigten Verbindungszeichenfolgen finden Sie im Azure Portal. Um die Verbindungszeichenfolgen aus dem Portal erhalten, aktivieren Sie das TemperatureDB DocumentDB speichern, und klicken Sie dann auf alle Einstellungen, gefolgt von Schlüsseln.

Von dort benötigen Sie zwei Stück von Informationen. Die erste ist der URI in den DocumentDB-Datenspeicher. Die zweite ist die Informationssicherheit Schlüssel (den Primärschlüssel auf dem Portal genannt), können Sie sicheren Zugriff vom Webserver Node.js zu erzwingen. Sie sehen die Verbindung und die Datenbankinformationen in den folgenden Code:

{
  "HOST"       : "https://temperaturedb.documents.azure.com:443/",
  "AUTH_KEY"   : "secret key from the portal",
  "DATABASE"   : "TemperatureDB",
  "COLLECTION" : "CityTempCollection"
}

Node.js-Webserver werden die Konfigurationsinformationen zu lesen. Feld "Host" in der Konfigurationsdatei wird unterschiedlich sein, da alle URIs global eindeutig sind. Der Autorisierungsschlüssel ist auch einzigartig.

In früheren Artikeln hieß die Temperatur-Datenbank TemperatureDB. Jede Datenbank kann mehrere Sammlungen haben, aber in diesem Fall es ist nur eine die CityTemperature-Auflistung aufgerufen. Eine Auflistung ist nichts anderes als eine Liste von Dokumenten. In diesem Datenmodell ist ein einzelnes Dokument eine Stadt mit Temperaturdaten für 12 Monate.

Wie Sie in die Details des Codes für den Webserver Node.js Tauchen, nutzen Sie die umfangreichen Netzes von Add-on Bibliotheksdienste­Ies für Node.js. Für dieses Projekt verwenden Sie zwei Bibliotheken (so genannte Knoten Pakete). Das erste Paket ist für DocumentDB Funktionalität. Der Befehl zum Installieren des DocumentDB-Pakets lautet: NPM Install Documentdb. Das zweite Paket ist für das Lesen der Konfigurationsdatei: NPM Install Nconf. Diese Pakete bieten zusätzliche Funktionen fehlen in der Standardinstallation von Node.js. Eine umfangreichere Tutorial über das Gebäude eine Node.js-Anwendung für DocumentDB finden Sie in der Azure-Dokumentation unter bit.ly/1E7j5Wg.

Gibt es sieben Abschnitte im Webserver Node.js, wie in Abbildung 1. Abschnitt 1 umfasst Verbindungen zu einigen der installierten Pakete, so Sie Zugang zu ihnen später im Code haben dann. Abschnitt 1 definiert auch den Standard-Port mit dem mobile Client verbunden wird. Wenn auf Azure bereitgestellt, die Port-Nummer von Azure verwaltet wird, damit die process.env.port erstellen.

Abbildung 1 die eingebaute heraus Webserver Node.js

// +-----------------------------+
// |        Section 1            |
// +-----------------------------+
var http = require('http');
var port = process.env.port || 1337;
var DocumentDBClient = require('documentdb').DocumentClient;
var nconf = require('nconf');
// +-----------------------------+
// |        Section 2            |
// +-----------------------------+
// Tell nconf which config file to use
nconf.env();
nconf.file({ file: 'config.json' });
// Read the configuration data
var host = nconf.get("HOST");
var authKey = nconf.get("AUTH_KEY");
var databaseId = nconf.get("DATABASE");
var collectionId = nconf.get("COLLECTION");
// +-----------------------------+
// |        Section 3            |
// +-----------------------------+
var client = new DocumentDBClient(host, { masterKey: authKey });
// +-----------------------------+
// |        Section 4            |
// +-----------------------------+
http.createServer(function (req, res) {
  // Before you can query for Items in the document store, you need to ensure you
  // have a database with a collection, then use the collection
  // to read the documents.
  readOrCreateDatabase(function (database) {
    readOrCreateCollection(database, function (collection) {
      // Perform a query to retrieve data and display
      listItems(collection, function (items) {
        var userString = JSON.stringify(items);
        var headers = {
          'Content-Type': 'application/json',
          'Content-Length': userString.length
        };
        res.write(userString);
        res.end();
      });
    });
  });
}).listen(8124,'localhost');  // 8124 seemed to be the
                              // port number that worked
                              // from my development machine.
// +-----------------------------+
// |        Section 5            |
// +-----------------------------+
// If the database does not exist, then create it, or return the database object.
// Use queryDatabases to check if a database with this name already exists. If you
// can't find one, then go ahead and use createDatabase to create a new database
// with the supplied identifier (from the configuration file) on the endpoint
// specified (also from the configuration file).
var readOrCreateDatabase = function (callback) {
  client.queryDatabases('SELECT * FROM root r WHERE r.id="' + databaseId +
    '"').toArray(function (err, results) {
    console.log('readOrCreateDatabase');
    if (err) {
      // Some error occured, rethrow up
      throw (err);
    }
    if (!err && results.length === 0) {
      // No error occured, but there were no results returned,
      // indicating no database exists matching the query.           
      client.createDatabase({ id: databaseId }, function (err, createdDatabase) {
        console.log('client.createDatabase');
        callback(createdDatabase);
      });
    } else {
      // we found a database
      console.log('found a database');
      callback(results[0]);
    }
  });
};
// +-----------------------------+
// |        Section 6            |
// +-----------------------------+
// If the collection does not exist for the database provided, create it,
// or return the collection object. As with readOrCreateDatabase, this method
// first tried to find a collection with the supplied identifier. If one exists,
// it is returned and if one does not exist it is created for you.
var readOrCreateCollection = function (database, callback) {
  client.queryCollections(database._self, 'SELECT * FROM root r WHERE r.id="' +
    collectionId + '"').toArray(function (err, results) {
    console.log('readOrCreateCollection');
    if (err) {
      // Some error occured, rethrow up
      throw (err);
    }
    if (!err && results.length === 0) {
      // No error occured, but there were no results returned, indicating no
      // collection exists in the provided database matching the query.
      client.createCollection(database._self, { id: collectionId },
        function (err, createdCollection) {
        console.log('client.createCollection');
        callback(createdCollection);
      });
    } else {
      // Found a collection
      console.log('found a collection');
      callback(results[0]);
    }
  });
};
// +-----------------------------+
// |        Section 7            |
// +-----------------------------+
// Query the provided collection for all non-complete items.
// Use queryDocuments to look for all documents in the collection that are
// not yet complete, or where completed = false. It uses the DocumentDB query
// grammar, which is based on ANSI - SQL to demonstrate this familiar, yet
// powerful querying capability.
var listItems = function (collection, callback) {
  client.queryDocuments(collection._self, 'SELECT c.City,
    c.Temperatures FROM c where c.id="WACO- TX"').toArray(function (err, docs) {
    console.log('called listItems');
    if (err) {
      throw (err);
    }
    callback(docs);
  });
}

Abschnitt 2 liest aus der config.json-Datei, die die Verbindungsinformationen, die Datenbank und Dokument-Sammlung enthält. Es immer sinnvoll, Zeichenfolgenliterale, die im Zusammenhang mit Verbindungsinformationen zu nehmen und platzieren Sie diese separat in einer Konfigurationsdatei.

Abschnitt 3 ist das Client-Connection-Objekt verwendeten Sie Interaktion mit DocumentDB. Die Verbindung, die für DocumentDBClient an den Konstruktor übergeben wird.

Abschnitt 4 stellt den Code ausgeführt, sobald der mobile Client an die Node.js-Web-Server-Anwendung verbindet. Die CreateServer ist ein Kern primitiven für Node.JS Anwendungen und umfasst eine Reihe von Begriffen rund um die Ereignisschleife und HTTP-Anforderungen verarbeitet. Lesen Sie mehr über dieses Konstrukt (bit.ly/1FcNq1E).

Dies entspricht den hochrangigen Einstiegspunkt für Clients, die eine Verbindung zum Webserver Node.js. Es ist auch verantwortlich für das Aufrufen von anderen Codeteile Node.js, die JSON-Daten aus DocumentDB abruft. Sobald die Daten abgerufen werden, wird es als JSON-basierte Nutzlast zu verpacken und liefern sie an einem mobilen Client. Sie nutzt den Request und Response-Objekte, die Parameter der Funktion CreateServer werden, (http.createServer (Funktion (Req, Res)...).

Abschnitt 5 beginnt die DocumentDB-Abfrage-Verarbeitung. DocumentDB Datenspeicher kann mehrere Datenbanken enthalten. Der Abschnitt 5 soll näher eingrenzen, die Daten an den DocumentDB-URI und zeigen Sie auf eine bestimmte Datenbank. In diesem Fall ist das TemperatureDB. Außerdem sehen Sie zusätzlichen Code, der nicht direkt verwendet, jedoch ist es lediglich für pädagogische Zwecke. Sie werden auch bemerken, dass einige Code zum Erstellen einer Datenbank, wenn eine nicht vorhanden ist. Ein Großteil der Logik in Abschnitt 5 und darüber hinaus basiert auf der DocumentDB-Npm-Paket bereits installiert.

Abschnitt 6 stellt den nächsten Schritt im Prozess Daten abrufen. Hier der Code wird automatisch aufgerufen, durch den Code im Abschnitt 5. Abschnitt 6 weiter verengt die Daten, Bohren bis auf die Dokument-Auflistung mit der Datenbank hergestellt (Temperatur­DB) in Abschnitt 5. Sie werden feststellen, dass die select-Anweisung, die enthält eine Where-Klausel für die CityTemperature-Auflistung. Dazu gehören einige Code zum Erstellen einer Auflistung, wenn eine nicht vorhanden ist.

Abschnitt 7 stellt die letzte Abfrage ausgeführt, bevor die Daten auf dem mobilen Client zurückgegeben werden. Um die Dinge einfach zu halten, ist die Abfrage hartcodiert Temperaturdaten für die Stadt Waco, Texas zurück. In einem realistischen Szenario würde der mobile Client in der Stadt (basierend auf Benutzereingaben oder möglicherweise der Gerätestandort) übergeben. Der Webserver Node.js würde dann analysieren die Stadt übergeben und hängen Sie es an die Where-Klausel in Ziffer 7.

Der Webserver Node.js ist jetzt fertig gestellt und bereit zur Ausführung. Einmal wird es liegt und es läuft, es auf unbestimmte Zeit auf Clientanforderungen vom mobilen Gerät warten. Sie werde den Node.js-Webserver lokal auf dem Entwicklungscomputer ausführen. An dieser Stelle ist es sinnvoll, Fiddler verwenden, um den Webserver Node.js Tests beginnen. Fiddler ermöglicht HTTP-Anforderungen (in diesem Fall GET) an den Webdienst ausstellen und Antwort anzeigen. Überprüfen von Verhalten in Fiddler helfen Ihnen vor dem Gebäude aus dem mobilen Client alle Probleme zu lösen.

Jetzt du bereit bist, aus dem mobilen Client zu bauen, die zwei grundlegende architektonische Komponenten beinhaltet — die XAML-UI und den CS-Code -­Behind (wo die Programmierlogik lebt). Der Code in Abbildung 2 das Markup für die visuelle Schnittstelle auf dem mobilen Client darstellt.

Abbildung 2 das XAML-Markup für Mobile Client Main Screen Balkendiagramm

<Page
  x:Class="CityTempApp.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:CityTempApp"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  xmlns:charting="using:WinRTXamlToolkit.Controls.DataVisualization.Charting"
  Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <Grid>
    <!-- WinRTXamlToolkit chart control -->
    <charting:Chart
      x:Name="BarChart"
      Title=""
      Margin="5,0">
      <charting:BarSeries
        Title="Rain (in)"
        IndependentValueBinding="{Binding Name}"
        DependentValueBinding="{Binding Value}"
        IsSelectionEnabled="True"/>
      </charting:Chart>
  </Grid>
</Page>

Beachten Sie, dass es den WinRTXamlToolkit enthält, die Sie auf CodePlex zu finden bit.ly/1PQdXwO. Dieses Toolkit enthält eine Reihe von interessanten Steuerelemente. Der, den Sie verwenden werden, ist das Chart-Steuerelement. Diagrammdaten, einfach ein Name/Wert-Sammlung aufzubauen und fügen es an das Steuerelement. In diesem Fall erstellen Sie sich eine Auflistung der Name-Wert des Niederschlagsmenge Daten für jeden Monat in einer bestimmten Stadt.

Vor der Vorlage der endgültigen Lösung, gibt es einige Einschränkungen. Man könnte mit einer systemeigenen Windows Phone-Anwendung zu Gunsten eines Web-basierten Ansatzes bestreiten.

Die mobile Client hier gebaut nimmt eine Reihe von Verknüpfungen zu kommen mit den nackten Mindestfunktionalität. Beispielsweise erscheint das Balkendiagramm, sofort nachdem Sie den Windows Phone-Client ausführen. Das ist, da gibt es eine Webanfrage an den Webserver Node.js aus OnNavigatedTo-Ereignis. Dies führt automatisch, sobald der Windows Phone-Client startet. Man kann das sehen in den mobilen Clientcode in Abschnitt 1 Abbildung 3.

Abbildung 3-Code für den mobilen Client

public sealed partial class MainPage : Page
{
  public MainPage()
  {
    this.InitializeComponent();
    this.NavigationCacheMode = NavigationCacheMode.Required;
  }
  // +-----------------------------+
  // |        Section 1            |
  // +-----------------------------+
  protected override void OnNavigatedTo(NavigationEventArgs e)
  {
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
      "http://localhost:8124");
    request.BeginGetResponse(MyCallBack, request);
  }
  // +-----------------------------+
  // |        Section 2            |
  // +-----------------------------+
  async void MyCallBack(IAsyncResult result)
  {
    HttpWebRequest request = result.AsyncState as HttpWebRequest;
    if (request != null)
    {
      try
      {
        WebResponse response = request.EndGetResponse(result);
        Stream stream = response.GetResponseStream();
        StreamReader reader = new StreamReader(stream);
        JsonSerializer serializer = new JsonSerializer();
        // +-----------------------------+
        // |        Section 3            |
        // +-----------------------------+
        // Data structures coming back from Node
        List<CityTemp> cityTemp = (List<CityTemp>)serializer.Deserialize(
          reader, typeof(List<CityTemp>));
        // Data structure suitable for the chart control on the phone
        List<NameValueItem> items = new List<NameValueItem>();
        string[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
        for (int i = 11; i >= 0; i-- )
        {
          items.Add(new NameValueItem { Name = months[i], Value =
            cityTemp[0].Temperatures[i] });
        }
        // +-----------------------------+
        // |        Section 4            |
        // +-----------------------------+
        // Provide bar chart the data
        await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
          this.BarChart.Title = cityTemp[0].City + ", 2014";
          ((BarSeries)this.BarChart.Series[0]).ItemsSource = items;
        });
      }
      catch (WebException e)
      {
        return;
      }
    }
  }
}
// +-----------------------------+
// |        Section 5            |
// +-----------------------------+
// Data structures coming back from Node
public class CityTemp
{
  public string City { get; set;  }
  public List<double> Temperatures { get; set; }
}
// Data structure suitable for the chart control on the phone
public class NameValueItem
{
  public string Name { get; set; }
  public double Value { get; set; }
}

In Abschnitt 1, werden Sie auch feststellen, dass es eine Verbindung zu der Node.js-Web-Server Localhost läuft. Natürlich würden Sie einen anderen Endpunkt angeben, wenn Sie Ihren Node.js-Webserver in der öffentlichen Cloud, z. B. Azure-Websites hosten. Nach der Ausstellung der Webanforderung, richten Sie den Rückruf mit BeginGetResponse. Webanforderungen sind asynchron, so dass der Code einen Rückruf (MyCallBack) einrichtet. Dies führt zu Abschnitt 2, wo die Daten abgerufen, verarbeitet und in ein Chart-Steuerelement geladen.

Rückruf in Abschnitt 2 für die asynchrone Webanforderung gemäß Abschnitt 1 Prozesse die Nutzdaten zurück durch den Webdienst. Der Code verarbeitet die Web-Antwort, die Daten, welche im JSON-Format serialisieren. Abschnitt 3 ist über die Umwandlung der JSON-Daten in zwei separaten Datenstrukturen definiert in Abschnitt 5. Das Ziel ist eine Liste von Name/Wert-Arrays oder Listen zu erstellen. Die NameValueItem-Klasse ist die Struktur, die das Chart-Steuerelement benötigt.

Abschnitt 4 befasst sich mit der GUI-Thread die Name-Wert-Liste das Chart-Steuerelement zuweisen. Sie können die Zuordnung Elements in der Quellauflistung Elemente sehen. Die Await dies. Dispatcher.RunAsync Syntax nutzt den GUI-Thread für das visuelle Steuerelemente aktualisieren. Der Code wird nicht ordnungsgemäß, wenn Sie versuchen, die visuelle Oberfläche mit der gleichen Thread wie die Verarbeitung der Daten und machen die Webanforderung aktualisieren.

Jetzt können Sie die mobile Client ausführen. Sie könnte einige Temperaturdaten, obwohl, so dass alle Bar fehlen, die Steuerelemente nicht angezeigt werden können.

Nachbereitung

Hiermit ist die dreiteilige Serie, wo ich dargelegt, eine Ende-zu-IoT Szenario zeigen — Daten Aufnahme für das Beibehalten der Daten zur Visualisierung der Daten. Ich begann diese Serie durch die Einnahme der Daten mithilfe eines C-Programms unter Ubuntu, als Versuch, den Code zu simulieren, was, den Sie brauchen für die Ausführung unter einem Raspberry Pi-Gerät, ausgeführt wird. Sie können aus einem Temperatursensor in Azure Event Verteiler erfassten Daten einfügen. Allerdings hier gespeicherte Daten ist kurzlebig und es zu einem dauerhaften Speicher verschoben werden müssen.

Das brachte Sie zum zweiten Artikel, in dem ein Hintergrundprozess nimmt die Daten von Ereignis-Hubs und verschiebt ihn in Azure SQL-Datenbank und DocumentDB. Diese letzte Rate ausgesetzt dann diese dauerhaft gespeicherten Daten auf mobilen Geräten mit einer mittleren Ebene Node.js ausgeführt.

Es gibt viele mögliche Erweiterungen und Verbesserungen, die ausgeführt werden können. Beispielsweise ist ein Bereich, den Sie erforschen, könnte der Begriff des maschinellen Lernens und Analytik. Die Balkendiagramms Visualisierung beantwortet die Grundfrage "Was ist passiert?" Eine weitere interessante Frage könnte sein, "Was wird passieren?" Mit anderen Worten, können Sie dann Vorhersagen zukünftigen Niederschläge? Die ultimative Frage könnte sein, "Was sollte ich heute basierend auf zukünftige vorhersagen?"


Bruno Terkaly ist principal Software Engineer bei Microsoft mit dem Ziel der Entwicklung von branchenführenden Anwendungen und Diensten über Geräte aktivieren. Er ist verantwortlich für das fahren die Topcloud und mobilen Möglichkeiten in den Vereinigten Staaten und darüber hinaus von einer Technologie-Aktivierung-Perspektive. Er hilft Partnern, die ihre Anwendungen auf den Markt zu bringen, indem Sie Anleitungen zur Architektur und tiefgehende technische Engagement während der ISV Bewertung, Entwicklung und Bereitstellung. Terkaly arbeitet auch eng mit der Cloud und mobile engineering Gruppen, für das Feedback und die Roadmap zu beeinflussen.

Dank den folgenden technischen Experten von Microsoft für die Überprüfung dieses Artikels: Leland Holmquest, David Magnotti und Nick Trogh
David Magnotti (Microsoft), Leland Holmquest (Microsoft), Nick Trogh (Microsoft)

David Magnotti ist ein Premier Field Engineer bei Microsoft, Software-Entwicklung spezialisiert. Er unterstützt in erster Linie Microsoft Unternehmenskunden durch Gebäude Nachweis von Konzepten, Durchführung von Beratungsdienstleistungen und Bereitstellung von Werkstätten. Er kann oft Debuggen Crash-Dumps und analysieren Windows Leistung Spuren gefunden werden.

Leland Holmquest ist ein Solution Manager für die Wissensmanagement-Plattform für Microsoft Services, langjähriger Fan des MSDN Magazine und Unterstützer des do'ers!

Nick Trogh ist ein Technical Evangelist bei Microsoft, wo er Entwicklern hilft, ihre Software-Träume auf der Microsoft-Plattform zu verwirklichen. Sie finden ihn Bloggen, Zwitschern oder anlässlich von Veranstaltungen für Entwickler.