private void FinderDiscoveryCallback(IAsyncResult ar) { try { UdpClient udpClient = (UdpClient)ar.AsyncState; IPEndPoint alpacaBroadcastResponseEndPoint = new IPEndPoint(IPAddress.Any, Constants.DEFAULT_DISCOVERY_PORT); // Obtain the UDP message body and convert it to a string, with remote IP address attached as well string ReceiveString = Encoding.ASCII.GetString(udpClient.EndReceive(ar, ref alpacaBroadcastResponseEndPoint)); LogMessage($"FinderDiscoveryCallback", $"Received {ReceiveString} from Alpaca device at {alpacaBroadcastResponseEndPoint.Address.ToString()}"); // Configure the UdpClient class to accept more messages, if they arrive udpClient.BeginReceive(FinderDiscoveryCallback, udpClient); //Only process Alpaca device responses if (ReceiveString.ToLowerInvariant().Contains(Constants.DISCOVERY_RESPONSE_STRING)) { // Extract the discovery response parameters from the device's JSON response AlpacaDiscoveryResponse discoveryResponse = JsonConvert.DeserializeObject <AlpacaDiscoveryResponse>(ReceiveString); IPEndPoint alpacaApiEndpoint = new IPEndPoint(alpacaBroadcastResponseEndPoint.Address, discoveryResponse.AlpacaPort); // Create if (!CachedEndpoints.Contains(alpacaApiEndpoint)) { CachedEndpoints.Add(alpacaApiEndpoint); LogMessage("FinderDiscoveryCallback", $"Received new Alpaca API endpoint: {alpacaApiEndpoint.ToString()} from broadcast endpoint: {alpacaBroadcastResponseEndPoint.ToString()}"); callbackFunctionDelegate?.Invoke(alpacaApiEndpoint, discoveryResponse); // Moved inside the loop so that the callback is only called once per IP address } else { LogMessage("FinderDiscoveryCallback", $"Ignoring duplicate Alpaca API endpoint: {alpacaApiEndpoint.ToString()} from broadcast endpoint: {alpacaBroadcastResponseEndPoint.ToString()}"); } } } catch (ObjectDisposedException) { // Ignore these, they can occur after the Finder is disposed } catch (Exception ex) { LogMessage("FinderDiscoveryCallback", $"Exception: " + ex.ToString()); } }
/// <summary> /// Handler for device responses coming from the Finder /// </summary> /// <param name="responderIPEndPoint">Responder's IP address and port</param> /// <param name="alpacaDiscoveryResponse">Class containing the information provided by the device in its response.</param> private void BroadcastResponseEventHandler(IPEndPoint responderIPEndPoint, AlpacaDiscoveryResponse alpacaDiscoveryResponse) { try { LogMessage("BroadcastResponseEventHandler", $"FOUND Alpaca device at {responderIPEndPoint.Address}:{responderIPEndPoint.Port}"); // Log reception of the broadcast response // Add the new device or ignore this duplicate if it already exists lock (deviceListLockObject) // Make sure that the device list dictionary can't change while being read and that only one thread can update it at a time { if (!alpacaDeviceList.ContainsKey(responderIPEndPoint)) { alpacaDeviceList.Add(responderIPEndPoint, new AlpacaDevice(responderIPEndPoint, Constants.TRYING_TO_CONTACT_MANAGEMENT_API_MESSAGE)); RaiseAnAlpacaDevicesChangedEvent(); // Device was added so set the changed flag } } // Create a task to query this device's DNS name, if configured to do so if (tryDnsNameResolution) { LogMessage("BroadcastResponseEventHandler", $"Creating task to retrieve DNS information for device {responderIPEndPoint.ToString()}:{responderIPEndPoint.Port}"); Thread dnsResolutionThread = new Thread(ResolveIpAddressToHostName); dnsResolutionThread.IsBackground = true; dnsResolutionThread.Start(responderIPEndPoint); } // Create a task to query this device's Alpaca management API LogMessage("BroadcastResponseEventHandler", $"Creating thread to retrieve Alpaca management description for device {responderIPEndPoint.ToString()}:{responderIPEndPoint.Port}"); Thread descriptionThread = new Thread(GetAlpacaDeviceInformation); descriptionThread.IsBackground = true; descriptionThread.Start(responderIPEndPoint); } catch (Exception ex) { LogMessage("BroadcastResponseEventHandler", $"AddresssFound Exception: {ex.ToString()}"); } }