/// <summary> /// Gets a user interface object for the device. /// </summary> private bool GetDeviceView(Settings.KP kp, bool common, out KPView kpView) { try { string dllPath = Path.Combine(Environment.AppDirs.KPDir, kp.Dll); KPView commonKpView = Environment.GetKPView(dllPath); if (common) { kpView = commonKpView; } else { kpView = KPFactory.GetKPView(commonKpView.GetType(), kp.Number); kpView.KPProps = new KPView.KPProperties(CustomParams, kp.CmdLine); kpView.AppDirs = Environment.AppDirs; } return(true); } catch (Exception ex) { ScadaUiUtils.ShowError(ex.Message); Environment.ErrLog.WriteException(ex); kpView = null; return(false); } }
/// <summary> /// Gets the user interface of the particular device. /// </summary> public KPView GetKPView(string dllPath, int kpNum, KPView.KPProperties kpProps) { KPView commonKpView = GetKPView(dllPath); KPView kpView = KPFactory.GetKPView(commonKpView.GetType(), kpNum); kpView.KPProps = kpProps ?? throw new ArgumentNullException("kpProps"); kpView.AppDirs = AppDirs; return(kpView); }
/// <summary> /// Отобразить форму модально /// </summary> public static void ShowDialog(int kpNum, KPView.KPProperties kpProps, AppDirs appDirs) { if (kpProps == null) throw new ArgumentNullException("kpProps"); if (appDirs == null) throw new ArgumentNullException("appDirs"); FrmDevProps frmDevProps = new FrmDevProps(); frmDevProps.kpNum = kpNum; frmDevProps.kpProps = kpProps; frmDevProps.appDirs = appDirs; frmDevProps.ShowDialog(); }
/// <summary> /// Initializes the driver item if needed. /// </summary> private void InitDriverItem(DriverItem driverItem) { if (!driverItem.IsInitialized) { driverItem.IsInitialized = true; try { KPView kpView = environment.GetKPView(driverItem.FilePath); driverItem.Descr = kpView.KPDescr?.Replace("\n", Environment.NewLine); driverItem.KPView = kpView; } catch (Exception ex) { driverItem.Descr = ex.Message; driverItem.KPView = null; } } }
/// <summary> /// Gets a user interface object for the device. /// </summary> public bool TryGetKPView(Settings.KP kp, bool common, SortedList <string, string> customParams, out KPView kpView, out string errMsg) { try { string dllPath = Path.Combine(AppDirs.KPDir, kp.Dll); kpView = common ? GetKPView(dllPath) : GetKPView(dllPath, kp.Number, new KPView.KPProperties(customParams, kp.CmdLine)); errMsg = null; return(true); } catch (Exception ex) { ErrLog.WriteException(ex); kpView = null; errMsg = ex.Message; return(false); } }
/// <summary> /// Создать каналы /// </summary> private void CreateCnls() { writer = null; bool logCreated = false; string logFileName = AppData.ExeDir + "ScadaAdminCreateCnls.txt"; try { // создание журанала создания каналов writer = new StreamWriter(logFileName, false, Encoding.UTF8); logCreated = true; string title = DateTime.Now.ToString("G", Localization.Culture) + " " + AppPhrases.CreateCnlsTitle; writer.WriteLine(title); writer.WriteLine(new string('-', title.Length)); writer.WriteLine(); // определение используемых выбранными КП объектов пользовательского интерфейса КП List <KPView> usedKPViewList = new List <KPView>(); foreach (KPParams kpParams in kpParamsList) { if (kpParams.Selected) { KPView kpView = kpParams.KPView; if (kpView != null && !usedKPViewList.Contains(kpView)) { usedKPViewList.Add(kpView); } } } // формирование справочников используемых наименований SortedList <string, int> paramList = new SortedList <string, int>(); SortedList <string, int> unitList = new SortedList <string, int>(); SortedList <string, int> cmdValList = new SortedList <string, int>(); foreach (KPView kpView in usedKPViewList) { if (kpView.DefaultCnls != null) { foreach (KPView.InCnlProps inCnlProps in kpView.DefaultCnls) { string s = inCnlProps.ParamName; if (s != "" && !paramList.ContainsKey(s)) { paramList.Add(s, -1); } s = inCnlProps.UnitName; if (s != "" && !unitList.ContainsKey(s)) { unitList.Add(s, -1); } if (inCnlProps.CtrlCnlProps != null) { s = inCnlProps.CtrlCnlProps.CmdValName; if (s != "" && !cmdValList.ContainsKey(s)) { cmdValList.Add(s, -1); } } } } } // определение идентификаторов в справочниках writer.WriteLine(AppPhrases.CheckDicts); bool paramError = FindDictIDs(paramList, Tables.GetParamTable(), "ParamID", AppPhrases.ParamNotFound); bool unitError = FindDictIDs(unitList, Tables.GetUnitTable(), "UnitID", AppPhrases.UnitNotFound); bool cmdValError = FindDictIDs(cmdValList, Tables.GetCmdValTable(), "CmdValID", AppPhrases.CmdValsNotFound); if (paramError || unitError || cmdValError) { writer.WriteLine(AppPhrases.CreateCnlsImpossible); } else { writer.WriteLine(AppPhrases.CreateCnlsStart); // заполнение схем таблиц входных каналов и каналов управления DataTable tblInCnl = new DataTable("InCnl"); DataTable tblCtrlCnl = new DataTable("CtrlCnl"); Tables.FillTableSchema(tblInCnl); Tables.FillTableSchema(tblCtrlCnl); // получение таблицы форматов чисел DataTable tblFormat = Tables.GetFormatTable(); tblFormat.DefaultView.Sort = "ShowNumber, DecDigits"; // создание каналов для КП foreach (KPParams kpParams in kpParamsList) { if (kpParams.Selected) { int inCnlNum = kpParams.FirstInCnlNum; int ctrlCnlNum = kpParams.FirstCtrlCnlNum; foreach (KPView.InCnlProps inCnlProps in kpParams.KPView.DefaultCnls) { KPView.CtrlCnlProps ctrlCnlProps = inCnlProps.CtrlCnlProps; object lastCtrlCnlNum; if (ctrlCnlProps == null) { lastCtrlCnlNum = DBNull.Value; } else { // создание канала управления DataRow newCtrlCnlRow = tblCtrlCnl.NewRow(); newCtrlCnlRow["CtrlCnlNum"] = ctrlCnlNum; newCtrlCnlRow["Active"] = true; newCtrlCnlRow["Name"] = ctrlCnlProps.Name; newCtrlCnlRow["CmdTypeID"] = (int)ctrlCnlProps.CmdType; newCtrlCnlRow["ObjNum"] = kpParams.ObjNum; newCtrlCnlRow["KPNum"] = kpParams.KPNum; newCtrlCnlRow["CmdNum"] = ctrlCnlProps.CmdNum; newCtrlCnlRow["CmdValID"] = ctrlCnlProps.CmdValName == "" ? DBNull.Value : (object)cmdValList[ctrlCnlProps.CmdValName]; newCtrlCnlRow["FormulaUsed"] = ctrlCnlProps.FormulaUsed; newCtrlCnlRow["Formula"] = ctrlCnlProps.Formula; newCtrlCnlRow["EvEnabled"] = ctrlCnlProps.EvEnabled; newCtrlCnlRow["ModifiedDT"] = DateTime.Now; tblCtrlCnl.Rows.Add(newCtrlCnlRow); lastCtrlCnlNum = ctrlCnlNum; ctrlCnlNum++; } // создание входного канала DataRow newInCnlRow = tblInCnl.NewRow(); newInCnlRow["CnlNum"] = inCnlNum; newInCnlRow["Active"] = true; newInCnlRow["CnlNum"] = inCnlNum; newInCnlRow["Name"] = inCnlProps.Name; newInCnlRow["CnlTypeID"] = (int)inCnlProps.CnlType; newInCnlRow["ModifiedDT"] = DateTime.Now; newInCnlRow["ObjNum"] = kpParams.ObjNum; newInCnlRow["KPNum"] = kpParams.KPNum; newInCnlRow["Signal"] = inCnlProps.Signal; newInCnlRow["FormulaUsed"] = inCnlProps.FormulaUsed; newInCnlRow["Formula"] = inCnlProps.Formula; newInCnlRow["Averaging"] = inCnlProps.Averaging; newInCnlRow["ParamID"] = inCnlProps.ParamName == "" ? DBNull.Value : (object)paramList[inCnlProps.ParamName]; newInCnlRow["FormatID"] = DBNull.Value; if (inCnlProps.ShowNumber) { int ind = tblFormat.DefaultView.Find(new object[] { true, inCnlProps.DecDigits }); if (ind >= 0) { newInCnlRow["FormatID"] = tblFormat.DefaultView[ind]["FormatID"]; } else { writer.WriteLine(string.Format( AppPhrases.NumFormatNotFound, inCnlNum, inCnlProps.DecDigits)); } } else { int ind = tblFormat.DefaultView.Find(new object[] { false, DBNull.Value }); if (ind >= 0) { newInCnlRow["FormatID"] = tblFormat.DefaultView[ind]["FormatID"]; } else { writer.WriteLine(string.Format(AppPhrases.TextFormatNotFound, inCnlNum)); } } newInCnlRow["UnitID"] = inCnlProps.UnitName == "" ? DBNull.Value : (object)unitList[inCnlProps.UnitName]; newInCnlRow["CtrlCnlNum"] = lastCtrlCnlNum; newInCnlRow["EvEnabled"] = inCnlProps.EvEnabled; newInCnlRow["EvSound"] = inCnlProps.EvSound; newInCnlRow["EvOnChange"] = inCnlProps.EvOnChange; newInCnlRow["EvOnUndef"] = inCnlProps.EvOnUndef; newInCnlRow["LimLowCrash"] = double.IsNaN(inCnlProps.LimLowCrash) ? DBNull.Value : (object)inCnlProps.LimLowCrash; newInCnlRow["LimLow"] = double.IsNaN(inCnlProps.LimLow) ? DBNull.Value : (object)inCnlProps.LimLow; newInCnlRow["LimHigh"] = double.IsNaN(inCnlProps.LimHigh) ? DBNull.Value : (object)inCnlProps.LimHigh; newInCnlRow["LimHighCrash"] = double.IsNaN(inCnlProps.LimHighCrash) ? DBNull.Value : (object)inCnlProps.LimHighCrash; tblInCnl.Rows.Add(newInCnlRow); inCnlNum++; } } } // сохранение каналов в БД bool updateOk = UpdateCnls(tblCtrlCnl, AppPhrases.AddedCtrlCnlsCount); updateOk = UpdateCnls(tblInCnl, AppPhrases.AddedInCnlsCount) && updateOk; string msg = updateOk ? AppPhrases.CreateCnlsComplSucc : AppPhrases.CreateCnlsComplWithErr; writer.WriteLine(); writer.WriteLine(msg); if (updateOk) { ScadaUtils.ShowInfo(msg + AppPhrases.RefreshRequired); } else { AppData.ErrLog.WriteAction(msg, Log.ActTypes.Error); ScadaUtils.ShowError(msg + AppPhrases.RefreshRequired); } } } catch (Exception ex) { string errMsg = AppPhrases.CreateCnlsError + ":\r\n" + ex.Message; try { writer.WriteLine(errMsg); } catch { } AppUtils.ProcError(errMsg); } finally { try { writer.Close(); } catch { } } if (logCreated) { Process.Start(logFileName); } }
/// <summary> /// Расчитать номера каналов и записать их в список информации о КП /// </summary> public static bool CalcCnlNums(Dictionary <string, Type> kpViewTypes, List <KPInfo> kpInfoList, Scada.Comm.AppDirs commDirs, List <int> inCnlNums, CnlNumParams inCnlNumParams, List <int> ctrlCnlNums, CnlNumParams ctrlCnlNumParams, out string errMsg) { if (kpViewTypes == null) { throw new ArgumentNullException("kpViewTypes"); } if (kpInfoList == null) { throw new ArgumentNullException("kpInfoList"); } if (inCnlNums == null) { throw new ArgumentNullException("inCnlNums"); } if (inCnlNumParams == null) { throw new ArgumentNullException("inCnlNumParams"); } if (ctrlCnlNums == null) { throw new ArgumentNullException("ctrlCnlNums"); } if (ctrlCnlNumParams == null) { throw new ArgumentNullException("ctrlCnlNumParams"); } bool hasChannels = false; bool hasErrors = false; errMsg = ""; try { // загрузка настроек SCADA-Коммуникатора Scada.Comm.Settings commSett = new Scada.Comm.Settings(); if (!commSett.Load(commDirs.ConfigDir + Scada.Comm.Settings.DefFileName, out errMsg)) { throw new Exception(errMsg); } // заполнение справочника свойств КП Dictionary <int, KPView.KPProperties> kpPropsDict = new Dictionary <int, KPView.KPProperties>(); foreach (Scada.Comm.Settings.CommLine commLine in commSett.CommLines) { foreach (Scada.Comm.Settings.KP kp in commLine.ReqSequence) { if (!kpPropsDict.ContainsKey(kp.Number)) { kpPropsDict.Add(kp.Number, new KPView.KPProperties(commLine.CustomParams, kp.CmdLine)); } } } // определение стартового номера входного канала int inCnlsStart = inCnlNumParams.Start; int inCnlsMultiple = inCnlNumParams.Multiple; int inCnlsSpace = inCnlNumParams.Space; int remainder = inCnlsStart % inCnlsMultiple; int curInCnlNum = remainder > 0 ? inCnlsStart - remainder : inCnlsStart; curInCnlNum += inCnlNumParams.Shift; if (curInCnlNum < inCnlsStart) { curInCnlNum += inCnlsMultiple; } // определение стартового номера канала управления int ctrlCnlsStart = ctrlCnlNumParams.Start; int ctrlCnlsMultiple = ctrlCnlNumParams.Multiple; int ctrlCnlsSpace = ctrlCnlNumParams.Space; remainder = ctrlCnlsStart % ctrlCnlNumParams.Multiple; int curCtrlCnlNum = remainder > 0 ? ctrlCnlsStart - remainder : ctrlCnlsStart; curCtrlCnlNum += ctrlCnlNumParams.Shift; if (curCtrlCnlNum < ctrlCnlNumParams.Start) { curCtrlCnlNum += ctrlCnlNumParams.Multiple; } // расчёт номеров каналов КП int curInCnlInd = 0; int inCnlNumsCnt = inCnlNums.Count; int curCtrlCnlInd = 0; int ctrlCnlNumsCnt = ctrlCnlNums.Count; foreach (KPInfo kpInfo in kpInfoList) { if (kpInfo.Selected) { // получение типа интерфейса КП Type kpViewType; if (!kpViewTypes.TryGetValue(kpInfo.DllFileName, out kpViewType)) { continue; } // создание экземпляра класса интерфейса КП KPView kpView = null; try { kpView = KPFactory.GetKPView(kpViewType, kpInfo.KPNum); KPView.KPProperties kpProps; if (kpPropsDict.TryGetValue(kpInfo.KPNum, out kpProps)) { kpView.KPProps = kpProps; } kpView.AppDirs = commDirs; } catch { kpInfo.SetInCnlNums(true); kpInfo.SetCtrlCnlNums(true); continue; } // получение прототипов каналов КП по умолчанию try { kpInfo.DefaultCnls = kpView.DefaultCnls; } catch { kpInfo.SetInCnlNums(true); kpInfo.SetCtrlCnlNums(true); continue; } // определение номеров входных каналов с учётом занятых существующими каналами номеров if (kpInfo.DefaultCnls != null && kpInfo.DefaultCnls.InCnls.Count > 0) { hasChannels = true; int firstInCnlNum; // номер первого входного канала КП int lastInCnlNum; // номер последнего входного канала КП int newInCnlInd; // новый индекс списка номеров входных каналов CalcFirstAndLastNums(curInCnlNum, curInCnlInd, inCnlNums, inCnlNumsCnt, kpInfo.DefaultCnls.InCnls.Count, inCnlsSpace, inCnlsMultiple, out firstInCnlNum, out lastInCnlNum, out newInCnlInd); if (lastInCnlNum > ushort.MaxValue) { hasErrors = true; kpInfo.SetInCnlNums(true); } else { kpInfo.SetInCnlNums(false, firstInCnlNum, lastInCnlNum); curInCnlInd = newInCnlInd; curInCnlNum = firstInCnlNum; do { curInCnlNum += inCnlsMultiple; }while (curInCnlNum - lastInCnlNum <= inCnlsSpace); } } else { // номера каналов не назначаются, т.к. КП не поддерживает создание входных каналов kpInfo.SetInCnlNums(false); } // определение номеров каналов управления с учётом занятых существующими каналами номеров if (kpInfo.DefaultCnls != null && kpInfo.DefaultCnls.CtrlCnls.Count > 0) { hasChannels = true; int firstCtrlCnlNum; // номер первого канала управления КП int lastCtrlCnlNum; // номер последнего канала управления КП int newCtrlCnlInd; // новый индекс списка номеров каналов управления CalcFirstAndLastNums(curCtrlCnlNum, curCtrlCnlInd, ctrlCnlNums, ctrlCnlNumsCnt, kpInfo.DefaultCnls.CtrlCnls.Count, ctrlCnlsSpace, ctrlCnlsMultiple, out firstCtrlCnlNum, out lastCtrlCnlNum, out newCtrlCnlInd); if (lastCtrlCnlNum > ushort.MaxValue) { hasErrors = true; kpInfo.SetCtrlCnlNums(true); } else { kpInfo.SetCtrlCnlNums(false, firstCtrlCnlNum, lastCtrlCnlNum); curCtrlCnlInd = newCtrlCnlInd; curCtrlCnlNum = firstCtrlCnlNum; do { curCtrlCnlNum += ctrlCnlsMultiple; }while (curCtrlCnlNum - lastCtrlCnlNum <= ctrlCnlsSpace); } } else { // номера каналов не назначаются, т.к. КП не поддерживает создание каналов управления kpInfo.SetCtrlCnlNums(false); } } else { // номера каналов не назначаются, т.к. КП не выбран kpInfo.SetInCnlNums(false, -1, -1); kpInfo.SetCtrlCnlNums(false, -1, -1); } } if (hasErrors) { errMsg = AppPhrases.CalcCnlNumsErrors; } else if (!hasChannels) { errMsg = AppPhrases.CreatedCnlsMissing; } } catch (Exception ex) { hasErrors = true; errMsg = AppPhrases.CalcCnlNumsError + ":\r\n" + ex.Message; } return(hasChannels && !hasErrors); }
/// <summary> /// Calculate the channel numbers and write them to the list of information on KP /// </summary> public static bool CalcCnlNums(Dictionary <string, Type> kpViewTypes, List <KPInfo> kpInfoList, Scada.Comm.AppDirs commDirs, List <int> inCnlNums, CnlNumParams inCnlNumParams, List <int> ctrlCnlNums, CnlNumParams ctrlCnlNumParams, out string errMsg) { if (kpViewTypes == null) { throw new ArgumentNullException(nameof(kpViewTypes)); } if (kpInfoList == null) { throw new ArgumentNullException(nameof(kpInfoList)); } if (inCnlNums == null) { throw new ArgumentNullException(nameof(inCnlNums)); } if (inCnlNumParams == null) { throw new ArgumentNullException(nameof(inCnlNumParams)); } if (ctrlCnlNums == null) { throw new ArgumentNullException(nameof(ctrlCnlNums)); } if (ctrlCnlNumParams == null) { throw new ArgumentNullException(nameof(ctrlCnlNumParams)); } var hasChannels = false; var hasErrors = false; errMsg = ""; try { // loading SCADA-Communicator settings Scada.Comm.Settings commSett = new Scada.Comm.Settings(); if (!commSett.Load(commDirs.ConfigDir + Scada.Comm.Settings.DefFileName, out errMsg)) { throw new Exception(errMsg); } // filling the directory of KP properties Dictionary <int, KPView.KPProperties> kpPropsDict = new Dictionary <int, KPView.KPProperties>(); foreach (Scada.Comm.Settings.CommLine commLine in commSett.CommLines) { foreach (Scada.Comm.Settings.KP kp in commLine.ReqSequence) { if (!kpPropsDict.ContainsKey(kp.Number)) { kpPropsDict.Add(kp.Number, new KPView.KPProperties(commLine.CustomParams, kp.CmdLine)); } } } // determining the starting number of the input channel int inCnlsStart = inCnlNumParams.Start; int inCnlsMultiple = inCnlNumParams.Multiple; int inCnlsSpace = inCnlNumParams.Space; int remainder = inCnlsStart % inCnlsMultiple; int curInCnlNum = remainder > 0 ? inCnlsStart - remainder : inCnlsStart; curInCnlNum += inCnlNumParams.Shift; if (curInCnlNum < inCnlsStart) { curInCnlNum += inCnlsMultiple; } // determination of the control channel start number int ctrlCnlsStart = ctrlCnlNumParams.Start; int ctrlCnlsMultiple = ctrlCnlNumParams.Multiple; int ctrlCnlsSpace = ctrlCnlNumParams.Space; remainder = ctrlCnlsStart % ctrlCnlNumParams.Multiple; int curCtrlCnlNum = remainder > 0 ? ctrlCnlsStart - remainder : ctrlCnlsStart; curCtrlCnlNum += ctrlCnlNumParams.Shift; if (curCtrlCnlNum < ctrlCnlNumParams.Start) { curCtrlCnlNum += ctrlCnlNumParams.Multiple; } // calculation channel numbers KP var curInCnlInd = 0; int inCnlNumsCnt = inCnlNums.Count; var curCtrlCnlInd = 0; int ctrlCnlNumsCnt = ctrlCnlNums.Count; foreach (var kpInfo in kpInfoList) { if (kpInfo.Selected) { // getting interface type kp if (!kpViewTypes.TryGetValue(kpInfo.DllFileName, out Type kpViewType)) { continue; } // instantiating a KP interface class KPView kpView = null; try { kpView = KPFactory.GetKPView(kpViewType, kpInfo.KPNum); KPView.KPProperties kpProps; if (kpPropsDict.TryGetValue(kpInfo.KPNum, out kpProps)) { kpView.KPProps = kpProps; } kpView.AppDirs = commDirs; } catch { kpInfo.SetInCnlNums(true); kpInfo.SetCtrlCnlNums(true); continue; } // default prototype channel acquisition try { kpInfo.DefaultCnls = kpView.DefaultCnls; } catch { kpInfo.SetInCnlNums(true); kpInfo.SetCtrlCnlNums(true); continue; } // definition of numbers of input channels, taking into account the numbers occupied by existing channels if (kpInfo.DefaultCnls != null && kpInfo.DefaultCnls.InCnls.Count > 0) { hasChannels = true; int firstInCnlNum; // first input channel number int lastInCnlNum; // number of last input channel KP int newInCnlInd; // new index of the number of input channels CalcFirstAndLastNums(curInCnlNum, curInCnlInd, inCnlNums, inCnlNumsCnt, kpInfo.DefaultCnls.InCnls.Count, inCnlsSpace, inCnlsMultiple, out firstInCnlNum, out lastInCnlNum, out newInCnlInd); if (lastInCnlNum > ushort.MaxValue) { hasErrors = true; kpInfo.SetInCnlNums(true); } else { kpInfo.SetInCnlNums(false, firstInCnlNum, lastInCnlNum); curInCnlInd = newInCnlInd; curInCnlNum = firstInCnlNum; do { curInCnlNum += inCnlsMultiple; } while (curInCnlNum - lastInCnlNum <= inCnlsSpace); } } else { // channel numbers are not assigned because KP does not support input channel creation kpInfo.SetInCnlNums(false); } // identification of control channel numbers with regard to numbers occupied by existing channels if (kpInfo.DefaultCnls != null && kpInfo.DefaultCnls.CtrlCnls.Count > 0) { hasChannels = true; int firstCtrlCnlNum; // first control channel number int lastCtrlCnlNum; // control channel last control channel number int newCtrlCnlInd; // new index of the list of control channel numbers CalcFirstAndLastNums(curCtrlCnlNum, curCtrlCnlInd, ctrlCnlNums, ctrlCnlNumsCnt, kpInfo.DefaultCnls.CtrlCnls.Count, ctrlCnlsSpace, ctrlCnlsMultiple, out firstCtrlCnlNum, out lastCtrlCnlNum, out newCtrlCnlInd); if (lastCtrlCnlNum > ushort.MaxValue) { hasErrors = true; kpInfo.SetCtrlCnlNums(true); } else { kpInfo.SetCtrlCnlNums(false, firstCtrlCnlNum, lastCtrlCnlNum); curCtrlCnlInd = newCtrlCnlInd; curCtrlCnlNum = firstCtrlCnlNum; do { curCtrlCnlNum += ctrlCnlsMultiple; } while (curCtrlCnlNum - lastCtrlCnlNum <= ctrlCnlsSpace); } } else { // channel numbers are not assigned because KP does not support the creation of control channels kpInfo.SetCtrlCnlNums(false); } } else { // channel numbers are not assigned because KP is not selected kpInfo.SetInCnlNums(false, -1, -1); kpInfo.SetCtrlCnlNums(false, -1, -1); } } if (hasErrors) { errMsg = AppPhrases.CalcCnlNumsErrors; } else if (!hasChannels) { errMsg = AppPhrases.CreatedCnlsMissing; } } catch (Exception ex) { hasErrors = true; errMsg = AppPhrases.CalcCnlNumsError + ":\r\n" + ex.Message; } return(hasChannels && !hasErrors); }