Esta biblioteca está diseñada para usarse con cualquier aplicación de la Plataforma universal de Windows (UWP) que necesite comunicarse con otras aplicaciones. Lo uso mucho en mis aplicaciones personales de Windows IoT que se ejecutan en Raspberry Pis.
DiscoveryClient se puede agregar a cualquier aplicación con solo dos líneas:
var discoveryClient = new DiscoveryClient("1234", "4567");
discoveryClient.Initialize("My Unique Name", serializableStateObject);
La primera línea creará una instancia del cliente con los puertos TCP y UDP deseados para operar. La segunda línea establece el nombre único de este dispositivo y un puntero a un objeto que contiene toda la información de estado del dispositivo. Se recomienda utilizar un JObject. Tras el inicio, el dispositivo enviará un paquete IDENTIFICAR y un paquete DESCUBRIR para encontrar todos los demás dispositivos en la red.
Una vez que se inicializa el cliente, puede acceder a los dispositivos por su nombre usando LINQ:
var iotDevice = discoveryClient.Devices.FirstOrDefault(device => device.Name == "iotDeviceName");
Una vez que tenga un objeto, tendrá acceso al Nombre, Dirección IP y Información del dispositivo, un objeto que contiene cualquier información proporcionada por el dispositivo.
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")}");
Dado que el cliente se identifica al inicio e intenta descubrir otros dispositivos, todo debería funcionar :) pero como vivimos en el mundo real, es posible que desees enviar periódicamente una solicitud de descubrimiento para asegurarte de que conoces todos los demás dispositivos. Puedes hacerlo con la función Discover().
var discoveryTimer = new Timer((state) =>
{
discoveryClient.Discover();
}, null, 0, 30000);
Llamar a Discover() transmite un mensaje UDP con una lista de dispositivos conocidos. Cada dispositivo mirará la lista y responderá si no está presente o si su dirección IP ha cambiado. Esto también significa que los nombres de los dispositivos deben ser únicos.
A veces querrás saber cuándo se agrega un dispositivo o cuándo se actualiza el estado de un dispositivo. El cliente utiliza observables System.Reactive a los que puede suscribirse:
Cuando se agrega el dispositivo
using System.Reactive.Linq;
using System.Threading;
var whenDeviceAdded = discoveryClient
.WhenDeviceAdded
.ObserveOn(SynchronizationContext.Current)
.Subscribe(device =>
{
Debug.WriteLine("A device was added");
});
Cuando se actualiza el dispositivo
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) se utiliza para garantizar que el código se ejecute en el subproceso de la interfaz de usuario. No olvides deshacerte de las suscripciones cuando hayas terminado;)
Una vez que se descubre un dispositivo, es posible enviar mensajes directamente a ese dispositivo. Esto se hace utilizando TCP para garantizar que se entregue el mensaje. Cada dispositivo ejecuta una API de descanso liviana que escucha los mensajes entrantes. Un mensaje puede ser tan simple como un carácter pero es más útil enviar un objeto serializado.
Enviar mensaje directo
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var jMessage = new JObject();
jMessage.Add("powerLevel", 100);
var success = await discoveryClient.SendDirectMessage("myDevice", jMessage.ToString());
Cuando mensaje directo
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");
});