/// <summary> /// Try to find ISCP devices on network. /// </summary> /// Waits for <paramref name="timeout"/> seconds, then returns all devices found, /// in form of a list of <see cref="IReceiver"/>s. public static List <IReceiver> Discover(double timeout, Func <IPAddress, int, string, IReceiver> constructor) { int onkyoPort = 60128; byte[] onkyoMagic = (new EiscpPacket("!xECNQSTN")).Bytes; var foundReceivers = new List <IReceiver>(); // Broadcast magic Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); using (socket) { socket.Blocking = false; // So we can use Poll socket.EnableBroadcast = true; socket.Bind(new IPEndPoint(IPAddress.Any, 0)); socket.SendTo(onkyoMagic, new IPEndPoint(IPAddress.Broadcast, onkyoPort)); EndPoint addr = new IPEndPoint(IPAddress.Broadcast, onkyoPort); byte[] data = new byte[1024]; int read = 0; while (true) { int microsecondTimeout = (int)(timeout * 1000000); if (!socket.Poll(microsecondTimeout, SelectMode.SelectRead)) { break; } read = socket.ReceiveFrom(data, ref addr); string response = Encoding.ASCII.GetString(EiscpPacket.Parse(data)); // Return string looks something like this: // !1ECNTX-NR609/60128/DX GroupCollection info = Regex.Match(response.Trim(), @"!" + @"(?<device_category>\d)" + @"ECN" + @"(?<model_name>[^/]*)/" + @"(?<iscp_port>\d{5})/" + @"(?<area_code>\w{2})/" + @"(?<identifier>.*)" ).Groups; int port = Int32.Parse(info["iscp_port"].Value); string model = info["model_name"].Value; // Give the user a ready-made receiver instance. It will only // connect on demand, when actually used. IReceiver receiver = constructor((addr as IPEndPoint).Address, port, model); foundReceivers.Add(receiver); } } return(foundReceivers); }
/// Return the next message sent by the receiver, or, after /// <paramref name="timeout"/> has passed, return <c>null</c>. public virtual byte[] Get(double timeout = 0.1) { EnsureSocketConnected(); int microsecondTimeout = (int)(timeout * 1000000); if (commandSocket.Poll(microsecondTimeout, SelectMode.SelectRead)) { byte[] headerBytes = new byte[16]; commandSocket.Receive(headerBytes); Header header = EiscpPacket.ParseHeader(headerBytes); byte[] message = new byte[header.messageSize]; commandSocket.Receive(message); return(IscpMessage.Parse(message)); } return(null); }