/// <summary>
        /// Event Handler for Programmatic events: Stop, Pause, Resume.
        /// Use this event to clean up when a program is stopping, pausing, and resuming.
        /// This event only applies to this SIMPL#Pro program, it doesn't receive events
        /// for other programs stopping
        /// </summary>
        /// <param name="programStatusEventType">The event type.</param>
        private void ControlSystem_ControllerProgramEventHandler(eProgramStatusEventType programStatusEventType)
        {
            switch (programStatusEventType)
            {
            case eProgramStatusEventType.Paused:
                // The program has been paused.  Pause all user threads/timers as needed.
                break;

            case eProgramStatusEventType.Resumed:
                // The program has been resumed. Resume all the user threads/timers as needed.
                break;

            case eProgramStatusEventType.Stopping:
                if (cws != null)
                {
                    cws.Dispose();
                    cws = null;
                }

                break;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ControlSystem"/> class.
        /// </summary>
        public ControlSystem()
            : base()
        {
            try
            {
                Thread.MaxNumberOfUserThreads = 20;

                // Setup the static instance reference for the control system.
                Instance = this;

                // Setup the path the options are saved to and loaded from.
                Options.FilePath = "/USER/pellucid.console-options.toml";

                // Add a console writer to the console.
                // This could be done with the ProConsole class as well, or your own
                // implementation extending the ConsoleBase class.
                // Technically if no writer is registered then the CrestronConsoleWriter
                // gets registered by default, precluding the need for this, but it shows
                // how to hook your own console nodes into the system.
                ConsoleBase.RegisterConsoleWriter(new Evands.Pellucid.Terminal.CrestronConsoleWriter());
                cws = new Crestron.SimplSharp.WebScripting.HttpCwsServer("/pellucid/");
                cws.Register();

                // This is the optional CwsConsoleWriter, usually used for something like VC-4 console access.
                if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server)
                {
                    ConsoleBase.RegisterConsoleWriter(new Evands.Pellucid.Cws.CwsConsoleWriter(cws, string.Format("console/{0}", InitialParametersClass.RoomId), 53000, false));
                }
                else
                {
                    if (CrestronEnvironment.ProgramCompatibility == eCrestronSeries.Series3)
                    {
                        ConsoleBase.RegisterConsoleWriter(new Evands.Pellucid.Cws.CwsConsoleWriter(cws, true, 53000, false));
                    }
                    else
                    {
                        ConsoleBase.RegisterConsoleWriter(new Evands.Pellucid.Cws.CwsConsoleWriter(cws, 53000, false));
                    }
                }

                // Setup the global command(s).
                var appCommand = new GlobalCommand("app", "Application commands.", Access.Programmer);
                var regResult  = appCommand.AddToConsole();
                appCommand.CommandExceptionEncountered += (o, a) => appCommand.LogException(a.Exception, "Exception while executing command '{0}'.", a.CommandContent);

                if (!regResult)
                {
                    Debug.WriteErrorLine(this, "Unable to add global app to the Crestron Console.");
                }

                // Initialize specific global commands.
                ProConsole.InitializeConsole("app");

                var csc = new ControlSystemCommands();
                csc.RegisterCommand("app");

                var exc1 = new ExampleCommands("1");
                exc1.RegisterCommand("app");

                var exc2 = new ExampleCommands("2");
                exc2.RegisterCommand("app");

                var cn1 = new CustomNameCommand("XCommand");
                cn1.RegisterCommand("app");

                var cn2 = new CustomNameCommand("ZedCommand");
                cn2.RegisterCommand("app");

                // Register log nodes.
                Logger.RegisterLogWriter(new CrestronLogWriter());

                // In addition to the CrestronLogWriter we're registering an additional writer that targets another file.
                var path = Path.Combine(Directory.GetApplicationRootDirectory(), "/user");
                path = Path.Combine(path, "logs");
                path = Path.Combine(path, string.Format("App{0}SimpleLog.log", InitialParametersClass.ApplicationNumber));
                Logger.RegisterLogWriter(new Evands.Pellucid.Diagnostics.SimpleFileLogger(path));

                // Subscribe to the controller events (System, Program, and Ethernet)
                CrestronEnvironment.SystemEventHandler        += new SystemEventHandler(ControlSystem_ControllerSystemEventHandler);
                CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(ControlSystem_ControllerProgramEventHandler);
                CrestronEnvironment.EthernetEventHandler      += new EthernetEventHandler(ControlSystem_ControllerEthernetEventHandler);
            }
            catch (Exception e)
            {
                this.LogException(e, "Exception in the constructor.");
            }
        }