// *************************************************************************************************
        // The thread callback function.  Sit and wait for work.  release thread on program stopping
        // by placing a null string at the end of the queue (happens in program event handler)
        // *************************************************************************************************

        #region Event Handlers
        void myKeypad_ButtonStateChange(GenericBase device, ButtonEventArgs args)
        {
            var btn = args.Button;
            var uo  = btn.UserObject;

            // CrestronConsole.PrintLine("Event sig: {0}, Type: {1}, State: {2}", btn.Number, btn.GetType(), btn.State);

            #region UserObject Action<> invocation
            // I have a big issue to contend with in these methods - what do you pass as arguments to the methods
            // I want to keep things decoupled but how do you get access to devices created, resgitered in control system
            // class when you in in classes that are outside the scope  e.g. Versiports, IRPorts etc.
            // Need to fix this section so the action is not fired more than once on button press - for now it does.
            // for some reason
            if (uo is System.Action <Button> )            //if this userObject has been defined and is correct type
            {
                (uo as System.Action <Button>)(btn);
            }
            else if (uo is System.Action)
            {
                (uo as System.Action)();
            }

            ButtonInterfaceController myBIC = new ButtonInterfaceController();
            #endregion
        } // Event Handler
        // *************************************************************************************************
        // InititalizeSystem - get in and out quickly - system startup stuff
        // *************************************************************************************************
        public override void InitializeSystem()
        {
            myComPortController.Initialize();

            // This statement defines the userobject for this signal as a delegate to run the class method
            // So, when this particular signal is invoked the delegate function invokes the class method
            // I have demonstrated 3 different ways to assign the action with and without parms as well
            // as lambda notation vs simplified - need to test to see whagt does and does not work
            myKPController = new ButtonInterfaceController(myKeypad);
        }
        // Keypad event handling
        void myKeypad_ButtonStateChange(GenericBase device, ButtonEventArgs args)
        {
            var btn = args.Button;
            var uo = btn.UserObject;

            // CrestronConsole.PrintLine("Event sig: {0}, Type: {1}, State: {2}", btn.Number, btn.GetType(), btn.State);

            #region UserObject Action<> invocation
            // I have a big issue to contend with in these methods - what do you pass as arguments to the methods
            // I want to keep things decoupled but how do you get access to devices created, resgitered in control system
            // class when you in in classes that are outside the scope  e.g. Versiports, IRPorts etc.
            // Need to fix this section so the action is not fired more than once on button press - for now it does.
            // for some reason
            if (uo is System.Action<Button>)            //if this userObject has been defined and is correct type
                (uo as System.Action<Button>)(btn);
            else if (uo is System.Action)
                (uo as System.Action)();

            ButtonInterfaceController myBIC = new ButtonInterfaceController();
            #endregion

            #region "Hardcoded* button invocation
            /*
            // Call direction until UserObject stuff working
            if (btn.State == eButtonState.Pressed)
            {
                this.VersiPorts[args.Button.Number].DigitalOut = true;
                switch (btn.Number)
                {
                    case 1:
                        myIRPort1.Press("UP_ARROW");
                        ComPorts[1].Send("Test transmition, please ignore");
                        break;
                    case 2:
                        myIRPort1.Press("DN_ARROW");
                        ComPorts[1].Send("\n");
                        break;
                    default:
                        CrestronConsole.PrintLine("Key Not Programmed: {0}", args.Button.Number);
                        break;
                }
            }

            if (args.Button.State == eButtonState.Released)
            {
                myIRPort1.Release();
                this.VersiPorts[args.Button.Number].DigitalOut = false;
            }
            */
            #endregion
        } // Event Handler
 public override void InitializeSystem()
 {
     try
     {
         rxHandler = new Thread(Gather, (object)null, Thread.eThreadStartOptions.Running);
     }
     catch (Exception e)
     {
         ErrorLog.Error("Error in InitializeSystem: {0}", e.Message);
     }
     // This statement defines the userobject for this signal as a delegate to run the class method
     // So, when this particular signal is invoked the delegate function invokes the class method
     // I have demonstrated 3 different ways to assign the action with and without parms as well
     // as lambda notation vs simplified - need to test to see whagt does and does not work
     actionBIC = new ButtonInterfaceController();
     myKeypad.Button[1].UserObject = new System.Action<Button>((p) => actionBIC.BPressUp(p));
     myKeypad.Button[2].UserObject = new System.Action<Button>((p) => actionBIC.BPressDn(p));
 }
        static public void DnRelease(string s)
        {
            ButtonInterfaceController bic = new ButtonInterfaceController();

            bic.PressDn_Released(Convert.ToUInt32(s));
        }
        static public void UpPress(string s)
        {
            ButtonInterfaceController bic = new ButtonInterfaceController();

            bic.PressUp_Pressed(Convert.ToUInt32(s));
        }