/// <summary> /// Sends a direct message to another device that has already been discovered. /// </summary> /// <typeparam name="T">The type to cast the response to.</typeparam> /// <param name="device">The device to send the message to.</param> /// <param name="message">The message to send. Make sure to override the objects ToString method.</param> /// <returns></returns> public override async Task <T> SendDirectMessage <T>(DiscoverableDevice device, object message) { try { using (var httpClient = new HttpClient()) { var uri = $"http://{device.IpAddress}:{tcpPort}/discovery/directMessage/{message.ToString()}"; var response = await httpClient.GetAsync(uri); response.EnsureSuccessStatusCode(); string content = await response.Content.ReadAsStringAsync(); return(JsonConvert.DeserializeObject <T>(content)); }; } catch (Exception ex) { Debug.WriteLine(ex); return(default(T)); } }
/// <summary> /// Asynchronously handle receiving a UDP packet /// </summary> /// <param name="socket"></param> /// <param name="eventArguments"></param> async void ReceivedDiscoveryMessage(DatagramSocket socket, DatagramSocketMessageReceivedEventArgs args) { try { // Get the data from the packet var result = args.GetDataStream(); var resultStream = result.AsStreamForRead(); using (var reader = new StreamReader(resultStream)) { // Load the raw data into a response object var potentialRequestString = await reader.ReadToEndAsync(); // Ignore messages from yourself if (args.RemoteAddress.DisplayName != IpAddress) { if (debug) { Debug.WriteLine("Discovery System: Received UDP packet"); Debug.WriteLine($" >>> {potentialRequestString}"); } } else { return; } JObject jRequest = JObject.Parse(potentialRequestString); // If the message was a valid request if (jRequest["command"] != null) { switch (jRequest.Value <string>("command").ToLower()) { case "data": // Get the intended recipients var intendedRecipients = jRequest.Value <string>("recipients").Split(','); // If I am in the list or it is for everyone if (intendedRecipients.Any(r => r == "all" || r == name)) { // Fire off a data event with the data payload whenDataReceived.OnNext(JObject.FromObject(jRequest["data"])); } break; case "discover": // If we initiated this discovery request if (args.RemoteAddress.DisplayName == IpAddress) { // Ignore it return; } // If the requestor included a list of its known devices if (jRequest["knownDevices"] != null) { // Go through each device foreach (var device in jRequest["knownDevices"]) { // If we are already registered with the requestor if (device.Value <string>("name") == name) { // Ignore return; } } } // Begin Broadcasting a discovery response until we get an acceptance or reach the timeout. StartBroadcasting(); break; case "identify": // The device must broadcast a name and its device info if (jRequest["name"] != null && jRequest["deviceInfo"] != null) { // Create a strongly typed model of this new device var newDevice = new DiscoverableDevice(); newDevice.DeviceInfo = jRequest.Value <JObject>("deviceInfo"); newDevice.Name = jRequest.Value <string>("name"); newDevice.IpAddress = args.RemoteAddress.DisplayName; // Add it to the database if (debug) { Debug.WriteLine($"Discovery System: Added {newDevice.Name} @ {newDevice.IpAddress}"); } await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Go through the existing devices foreach (var device in Devices) { if (device.Name == newDevice.Name) { // If the IP address has changed if (device.IpAddress != newDevice.IpAddress) { // Update the smart device in the database device.IpAddress = newDevice.IpAddress; return; } else // If its a perfect match { // Ignore the response return; } } } Devices.Add(newDevice); whenDeviceAdded.OnNext(newDevice); }); } break; case "update": // The device must broadcast a name and its device info if (jRequest["name"] != null && jRequest["deviceInfo"] != null) { // Create a strongly typed model of this new device var newDevice = new DiscoverableDevice(); newDevice.DeviceInfo = jRequest.Value <JObject>("deviceInfo"); newDevice.Name = jRequest.Value <string>("name"); newDevice.IpAddress = args.RemoteAddress.DisplayName; // Go through the existing devices foreach (var device in Devices) { // If we find a match if (device.Name == newDevice.Name) { // Update the device info device.DeviceInfo = newDevice.DeviceInfo; // Update the Ip Address device.IpAddress = newDevice.IpAddress; whenDeviceUpdated.OnNext(device); // Bounce out! return; } } // If no matches were found, add this device if (debug) { Debug.WriteLine($"Discovery System: Added {newDevice.Name} @ {newDevice.IpAddress}"); } await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { Devices.Add(newDevice); whenDeviceAdded.OnNext(newDevice); }); } break; } ; } } } catch (Exception ex) { Debug.WriteLine($"Discovery System: {ex}"); return; } }