SignalR auf dem Arduino Part1: Das Protokoll verstehen

Für mein Smart-Home Projekt sollen einige Arduinos als Temperatursensoren zum Einsatz kommen.
Da als Bus SignalR genutzt wird, es aber für den Arduino noch keine SignalR Bibliothek gibt, muss ich selbst etws basteln.
Das Ergebnis soll hierbei nicht eine vollständige SignalR Implementation für den Arduino sein, sondern nur soweit funktionieren, dass ich mittels Websockets Nachrichten an den Server schicken kann, um so die Temperatur zu übermitteln.

Für den Arduino gibt es bereits HTTP, Websocket und JSON Bibliotheken.
Diese müssen aber zu einer SignalR Bibliothek verbunden werden.
Als erstes muss also das Protokoll verstanden werden.

Unter http://blog.3d-logic.com/2015/03/29/signalr-on-the-wire-an-informal-description-of-the-signalr-protocol/ habe ich eine gute Beschreibung des SignalR Protokolls gefunden.
Diese habe ich als Ausgangsbasis genommen, um in C# ein kleines Programm zu schreiben, um Schritt für Schritt eine Verbindung mit dem SignalR-Server herzustellen.

Als erstes wird ein Testserver benötigt, auf den man sich verbinden kann.
Hierzu habe ich einfach den SignalR Quellcode von Github geladen, welchen man unter https://github.com/SignalR/SignalR findet.
Dort ist bereits ein simples SelfHost Beispiel dabei, welches man ersteinmal benutzen kann.
Der Vorteil, den man hat, wenn man sich direkt den Quellcode lädt ist, dass man besser Debuggen kann, wenn mal etwas nicht klappen sollte.

Wenn der Server nun läuft, kann man sich daran machen, den Client zu entwickeln.
Hierfür kann man entweder in Visual Studio eine simple Console Application schreiben, oder man nutzt LinqPad.
Ohne viele Umschweife hier der Code, der benötigt wird, um sich per WebSocket mit einem SignalR Server zu verbinden (nur für Demozwecke, man kann dort sicher noch einiges an Refactoring betreiben):

using (var client = new HttpClient())
{
    // negotiate
    client.BaseAddress = new Uri("http://localhost:8080/signalr/");
    var negotianResulttString = await client.GetStringAsync("negotiate?clientProtocol=2.2");
    dynamic negotiationnResult = JsonConvert.DeserializeObject(negotianResulttString);
    var connectionToken = negotiationnResult.ConnectionToken;
    var escapedConnectionToken = Uri.EscapeDataString(connectionToken);

    using (var socket = new ClientWebSocket())
    {
        // connect
        var buffer = new ArraySegment<byte>(new byte[1000]);
        await socket.ConnectAsync(new Uri($"ws://localhost:8080/signalr/connect?transport=webSockets&clientProtocol=2.2&connectionToken={escapedConnectionToken}"), CancellationToken.None);
        await socket.ReceiveAsync(buffer, CancellationToken.None);
        var initMessage = Encoding.UTF8.GetString(buffer.Array);

        // start
        var startResponseString = client.GetStringAsync($"start?transport=webSockets&clientProtocol=2.2&connectionToken={escapedConnectionToken}");
    }
}

Als Erstes wird im negotiate-Block mit dem Server ausgehandelt, wie man sich verbinden möchte.
Die wirklich wichtige Information, die wir vom Server bekommen ist der Connection Token.
Diesen müssen wir uns also umbedingt merken, da er für jede weitere Nachricht benötigt wird und wir uns damit gegenüber dem Server authentifizieren.

Da ich weiß, dass sowohl Client als auch Server Websockets unterstützen, wird die Antwort nicht weiter ausgewertet, sondern direkt eine Verbindung per Websocket aufgemacht.
Für eine vollständige Implementation müsste hier ausgewertet werden, was der Server unterstützt und dementsprechend eine Verbindung gestartet werden.
initMessage ist nun die JSON codierte Antwort des Servers.

Diese Antwort wird nun auch ignoriert (da es nur ein Test ist) und es wird dem Server gesagt, dass die Verbindung gestartet werden soll.

Von nun an können über den Websocket an den SignalR Server Nachrichten geschickt werden.

Der nächste Schritt ist nun, die Erkentnisse auf den Ardunio zu übertragen und von dort aus eine Verbindung mit dem SignalR Server herzustellen.

Der letzte Schritt ist dann schlussendlich das Senden von den ausgelesenen Temperaturwerten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.