Exemplo n.º 1
0
        private object SshCommsProcess(object userSpecific)
        {
            var errorOnConnect = false;

            try
            {
                Thread.Sleep(1000);

                CloudLog.Info("{0} attempting connection to {1}", GetType().Name, _address);

                var firstFail = false;

                while (!_client.IsConnected && _reconnect)
                {
                    try
                    {
                        ConnectionStatus = SshClientStatus.AttemptingConnection;
                        _client.Connect();
                    }
                    catch
                    {
                        ConnectionStatus = SshClientStatus.Disconnected;
                        if (!firstFail)
                        {
                            CloudLog.Warn("{0} could not connect to {1}, will retry every 30 seconds until connected",
                                          GetType().Name, _address);
                            firstFail = true;
                        }

                        if (_threadWait.WaitOne(30000))
                        {
                            CloudLog.Info("{0} - Signal sent to leave thread on attempt to connect", GetType().Name);
                            _reconnect = false;
                            break;
                        }
                    }
                }

                if (!_client.IsConnected && !_reconnect)
                {
                    _client.Dispose();
                    _client          = null;
                    ConnectionStatus = SshClientStatus.Disconnected;
                    return(null);
                }

                CloudLog.Notice("{0} Connected to {1}", GetType().Name, _address);

                _shell = _client.CreateShellStream("terminal", 80, 24, 800, 600, 100000);

                //_shell.DataReceived += (sender, args) => _threadWait.Set();

                var data = string.Empty;

                try
                {
                    while (_programRunning && _client.IsConnected)
                    {
                        while (_shell.CanRead && _shell.DataAvailable)
                        {
                            var bytes  = new byte[100000];
                            var length = _shell.Read(bytes, 0, bytes.Length);
#if DEBUG
                            _stopWatch.Start();
                            Debug.WriteSuccess("Codec rx {0} bytes", length);
#endif
                            var incoming = Encoding.ASCII.GetString(bytes, 0, length);

                            if (!_loggedIn && incoming.Contains("Failed to connect to system software"))
                            {
                                CloudLog.Error("Error received from codec at \"{0}\" on connect:\r\n{1}",
                                               _address, incoming);
                                errorOnConnect = true;
                                break;
                            }
#if DEBUG
                            Debug.WriteNormal(Debug.AnsiBlue + incoming + Debug.AnsiReset);
#endif
                            data = data + incoming;

                            if (!_loggedIn)
                            {
                                foreach (var line in Regex.Split(data, "\r\n|\r|\n"))
                                {
                                    if (line == "*r Login successful")
                                    {
                                        _loggedIn = true;
                                        try
                                        {
                                            Debug.WriteSuccess("Connected!", "{0} logged into {1}", GetType().Name,
                                                               _address);
                                            CloudLog.Info("{0} logged into {1}", GetType().Name, _address);

                                            _sendQueue.Enqueue(@"echo off");

                                            var adapterType = _client.EthernetAdapter;
                                            var adapterId   =
                                                CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(adapterType);
                                            var currentIp = CrestronEthernetHelper.GetEthernetParameter(
                                                CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS,
                                                adapterId);
                                            var assembly     = Assembly.GetExecutingAssembly().GetName();
                                            var softwareInfo = assembly.Name + " " + assembly.Version;
                                            var model        = InitialParametersClass.ControllerPromptName;
                                            _sendQueue.Enqueue(string.Format(
                                                                   "xCommand Peripherals Connect ID: {0} Name: \"Crestron Control System\" HardwareInfo: \"{1}\" NetworkAddress: \"{2}\" SoftwareInfo: \"{3}\" Type: ControlSystem",
                                                                   _heartbeatId, string.Format("Crestron {0}", model), currentIp,
                                                                   softwareInfo));

                                            _sendQueue.Enqueue(@"xFeedback register /Configuration");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/SystemUnit");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Diagnostics");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Audio");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Standby");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Video");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Cameras");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Call");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Conference");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/UserInterface");
                                            _sendQueue.Enqueue(@"xFeedback register /Status/Bookings");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/OutgoingCallIndication");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/IncomingCallIndication");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/CallSuccessful");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/CallDisconnect");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/Bookings");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/CallHistory");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/UserInterface/Extensions");
                                            _sendQueue.Enqueue(@"xFeedback register /Event/UserInterface/Presentation/ExternalSource");

                                            _sendQueue.Enqueue(@"xStatus");

                                            _heartBeatTimer =
                                                new CTimer(
                                                    specific =>
                                                    _sendQueue.Enqueue(
                                                        string.Format("xCommand Peripherals HeartBeat ID: {0}",
                                                                      _heartbeatId)),
                                                    null, 60000, 60000);

                                            ConnectionStatus = SshClientStatus.Connected;
                                        }
                                        catch (Exception e)
                                        {
                                            CloudLog.Exception(e);
                                        }
                                    }
                                }

                                data = string.Empty;
                            }
                            else if (data.Contains("** end"))
                            {
                                var chunks = Regex.Matches(data, @"(\*(\w) [\S\s]*?)(?=\*\* end)");

                                data = string.Empty;

                                if (chunks.Count > 0)
                                {
                                    foreach (Match chunk in chunks)
                                    {
                                        var type = ReceivedDataType.Status;

                                        switch (chunk.Groups[2].Value)
                                        {
                                        case "e":
                                            type = ReceivedDataType.Event;
                                            break;

                                        case "r":
                                            type = ReceivedDataType.Response;
                                            break;

                                        case "c":
                                            type = ReceivedDataType.Configuration;
                                            break;
                                        }
                                        OnReceivedData(this, type, chunk.Groups[1].Value);
                                    }
                                }
                            }
#if DEBUG
                            else
                            {
                                Debug.WriteWarn("Waiting for more data...");
                            }

                            _stopWatch.Stop();
                            Debug.WriteNormal("Time to process: {0} ms", _stopWatch.ElapsedMilliseconds);
                            _stopWatch.Reset();
#endif
                            CrestronEnvironment.AllowOtherAppsToRun();
                        }

                        if (errorOnConnect)
                        {
                            try
                            {
                                _client.Disconnect();
                            }
                            catch (Exception e)
                            {
                                CloudLog.Warn("Error closing connection to codec after error, {0}", e.Message);
                            }

                            break;
                        }

                        if (!_programRunning || !_client.IsConnected)
                        {
                            break;
                        }

                        while (_shell.CanWrite && !_sendQueue.IsEmpty)
                        {
                            var s = _sendQueue.Dequeue();
#if DEBUG
                            Debug.WriteWarn("Codec Tx", s);
#endif
                            _shell.WriteLine(s);
                        }
                    }

                    CloudLog.Debug("{0} left while(connected) loop", Thread.CurrentThread.Name);
                }
                catch (ObjectDisposedException e)
                {
                    CloudLog.Warn("{0} ObjectDisposedException, {1}, {2}", GetType().Name,
                                  string.IsNullOrEmpty(e.ObjectName) ? "unknown" : e.ObjectName, e.Message);
                }
                catch (Exception e)
                {
                    CloudLog.Exception(e, "Error handling comms process");
                }

                _loggedIn = false;

                try
                {
                    if (_heartBeatTimer != null && !_heartBeatTimer.Disposed)
                    {
                        _heartBeatTimer.Stop();
                        _heartBeatTimer.Dispose();
                    }

                    if (_client != null)
                    {
                        CloudLog.Info("Disposing {0}", _client.ToString());
                        _client.Dispose();
                        _client = null;
                    }
                }
                catch (Exception e)
                {
                    CloudLog.Exception(e, "Error trying to dispose items in leaving thread");
                }

                CloudLog.Notice("{0} Disconnected from {1}", GetType().Name, _address);
            }
            catch (Exception e)
            {
                CloudLog.Exception(e, "Error in {0}.SshCommsProcess()", GetType().Name);
            }

            ConnectionStatus = SshClientStatus.Disconnected;

            if (errorOnConnect)
            {
                CloudLog.Warn("Error message while connecting to {0}, Disconnected and will retry in 60 seconds", _address);

                if (_threadWait.WaitOne(60000))
                {
                    CloudLog.Info("{0} - Signal sent to leave thread on attempt to connect", GetType().Name);
                    _reconnect = false;
                }
            }

            if (!_reconnect)
            {
                CloudLog.Notice("Leaving connect thread for codec at {0}", _address);
                return(null);
            }

            CloudLog.Notice("Waiting for 10 seconds before reconnect attempt to {0}", _address);
            if (_threadWait.WaitOne(10000))
            {
                CloudLog.Info("{0} - Signal sent to leave thread on attempt to connect", GetType().Name);
                _reconnect = false;
                return(null);
            }

            CloudLog.Notice("Attempting reconnect to codec at {0}", _address);
            ConnectionStatus = SshClientStatus.AttemptingConnection;

            Connect();

            return(null);
        }