/// <summary>
 /// Sets the FRCDigitalIOSignal at dioIndex. Should only be used to override robot IO.
 /// </summary>
 /// <param name="robot">FRCRobot object that is connected to the robot.</param>
 /// <param name="dioIndex">The index of the digital out signal to set.</param>
 public void SetDigitalOutSignal(FRCRobot robot, long dioIndex, bool dioValue)
 {
     try
     {
         FRCDigitalIOType   dioType   = (FRCDigitalIOType)robot.IOTypes[FREIOTypeConstants.frDOutType];
         FRCDigitalIOSignal dioSignal = (FRCDigitalIOSignal)dioType.Signals[dioIndex];
         dioSignal.Value = dioValue;
     }
     catch (Exception e) { }
 }
        /// <summary>
        /// Метод изменения значения сигнала
        /// </summary>
        /// <param name="robot">экземпляр подключения к роботу</param>
        /// <param name="ioTypeConstant">константа типа сигнала</param>
        /// <param name="index">индекс сигнала, значение которое нужно изменить</param>
        /// <param name="value">новое значение сигнала</param>
        private async void SetSignalsIO(FRCRobot robot, FREIOTypeConstants ioTypeConstant, long index, bool value)
        {
            try
            {
                if (robot.IsConnected)
                {
                    switch (ioTypeConstant)
                    {
                    case FREIOTypeConstants.frDInType:
                    case FREIOTypeConstants.frDOutType:
                        FRCDigitalIOSignal dioSignal = (FRCDigitalIOSignal)((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[index];
                        dioSignal.Value = value;
                        dioSignal.Update();
                        break;

                    case FREIOTypeConstants.frUOPInType:
                    case FREIOTypeConstants.frUOPOutType:
                        FRCUOPIOSignal uop = (FRCUOPIOSignal)((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[index];
                        uop.Value = value;
                        uop.Update();
                        break;

                    case FREIOTypeConstants.frSOPInType:
                    case FREIOTypeConstants.frSOPOutType:
                        FRCSOPIOSignal sop = (FRCSOPIOSignal)((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[index];
                        sop.Value = value;
                        sop.Update();
                        break;

                    case FREIOTypeConstants.frFlagType:
                        FRCFlagSignal flagSignal = (FRCFlagSignal)((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[index];
                        flagSignal.Value = value;
                        flagSignal.Update();
                        break;

                    case FREIOTypeConstants.frRDInType:
                    case FREIOTypeConstants.frRDOutType:
                        FRCRobotIOSignal rd = (FRCRobotIOSignal)((FRCRobotIOType)robot.IOTypes[ioTypeConstant]).Signals[index];
                        rd.Value = value;
                        rd.Update();
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                Signals.Clear();
                await GetSignalsIO(robot, ioTypeConstant);
            }
        }
        /// <summary>
        /// Gets the FRCIOSignal of FREIOTypeConstants at ioIndex. It is recommended that you typecast the returned FRCIOSignal to the correct IO signal type.
        /// </summary>
        /// <param name="robot">FRCRobot object that is connected to the robot.</param>
        /// <param name="ioTypeConstant">The intended IO type constant from FREIOTypeConstants.</param>
        /// <param name="dioIndex">The index of the digital out signal to get.</param>
        /// <returns></returns>
        public FRCIOSignal GetRobotIOSignal(FRCRobot robot, FREIOTypeConstants ioTypeConstant, long ioIndex)
        {
            try
            {
                if (robot.IsConnected)
                {
                    // Stacked case statements create the logical OR condition.
                    // http://stackoverflow.com/questions/848472/how-add-or-in-switch-statements
                    switch (ioTypeConstant)
                    {
                    case FREIOTypeConstants.frAInType:
                    case FREIOTypeConstants.frAOutType:
                        ((FRCAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frDInType:
                    case FREIOTypeConstants.frDOutType:
                        ((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frFlagType:
                        ((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frGPInType:
                    case FREIOTypeConstants.frGPOutType:
                        ((FRCGroupIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCGroupIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frLAInType:
                    case FREIOTypeConstants.frLAOutType:
                        return(((FRCLaserAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frLDInType:
                    case FREIOTypeConstants.frLDOutType:
                        ((FRCLaserDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCLaserDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frMarkerType:
                        ((FRCMarkerType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCMarkerType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frMaxIOType:
                        return(new FRCIOSignal());    // There is no FRCMaxIOType.

                        break;

                    case FREIOTypeConstants.frPLCInType:
                    case FREIOTypeConstants.frPLCOutType:
                        ((FRCPLCIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCPLCIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frRDInType:
                    case FREIOTypeConstants.frRDOutType:
                        return(new FRCIOSignal());    // There is no FRCRDIOType.

                        break;

                    case FREIOTypeConstants.frSOPInType:
                    case FREIOTypeConstants.frSOPOutType:
                        ((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frTPInType:
                    case FREIOTypeConstants.frTPOutType:
                        ((FRCTPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCTPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frUOPInType:
                    case FREIOTypeConstants.frUOPOutType:
                        ((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frWDInType:
                    case FREIOTypeConstants.frWDOutType:
                        ((FRCWeldDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCWeldDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                        break;

                    case FREIOTypeConstants.frWSTKInType:
                    case FREIOTypeConstants.frWSTKOutType:
                        ((FRCWeldStickIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                        return(((FRCWeldStickIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex]);

                    default:
                        return(new FRCIOSignal());

                        break;
                    }
                }
                return(new FRCIOSignal());
            }
            catch (Exception e)
            {
                return(new FRCIOSignal());
            }
        }
        /// <summary>
        /// Sets the FRCIOSignal of FREIOTypeConstants at ioIndex.
        /// </summary>
        /// <param name="robot">FRCRobot object that is connected to the robot.</param>
        /// <param name="ioTypeConstant">The intended IO type constant from FREIOTypeConstants.</param>
        /// <param name="dioIndex">The index of the digital out signal to get.</param>
        /// <returns></returns>
        public void SetRobotIOSignal(FRCRobot robot, FREIOTypeConstants ioTypeConstant, long ioIndex, FRCIOSignal ioSignal)
        {
            try
            {
                if (robot.IsConnected)
                {
                    // Stacked case statements create the logical OR condition.
                    // http://stackoverflow.com/questions/848472/how-add-or-in-switch-statements
                    switch (ioTypeConstant)
                    {
                    case FREIOTypeConstants.frAInType:
                    case FREIOTypeConstants.frAOutType:
                        FRCAnalogIOSignal aioSignal = (FRCAnalogIOSignal)((FRCAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        aioSignal.Comment = ((FRCAnalogIOSignal)ioSignal).Comment;
                        aioSignal.Value   = ((FRCAnalogIOSignal)ioSignal).Value;
                        aioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frDInType:
                    case FREIOTypeConstants.frDOutType:
                        FRCDigitalIOSignal dioSignal = (FRCDigitalIOSignal)((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        dioSignal.Comment = ((FRCDigitalIOSignal)ioSignal).Comment;
                        dioSignal.Value   = ((FRCDigitalIOSignal)ioSignal).Value;
                        dioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frFlagType:
                        FRCFlagSignal fioSignal = (FRCFlagSignal)((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        fioSignal.Comment = ((FRCFlagSignal)ioSignal).Comment;
                        fioSignal.Value   = ((FRCFlagSignal)ioSignal).Value;
                        fioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frGPInType:
                    case FREIOTypeConstants.frGPOutType:
                        FRCGroupIOSignal gioSignal = (FRCGroupIOSignal)((FRCGroupIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        gioSignal.Comment = ((FRCGroupIOSignal)ioSignal).Comment;
                        gioSignal.Value   = ((FRCGroupIOSignal)ioSignal).Value;
                        gioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frLAInType:
                    case FREIOTypeConstants.frLAOutType:
                        FRCLaserAnalogIOSignal laioSignal = (FRCLaserAnalogIOSignal)((FRCLaserAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        laioSignal.Comment = ((FRCLaserAnalogIOSignal)ioSignal).Comment;
                        laioSignal.Value   = ((FRCLaserAnalogIOSignal)ioSignal).Value;
                        laioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frLDInType:
                    case FREIOTypeConstants.frLDOutType:
                        FRCLaserDigitalIOSignal ldioSignal = (FRCLaserDigitalIOSignal)((FRCLaserDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        ldioSignal.Comment = ((FRCLaserDigitalIOSignal)ioSignal).Comment;
                        ldioSignal.Value   = ((FRCLaserDigitalIOSignal)ioSignal).Value;
                        ldioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frMarkerType:
                        FRCMarkerSignal mrkioSignal = (FRCMarkerSignal)((FRCMarkerType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        mrkioSignal.Comment = ((FRCMarkerSignal)ioSignal).Comment;
                        mrkioSignal.Value   = ((FRCMarkerSignal)ioSignal).Value;
                        mrkioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frMaxIOType:
                        // There is no FRCMaxIOType.
                        return;

                        break;

                    case FREIOTypeConstants.frPLCInType:
                    case FREIOTypeConstants.frPLCOutType:
                        FRCPLCIOSignal plcioSignal = (FRCPLCIOSignal)((FRCPLCIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        plcioSignal.Comment = ((FRCPLCIOSignal)ioSignal).Comment;
                        plcioSignal.Value   = ((FRCPLCIOSignal)ioSignal).Value;
                        plcioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frRDInType:
                    case FREIOTypeConstants.frRDOutType:
                        // There is no FRCRDIOType.
                        return;

                        break;

                    case FREIOTypeConstants.frSOPInType:
                    case FREIOTypeConstants.frSOPOutType:
                        FRCSOPIOSignal sopioSignal = (FRCSOPIOSignal)((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        sopioSignal.Comment = ((FRCSOPIOSignal)ioSignal).Comment;
                        sopioSignal.Value   = ((FRCSOPIOSignal)ioSignal).Value;
                        sopioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frTPInType:
                    case FREIOTypeConstants.frTPOutType:
                        FRCTPIOSignal tpioSignal = (FRCTPIOSignal)((FRCTPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        tpioSignal.Comment = ((FRCTPIOSignal)ioSignal).Comment;
                        tpioSignal.Value   = ((FRCTPIOSignal)ioSignal).Value;
                        tpioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frUOPInType:
                    case FREIOTypeConstants.frUOPOutType:
                        FRCUOPIOSignal uopioSignal = (FRCUOPIOSignal)((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        uopioSignal.Comment = ((FRCUOPIOSignal)ioSignal).Comment;
                        uopioSignal.Value   = ((FRCUOPIOSignal)ioSignal).Value;

                        return;

                        break;

                    case FREIOTypeConstants.frWDInType:
                    case FREIOTypeConstants.frWDOutType:
                        FRCWeldDigitalIOSignal wdioSignal = (FRCWeldDigitalIOSignal)((FRCWeldDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        wdioSignal.Comment = ((FRCWeldDigitalIOSignal)ioSignal).Comment;
                        wdioSignal.Value   = ((FRCWeldDigitalIOSignal)ioSignal).Value;
                        wdioSignal.Update();
                        return;

                        break;

                    case FREIOTypeConstants.frWSTKInType:
                    case FREIOTypeConstants.frWSTKOutType:
                        FRCWeldStickIOSignal wsioSignal = (FRCWeldStickIOSignal)((FRCWeldStickIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                        wsioSignal.Comment = ((FRCWeldStickIOSignal)ioSignal).Comment;
                        wsioSignal.Value   = ((FRCWeldStickIOSignal)ioSignal).Value;
                        wsioSignal.Update();
                        return;

                        break;

                    default:
                        return;

                        break;
                    }
                }
                return;
            }
            catch (Exception e)
            {
                return;
            }
        }
        static void Main(string[] args)
        {
            OptionSet optionSet = new OptionSet()
            {
                { "h=|hostname=",   "The {HOSTNAME} (or IP address) of the robot.", v => sHostname = v },
                { "d|debug",        "Show debug messages.",                         v => bShowDebug = v != null },
                { "?|help",         "Show this help message and exit.",             v => bShowHelp = v != null }
            };

            List<string> lsArgs;
            try
            {
                lsArgs = optionSet.Parse(args);
            }
            catch (OptionException e)
            {
                ui.WriteErrorMessage(e.Message);
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            if (bShowHelp)
            {
                // User has requested the help message.
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            if (sHostname == string.Empty)
            {
                // User did not provide required hostname field.
                ui.WriteErrorMessage("A hostname or IP address must be provided.");
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            // Check to see if sHostname matches an IP Address or Hostname pattern.
            string sRegexIPAddressPattern = @"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
            string sRegexHostnamePattern = @"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$";
            Regex rIPAddress = new Regex(sRegexIPAddressPattern);
            Regex rHostname = new Regex(sRegexHostnamePattern);

            if (!rIPAddress.Match(sHostname).Success && !rHostname.Match(sHostname).Success)
            {
                ui.WriteErrorMessage("The hostname/IP address provided is not valid.");
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            // Unnecessary to check every time, bShowDebug is checked within WriteDebugMessage().
            if (bShowDebug)
            {
                // User has requested debug messages.
                ui.WriteDebugMessage("Debug messages will be shown.");
            }

            ui.ShowTitleMessage();

            ui.WriteDebugMessage("User provided a valid hostname/IP address.");
            try
            {
                ui.WriteDebugMessage("Attempting to create a new FRCRobot object using the FRRobot library.");
                robot = new FRCRobot();

                ui.WriteDebugMessage("Attempting to connect to the robot at the hostname/IP address.");
                robot.Connect(sHostname);
            }
            catch (Exception e)
            {
                ui.WriteErrorMessage(e.Message);
            }

            if (robot.IsConnected)
            {
                ui.WriteDebugMessage("Sucessfully connected to robot at {0}.", sHostname);
            }

            try
            {
                /*
                MBTCP_Core c = new MBTCP_Core();
                c.GetCommChannel();
                modbusTCPScanner = new ModbusTCPScanner();
                modbusTCPScanner.Scan("127.0.0.1", 1000);
                */
            }
            catch (Exception e)
            {
                ui.WriteErrorMessage("Problem creating/connecting to Modbus PLC - {0}", e.Message);
            }

            FRCUOPIOSignal UOPI_IMSTP    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_IMSTP);
            FRCUOPIOSignal UOPI_HOLD     = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_HOLD);
            FRCUOPIOSignal UOPI_SFSPD    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_SFSPD);
            FRCUOPIOSignal UOPI_CSTOP    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_CSTOP);
            FRCUOPIOSignal UOPI_RESET    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_RESET);
            FRCUOPIOSignal UOPI_START    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_START);
            FRCUOPIOSignal UOPI_HOME     = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_HOME);
            FRCUOPIOSignal UOPI_ENABL    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_ENABL);
            List<FRCUOPIOSignal> UOPI_SIGNALS = new List<FRCUOPIOSignal> { UOPI_IMSTP, UOPI_HOLD, UOPI_SFSPD, UOPI_CSTOP, UOPI_RESET, UOPI_START, UOPI_HOME, UOPI_ENABL };

            FRCGroupIOSignal GI_CARR = (FRCGroupIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frGPInType, (long)GINumber.GI_CARR);
            List<FRCGroupIOSignal> GI_SIGNALS = new List<FRCGroupIOSignal> { GI_CARR };

            FRCDigitalIOSignal DI_CARR_DAT_RDY = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_CARR_DAT_RDY);
            //FRCDigitalIOSignal DI_SPARE_1    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_SPARE_1);
            //FRCDigitalIOSignal DI_SPARE_2    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_SPARE_2);
            FRCDigitalIOSignal DI_ON_LINE      = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_ON_LINE);
            FRCDigitalIOSignal DI_LINE_STOP    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_LINE_STOP);
            FRCDigitalIOSignal DI_PE_SIGNAL    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_PE_SIGNAL);
            FRCDigitalIOSignal DI_NXT_MLD_RDY  = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_NXT_MLD_RDY);
            FRCDigitalIOSignal DI_MACRO_RUN    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_MACRO_RUN);
            List<FRCDigitalIOSignal> DI_SIGNALS = new List<FRCDigitalIOSignal> { DI_CARR_DAT_RDY, /* DI_SPARE_1, DI_SPARE_2, */ DI_ON_LINE, DI_LINE_STOP, DI_PE_SIGNAL, DI_NXT_MLD_RDY, DI_MACRO_RUN };

            FRCUOPIOSignal UOPO_CMDEN    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_CMDEN);
            FRCUOPIOSignal UOPO_SYSRD    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_SYSRD);
            FRCUOPIOSignal UOPO_PROGR    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_PROGR);
            FRCUOPIOSignal UOPO_PAUSD    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_PAUSD);
            FRCUOPIOSignal UOPO_HELD     = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_HELD);
            FRCUOPIOSignal UOPO_FAULT    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_FAULT);
            FRCUOPIOSignal UOPO_PERCH    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_PERCH);
            FRCUOPIOSignal UOPO_TPENB    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_TPENB);
            List<FRCUOPIOSignal> UOPO_SIGNALS = new List<FRCUOPIOSignal> { UOPO_CMDEN, UOPO_SYSRD, UOPO_PROGR, UOPO_PAUSD, UOPO_HELD, UOPO_FAULT, UOPO_PERCH, UOPO_TPENB };

            FRCDigitalIOSignal DO_CARR_DAT_ACK      = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_CARR_DAT_ACK);
            FRCDigitalIOSignal DO_NXT_MLD_DAT_RDY   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_NXT_MLD_DAT_RDY);
            FRCDigitalIOSignal DO_PATH_RUNG         = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PATH_RUNG);
            FRCDigitalIOSignal DO_SYS_RUNG          = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_SYS_RUNG);
            FRCDigitalIOSignal DO_FAN_1_REQ         = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_FAN_1_REQ);
            FRCDigitalIOSignal DO_FAN_2_REQ         = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_FAN_2_REQ);
            FRCDigitalIOSignal DO_HI_PUFF_REQ       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_HI_PUFF_REQ);
            FRCDigitalIOSignal DO_LO_PUFF_REQ       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_LO_PUFF_REQ);

            FRCGroupIOSignal GO_PH_CARR = (FRCGroupIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frGPOutType, (long)GONumber.GO_PH_CARR);
            List<FRCGroupIOSignal> GO_SIGNALS = new List<FRCGroupIOSignal> { GO_PH_CARR };

            FRCDigitalIOSignal DO_PH_MOL_BIT0   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PH_MOL_BIT0);
            FRCDigitalIOSignal DO_PH_MOL_BIT1   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PH_MOL_BIT1);
            FRCDigitalIOSignal DO_PH_MOL_BIT2   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PH_MOL_BIT2);
            FRCDigitalIOSignal DO_LINEUP_ERR    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_LINEUP_ERR);
            FRCDigitalIOSignal DO_PROGRAM       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PROGRAM);
            FRCDigitalIOSignal DO_HEAD_OPEN     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_HEAD_OPEN);
            FRCDigitalIOSignal DO_PROG_RUNG     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PROG_RUNG);
            FRCDigitalIOSignal DO_OPEN_PH       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_OPEN_PH);
            List<FRCDigitalIOSignal> DO_SIGNALS = new List<FRCDigitalIOSignal> { DO_CARR_DAT_ACK, DO_NXT_MLD_DAT_RDY, DO_PATH_RUNG, DO_SYS_RUNG, DO_FAN_1_REQ, DO_FAN_2_REQ, DO_HI_PUFF_REQ, DO_LO_PUFF_REQ,
                DO_PH_MOL_BIT0, DO_PH_MOL_BIT1, DO_PH_MOL_BIT2, DO_LINEUP_ERR, DO_PROGRAM, DO_HEAD_OPEN, DO_PROG_RUNG, DO_OPEN_PH};

            foreach (FRCDigitalIOSignal signal in DI_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(DINumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCDigitalIOSignal signal in DO_SIGNALS)
            {
                signal.StartMonitor(1);
                //signal.Change += delegate () { eventType = EventType.Change; eventSender = (FRCIOSignal)signal; eventSenderType = FREIOTypeConstants.frDOutType; bEvent = true; };
                signal.Change += delegate () { utility.RobotIO_Change((FRCIOSignal)signal, FREIOTypeConstants.frDOutType); };
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(DONumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCGroupIOSignal signal in GI_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(GINumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCGroupIOSignal signal in GO_SIGNALS)
            {
                //signal.StartMonitor(1);
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(GONumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCUOPIOSignal signal in UOPI_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(UOPINumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCUOPIOSignal signal in UOPO_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(UOPONumber), signal.LogicalNum), signal.Value.ToString());
                //signal.StartMonitor(1);
            }

            ui.WriteDebugMessage("Robot Time: {0}", robot.SysInfo.Clock.ToLongTimeString());

            ui.WriteDebugMessage("DO[2] = \"{0}\"", ((FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)2)).Value.ToString());
            ui.WriteDebugMessage("GO[1] = \"{0}\"", ((FRCGroupIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frGPOutType, (long)1)).Value.ToString());

            //ioSignal = ioType.
            //ioTypes.Add(ioType);

            while (!bEvent)
            {
                if (bEvent)
                {
                    ui.WriteDebugMessage("****** EVENT TRIGGERED ******");
                    ui.WriteDebugMessage("Event Type:        {0}", Enum.GetName(typeof(EventType), eventType));
                    ui.WriteDebugMessage("Event Sender:      {0}", Enum.GetName(typeof(DONumber), eventSender.LogicalNum));
                    ui.WriteDebugMessage("Event Sender Type: {0}", Enum.GetName(typeof(FREIOTypeConstants), eventSenderType));
                    ui.WriteDebugMessage("*****************************");
                }
            }

            /*
            foreach (FRCDigitalIOSignal signal in DO_SIGNALS)
            {
                ui.WriteDebugMessage(".Equals {0,18}?: {1}", Enum.GetName(typeof(DONumber), signal.LogicalNum), LastChangeEventSender.Equals(signal));
            }
            */

            ui.ShowExitMessage();
        }
        /// <summary>
        /// Gets the FRCIOSignal of FREIOTypeConstants at ioIndex. It is recommended that you typecast the returned FRCIOSignal to the correct IO signal type.
        /// </summary>
        /// <param name="robot">FRCRobot object that is connected to the robot.</param>
        /// <param name="ioTypeConstant">The intended IO type constant from FREIOTypeConstants.</param>
        /// <param name="dioIndex">The index of the digital out signal to get.</param>
        /// <returns></returns>
        public FRCIOSignal GetRobotIOSignal(FRCRobot robot, FREIOTypeConstants ioTypeConstant, long ioIndex)
        {
            try
            {
                if (robot.IsConnected)
                {
                    // Stacked case statements create the logical OR condition.
                    // http://stackoverflow.com/questions/848472/how-add-or-in-switch-statements
                    switch (ioTypeConstant)
                    {
                        case FREIOTypeConstants.frAInType:
                        case FREIOTypeConstants.frAOutType:
                            ((FRCAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frDInType:
                        case FREIOTypeConstants.frDOutType:
                            ((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frFlagType:
                            ((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frGPInType:
                        case FREIOTypeConstants.frGPOutType:
                            ((FRCGroupIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCGroupIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frLAInType:
                        case FREIOTypeConstants.frLAOutType:
                            return ((FRCLaserAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frLDInType:
                        case FREIOTypeConstants.frLDOutType:
                            ((FRCLaserDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCLaserDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frMarkerType:
                            ((FRCMarkerType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCMarkerType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frMaxIOType:
                            return new FRCIOSignal(); // There is no FRCMaxIOType.
                            break;

                        case FREIOTypeConstants.frPLCInType:
                        case FREIOTypeConstants.frPLCOutType:
                            ((FRCPLCIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCPLCIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frRDInType:
                        case FREIOTypeConstants.frRDOutType:
                            return new FRCIOSignal(); // There is no FRCRDIOType.
                            break;

                        case FREIOTypeConstants.frSOPInType:
                        case FREIOTypeConstants.frSOPOutType:
                            ((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frTPInType:
                        case FREIOTypeConstants.frTPOutType:
                            ((FRCTPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCTPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frUOPInType:
                        case FREIOTypeConstants.frUOPOutType:
                            ((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frWDInType:
                        case FREIOTypeConstants.frWDOutType:
                            ((FRCWeldDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCWeldDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            break;

                        case FREIOTypeConstants.frWSTKInType:
                        case FREIOTypeConstants.frWSTKOutType:
                            ((FRCWeldStickIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex].Refresh();
                            return ((FRCWeldStickIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];

                        default:
                            return new FRCIOSignal();
                            break;
                    }
                }
                return new FRCIOSignal();
            }
            catch (Exception e)
            {
                return new FRCIOSignal();
            }
        }
        /// <summary>
        /// Sets the FRCIOSignal of FREIOTypeConstants at ioIndex.
        /// </summary>
        /// <param name="robot">FRCRobot object that is connected to the robot.</param>
        /// <param name="ioTypeConstant">The intended IO type constant from FREIOTypeConstants.</param>
        /// <param name="dioIndex">The index of the digital out signal to get.</param>
        /// <returns></returns>
        public void SetRobotIOSignal(FRCRobot robot, FREIOTypeConstants ioTypeConstant, long ioIndex, FRCIOSignal ioSignal)
        {
            try
            {
                if (robot.IsConnected)
                {
                    // Stacked case statements create the logical OR condition.
                    // http://stackoverflow.com/questions/848472/how-add-or-in-switch-statements
                    switch (ioTypeConstant)
                    {
                        case FREIOTypeConstants.frAInType:
                        case FREIOTypeConstants.frAOutType:
                            FRCAnalogIOSignal aioSignal = (FRCAnalogIOSignal)((FRCAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            aioSignal.Comment = ((FRCAnalogIOSignal)ioSignal).Comment;
                            aioSignal.Value = ((FRCAnalogIOSignal)ioSignal).Value;
                            aioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frDInType:
                        case FREIOTypeConstants.frDOutType:
                            FRCDigitalIOSignal dioSignal = (FRCDigitalIOSignal)((FRCDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            dioSignal.Comment = ((FRCDigitalIOSignal)ioSignal).Comment;
                            dioSignal.Value = ((FRCDigitalIOSignal)ioSignal).Value;
                            dioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frFlagType:
                            FRCFlagSignal fioSignal = (FRCFlagSignal)((FRCFlagType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            fioSignal.Comment = ((FRCFlagSignal)ioSignal).Comment;
                            fioSignal.Value = ((FRCFlagSignal)ioSignal).Value;
                            fioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frGPInType:
                        case FREIOTypeConstants.frGPOutType:
                            FRCGroupIOSignal gioSignal = (FRCGroupIOSignal)((FRCGroupIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            gioSignal.Comment = ((FRCGroupIOSignal)ioSignal).Comment;
                            gioSignal.Value = ((FRCGroupIOSignal)ioSignal).Value;
                            gioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frLAInType:
                        case FREIOTypeConstants.frLAOutType:
                            FRCLaserAnalogIOSignal laioSignal = (FRCLaserAnalogIOSignal)((FRCLaserAnalogIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            laioSignal.Comment = ((FRCLaserAnalogIOSignal)ioSignal).Comment;
                            laioSignal.Value = ((FRCLaserAnalogIOSignal)ioSignal).Value;
                            laioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frLDInType:
                        case FREIOTypeConstants.frLDOutType:
                            FRCLaserDigitalIOSignal ldioSignal = (FRCLaserDigitalIOSignal)((FRCLaserDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            ldioSignal.Comment = ((FRCLaserDigitalIOSignal)ioSignal).Comment;
                            ldioSignal.Value = ((FRCLaserDigitalIOSignal)ioSignal).Value;
                            ldioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frMarkerType:
                            FRCMarkerSignal mrkioSignal = (FRCMarkerSignal)((FRCMarkerType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            mrkioSignal.Comment = ((FRCMarkerSignal)ioSignal).Comment;
                            mrkioSignal.Value = ((FRCMarkerSignal)ioSignal).Value;
                            mrkioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frMaxIOType:
                            // There is no FRCMaxIOType.
                            return;
                            break;

                        case FREIOTypeConstants.frPLCInType:
                        case FREIOTypeConstants.frPLCOutType:
                            FRCPLCIOSignal plcioSignal = (FRCPLCIOSignal)((FRCPLCIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            plcioSignal.Comment = ((FRCPLCIOSignal)ioSignal).Comment;
                            plcioSignal.Value = ((FRCPLCIOSignal)ioSignal).Value;
                            plcioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frRDInType:
                        case FREIOTypeConstants.frRDOutType:
                            // There is no FRCRDIOType.
                            return;
                            break;

                        case FREIOTypeConstants.frSOPInType:
                        case FREIOTypeConstants.frSOPOutType:
                            FRCSOPIOSignal sopioSignal = (FRCSOPIOSignal)((FRCSOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            sopioSignal.Comment = ((FRCSOPIOSignal)ioSignal).Comment;
                            sopioSignal.Value = ((FRCSOPIOSignal)ioSignal).Value;
                            sopioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frTPInType:
                        case FREIOTypeConstants.frTPOutType:
                            FRCTPIOSignal tpioSignal = (FRCTPIOSignal)((FRCTPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            tpioSignal.Comment = ((FRCTPIOSignal)ioSignal).Comment;
                            tpioSignal.Value = ((FRCTPIOSignal)ioSignal).Value;
                            tpioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frUOPInType:
                        case FREIOTypeConstants.frUOPOutType:
                            FRCUOPIOSignal uopioSignal = (FRCUOPIOSignal)((FRCUOPIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            uopioSignal.Comment = ((FRCUOPIOSignal)ioSignal).Comment;
                            uopioSignal.Value = ((FRCUOPIOSignal)ioSignal).Value;

                            return;
                            break;

                        case FREIOTypeConstants.frWDInType:
                        case FREIOTypeConstants.frWDOutType:
                            FRCWeldDigitalIOSignal wdioSignal = (FRCWeldDigitalIOSignal)((FRCWeldDigitalIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            wdioSignal.Comment = ((FRCWeldDigitalIOSignal)ioSignal).Comment;
                            wdioSignal.Value = ((FRCWeldDigitalIOSignal)ioSignal).Value;
                            wdioSignal.Update();
                            return;
                            break;

                        case FREIOTypeConstants.frWSTKInType:
                        case FREIOTypeConstants.frWSTKOutType:
                            FRCWeldStickIOSignal wsioSignal = (FRCWeldStickIOSignal)((FRCWeldStickIOType)robot.IOTypes[ioTypeConstant]).Signals[ioIndex];
                            wsioSignal.Comment = ((FRCWeldStickIOSignal)ioSignal).Comment;
                            wsioSignal.Value = ((FRCWeldStickIOSignal)ioSignal).Value;
                            wsioSignal.Update();
                            return;
                            break;

                        default:
                            return;
                            break;
                    }
                }
                return;
            }
            catch (Exception e)
            {
                return;
            }
        }
 /// <summary>
 /// Sets the FRCDigitalIOSignal at dioIndex. Should only be used to override robot IO.
 /// </summary>
 /// <param name="robot">FRCRobot object that is connected to the robot.</param>
 /// <param name="dioIndex">The index of the digital out signal to set.</param>
 public void SetDigitalOutSignal(FRCRobot robot, long dioIndex, bool dioValue)
 {
     try
     {
         FRCDigitalIOType dioType = (FRCDigitalIOType)robot.IOTypes[FREIOTypeConstants.frDOutType];
         FRCDigitalIOSignal dioSignal = (FRCDigitalIOSignal)dioType.Signals[dioIndex];
         dioSignal.Value = dioValue;
     }
     catch (Exception e) { }
 }
 public CurrentPosition(FRCRobot robot)
 {
     this.robot = robot;
 }
        static void Main(string[] args)
        {
            OptionSet optionSet = new OptionSet()
            {
                { "h=|hostname=", "The {HOSTNAME} (or IP address) of the robot.", v => sHostname = v },
                { "d|debug", "Show debug messages.", v => bShowDebug = v != null },
                { "?|help", "Show this help message and exit.", v => bShowHelp = v != null }
            };



            List <string> lsArgs;

            try
            {
                lsArgs = optionSet.Parse(args);
            }
            catch (OptionException e)
            {
                ui.WriteErrorMessage(e.Message);
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            if (bShowHelp)
            {
                // User has requested the help message.
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            if (sHostname == string.Empty)
            {
                // User did not provide required hostname field.
                ui.WriteErrorMessage("A hostname or IP address must be provided.");
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            // Check to see if sHostname matches an IP Address or Hostname pattern.
            string sRegexIPAddressPattern = @"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
            string sRegexHostnamePattern  = @"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$";
            Regex  rIPAddress             = new Regex(sRegexIPAddressPattern);
            Regex  rHostname = new Regex(sRegexHostnamePattern);

            if (!rIPAddress.Match(sHostname).Success&& !rHostname.Match(sHostname).Success)
            {
                ui.WriteErrorMessage("The hostname/IP address provided is not valid.");
                ui.ShowHelpMessage(optionSet);
                ui.ShowExitMessage();
                return;
            }

            // Unnecessary to check every time, bShowDebug is checked within WriteDebugMessage().
            if (bShowDebug)
            {
                // User has requested debug messages.
                ui.WriteDebugMessage("Debug messages will be shown.");
            }

            ui.ShowTitleMessage();

            ui.WriteDebugMessage("User provided a valid hostname/IP address.");
            try
            {
                ui.WriteDebugMessage("Attempting to create a new FRCRobot object using the FRRobot library.");
                robot = new FRCRobot();

                ui.WriteDebugMessage("Attempting to connect to the robot at the hostname/IP address.");
                robot.Connect(sHostname);
            }
            catch (Exception e)
            {
                ui.WriteErrorMessage(e.Message);
            }

            if (robot.IsConnected)
            {
                ui.WriteDebugMessage("Sucessfully connected to robot at {0}.", sHostname);
            }

            try
            {
                /*
                 * MBTCP_Core c = new MBTCP_Core();
                 * c.GetCommChannel();
                 * modbusTCPScanner = new ModbusTCPScanner();
                 * modbusTCPScanner.Scan("127.0.0.1", 1000);
                 */
            }
            catch (Exception e)
            {
                ui.WriteErrorMessage("Problem creating/connecting to Modbus PLC - {0}", e.Message);
            }

            FRCUOPIOSignal        UOPI_IMSTP   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_IMSTP);
            FRCUOPIOSignal        UOPI_HOLD    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_HOLD);
            FRCUOPIOSignal        UOPI_SFSPD   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_SFSPD);
            FRCUOPIOSignal        UOPI_CSTOP   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_CSTOP);
            FRCUOPIOSignal        UOPI_RESET   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_RESET);
            FRCUOPIOSignal        UOPI_START   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_START);
            FRCUOPIOSignal        UOPI_HOME    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_HOME);
            FRCUOPIOSignal        UOPI_ENABL   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPInType, (long)UOPINumber.UOPI_ENABL);
            List <FRCUOPIOSignal> UOPI_SIGNALS = new List <FRCUOPIOSignal> {
                UOPI_IMSTP, UOPI_HOLD, UOPI_SFSPD, UOPI_CSTOP, UOPI_RESET, UOPI_START, UOPI_HOME, UOPI_ENABL
            };

            FRCGroupIOSignal        GI_CARR    = (FRCGroupIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frGPInType, (long)GINumber.GI_CARR);
            List <FRCGroupIOSignal> GI_SIGNALS = new List <FRCGroupIOSignal> {
                GI_CARR
            };

            FRCDigitalIOSignal DI_CARR_DAT_RDY = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_CARR_DAT_RDY);
            //FRCDigitalIOSignal DI_SPARE_1    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_SPARE_1);
            //FRCDigitalIOSignal DI_SPARE_2    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_SPARE_2);
            FRCDigitalIOSignal        DI_ON_LINE     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_ON_LINE);
            FRCDigitalIOSignal        DI_LINE_STOP   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_LINE_STOP);
            FRCDigitalIOSignal        DI_PE_SIGNAL   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_PE_SIGNAL);
            FRCDigitalIOSignal        DI_NXT_MLD_RDY = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_NXT_MLD_RDY);
            FRCDigitalIOSignal        DI_MACRO_RUN   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDInType, (long)DINumber.DI_MACRO_RUN);
            List <FRCDigitalIOSignal> DI_SIGNALS     = new List <FRCDigitalIOSignal> {
                DI_CARR_DAT_RDY, /* DI_SPARE_1, DI_SPARE_2, */ DI_ON_LINE, DI_LINE_STOP, DI_PE_SIGNAL, DI_NXT_MLD_RDY, DI_MACRO_RUN
            };

            FRCUOPIOSignal        UOPO_CMDEN   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_CMDEN);
            FRCUOPIOSignal        UOPO_SYSRD   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_SYSRD);
            FRCUOPIOSignal        UOPO_PROGR   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_PROGR);
            FRCUOPIOSignal        UOPO_PAUSD   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_PAUSD);
            FRCUOPIOSignal        UOPO_HELD    = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_HELD);
            FRCUOPIOSignal        UOPO_FAULT   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_FAULT);
            FRCUOPIOSignal        UOPO_PERCH   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_PERCH);
            FRCUOPIOSignal        UOPO_TPENB   = (FRCUOPIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frUOPOutType, (long)UOPONumber.UOPO_TPENB);
            List <FRCUOPIOSignal> UOPO_SIGNALS = new List <FRCUOPIOSignal> {
                UOPO_CMDEN, UOPO_SYSRD, UOPO_PROGR, UOPO_PAUSD, UOPO_HELD, UOPO_FAULT, UOPO_PERCH, UOPO_TPENB
            };

            FRCDigitalIOSignal DO_CARR_DAT_ACK    = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_CARR_DAT_ACK);
            FRCDigitalIOSignal DO_NXT_MLD_DAT_RDY = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_NXT_MLD_DAT_RDY);
            FRCDigitalIOSignal DO_PATH_RUNG       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PATH_RUNG);
            FRCDigitalIOSignal DO_SYS_RUNG        = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_SYS_RUNG);
            FRCDigitalIOSignal DO_FAN_1_REQ       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_FAN_1_REQ);
            FRCDigitalIOSignal DO_FAN_2_REQ       = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_FAN_2_REQ);
            FRCDigitalIOSignal DO_HI_PUFF_REQ     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_HI_PUFF_REQ);
            FRCDigitalIOSignal DO_LO_PUFF_REQ     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_LO_PUFF_REQ);

            FRCGroupIOSignal        GO_PH_CARR = (FRCGroupIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frGPOutType, (long)GONumber.GO_PH_CARR);
            List <FRCGroupIOSignal> GO_SIGNALS = new List <FRCGroupIOSignal> {
                GO_PH_CARR
            };

            FRCDigitalIOSignal        DO_PH_MOL_BIT0 = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PH_MOL_BIT0);
            FRCDigitalIOSignal        DO_PH_MOL_BIT1 = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PH_MOL_BIT1);
            FRCDigitalIOSignal        DO_PH_MOL_BIT2 = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PH_MOL_BIT2);
            FRCDigitalIOSignal        DO_LINEUP_ERR  = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_LINEUP_ERR);
            FRCDigitalIOSignal        DO_PROGRAM     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PROGRAM);
            FRCDigitalIOSignal        DO_HEAD_OPEN   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_HEAD_OPEN);
            FRCDigitalIOSignal        DO_PROG_RUNG   = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_PROG_RUNG);
            FRCDigitalIOSignal        DO_OPEN_PH     = (FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)DONumber.DO_OPEN_PH);
            List <FRCDigitalIOSignal> DO_SIGNALS     = new List <FRCDigitalIOSignal> {
                DO_CARR_DAT_ACK, DO_NXT_MLD_DAT_RDY, DO_PATH_RUNG, DO_SYS_RUNG, DO_FAN_1_REQ, DO_FAN_2_REQ, DO_HI_PUFF_REQ, DO_LO_PUFF_REQ,
                DO_PH_MOL_BIT0, DO_PH_MOL_BIT1, DO_PH_MOL_BIT2, DO_LINEUP_ERR, DO_PROGRAM, DO_HEAD_OPEN, DO_PROG_RUNG, DO_OPEN_PH
            };

            foreach (FRCDigitalIOSignal signal in DI_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(DINumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCDigitalIOSignal signal in DO_SIGNALS)
            {
                signal.StartMonitor(1);
                //signal.Change += delegate () { eventType = EventType.Change; eventSender = (FRCIOSignal)signal; eventSenderType = FREIOTypeConstants.frDOutType; bEvent = true; };
                signal.Change += delegate() { utility.RobotIO_Change((FRCIOSignal)signal, FREIOTypeConstants.frDOutType); };
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(DONumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCGroupIOSignal signal in GI_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(GINumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCGroupIOSignal signal in GO_SIGNALS)
            {
                //signal.StartMonitor(1);
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(GONumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCUOPIOSignal signal in UOPI_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(UOPINumber), signal.LogicalNum), signal.Value.ToString());
            }

            foreach (FRCUOPIOSignal signal in UOPO_SIGNALS)
            {
                ui.WriteDebugMessage("{0,18} = \"{1}\"", Enum.GetName(typeof(UOPONumber), signal.LogicalNum), signal.Value.ToString());
                //signal.StartMonitor(1);
            }

            ui.WriteDebugMessage("Robot Time: {0}", robot.SysInfo.Clock.ToLongTimeString());

            ui.WriteDebugMessage("DO[2] = \"{0}\"", ((FRCDigitalIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frDOutType, (long)2)).Value.ToString());
            ui.WriteDebugMessage("GO[1] = \"{0}\"", ((FRCGroupIOSignal)utility.GetRobotIOSignal(robot, FREIOTypeConstants.frGPOutType, (long)1)).Value.ToString());

            //ioSignal = ioType.
            //ioTypes.Add(ioType);

            while (!bEvent)
            {
                if (bEvent)
                {
                    ui.WriteDebugMessage("****** EVENT TRIGGERED ******");
                    ui.WriteDebugMessage("Event Type:        {0}", Enum.GetName(typeof(EventType), eventType));
                    ui.WriteDebugMessage("Event Sender:      {0}", Enum.GetName(typeof(DONumber), eventSender.LogicalNum));
                    ui.WriteDebugMessage("Event Sender Type: {0}", Enum.GetName(typeof(FREIOTypeConstants), eventSenderType));
                    ui.WriteDebugMessage("*****************************");
                }
            }

            /*
             * foreach (FRCDigitalIOSignal signal in DO_SIGNALS)
             * {
             *  ui.WriteDebugMessage(".Equals {0,18}?: {1}", Enum.GetName(typeof(DONumber), signal.LogicalNum), LastChangeEventSender.Equals(signal));
             * }
             */

            ui.ShowExitMessage();
        }
        /// <summary>
        /// Получение списка сигналов и передача в список Signals
        /// </summary>
        /// <param name="robot">экземпляр подключения к роботу</param>
        /// <param name="ioTypeConstant">константа типа сигналов</param>
        /// <returns>возвращаемое значение-текущая задача</returns>
        private async Task GetSignalsIO(FRCRobot robot, FREIOTypeConstants ioTypeConstant)
        {
            Task task = new Task(() =>
            {
                Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    try
                    {
                        if (robot.IsConnected)
                        {
                            Signals.Clear();
                            switch (ioTypeConstant)
                            {
                            //DIN DOUT
                            case FREIOTypeConstants.frDOutType:
                            case FREIOTypeConstants.frDInType:
                                FRCDigitalIOType dioTypeIn = (FRCDigitalIOType)robot.IOTypes[ioTypeConstant];
                                foreach (FRCDigitalIOSignal item in dioTypeIn.Signals)
                                {
                                    Signals.Add(new IOSignals {
                                        NumberIO = item.LogicalNum, Status = item.Value,
                                        Comment  = item.Comment, TypeConstants = ioTypeConstant
                                    });
                                }

                                break;

                            //UI UO
                            case FREIOTypeConstants.frUOPInType:
                            case FREIOTypeConstants.frUOPOutType:
                                FRCUOPIOType TypeUO = (FRCUOPIOType)robot.IOTypes[ioTypeConstant];
                                foreach (FRCUOPIOSignal item in TypeUO.Signals)
                                {
                                    Signals.Add(new IOSignals {
                                        NumberIO = item.LogicalNum, Status = item.Value,
                                        Comment  = item.Comment, TypeConstants = ioTypeConstant
                                    });
                                }
                                break;

                            //SI SO
                            case FREIOTypeConstants.frSOPInType:
                            case FREIOTypeConstants.frSOPOutType:
                                FRCSOPIOType TypeSO = (FRCSOPIOType)robot.IOTypes[ioTypeConstant];
                                foreach (FRCSOPIOSignal item in TypeSO.Signals)
                                {
                                    Signals.Add(new IOSignals {
                                        NumberIO = item.LogicalNum, Status = item.Value, Comment = item.Comment, TypeConstants = ioTypeConstant
                                    });
                                }
                                break;

                            //FLAG
                            case FREIOTypeConstants.frFlagType:
                                FRCFlagType TypeFlag = (FRCFlagType)robot.IOTypes[ioTypeConstant];
                                foreach (FRCFlagSignal item in TypeFlag.Signals)
                                {
                                    Signals.Add(new IOSignals {
                                        NumberIO = item.LogicalNum, Status = item.Value, Comment = item.Comment, TypeConstants = ioTypeConstant
                                    });
                                }
                                break;

                            //RO RI
                            case FREIOTypeConstants.frRDOutType:
                            case FREIOTypeConstants.frRDInType:
                                FRCRobotIOType TypeRI = (FRCRobotIOType)robot.IOTypes[ioTypeConstant];
                                foreach (FRCRobotIOSignal item in TypeRI.Signals)
                                {
                                    Signals.Add(new IOSignals {
                                        NumberIO = item.LogicalNum, Status = item.Value, Comment = item.Comment, TypeConstants = ioTypeConstant
                                    });
                                }
                                break;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }));
            }, TaskCreationOptions.LongRunning);

            task.Start();
            await task;
        }
 public ConnectionToFanuc()
 {
     robot     = new FRCRobot();
     IPaddress = ConfigurationManager.AppSettings["IPaddressFanuc"];
 }