Diese Bibliothek ist für die Verwendung mit jeder UWP-App (Universal Windows Platform) vorgesehen, die mit anderen Apps kommunizieren muss. Ich verwende es häufig in meinen persönlichen Windows IoT-Apps, die auf Raspberry Pis laufen.
Der DiscoveryClient kann mit nur zwei Zeilen zu jeder App hinzugefügt werden:
var discoveryClient = new DiscoveryClient("1234", "4567");
discoveryClient.Initialize("My Unique Name", serializableStateObject);
Die erste Zeile erstellt eine Instanz des Clients mit den gewünschten TCP- und UDP-Ports für den Betrieb. Die zweite Zeile legt den eindeutigen Namen dieses Geräts und einen Zeiger auf ein Objekt fest, das alle Statusinformationen für das Gerät enthält. Es wird empfohlen, ein JObject zu verwenden. Bei der Initiierung sendet das Gerät ein IDENTIFY-Paket und ein DISCOVER-Paket, um alle anderen Geräte im Netzwerk zu finden.
Sobald der Client initialisiert ist, können Sie mit LINQ über ihren Namen auf Geräte zugreifen:
var iotDevice = discoveryClient.Devices.FirstOrDefault(device => device.Name == "iotDeviceName");
Sobald Sie ein Objekt haben, haben Sie Zugriff auf den Namen, die IP-Adresse und die Geräteinfo – ein Objekt, das alle vom Gerät bereitgestellten Informationen enthält.
string iotDeviceIpAddress = iotDevice.IpAddress;
string iotDeviceName = iotDevice.Name;
JObject iotDeviceInfo = iotDevice.DeviceInfo;
Debug.WriteLine($"{iotDevice.Name} at {iotDevice.IpAddress} has a state of {iotDevice.DeviceInfo.GetValue<string>("state")}");
Da sich der Client beim Start identifiziert und versucht, andere Geräte zu erkennen, sollte einfach alles funktionieren :) Da wir aber in der realen Welt leben, möchten Sie möglicherweise regelmäßig eine Erkennungsanfrage senden, um sicherzustellen, dass Sie über alle anderen Geräte informiert sind. Sie können dies mit der Funktion Discover() tun.
var discoveryTimer = new Timer((state) =>
{
discoveryClient.Discover();
}, null, 0, 30000);
Durch den Aufruf von Discover() wird eine UDP-Nachricht mit einer Liste bekannter Geräte gesendet. Jedes Gerät sieht sich die Liste an und antwortet, wenn es nicht vorhanden ist oder sich seine IP-Adresse geändert hat. Das bedeutet auch, dass Gerätenamen eindeutig sein müssen.
Manchmal möchten Sie wissen, wann ein Gerät hinzugefügt oder der Status eines Geräts aktualisiert wird. Der Client nutzt System.Reactive-Observables, die Sie abonnieren können:
WhenDeviceAdded
using System.Reactive.Linq;
using System.Threading;
var whenDeviceAdded = discoveryClient
.WhenDeviceAdded
.ObserveOn(SynchronizationContext.Current)
.Subscribe(device =>
{
Debug.WriteLine("A device was added");
});
WhenDeviceUpdated
using System.Reactive.Linq;
using System.Threading;
var whenDeviceUpdated = discoveryClient
.WhenDeviceUpdated
.ObserveOn(SynchronizationContext.Current)
.Subscribe(device =>
{
Debug.WriteLine("A device was updated");
});
ObserveOn(SynchronizationContext.Current) wird verwendet, um sicherzustellen, dass der Code im UI-Thread ausgeführt wird. Vergessen Sie nicht, die Abonnements zu entsorgen, wenn Sie fertig sind ;)
Sobald ein Gerät erkannt wurde, ist es möglich, Nachrichten direkt an dieses Gerät zu senden. Dies erfolgt über TCP, um sicherzustellen, dass die Nachricht zugestellt wird. Auf jedem Gerät wird eine einfache Rest-API ausgeführt, die auf eingehende Nachrichten wartet. Eine Nachricht kann so einfach wie ein Zeichen sein, es ist jedoch sinnvoller, ein serialisiertes Objekt zu senden.
SendDirectMessage
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var jMessage = new JObject();
jMessage.Add("powerLevel", 100);
var success = await discoveryClient.SendDirectMessage("myDevice", jMessage.ToString());
WhenDirectMessage
using System.Reactive.Linq;
using System.Threading;
var whenDirectMessage = discoveryClient
.WhenDirectMessage
.ObserveOn(SynchronizationContext.Current)
.Subscribe(message => {
var jMessage = JObject.Parse(message);
var powerLevel = message.GetValue<int>("powerLevel");
});