示例#1
0
        public static ISCPMessage Parse(string raw)
        {
            if (raw[0] == '!')
            {
                raw = raw.Substring(2); // skip !1
            }
            raw = raw.TrimEnd((char)0x0a, (char)0x0d, (char)0x1a);

            var m = new ISCPMessage()
            {
                Command = raw.Length >= 3 ? raw.Substring(0, 3) : ""
            };

            if (raw.Length > 3)
            {
                var i = raw.IndexOf("<?xml");
                if (i > 0)
                {
                    m.RawData = raw.Substring(3, i - 3);
                    m.Xml     = XDocument.Parse(raw.Substring(i)).Root;
                }
                else
                {
                    m.RawData = raw.Substring(3);
                }
            }
            return(m);
        }
示例#2
0
 public virtual void ParseFrom(ISCPMessage source)
 {
     // just copy
     Command = source.Command;
     RawData = source.RawData;
     Xml     = source.Xml;
 }
示例#3
0
 protected bool DefaultResponseAcceptFunc(ISCPMessage originalMessage, ISCPMessage receivedMessage)
 {
     if (originalMessage.Command == receivedMessage.Command)
     {
         return(true);
     }
     return(false);
 }
示例#4
0
        public async Task <TResponse> SendCommandAsync <TResponse>(ISCPMessage message, int millisecondsTimeout = 2000, Func <ISCPMessage, ISCPMessage, bool> acceptedResponseFunc = null) where TResponse : ISCPMessage, new()
        {
            var response = await SendCommandAsync(message, millisecondsTimeout, acceptedResponseFunc);

            if (response != null)
            {
                var newReponse = new TResponse();
                newReponse.ParseFrom(response);
                return(newReponse);
            }

            return(null);
        }
示例#5
0
        public static ISCPMessage Parse(byte[] buf)
        {
            if (buf.Take(4).SequenceEqual(Magic))
            {
                // ISCP
                var messageSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 8));
                var msg         = Encoding.ASCII.GetString(buf, 16, messageSize);

                var end = msg.IndexOfAny(new[] { (char)0x0a, (char)0x0d, (char)0x1a });
                msg = msg.Substring(2, end - 2); // remove !1 and EOF

                return(ISCPMessage.Parse(msg));
            }
            return(null);
        }
示例#6
0
        public async Task <ISCPMessage> SendCommandAsync(ISCPMessage message, int millisecondsTimeout = 2000, Func <ISCPMessage, ISCPMessage, bool> acceptedResponseFunc = null)
        {
            var         wait     = new ManualResetEventSlim(false);
            ISCPMessage response = null;

            // handle to check if command matches. this methods seems more efective then observeable events with Rx.
            var messsageHandler = new EventHandler <ISCPMessageEventArgs>((sender, args) =>
            {
                // check if response is accepted. default behavior ist just verifing if command is the same
                if ((acceptedResponseFunc != null && acceptedResponseFunc(message, args.Message)) || DefaultResponseAcceptFunc(message, args.Message))
                {
                    response = args.Message;
                    wait.Set();
                }
            });

            try
            {
                MessageReceived += messsageHandler;
                System.Diagnostics.Trace.WriteLine($"{DateTime.Now:O} Send:{message.ToString()}");

                var bytes = message.GetBytes();
                await _networkStream.WriteAsync(bytes, 0, bytes.Length);

                var timeout = !wait.Wait(millisecondsTimeout);
            }
            catch (Exception exp)
            {
                System.Diagnostics.Trace.WriteLine($"{DateTime.Now:O} Error ({message.ToString()}):{exp.ToString()}");
                throw exp;
            }
            finally
            {
                MessageReceived -= messsageHandler; // detach!
            }

            if (response != null)
            {
                System.Diagnostics.Trace.WriteLine($"{DateTime.Now:O} Response({message.Command}):{response.ToString()}");
            }
            else
            {
                System.Diagnostics.Trace.WriteLine($"{DateTime.Now:O} Response timeout ({message.Command}, {millisecondsTimeout} ms).");
                throw new TimeoutException("Response timeout ({message.Command}, {millisecondsTimeout} ms).");
            }

            return(response);
        }
示例#7
0
        public async Task <ISCPMessage> SendCommandWithRetryAsync(ISCPMessage message, int nbrOfRetries = 3, int millisecondsTimeout = 2000, Func <ISCPMessage, ISCPMessage, bool> acceptedResponseFunc = null)
        {
            int         i        = 0;
            ISCPMessage response = null;

            while (i < nbrOfRetries)
            {
                try
                {
                    response = await SendCommandAsync(message, millisecondsTimeout, acceptedResponseFunc);

                    break;
                }
                catch (TimeoutException)
                {
                    i++;
                }
            }
            return(response);
        }
示例#8
0
        private void MessageReceiveListener(object obj)
        {
            var readBuf = new byte[2048];

            int startIndex = 0;

            while (_listenerCancellationToken.IsCancellationRequested == false)
            {
                try
                {
                    _messageProcessingResetEvent.Set();
                    var readTask = _networkStream.ReadAsync(readBuf, startIndex, readBuf.Length - startIndex, _listenerCancellationToken.Token);
                    int read     = readTask.Result;

                    _messageProcessingResetEvent.Reset();

                    // detect ISCP blocks
                    int endIndex = 0;
                    for (int i = 0; i < read - 4; i++)
                    {
                        try
                        {
                            // message start with ISCP
                            if (readBuf.Skip(i).Take(4).SequenceEqual(ISCPMessage.Magic))
                            {
                                startIndex = i;
                                var messageSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(readBuf, startIndex + 8));
                                endIndex = startIndex + 16 + messageSize;
                                var msgString = Encoding.ASCII.GetString(readBuf, startIndex + 16, messageSize);
                                i = endIndex - 1;

                                var msg = ISCPMessage.Parse(msgString);

                                if (msg != null)
                                {
                                    System.Diagnostics.Trace.WriteLine($"{DateTime.Now:O} Received {msg.ToString()}");
                                    MessageReceived?.Invoke(this, new ISCPMessageEventArgs()
                                    {
                                        Message = msg
                                    });
                                }
                            }
                        }
                        catch (Exception exp)
                        {
                            System.Diagnostics.Trace.Fail("Failed extracting ISCP message", exp.ToString());
                            // just try next byte
                        }
                    }

                    if (endIndex < read)
                    {
                        // still some uncompleted messages in remaining buffer
                        startIndex = read - endIndex;
                        readBuf.Skip(endIndex).Take(startIndex).ToArray().CopyTo(readBuf, 0); // copy to start of buf
                    }
                    else
                    {
                        startIndex = 0;
                    }
                }
                catch (AggregateException exp)
                {
                    if (!(exp.InnerException is OperationCanceledException))
                    {
                        System.Diagnostics.Trace.Fail($"Error reading message.", exp.ToString());
                    }
                }
                catch (Exception exp)
                {
                    System.Diagnostics.Trace.Fail($"Error parsing message.", exp.ToString());
                }
            }
        }
示例#9
0
        /// <summary>
        /// Try to find ISCP devices on network.
        /// </summary>
        public static Task <List <ReceiverInfo> > DiscoverAsync(int millisecondsTimeout = 5000)
        {
            return(Task.Run(() =>
            {
                int onkyoPort = 60128;
                byte[] onkyoMagic = new ISCPMessage("ECNQSTN").GetBytes("!x");
                var foundReceivers = new List <ReceiverInfo>();

                IEnumerable <string> ips = GetInterfaceAddresses();

                // 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));

                    foreach (var i in ips)
                    {
                        try
                        {
                            var ip = IPAddress.Parse(i);
                            socket.SendTo(onkyoMagic, new IPEndPoint(ip, onkyoPort));
                        }
                        catch (SocketException)
                        { }
                    }

                    EndPoint addr = new IPEndPoint(IPAddress.Broadcast, onkyoPort);
                    byte[] data = new byte[1024];
                    int read = 0;
                    while (true)
                    {
                        int microsecondTimeout = (int)(millisecondsTimeout * 1000);
                        if (!socket.Poll(microsecondTimeout, SelectMode.SelectRead))
                        {
                            break;
                        }

                        read = socket.ReceiveFrom(data, ref addr);
                        var msg = ISCPMessage.Parse(data);

                        // Return string looks something like this:
                        // !1ECNTX-NR609/60128/DX
                        GroupCollection info = Regex.Match(msg.ToString(),
                                                           //@"!" +
                                                           //@"(?<device_category>\d)" +
                                                           @"ECN" +
                                                           @"(?<model_name>[^/]*)/" +
                                                           @"(?<iscp_port>\d{5})/" +
                                                           @"(?<area_code>\w{2})/" +
                                                           @"(?<identifier>.*)"
                                                           ).Groups;

                        IPAddress adr = (addr as IPEndPoint).Address;

                        if (!foundReceivers.Any(p => p.IPAddress == adr))
                        {
                            var ri = new ReceiverInfo
                            {
                                Port = Int32.Parse(info["iscp_port"].Value),
                                Model = info["model_name"].Value,
                                IPAddress = adr
                            };
                            foundReceivers.Add(ri);
                        }
                    }
                }
                return foundReceivers;
            }));
        }
示例#10
0
        public async Task <ISCPMessage> SendCommandAsync(string message)
        {
            var m = ISCPMessage.Parse(message);

            return(await SendCommandAsync(m));
        }