/// <summary> /// Initializes a new instance of the class. /// </summary> public CnlTag(int index, int cnlNum, InCnl inCnl, Lim lim) { Index = index; CnlNum = cnlNum; InCnl = inCnl ?? throw new ArgumentNullException(nameof(inCnl)); Lim = lim; LimCnlIndex = null; CalcEngine = null; CalcCnlDataFunc = null; }
/// <summary> /// Clones input channels. /// </summary> private bool CloneInCnls(int srcStartNum, int srcEndNum, int destStartNum, int replaceObjNum, int replaceKpNum, bool updateFormulas) { try { BaseTable <InCnl> inCnlTable = configBase.InCnlTable; int affectedRows = 0; if (srcStartNum <= srcEndNum) { // create new channels int shiftNum = destStartNum - srcStartNum; List <InCnl> cnlsToAdd = new List <InCnl>(srcEndNum - srcStartNum + 1); foreach (InCnl inCnl in inCnlTable.Items.Values) { int cnlNum = inCnl.CnlNum; if (srcStartNum <= cnlNum && cnlNum <= srcEndNum) { int newCnlNum = cnlNum + shiftNum; if (newCnlNum <= AdminUtils.MaxCnlNum && !inCnlTable.PkExists(newCnlNum)) { InCnl newInCnl = ScadaUtils.DeepClone(inCnl); newInCnl.CnlNum = newCnlNum; if (replaceObjNum >= 0) { newInCnl.ObjNum = replaceObjNum > 0 ? replaceObjNum : (int?)null; } if (replaceKpNum >= 0) { newInCnl.KPNum = replaceKpNum > 0 ? replaceKpNum : (int?)null; } if (updateFormulas) { newInCnl.Formula = UpdateFormula(newInCnl.Formula, shiftNum); } cnlsToAdd.Add(newInCnl); } } else if (cnlNum > srcEndNum) { break; } } // add the created channels foreach (InCnl inCnl in cnlsToAdd) { inCnlTable.AddItem(inCnl); } affectedRows = cnlsToAdd.Count; } if (affectedRows > 0) { inCnlTable.Modified = true; } ScadaUiUtils.ShowInfo(string.Format(AppPhrases.CloneCnlsComplete, affectedRows)); return(true); } catch (Exception ex) { appData.ProcError(ex, AppPhrases.CloneInCnlsError); return(false); } }
/// <summary> /// Вычислить данные входного канала /// </summary> private void CalcCnlData(InCnl inCnl, SrezTableLight.CnlData oldCnlData, ref SrezTableLight.CnlData newCnlData) { if (inCnl != null) { try { // вычисление новых данных if (inCnl.CalcCnlData != null) inCnl.CalcCnlData(ref newCnlData); // увеличение счётчика количества переключений if (inCnl.CnlTypeID == BaseValues.CnlTypes.SWCNT && newCnlData.Stat > BaseValues.CnlStatuses.Undefined) { bool even = (int)oldCnlData.Val % 2 == 0; // старое значение чётное newCnlData.Val = newCnlData.Val < 0 && even || newCnlData.Val >= 0 && !even ? Math.Truncate(oldCnlData.Val) + 1 : Math.Truncate(oldCnlData.Val); } // корректировка нового статуса, если задана проверка границ значения if (newCnlData.Stat == BaseValues.CnlStatuses.Defined && (inCnl.LimLow < inCnl.LimHigh || inCnl.LimLowCrash < inCnl.LimHighCrash)) { newCnlData.Stat = BaseValues.CnlStatuses.Normal; if (inCnl.LimLow < inCnl.LimHigh) { if (newCnlData.Val < inCnl.LimLow) newCnlData.Stat = BaseValues.CnlStatuses.Low; else if (newCnlData.Val > inCnl.LimHigh) newCnlData.Stat = BaseValues.CnlStatuses.High; } if (inCnl.LimLowCrash < inCnl.LimHighCrash) { if (newCnlData.Val < inCnl.LimLowCrash) newCnlData.Stat = BaseValues.CnlStatuses.LowCrash; else if (newCnlData.Val > inCnl.LimHighCrash) newCnlData.Stat = BaseValues.CnlStatuses.HighCrash; } } } catch { newCnlData.Stat = BaseValues.CnlStatuses.FormulaError; } } }
/// <summary> /// Считать входные каналы из базы конфигурации /// </summary> private bool ReadInCnls() { try { lock (inCnls) { // очистка информации о каналах inCnls.Clear(); drCnls = new List<InCnl>(); drmCnls = new List<InCnl>(); drhCnls = new List<InCnl>(); drCnlNums = null; drmCnlNums = null; drhCnlNums = null; avgCnlInds = new List<int>(); // заполнение информации о каналах DataTable tblInCnl = new DataTable(); BaseAdapter adapter = new BaseAdapter(); adapter.FileName = Settings.BaseDATDir + "incnl.dat"; adapter.Fill(tblInCnl, false); foreach (DataRow dataRow in tblInCnl.Rows) { if ((bool)dataRow["Active"]) { // заполняются только свойства, используемые приложением InCnl inCnl = new InCnl(); inCnl.CnlNum = (int)dataRow["CnlNum"]; inCnl.CnlTypeID = (int)dataRow["CnlTypeID"]; inCnl.ObjNum = (int)dataRow["ObjNum"]; inCnl.KPNum = (int)dataRow["KPNum"]; inCnl.FormulaUsed = (bool)dataRow["FormulaUsed"]; inCnl.Formula = (string)dataRow["Formula"]; inCnl.Averaging = (bool)dataRow["Averaging"]; inCnl.ParamID = (int)dataRow["ParamID"]; inCnl.EvEnabled = (bool)dataRow["EvEnabled"]; inCnl.EvOnChange = (bool)dataRow["EvOnChange"]; inCnl.EvOnUndef = (bool)dataRow["EvOnUndef"]; inCnl.LimLowCrash = (double)dataRow["LimLowCrash"]; inCnl.LimLow = (double)dataRow["LimLow"]; inCnl.LimHigh = (double)dataRow["LimHigh"]; inCnl.LimHighCrash = (double)dataRow["LimHighCrash"]; int cnlTypeID = inCnl.CnlTypeID; if (BaseValues.CnlTypes.MinCnlTypeID <= cnlTypeID && cnlTypeID <= BaseValues.CnlTypes.MaxCnlTypeID) inCnls.Add(inCnl.CnlNum, inCnl); if (cnlTypeID == BaseValues.CnlTypes.TSDR || cnlTypeID == BaseValues.CnlTypes.TIDR || cnlTypeID == BaseValues.CnlTypes.SWCNT) drCnls.Add(inCnl); else if (cnlTypeID == BaseValues.CnlTypes.TSDRM || cnlTypeID == BaseValues.CnlTypes.TIDRM) drmCnls.Add(inCnl); else if (cnlTypeID == BaseValues.CnlTypes.TSDRH || cnlTypeID == BaseValues.CnlTypes.TIDRH) drhCnls.Add(inCnl); if (inCnl.Averaging && cnlTypeID == BaseValues.CnlTypes.TI) avgCnlInds.Add(inCnls.Count - 1); } } // заполнение номеров дорасчётных каналов int cnt = drCnls.Count; drCnlNums = new int[cnt]; for (int i = 0; i < cnt; i++) drCnlNums[i] = drCnls[i].CnlNum; cnt = drmCnls.Count; drmCnlNums = new int[cnt]; for (int i = 0; i < cnt; i++) drmCnlNums[i] = drmCnls[i].CnlNum; cnt = drhCnls.Count; drhCnlNums = new int[cnt]; for (int i = 0; i < cnt; i++) drhCnlNums[i] = drhCnls[i].CnlNum; // определение результата if (inCnls.Count > 0) { AppLog.WriteAction(string.Format(Localization.UseRussian ? "Входные каналы считаны из базы конфигурации. Количество активных каналов: {0}" : "Input channels are read from the configuration database. Active channel count: {0}", inCnls.Count), Log.ActTypes.Action); return true; } else { AppLog.WriteAction(Localization.UseRussian ? "В базе конфигурации отсутствуют активные входные каналы" : "No active input channels in the configuration database", Log.ActTypes.Error); return false; } } } catch (Exception ex) { AppLog.WriteAction((Localization.UseRussian ? "Ошибка при считывании входных каналов из базы конфигурации: " : "Error reading input channels from the configuration database: ") + ex.Message, Log.ActTypes.Exception); return false; } }
/// <summary> /// Генерировать событие в соответствии со свойствами и данными входного канала /// </summary> private void GenEvent(InCnl inCnl, SrezTableLight.CnlData oldCnlData, SrezTableLight.CnlData newCnlData) { if (inCnl.EvEnabled) { double oldVal = oldCnlData.Val; double newVal = newCnlData.Val; int oldStat = oldCnlData.Stat; int newStat = newCnlData.Stat; bool dataHasChanged = oldStat > BaseValues.CnlStatuses.Undefined && newStat > BaseValues.CnlStatuses.Undefined && (oldVal != newVal || oldStat != newStat); if (// события по изменению inCnl.EvOnChange && dataHasChanged || // события по неопределённому состоянию и выходу из него inCnl.EvOnUndef && (oldStat > BaseValues.CnlStatuses.Undefined && newStat == BaseValues.CnlStatuses.Undefined || oldStat == BaseValues.CnlStatuses.Undefined && newStat > BaseValues.CnlStatuses.Undefined) || // события нормализации, занижения и завышения (newStat == BaseValues.CnlStatuses.Normal || newStat == BaseValues.CnlStatuses.LowCrash || newStat == BaseValues.CnlStatuses.Low || newStat == BaseValues.CnlStatuses.High || newStat == BaseValues.CnlStatuses.HighCrash) && oldStat != newStat) { // создание события EventTableLight.Event ev = new EventTableLight.Event(); ev.DateTime = DateTime.Now; ev.ObjNum = inCnl.ObjNum; ev.KPNum = inCnl.KPNum; ev.ParamID = inCnl.ParamID; ev.CnlNum = inCnl.CnlNum; ev.OldCnlVal = oldCnlData.Val; ev.OldCnlStat = oldStat; ev.NewCnlVal = newCnlData.Val; ev.NewCnlStat = dataHasChanged && oldStat == BaseValues.CnlStatuses.Defined && newStat == BaseValues.CnlStatuses.Defined ? BaseValues.CnlStatuses.Changed : newStat; // запись события и выполнение действий модулей WriteEvent(ev); } } }
/// <summary> /// Creates channels based on the prototypes. /// </summary> private bool CreateChannels() { try { List <KPView.InCnlPrototype> inCnlPrototypes = ctrlCnlCreate1.CnlPrototypes.InCnls; List <KPView.CtrlCnlPrototype> ctrlCnlPrototypes = ctrlCnlCreate1.CnlPrototypes.CtrlCnls; int? objNum = ctrlCnlCreate2.ObjNum; int kpNum = ctrlCnlCreate1.SelectedDevice.KPNum; string cnlPrefix = ctrlCnlCreate1.SelectedDevice.Name + " - "; int inCnlNum = ctrlCnlCreate3.StartInCnl; int ctrlCnlNum = ctrlCnlCreate3.StartOutCnl; int inCnlsAdded = 0; int ctrlCnlsAdded = 0; BaseTable <InCnl> inCnlTable = project.ConfigBase.InCnlTable; BaseTable <CtrlCnl> ctrlCnlTable = project.ConfigBase.CtrlCnlTable; BaseTable <Format> formatTable = project.ConfigBase.FormatTable; DictIndexes dictIndexes = new DictIndexes(project.ConfigBase); // create output channels foreach (KPView.CtrlCnlPrototype ctrlCnlPrototype in ctrlCnlPrototypes) { ctrlCnlPrototype.CtrlCnlNum = ctrlCnlNum; CtrlCnl ctrlCnl = new CtrlCnl { CtrlCnlNum = ctrlCnlNum++, Active = ctrlCnlPrototype.Active, Name = cnlPrefix + ctrlCnlPrototype.CtrlCnlName, CmdTypeID = ctrlCnlPrototype.CmdTypeID, ObjNum = objNum, KPNum = kpNum, CmdNum = ctrlCnlPrototype.CmdNum > 0 ? (int?)ctrlCnlPrototype.CmdNum : null, CmdValID = dictIndexes.GetID(dictIndexes.CmdValByName, ctrlCnlPrototype.CmdVal), FormulaUsed = ctrlCnlPrototype.FormulaUsed, Formula = ctrlCnlPrototype.Formula, EvEnabled = ctrlCnlPrototype.EvEnabled }; if (ctrlCnl.Name.Length > ColumnLength.Name) { ctrlCnl.Name = ctrlCnl.Name.Substring(0, ColumnLength.Name); } ctrlCnlTable.AddItem(ctrlCnl); ctrlCnlsAdded++; if (ctrlCnlNum > ushort.MaxValue) { break; } } if (ctrlCnlsAdded > 0) { ctrlCnlTable.Modified = true; } // create input channels foreach (KPView.InCnlPrototype inCnlPrototype in inCnlPrototypes) { int formatID = inCnlPrototype.ShowNumber ? Math.Min(inCnlPrototype.DecDigits, BaseValues.Formats.MaxFixedID) : BaseValues.Formats.EnumText; InCnl inCnl = new InCnl { CnlNum = inCnlNum++, Active = inCnlPrototype.Active, Name = cnlPrefix + inCnlPrototype.CnlName, CnlTypeID = inCnlPrototype.CnlTypeID, ObjNum = objNum, KPNum = kpNum, Signal = inCnlPrototype.Signal > 0 ? (int?)inCnlPrototype.Signal : null, FormulaUsed = inCnlPrototype.FormulaUsed, Formula = inCnlPrototype.Formula, Averaging = inCnlPrototype.Averaging, ParamID = dictIndexes.GetID(dictIndexes.ParamByName, inCnlPrototype.ParamName), FormatID = formatTable.PkExists(formatID) ? (int?)formatID : null, UnitID = dictIndexes.GetID(dictIndexes.UnitByName, inCnlPrototype.UnitName), CtrlCnlNum = inCnlPrototype.CtrlCnlProps?.CtrlCnlNum, EvEnabled = inCnlPrototype.EvEnabled, EvSound = inCnlPrototype.EvSound, EvOnChange = inCnlPrototype.EvOnChange, EvOnUndef = inCnlPrototype.EvOnUndef, LimLowCrash = double.IsNaN(inCnlPrototype.LimLowCrash) ? null : (double?)inCnlPrototype.LimLowCrash, LimLow = double.IsNaN(inCnlPrototype.LimLow) ? null : (double?)inCnlPrototype.LimLow, LimHigh = double.IsNaN(inCnlPrototype.LimHigh) ? null : (double?)inCnlPrototype.LimHigh, LimHighCrash = double.IsNaN(inCnlPrototype.LimHighCrash) ? null : (double?)inCnlPrototype.LimHighCrash }; if (inCnl.Name.Length > ColumnLength.Name) { inCnl.Name = inCnl.Name.Substring(0, ColumnLength.Name); } inCnlTable.AddItem(inCnl); inCnlsAdded++; if (inCnlNum > ushort.MaxValue) { break; } } if (inCnlsAdded > 0) { inCnlTable.Modified = true; } ScadaUiUtils.ShowInfo(string.Format(AppPhrases.CreateCnlsComplete, inCnlsAdded, ctrlCnlsAdded)); return(true); } catch (Exception ex) { appData.ProcError(ex, AppPhrases.CreateCnlsError); return(false); } }
/// <summary> /// Performs the necessary actions after the calculation of the input channel data. /// </summary> public void EndCalcCnlData() { cnlNum = 0; inCnl = null; initialCnlData = CnlData.Empty; }
/// <summary> /// Performs the necessary actions before the calculation of the input channel data. /// </summary> public void BeginCalcCnlData(int cnlNum, InCnl inCnl, CnlData initialCnlData) { this.cnlNum = cnlNum; this.inCnl = inCnl; this.initialCnlData = initialCnlData; }