/// <summary>
 /// Добавление канала ввода\вывода к устройству.
 /// </summary>
 /// <param name="dev">Устройство.</param>
 /// <param name="addressSpace">Адресное пространство.</param>
 /// <param name="node">Узел.</param>
 /// <param name="module">Модуль.</param>
 /// <param name="physicalKlemme">Клемма.</param>
 /// <param name="comment">Описание канала.</param>
 /// <param name="errors">Строка с описанием ошибки при наличии таковой.</param>
 /// <param name="fullModule">Полный номер модуля</param>
 /// <param name="logicalClamp">Логический порядковый номер клеммы</param>
 /// <param name="moduleOffset">Начальный сдвиг модуля</param>
 public void AddDeviceChannel(IODevice dev,
                              IO.IOModuleInfo.ADDRESS_SPACE_TYPE addressSpace,
                              int node, int module, int physicalKlemme, string comment,
                              out string errors, int fullModule, int logicalClamp, int moduleOffset, string channelName)
 {
     dev.SetChannel(addressSpace, node, module, physicalKlemme,
                    comment, out errors, fullModule, logicalClamp, moduleOffset, channelName);
 }
        /// <summary>
        /// Добавление канала ввода\вывода к устройству.
        /// </summary>
        /// <param name="devName">Имя устройство.</param>
        /// <param name="description">Описание устройства.</param>
        /// <param name="subType">Подтип устройства.</param>
        /// <param name="paramStr">Дополнительный строковый параметр - параметры.</param>
        /// <param name="rtParamStr">Дополнительный строковый параметр - рабочие параметры.</param>
        /// <param name="propStr">Дополнительный строковый параметр - свойства.</param>
        /// <param name="errStr">Описание ошибки при ее наличии.</param>
        public IODevice AddDeviceAndEFunction(string devName, string description,
                                              string subType, string paramStr, string rtParamStr, string propStr, int dLocation,
                                              Eplan.EplApi.DataModel.Function oF, out string errStr, string articleName)
        {
            IODevice dev = AddDevice(devName, description, subType, paramStr,
                                     rtParamStr, propStr, dLocation, out errStr, articleName);

            if (dev != null)
            {
                dev.EplanObjectFunction = oF;
            }

            return(dev);
        }
        public int GetDeviceIndex(string devName)
        {
            string name;
            string objectName;
            int    objectNumber;
            string deviceType;
            int    deviceNumber;

            CheckDeviceName(devName, out name, out objectName, out objectNumber,
                            out deviceType, out deviceNumber);
            IODevice devStub = new IODevice(name, StaticHelper.CommonConst.Cap,
                                            deviceType, deviceNumber, objectName, objectNumber);

            int resDevN = devices.IndexOf(devStub);

            return(resDevN);
        }
        /// <summary>
        /// Получение устройства по его имени (ОУ) из глобального списка.
        /// </summary>
        /// <param name="devName">Имя устройства.</param>
        /// <returns>Устройство с заданными именем или устройство-заглушка.</returns>
        public IODevice GetDevice(string devName)
        {
            string name;
            string objectName;
            int    objectNumber;
            string deviceType;
            int    deviceNumber;

            CheckDeviceName(devName, out name, out objectName, out objectNumber,
                            out deviceType, out deviceNumber);

            IODevice devStub = new IODevice(name, StaticHelper.CommonConst.Cap,
                                            deviceType, deviceNumber, objectName, objectNumber);

            int resDevN = devices.BinarySearch(devStub);

            if (resDevN >= 0)
            {
                return(devices[resDevN]);
            }

            return(devStub);
        }
        /// <summary>
        /// Добавление канала ввода\вывода к устройству.
        /// </summary>
        /// <param name="devName">Имя устройство.</param>
        /// <param name="description">Описание устройства.</param>
        /// <param name="subType">Подтип устройства.</param>
        /// <param name="paramStr">Дополнительный строковый параметр - параметры.</param>
        /// <param name="rtParamStr">Дополнительный строковый параметр - рабочие параметры.</param>
        /// <param name="propStr">Дополнительный строковый параметр - свойства.</param>
        /// <param name="errStr">Описание ошибки при ее наличии.</param>
        private IODevice AddDevice(string devName, string description,
                                   string subType, string paramStr, string rtParamStr, string propStr,
                                   int dLocation, out string errStr, string articleName)
        {
            errStr = "";
            IODevice dev = null;

            string name;
            string objectName;
            int    objectNumber;
            string deviceType;
            int    deviceNumber;


            CheckDeviceName(devName, out name, out objectName,
                            out objectNumber, out deviceType, out deviceNumber);

            // Если изделия нет или пустое, то оставляем пустое
            if (articleName == "" || articleName == null)
            {
                articleName = "";
            }

            switch (deviceType)
            {
            case "V":
                dev = new V(name, description, deviceNumber, objectName,
                            objectNumber, articleName);
                break;

            case "VC":
                dev = new VC(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "M":
            case "N":
                dev = new M(name, description, deviceNumber, objectName,
                            objectNumber, articleName);
                break;

            case "LS":
                dev = new LS(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "TE":
                dev = new TE(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "GS":
                dev = new GS(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "FS":
                dev = new FS(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "FQT":
                dev = new FQT(name, description, deviceNumber, objectName,
                              objectNumber, articleName);
                break;

            case "AO":
                dev = new AO(name, description, deviceNumber, objectName,
                             objectNumber);
                break;

            case "LT":
                dev = new LT(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "OS":
            case "DI":
                dev = new DI(name, description, deviceNumber, objectName,
                             objectNumber);
                break;

            case "UPR":
            case "DO":
                dev = new DO(name, description, deviceNumber, objectName,
                             objectNumber);
                break;

            case "QT":
                dev = new QT(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "AI":
                dev = new AI(name, description, deviceNumber, objectName,
                             objectNumber);
                break;

            case "HA":
                dev = new HA(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "HL":
                dev = new HL(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "SB":
                dev = new SB(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "WT":
                dev = new WT(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "PT":
                dev = new PT(name, description, deviceNumber, objectName,
                             objectNumber, articleName);
                break;

            case "Y":
                dev = new Y(name, description, deviceNumber, objectName,
                            objectNumber, articleName);
                break;

            case "DEV_VTUG":     // Совместимость со старыми проектами
                dev = new DEV_VTUG(name, description, deviceNumber, objectName,
                                   objectNumber, articleName);
                break;

            case "F":
                dev = new F(name, description, deviceNumber, objectName,
                            objectNumber, articleName);
                break;

            default:
                break;
            }

            if (dev != null)
            {
                if (!devices.Contains(dev))
                {
                    subType = subType.ToUpper();

                    errStr += dev.SetSubType(subType);

                    //Разбор параметров.
                    if (paramStr != "")
                    {
                        //Шаблоны для разбора параметров - 0-20 .
                        const string paramsPattern = @"(?<p_name>\w+)=(?<p_value>-?\d+\.?\d*),*";

                        Match paramsMatch = Regex.Match(paramStr, paramsPattern, RegexOptions.IgnoreCase);
                        while (paramsMatch.Success)
                        {
                            string res;
                            if (paramsMatch.Groups["p_value"].Value.EndsWith("."))
                            {
                                string str = paramsMatch.Groups["p_value"].Value.Remove(paramsMatch.Groups["p_value"].Value.Length - 1);
                                res = dev.SetParameter(paramsMatch.Groups["p_name"].Value, Convert.ToDouble(str));
                            }
                            else
                            {
                                res = dev.SetParameter(paramsMatch.Groups["p_name"].Value,
                                                       Convert.ToDouble(paramsMatch.Groups["p_value"].Value));
                            }
                            if (res != "")
                            {
                                errStr += devName + " - " + res;
                            }

                            paramsMatch = paramsMatch.NextMatch();
                        }
                    }

                    //Разбор рабочих параметров.
                    if (rtParamStr != "")
                    {
                        //Шаблоны для разбора параметров - 0-20 .
                        const string paramsPattern = @"(?<p_name>\w+)=(?<p_value>-?\d+\.?\d*),*";

                        Match paramsMatch = Regex.Match(rtParamStr, paramsPattern, RegexOptions.IgnoreCase);
                        while (paramsMatch.Success)
                        {
                            string res;
                            if (paramsMatch.Groups["p_value"].Value.EndsWith("."))
                            {
                                string str = paramsMatch.Groups["p_value"].Value.Remove(paramsMatch.Groups["p_value"].Value.Length - 1);
                                res = dev.SetRuntimeParameter(paramsMatch.Groups["p_name"].Value, Convert.ToDouble(str));
                            }
                            else
                            {
                                res = dev.SetRuntimeParameter(paramsMatch.Groups["p_name"].Value,
                                                              Convert.ToDouble(paramsMatch.Groups["p_value"].Value));
                            }
                            if (res != "")
                            {
                                errStr += devName + " - " + res;
                            }

                            paramsMatch = paramsMatch.NextMatch();
                        }
                    }

                    //Разбор свойств.
                    if (propStr != "")
                    {
                        //Шаблоны для разбора параметров - 0-20 .
                        const string propPattern = @"(?<p_name>\w+)=(?<p_value>\'[\w.]*\'),*";

                        Match propsMatch = Regex.Match(propStr, propPattern, RegexOptions.IgnoreCase);
                        while (propsMatch.Success)
                        {
                            string res = dev.SetProperty(propsMatch.Groups["p_name"].Value,
                                                         propsMatch.Groups["p_value"].Value);

                            if (res != "")
                            {
                                errStr += devName + " - " + res;
                            }
                            if (propsMatch.Groups["p_name"].Value.Equals("IP"))
                            {
                                bool foundMatch = false;
                                var  ipprop     = propsMatch.Groups["p_value"].Value.Trim(new char[] { '\'' });
                                try
                                {
                                    foundMatch = Regex.IsMatch(ipprop, @"\A(?:^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$)\Z");
                                }
                                catch
                                {
                                    // Syntax error in the regular expression
                                }
                                if (!foundMatch)
                                {
                                    errStr += String.Format("Устройство {0}: неверный IP-адрес - \'{1}\'.\n", devName, ipprop);
                                }
                            }

                            propsMatch = propsMatch.NextMatch();
                        }
                    }

                    //Установка параметра номер а шкафа для устройства.
                    dev.SetLocation(dLocation);

                    devices.Add(dev);
                }
                else
                {
                    errStr = string.Format("\"{0}\"  - дублируется.",
                                           devName);
                }
            }
            else
            {
                errStr = string.Format("\"{0}\" - неизвестное устройство.",
                                       devName);
            }
            return(dev);
        }