이 라이브러리는 다른 앱과 통신해야 하는 모든 UWP(유니버설 Windows 플랫폼) 앱과 함께 사용하기 위한 것입니다. 저는 Raspberry Pis에서 실행되는 개인용 Windows IoT 앱에서 이를 광범위하게 사용합니다.
DiscoveryClient는 단 두 줄만 사용하여 모든 앱에 추가할 수 있습니다.
var discoveryClient = new DiscoveryClient("1234", "4567");
discoveryClient.Initialize("My Unique Name", serializableStateObject);
첫 번째 줄에서는 작동할 원하는 TCP 및 UDP 포트를 사용하여 클라이언트 인스턴스를 생성합니다. 두 번째 줄은 이 장치의 고유 이름과 장치의 모든 상태 정보를 보유하는 개체에 대한 포인터를 설정합니다. JObject를 사용하는 것이 좋습니다. 시작 시 장치는 IDENTIFY 패킷과 DISCOVER 패킷을 전송하여 네트워크의 다른 모든 장치를 찾습니다.
클라이언트가 초기화되면 LINQ를 사용하여 해당 이름으로 장치에 액세스할 수 있습니다.
var iotDevice = discoveryClient.Devices.FirstOrDefault(device => device.Name == "iotDeviceName");
개체가 있으면 장치가 제공한 모든 정보가 포함된 개체인 Name, IpAdress 및 DeviceInfo에 액세스할 수 있습니다.
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")}");
클라이언트는 시작 시 식별하고 다른 장치 검색을 시도하므로 모든 것이 제대로 작동해야 합니다. 하지만 우리는 현실 세계에 살고 있기 때문에 다른 모든 장치를 인식하고 있는지 확인하기 위해 주기적으로 검색 요청을 보내는 것이 좋습니다. Discover() 함수를 사용하면 됩니다.
var discoveryTimer = new Timer((state) =>
{
discoveryClient.Discover();
}, null, 0, 30000);
Discover()를 호출하면 알려진 장치 목록과 함께 UDP 메시지가 브로드캐스트됩니다. 각 장치는 목록을 보고 존재하지 않거나 IP 주소가 변경된 경우 응답합니다. 이는 또한 장치 이름이 고유해야 함을 의미합니다.
때로는 장치가 추가되거나 장치 상태가 업데이트되는 시기를 알고 싶을 때가 있습니다. 클라이언트는 구독할 수 있는 System.Reactive 관찰 가능 항목을 활용합니다.
장치가 추가된 경우
using System.Reactive.Linq;
using System.Threading;
var whenDeviceAdded = discoveryClient
.WhenDeviceAdded
.ObserveOn(SynchronizationContext.Current)
.Subscribe(device =>
{
Debug.WriteLine("A device was added");
});
장치가 업데이트될 때
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)은 코드가 UI 스레드에서 실행되는지 확인하는 데 사용됩니다. 완료되면 구독을 폐기하는 것을 잊지 마세요. ;)
장치가 검색되면 해당 장치에 직접 메시지를 보낼 수 있습니다. 이는 메시지 전달을 보장하기 위해 TCP를 활용하여 수행됩니다. 각 장치는 수신 메시지를 수신하는 경량 휴식 API를 실행합니다. 메시지는 문자만큼 간단할 수 있지만 직렬화된 개체를 보내는 것이 더 유용합니다.
다이렉트 메시지 보내기
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var jMessage = new JObject();
jMessage.Add("powerLevel", 100);
var success = await discoveryClient.SendDirectMessage("myDevice", jMessage.ToString());
언제 다이렉트 메시지
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");
});