/// <summary> /// Formats the channel data according to the channel properties. /// </summary> public CnlDataFormatted FormatCnlData(CnlData cnlData, Cnl cnl, bool appendUnit) { return(FormatCnlData(cnlData, cnl?.DataTypeID ?? DataTypeID.Double, cnl?.FormatID ?? 0, appendUnit ? cnl?.UnitID ?? 0 : 0)); }
/// <summary> /// Performs the necessary actions before the calculation of the command data. /// </summary> public void BeginCalcCmdData(int cnlNum, Cnl cnl, double initialCmdVal, byte[] initialCmdData) { this.cnlNum = cnlNum; this.cnl = cnl; this.initialCmdVal = initialCmdVal; this.initialCmdData = initialCmdData; }
/// <summary> /// Performs the necessary actions after the calculation of the command data. /// </summary> public void EndCalcCmdData() { cnlNum = 0; cnl = null; initialCmdVal = double.NaN; initialCmdData = null; }
/// <summary> /// Requests historical data from the server. /// </summary> private HistData RequestHistData(int archiveBit, TimeRange timeRange, IList <int> cnlNums) { if (cnlNums == null) { cnlNums = Array.Empty <int>(); } int cnlCnt = cnlNums.Count; HistData.RecordList[] trends = new HistData.RecordList[cnlCnt]; HistData histData = new() { CnlNums = cnlNums, Timestamps = Array.Empty <TimeRecord>(), Trends = trends }; if (cnlCnt > 0) { // request trends TrendBundle trendBundle = clientAccessor.ScadaClient.GetTrends( archiveBit, timeRange, cnlNums.ToArray()); // copy timestamps int pointCount = trendBundle.Timestamps.Count; TimeRecord[] timestamps = new TimeRecord[pointCount]; histData.Timestamps = timestamps; for (int i = 0; i < pointCount; i++) { timestamps[i] = TimeRecord.Create(trendBundle.Timestamps[i], userContext.TimeZone); } // copy channel data CnlDataFormatter formatter = CreateFormatter(); for (int cnlIdx = 0; cnlIdx < cnlCnt; cnlIdx++) { int cnlNum = cnlNums[cnlIdx]; Cnl cnl = webContext.ConfigDatabase.CnlTable.GetItem(cnlNum); HistData.RecordList records = trends[cnlIdx] = new(pointCount); TrendBundle.CnlDataList cnlDataList = trendBundle.Trends[cnlIdx]; for (int ptIdx = 0; ptIdx < pointCount; ptIdx++) { CnlData cnlData = cnlDataList[ptIdx]; records.Add(new HistDataRecord { D = cnlData, Df = formatter.FormatCnlData(cnlData, cnl, false) }); } } } return(histData); }
public CnlProps(Cnl cnl, ConfigDataset configDataset) { ArgumentNullException.ThrowIfNull(cnl, nameof(cnl)); ArgumentNullException.ThrowIfNull(configDataset, nameof(configDataset)); CnlNum = cnl.CnlNum; JoinLen = cnl.IsString() ? cnl.GetDataLength() : 1; Unit = cnl.UnitID.HasValue ? configDataset.UnitTable.GetItem(cnl.UnitID.Value)?.Name : null; }
/// <summary> /// Initializes a new instance of the class. /// </summary> public CnlTag(int index, int cnlNum, Cnl cnl, Lim lim) { Index = index; CnlNum = cnlNum; Cnl = cnl ?? throw new ArgumentNullException(nameof(cnl)); Lim = lim; LimCnlIndex = null; CalcEngine = null; CalcCnlDataFunc = null; }
public void LoadCnls() { foreach (string cnl in cnlNums) { int srvId = int.Parse(cnl.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries)[0]); int cnlNum = int.Parse(cnl.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries)[1]); Argument lArg = new Argument("c" + srvId + "_" + cnlNum.ToString(), 0); Cnl cCnl = new Cnl(srvId, cnlNum); Cnls.Add(cCnl); } }
private string GetQuantityIconUrl(Cnl cnl) { string icon = cnl?.QuantityID == null ? "" : webContext.ConfigDatabase.QuantityTable.GetItem(cnl.QuantityID.Value).Icon; if (string.IsNullOrEmpty(icon)) { icon = "item.png"; } return(Url.Content("~/plugins/Main/images/quantity/" + icon)); }
private void AddTooltipHtml(StringBuilder sbHtml, int cnlNum, Cnl cnl) { int deviceNum = 0; int objNum = 0; int quantityID = 0; int unitID = 0; if (cnlNum > 0) { sbHtml.Append(PluginPhrases.CnlTip).Append(": [").Append(cnlNum).Append("] "); if (cnl != null) { sbHtml.Append(HttpUtility.HtmlEncode(cnl.Name)); deviceNum = cnl.DeviceNum ?? 0; objNum = cnl.ObjNum ?? 0; quantityID = cnl.QuantityID ?? 0; unitID = cnl.UnitID ?? 0; } } if (deviceNum > 0 && webContext.ConfigDatabase.DeviceTable.GetItem(deviceNum) is Device device) { sbHtml.Append("<br>").Append(PluginPhrases.DeviceTip).Append(": [") .Append(device.DeviceNum).Append("] ").Append(HttpUtility.HtmlEncode(device.Name)); } if (objNum > 0 && webContext.ConfigDatabase.ObjTable.GetItem(objNum) is Obj obj) { sbHtml.Append("<br>").Append(PluginPhrases.ObjTip).Append(": [") .Append(obj.ObjNum).Append("] ").Append(HttpUtility.HtmlEncode(obj.Name)); } if (quantityID > 0 && webContext.ConfigDatabase.QuantityTable.GetItem(quantityID) is Quantity quantity) { sbHtml.Append("<br>").Append(PluginPhrases.QuantityTip).Append(": ") .Append(HttpUtility.HtmlEncode(quantity.Name)); } if (unitID > 0 && webContext.ConfigDatabase.UnitTable.GetItem(unitID) is Unit unit) { sbHtml.Append("<br>").Append(PluginPhrases.UnitTip).Append(": ") .Append(HttpUtility.HtmlEncode(unit.Name)); } }
/// <summary> /// Checks user permissions and throws an exception if access is denied. /// </summary> private void CheckAccessRights(IdList cnlNums) { if (cnlNums == null || userContext.Rights.ViewAll) { return; } foreach (int cnlNum in cnlNums) { Cnl cnl = webContext.ConfigDatabase.CnlTable.GetItem(cnlNum); if (cnl == null) { throw new AccessDeniedException(); // no rights on undefined channel } if (!userContext.Rights.GetRightByObj(cnl.ObjNum).View) { throw new AccessDeniedException(); } } }
/// <summary> /// Checks channel access rights. /// </summary> private bool CheckChannelAccess(string cnlNumsStr) { if (!string.IsNullOrEmpty(cnlNumsStr)) { IList <int> cnlNums = ScadaUtils.ParseRange(cnlNumsStr, true, true); foreach (int cnlNum in cnlNums) { Cnl cnl = webContext.ConfigDatabase.CnlTable.GetItem(cnlNum); if (cnl == null) { return(false); // no rights on undefined channel } else if (!userContext.Rights.GetRightByObj(cnl.ObjNum).View) { return(false); } } } return(true); }
/// <summary> /// Appends the points of the trend bundle to the string builder. /// </summary> private void AppendTrendPoints(StringBuilder stringBuilder, TrendBundle trendBundle, int trendIndex) { stringBuilder.Append('['); if (trendBundle != null) { Cnl cnl = cnls[trendIndex]; int counter = 0; foreach (CnlData cnlData in trendBundle.Trends[trendIndex]) { CnlDataFormatted cnlDataFormatted = formatter.FormatCnlData(cnlData, cnl, false); TrendPoint.Append(stringBuilder, cnlData, cnlDataFormatted.DispVal); if (++counter == ItemsPerLine) { counter = 0; stringBuilder.AppendLine(); } } } stringBuilder.Append(']'); }
/// <summary> /// Appends the points of the single trend to the string builder. /// </summary> private void AppendTrendPoints(StringBuilder stringBuilder, Trend trend, Cnl cnl) { stringBuilder.Append('['); if (trend != null) { int counter = 0; foreach (Data.Models.TrendPoint point in trend.Points) { CnlData cnlData = new(point.Val, point.Stat); CnlDataFormatted cnlDataFormatted = formatter.FormatCnlData(cnlData, cnl, false); TrendPoint.Append(stringBuilder, cnlData, cnlDataFormatted.DispVal); if (++counter == ItemsPerLine) { counter = 0; stringBuilder.AppendLine(); } } } stringBuilder.Append(']'); }
/// <summary> /// Clones channels with the specified parameters. /// </summary> private bool CloneChannels(int srcStartNum, int srcEndNum, int destStartNum, int replaceObjNum, int replaceDeviceNum, bool updateFormulas) { try { BaseTable <Cnl> cnlTable = configDatabase.CnlTable; int affectedRows = 0; if (srcStartNum <= srcEndNum) { // create new channels ExtensionUtils.NormalizeIdRange(ConfigDatabase.MinID, ConfigDatabase.MaxID, ref srcStartNum, ref srcEndNum, destStartNum, out int numOffset); List <Cnl> cnlsToAdd = new(srcEndNum - srcStartNum + 1); foreach (Cnl cnl in cnlTable.EnumerateItems()) { if (cnl.CnlNum < srcStartNum) { continue; } else if (cnl.CnlNum > srcEndNum) { break; } else if (!cnlTable.PkExists(cnl.CnlNum + numOffset)) { Cnl newCnl = ScadaUtils.DeepClone(cnl); newCnl.CnlNum = cnl.CnlNum + numOffset; if (replaceObjNum >= 0) { newCnl.ObjNum = replaceObjNum > 0 ? replaceObjNum : null; } if (replaceDeviceNum >= 0) { newCnl.DeviceNum = replaceDeviceNum > 0 ? replaceDeviceNum : null; } if (updateFormulas) { newCnl.InFormula = UpdateFormula(newCnl.InFormula, numOffset); newCnl.OutFormula = UpdateFormula(newCnl.OutFormula, numOffset); } cnlsToAdd.Add(newCnl); } } // add created channels cnlsToAdd.ForEach(cnl => cnlTable.AddItem(cnl)); affectedRows = cnlsToAdd.Count; } if (affectedRows > 0) { cnlTable.Modified = true; } ScadaUiUtils.ShowInfo(string.Format(ExtensionPhrases.CloneChannelsCompleted, affectedRows)); return(true); } catch (Exception ex) { adminContext.ErrLog.HandleError(ex, ExtensionPhrases.CloneChannelsError); return(false); } }
public HtmlString RenderTableView() { StringBuilder sbHtml = new(); sbHtml.AppendLine("<table class='table-main'>"); // columns sbHtml.AppendLine("<colgroup>"); sbHtml.AppendLine("<col class='col-cap'>"); sbHtml.AppendLine("<col class='col-cur'>"); foreach (ColumnMeta columnMeta in allColumnMetas) { sbHtml.Append("<col class='col-hist' data-time='").Append(columnMeta.UtcTime).AppendLine("'>"); } sbHtml.AppendLine("</colgroup>"); // header sbHtml.AppendLine("<thead><tr class='row-hdr'>"); sbHtml.Append("<th class='hdr-cap'>").Append(PluginPhrases.ItemColumn).AppendLine("</th>"); sbHtml.Append("<th class='hdr-cur'>").Append(PluginPhrases.CurrentColumn).AppendLine("</th>"); foreach (ColumnMeta columnMeta in allColumnMetas) { sbHtml.Append("<th class='hdr-hist'><span class='hdr-date'>").Append(columnMeta.ShortDate) .Append("</span> <span class='hdr-time'>").Append(columnMeta.ShortTime) .AppendLine("</span></th>"); } sbHtml.AppendLine("</tr></thead>"); // rows bool enableCommands = webContext.AppConfig.GeneralOptions.EnableCommands && userContext.Rights.GetRightByView(tableView.ViewEntity).Control; sbHtml.AppendLine("<tbody>"); foreach (TableItem tableItem in tableView.VisibleItems) { Cnl itemCnl = tableItem.Cnl; bool showVal = itemCnl != null && itemCnl.IsArchivable(); int joinLen = itemCnl != null && itemCnl.IsString() ? itemCnl.GetDataLength() : 1; string itemText = string.IsNullOrWhiteSpace(tableItem.Text) ? " " : HttpUtility.HtmlEncode(tableItem.Text); sbHtml.Append("<tr class='row-item' data-cnlnum='").Append(tableItem.CnlNum) .Append("' data-showval='").Append(showVal.ToLowerString()) .Append("' data-joinlen='").Append(joinLen).AppendLine("'>") .Append("<td><div class='item'>"); if (tableItem.CnlNum > 0) { sbHtml .Append("<span class='item-icon'><img src='").Append(GetQuantityIconUrl(itemCnl)) .Append("' data-bs-toggle='tooltip' data-bs-placement='right' data-bs-html='true' title='"); AddTooltipHtml(sbHtml, tableItem.CnlNum, itemCnl); sbHtml .Append("' /></span>") .Append("<span class='item-text item-link'>").Append(itemText).Append("</span>"); if (enableCommands && itemCnl != null && itemCnl.IsOutput()) { sbHtml .Append("<span class='item-cmd' title='").Append(PluginPhrases.SendCommandTip) .Append("'><i class='fas fa-rocket'></i></span>"); } } else { sbHtml.Append("<span class='item-text'>").Append(itemText).Append("</span>"); } sbHtml.AppendLine("</div></td>"); // close first cell sbHtml.AppendLine("<td class='cell-cur'></td>"); // current data cell for (int i = 0, cnt = allColumnMetas.Count; i < cnt; i++) { sbHtml.AppendLine("<td class='cell-hist'></td>"); // historical data cell } sbHtml.AppendLine("</tr>"); } sbHtml.AppendLine("</tbody>"); sbHtml.AppendLine("</table>"); return(new HtmlString(sbHtml.ToString())); }
/// <summary> /// Performs the necessary actions after the calculation of the channel data. /// </summary> public void EndCalcCnlData() { cnlNum = 0; cnl = null; initialCnlData = CnlData.Empty; }
/// <summary> /// Performs the necessary actions before the calculation of the channel data. /// </summary> public void BeginCalcCnlData(int cnlNum, Cnl cnl, CnlData initialCnlData) { this.cnlNum = cnlNum; this.cnl = cnl; this.initialCnlData = initialCnlData; }
/// <summary> /// Formats the event according to the channel properties. /// </summary> public EventFormatted FormatEvent(Event ev) { if (ev == null) { throw new ArgumentNullException(nameof(ev)); } EventFormatted eventFormatted = new EventFormatted { Time = TimeZoneInfo.ConvertTimeFromUtc(ev.Timestamp, timeZone).ToLocalizedString() }; // object if (ev.ObjNum > 0) { eventFormatted.Obj = configDataset.ObjTable.GetItem(ev.ObjNum)?.Name ?? ""; } // device if (ev.DeviceNum > 0) { eventFormatted.Dev = configDataset.DeviceTable.GetItem(ev.DeviceNum)?.Name ?? ""; } // channel Cnl cnl = null; if (ev.CnlNum > 0) { cnl = configDataset.CnlTable.GetItem(ev.CnlNum); eventFormatted.Cnl = cnl?.Name ?? ""; } // description StringBuilder sbDescr = new StringBuilder(); CnlDataFormatted dataFormatted; if (ev.TextFormat == EventTextFormat.Command) { // Command Value, Data. Custom text sbDescr.Append(CommonPhrases.CommandDescrPrefix); dataFormatted = FormatCnlData(new CnlData(ev.CnlVal, CnlStatusID.Defined), DataTypeID.Double, cnl?.FormatID ?? 0, cnl?.UnitID ?? 0); if (ev.CnlStat > 0) { sbDescr.Append(dataFormatted.DispVal); } if (ev.Data != null && ev.Data.Length > 0) { sbDescr .Append(ev.CnlStat > 0 ? ", " : "") .Append("0x") .Append(ScadaUtils.BytesToHex(ev.Data, 0, Math.Min(DataDisplayLength, ev.Data.Length))) .Append(DataDisplayLength < ev.Data.Length ? "..." : ""); } } else { // Status, Value. Custom text dataFormatted = FormatCnlData(new CnlData(ev.CnlVal, ev.CnlStat), cnl, true); if (ev.TextFormat == EventTextFormat.Full || ev.TextFormat == EventTextFormat.AutoText) { string statusName = configDataset.CnlStatusTable.GetItem(ev.CnlStat)?.Name ?? string.Format(CommonPhrases.StatusFormat, ev.CnlStat); sbDescr.Append(statusName).Append(", ").Append(dataFormatted.DispVal); } } if (!string.IsNullOrEmpty(ev.Text) && ev.TextFormat != EventTextFormat.AutoText) { if (sbDescr.Length > 0) { sbDescr.Append(". "); } sbDescr.Append(ev.Text); } eventFormatted.Descr = sbDescr.ToString(); // severity int knownSeverity = Severity.Closest(ev.Severity); if (knownSeverity != Severity.Undefined) { switch (knownSeverity) { case Severity.Critical: eventFormatted.Sev = CommonPhrases.CriticalSeverity; break; case Severity.Major: eventFormatted.Sev = CommonPhrases.MajorSeverity; break; case Severity.Minor: eventFormatted.Sev = CommonPhrases.MinorSeverity; break; case Severity.Info: eventFormatted.Sev = CommonPhrases.InfoSeverity; break; } eventFormatted.Sev += ", " + ev.Severity; } // acknowledgement if (ev.Ack) { eventFormatted.Ack = string.Join(", ", configDataset.UserTable.GetItem(ev.AckUserID)?.Name, TimeZoneInfo.ConvertTimeFromUtc(ev.AckTimestamp, timeZone).ToLocalizedString()); } // color if (dataFormatted.Colors.Length > 0) { eventFormatted.Color = dataFormatted.Colors[0]; } // beep if (cnl != null && new EventMask(cnl.EventMask).Beep) { eventFormatted.Beep = true; } return(eventFormatted); }
/// <summary> /// Initializes a new instance of the class. /// </summary> public OutCnlTag(Cnl cnl) { Cnl = cnl ?? throw new ArgumentNullException(nameof(cnl)); CalcEngine = null; CalcCmdDataFunc = null; }
public override TaskStatus Run () { Info("Start RSSendValues task"); bool IsIndata = false; try { if(indata=="file") { foreach(FileInf fi in SelectFiles()) { SrezTableLight stl = new SrezTableLight (); sa.FileName = fi.Path; sa.Fill(stl); int id = int.Parse (fi.FileName.Split (new char[]{'.'},StringSplitOptions.RemoveEmptyEntries)[1]); stls.AddSrez(id,stl.SrezList.Values[0]); } IsIndata = true; } if (indata == "mem") { foreach(RSServer srv in srvs.GetRSServers()) { stls.AddSrez(srv.Id,srv.GetCurrSrez()); } IsIndata = true; } if(IsIndata) { foreach(Cnl cnl in Cnls) { Argument cArg = new Argument(cnl.ToString(),stls.GetCnlData(cnl.ID,cnl.Num)); CalcArgs.Add(cArg); } CalcArgs.AddRange(xArgs); List<Cnl> cnls = new List<Cnl>(); foreach(Argument arg in SendVals) { PrimitiveElement[] pes = CalcArgs.ToArray(); arg.addDefinitions(pes); Cnl cnl = new Cnl(arg.getArgumentName(),arg.getArgumentValue(),1); cnls.Add(cnl); arg.removeDefinitions(CalcArgs.ToArray()); } srvs.SendCurrSrez(cnls); } else{ Info("No set parametr indata"); } CalcArgs.Clear(); stls.ClearSrez(); } catch (ThreadAbortException) { throw; } catch (Exception ex) { InfoFormat ("An error RSSendValues: {0}", ex.Message); } Info("Task RSSendValues finished"); return new TaskStatus (Status.Success, false); }
/// <summary> /// Converts the chart data to JavaScript. /// </summary> public void ToJs(StringBuilder stringBuilder) { ArgumentNullException.ThrowIfNull(stringBuilder, nameof(stringBuilder)); // time range DateTime t1 = options.TimeRange.StartTime; DateTime t2 = options.TimeRange.EndTime; stringBuilder .AppendLine("var timeRange = new scada.chart.TimeRange();") .AppendFormat("timeRange.startTime = {0};", t1.GetUnixMilliseconds()).AppendLine() .AppendFormat("timeRange.endTime = {0};", t2.GetUnixMilliseconds()).AppendLine() .AppendLine() .AppendLine("var hourMap = timeRange.hourMap;"); DateTime startHour = new(t1.Year, t1.Month, t1.Day, t1.Hour, 0, 0, t1.Kind); DateTime endHour = new(t2.Year, t2.Month, t2.Day, t2.Hour, 0, 0, t2.Kind); DateTime curHour = startHour; while (curHour <= endHour) { stringBuilder.Append("hourMap.set(") .Append(curHour.GetUnixMilliseconds()).Append(", '") .Append(curHour.ToLocalTimeString(options.TimeZone)).AppendLine("');"); curHour = curHour.AddHours(1); } stringBuilder.AppendLine(); // time points stringBuilder .AppendLine("var chartData = new scada.chart.ChartData();") .Append("chartData.timePoints = "); if (singleTrend == null) { AppendTimestamps(stringBuilder, trendBundle); } else { AppendTimestamps(stringBuilder, singleTrend); } stringBuilder.AppendLine(";").AppendLine(); // trends StringBuilder sbTrends = new("chartData.trends = ["); for (int i = 0, cnlCnt = cnls.Length; i < cnlCnt; i++) { string trendName = "trend" + i; Cnl cnl = cnls[i]; sbTrends.Append(trendName).Append(", "); stringBuilder .Append("var ").Append(trendName).AppendLine(" = new scada.chart.Trend();") .Append(trendName).AppendFormat(".cnlNum = {0};", cnl.CnlNum).AppendLine() .Append(trendName).AppendFormat(".cnlName = '{0}';", cnl.Name.JsEncode()).AppendLine() .Append(trendName).AppendFormat(".quantityID = {0};", cnl.QuantityID ?? 0).AppendLine() .Append(trendName).AppendFormat(".quantityName = '{0}';", GetQuantityName(cnl).JsEncode()).AppendLine() .Append(trendName).AppendFormat(".unitName = '{0}';", GetUnitName(cnl).JsEncode()).AppendLine() .Append(trendName).Append(".points = "); if (singleTrend == null) { AppendTrendPoints(stringBuilder, trendBundle, i); } else { AppendTrendPoints(stringBuilder, singleTrend, cnl); } stringBuilder.AppendLine(";").AppendLine(); } sbTrends.AppendLine("];"); stringBuilder.Append(sbTrends).AppendLine(); // channel statuses stringBuilder.AppendLine("var statusMap = chartData.cnlStatusMap;"); foreach (CnlStatus cnlStatus in configDataset.CnlStatusTable.Enumerate()) { stringBuilder .AppendFormat("statusMap.set({0}, new scada.chart.CnlStatus({0}, '{1}', '{2}'));", cnlStatus.CnlStatusID, cnlStatus.Name.JsEncode(), cnlStatus.MainColor.JsEncode()) .AppendLine(); } stringBuilder.AppendLine(); }
/// <summary> /// Gets the unit name (with leading space) of the specified channel. /// </summary> private string GetUnitName(Cnl cnl) { Unit unit = cnl.UnitID == null ? null : configDataset.UnitTable.GetItem(cnl.UnitID.Value); return(unit?.Name ?? ""); }
/// <summary> /// Gets the quantity name and unit of the specified channel. /// </summary> private string GetQuantityName(Cnl cnl) { Quantity quantity = cnl.QuantityID == null ? null : configDataset.QuantityTable.GetItem(cnl.QuantityID.Value); return(quantity?.Name ?? ""); }