/// <summary> /// Gets the date and time value of the tag. /// </summary> public DateTime GetDateTime(int tagIndex) { CnlData cnlData = this[tagIndex]; if (cnlData.IsDefined) { DeviceTag deviceTag = deviceTags[tagIndex]; if (deviceTag.DataType == TagDataType.Int64) { return(new DateTime(BitConverter.DoubleToInt64Bits(cnlData.Val), DateTimeKind.Utc)); } else if (deviceTag.DataType == TagDataType.Double) { return(DateTime.FromOADate(cnlData.Val)); } } return(DateTime.MinValue); }
/// <summary> /// Sets the display values of the tags. /// </summary> private void SetDisplayValues() { if (deviceTags != null) { foreach (DeviceTag deviceTag in deviceTags) { int tagIndex = deviceTag.Index; dataView.SetDisplayValue(tagIndex, 0, FormatTagData(deviceTag)); if (deviceTag.IsNumericArray) { for (int i = 0, len = deviceTag.DataLength; i < len; i++) { CnlData cnlData = GetCnlData(tagIndex, i); dataView.SetDisplayValue(tagIndex, i + 1, FormatNumericData(deviceTag, cnlData)); } } } } }
/// <summary> /// Calculates the channel data. /// </summary> public CnlData CalcCnlData(CnlTag cnlTag, CnlData initialCnlData) { if (cnlTag != null && cnlTag.CalcEngine != null && cnlTag.CalcCnlDataFunc != null) { try { cnlTag.CalcEngine.BeginCalcCnlData(cnlTag.CnlNum, cnlTag.Cnl, initialCnlData); return(cnlTag.CalcCnlDataFunc()); } catch { return(new CnlData(initialCnlData.Val, CnlStatusID.FormulaError)); } finally { cnlTag.CalcEngine.EndCalcCnlData(); } } else { return(initialCnlData); } }
/// <summary> /// Writes the current data. /// </summary> protected void WriteCurrentData(ConnectedClient client, DataPacket request, out ResponsePacket response) { byte[] buffer = request.Buffer; int index = ArgumentIndex; int deviceNum = GetInt32(buffer, ref index); int cnlCnt = GetInt32(buffer, ref index); int[] cnlNums = new int[cnlCnt]; CnlData[] cnlData = new CnlData[cnlCnt]; for (int i = 0, idx1 = index, idx2 = idx1 + cnlCnt * 4; i < cnlCnt; i++) { cnlNums[i] = GetInt32(buffer, ref idx1); cnlData[i] = GetCnlData(buffer, ref idx2); } index += cnlCnt * 14; bool applyFormulas = buffer[index] > 0; coreLogic.WriteCurrentData(deviceNum, cnlNums, cnlData, applyFormulas); response = new ResponsePacket(request, client.OutBuf); }
/// <summary> /// Gets a double-precision floating point number from the buffer. /// </summary> public static double GetDouble(CnlData[] buffer, int index) { CnlData cnlData = buffer[index]; return(cnlData.IsDefined ? cnlData.Val : 0.0); }
/// <summary> /// Enqueues a data point without locking the queue. /// </summary> public void EnqueueWithoutLock(int cnlNum, DateTime timestamp, CnlData cnlData) { dataQueue.Enqueue(new CnlDataPoint(cnlNum, timestamp, cnlData)); }
/// <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 channel data according to the specified data type and format. /// </summary> public CnlDataFormatted FormatCnlData(CnlData cnlData, int dataTypeID, int formatID, int unitID) { CnlDataFormatted cnlDataFormatted = new CnlDataFormatted(); Format format = formatID > 0 ? configDataset.FormatTable.GetItem(formatID) : null; Unit unit = unitID > 0 ? configDataset.UnitTable.GetItem(unitID) : null; EnumFormat enumFormat = null; if (format != null && format.IsEnum) { enums.TryGetValue(format.FormatID, out enumFormat); } // displayed value try { if (cnlData.IsUndefined) { cnlDataFormatted.DispVal = CommonPhrases.UndefinedSign; } else if (format == null) { cnlDataFormatted.DispVal = FormatByDataType(cnlData.Val, dataTypeID); } else if (format.IsNumber) { cnlDataFormatted.DispVal = FormatNumber(cnlData.Val, dataTypeID, format.Frmt); } else if (format.IsEnum) { cnlDataFormatted.DispVal = FormatEnum(cnlData.Val, dataTypeID, enumFormat); } else if (format.IsDate) { cnlDataFormatted.DispVal = FormatDate(cnlData.Val, dataTypeID, format.Frmt); } else // format.IsString or not specified { cnlDataFormatted.DispVal = FormatByDataType(cnlData.Val, dataTypeID); } if (!string.IsNullOrEmpty(unit?.Name)) { cnlDataFormatted.DispVal += " " + unit.Name; } } catch { cnlDataFormatted.DispVal = FormatError; } // color try { // color determined by status CnlStatus cnlStatus = configDataset.CnlStatusTable.GetItem(cnlData.Stat); cnlDataFormatted.SetColors(cnlStatus); // color determined by value if (enumFormat != null && cnlData.Stat == CnlStatusID.Defined && 0 <= cnlData.Val && cnlData.Val < enumFormat.Colors.Length && enumFormat.Colors[(int)cnlData.Val] is string color && color != "") { cnlDataFormatted.SetFirstColor(color); } } catch { cnlDataFormatted.SetColorsToDefault(); } return(cnlDataFormatted); }
/// <summary> /// Sets the integer value and status of the tag. /// </summary> public void SetInt64(string tagCode, long val, int stat) { this[tagCode] = new CnlData(BitConverter.Int64BitsToDouble(val), stat); }
/// <summary> /// Sets the floating point value and status of the tag. /// </summary> public void Set(string tagCode, double val, int stat) { this[tagCode] = new CnlData(val, stat); }
/// <summary> /// Sets the input channel data. /// </summary> public void SetCnlData(int cnlNum, CnlData cnlData) { archiveLogic.WriteCnlData(cnlNum, Timestamp, cnlData); }
/// <summary> /// Copies the input channel data to the buffer. /// </summary> public static void CopyCnlData(CnlData cnlData, byte[] buffer, ref int index) { CopyDouble(cnlData.Val, buffer, ref index); CopyUInt16((ushort)cnlData.Stat, buffer, ref index); }
/// <summary> /// Writes the input channel data. /// </summary> public abstract void WriteCnlData(int cnlNum, DateTime timestamp, CnlData cnlData);
/// <summary> /// Converts the current tag data with a numeric data type to a string value. /// </summary> private string FormatNumericData(DeviceTag deviceTag, CnlData cnlData) { if (cnlData.IsUndefined) { return(CommonPhrases.UndefinedSign); } const string DefaultFormat = "N3"; try { TagFormat tagFormat = deviceTag.Format; if (tagFormat == null) { return(deviceTag.DataType == TagDataType.Int64 ? BitConverter.DoubleToInt64Bits(cnlData.Val).ToString() : cnlData.Val.ToString(DefaultFormat)); } else { string FormatEnum(int val) { return(tagFormat.EnumValues != null && 0 <= val && val < tagFormat.EnumValues.Length ? tagFormat.EnumValues[val] : val.ToString()); } bool FormatIsHex(string format) { return(format[0] == 'x' || format[0] == 'X'); } if (deviceTag.DataType == TagDataType.Int64) { long longVal = BitConverter.DoubleToInt64Bits(cnlData.Val); switch (tagFormat.FormatType) { case TagFormatType.Enum: return(FormatEnum((int)longVal)); case TagFormatType.Date: DateTime dt = new DateTime(longVal, DateTimeKind.Utc).ToLocalTime(); return(string.IsNullOrEmpty(tagFormat.Format) ? dt.ToLocalizedString() : dt.ToString(tagFormat.Format)); default: if (string.IsNullOrEmpty(tagFormat.Format)) { return(longVal.ToString()); } else { string s = longVal.ToString(tagFormat.Format); return(FormatIsHex(tagFormat.Format) ? s + 'h' : s); } } } else { double doubleVal = cnlData.Val; switch (tagFormat.FormatType) { case TagFormatType.Enum: return(FormatEnum((int)doubleVal)); case TagFormatType.Date: DateTime dt = DateTime.FromOADate(doubleVal).ToLocalTime(); return(string.IsNullOrEmpty(tagFormat.Format) ? dt.ToLocalizedString() : dt.ToString(tagFormat.Format)); default: return(string.IsNullOrEmpty(tagFormat.Format) ? doubleVal.ToString(DefaultFormat) : FormatIsHex(tagFormat.Format) ? ((int)doubleVal).ToString(tagFormat.Format) + 'h' : doubleVal.ToString(tagFormat.Format)); } } } } catch { return(cnlData.Val.ToString(DefaultFormat)); } }
/// <summary> /// Установить данные входного канала по номеру /// </summary> public bool SetCnlData(int cnlNum, CnlData cnlData) { int index = GetCnlIndex(cnlNum); if (index < 0) { return false; } else { CnlData[index] = cnlData; return true; } }
/// <summary> /// Reads a single slice from a file or stream. /// </summary> public Slice ReadSingleSlice() { Stream stream; BinaryReader reader = null; try { stream = Stream ?? new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); reader = new BinaryReader(stream, Encoding.UTF8, Stream != null); // read header byte[] buffer = new byte[HeaderSize]; if (!ReadHeader(reader, buffer)) { return(null); } // read the first slice if (reader.ReadUInt16() != BlockMarker) { throw new ScadaException("Slice marker not found."); } DateTime timestamp = ScadaUtils.TicksToTime(reader.ReadInt64()); int cnlCnt = reader.ReadInt32(); if (cnlCnt > 0) { // read channel numbers int cnlDataSize = cnlCnt * 10; int cnlNumsSize = cnlCnt * 4; buffer = new byte[cnlDataSize]; ReadData(reader, buffer, 0, cnlNumsSize + 4, true); int[] cnlNums = new int[cnlCnt]; Buffer.BlockCopy(buffer, 0, cnlNums, 0, cnlNumsSize); if (ScadaUtils.CRC32(buffer, 0, cnlNumsSize) != BitConverter.ToUInt32(buffer, cnlNumsSize)) { throw new ScadaException("CRC error."); } // read channel data ReadData(reader, buffer, 0, cnlDataSize, true); CnlData[] cnlData = new CnlData[cnlCnt]; for (int i = 0, index = 0; i < cnlCnt; i++) { cnlData[i] = GetCnlData(buffer, ref index); } return(new Slice(timestamp, cnlNums, cnlData)); } else if (cnlCnt == 0) { return(new Slice(timestamp, 0)); } else { throw new ScadaException("Invalid channel count."); } } catch (EndOfStreamException) { // unable to read slice return(null); } finally { reader?.Close(); } }
/// <summary> /// Sets the floating point value and status of the tag. /// </summary> public void Set(int tagIndex, double val, int stat) { this[tagIndex] = new CnlData(val, stat); }
/// <summary> /// Writes the current data of the input channel. /// </summary> public void WriteCurrentData(int cnlNum, CnlData cnlData) { coreLogic.WriteCurrentData(0, new int[] { cnlNum }, new CnlData[] { cnlData }, true); }
/// <summary> /// Sets the integer value and status of the tag. /// </summary> public void SetInt64(int tagIndex, long val, int stat) { this[tagIndex] = new CnlData(BitConverter.Int64BitsToDouble(val), stat); }
/// <summary> /// Converts the device slice to a general purpose slice. /// </summary> private bool ConvertSlice(DeviceSlice srcSlice, out Slice destSlice) { try { int srcDataLength = srcSlice.CnlData.Length; int destDataLength = 0; List <int> cnlNums = new List <int>(srcDataLength); foreach (DeviceTag deviceTag in srcSlice.DeviceTags) { if (deviceTag == null) { throw new ScadaException(Locale.IsRussian ? "Неопределенные теги в срезе не допускаются." : "Undefined tags are not allowed in a slice."); } if (deviceTag.Cnl != null) { int tagDataLength = deviceTag.DataLength; for (int i = 0; i < tagDataLength; i++) { cnlNums.Add(deviceTag.Cnl.CnlNum + i); } destDataLength += tagDataLength; } } if (destDataLength == 0) { destSlice = null; return(false); } else if (destDataLength == srcDataLength) { destSlice = new Slice(srcSlice.Timestamp, cnlNums.ToArray(), srcSlice.CnlData); return(true); } else { CnlData[] destCnlData = new CnlData[destDataLength]; int srcDataIndex = 0; int destDataIndex = 0; foreach (DeviceTag deviceTag in srcSlice.DeviceTags) { int tagDataLength = deviceTag.DataLength; if (deviceTag.Cnl != null) { Array.Copy(srcSlice.CnlData, srcDataIndex, destCnlData, destDataIndex, tagDataLength); destDataIndex += tagDataLength; } srcDataIndex += tagDataLength; } destSlice = new Slice(srcSlice.Timestamp, cnlNums.ToArray(), destCnlData); return(true); } } catch (Exception ex) { log.WriteError(ex, CommPhrases.DataSourceMessage, Code, string.Format(Locale.IsRussian ? "Ошибка при конвертировании среза от устройства {0}" : "Error converting slice from the device {0}", srcSlice.DeviceNum)); destSlice = null; return(false); } }
/// <summary> /// Processes new data. /// </summary> /// <remarks>Returns true if the data has been written to the archive.</remarks> public override bool ProcessData(ICurrentData curData) { if (archiveOptions.WritingMode == WritingMode.AutoWithPeriod) { if (nextWriteTime <= curData.Timestamp) { DateTime writeTime = GetClosestWriteTime(curData.Timestamp, writingPeriod); nextWriteTime = writeTime.AddSeconds(writingPeriod); stopwatch.Restart(); InitCnlIndexes(curData, ref cnlIndexes); int cnlCnt = CnlNums.Length; lock (pointQueue.SyncRoot) { for (int i = 0; i < cnlCnt; i++) { pointQueue.EnqueueWithoutLock(CnlNums[i], writeTime, curData.CnlData[cnlIndexes[i]]); } } pointQueue.RemoveExcessPoints(); stopwatch.Stop(); arcLog?.WriteAction(ServerPhrases.QueueingPointsCompleted, cnlCnt, stopwatch.ElapsedMilliseconds); return(true); } } else if (archiveOptions.WritingMode == WritingMode.AutoOnChange) { stopwatch.Restart(); int changesCnt = 0; bool firstTime = cnlIndexes == null; InitCnlIndexes(curData, ref cnlIndexes); if (firstTime) { // do not write data for the first time for (int i = 0, cnlCnt = CnlNums.Length; i < cnlCnt; i++) { prevCnlData[i] = curData.CnlData[cnlIndexes[i]]; } } else { for (int i = 0, cnlCnt = CnlNums.Length; i < cnlCnt; i++) { CnlData curCnlData = curData.CnlData[cnlIndexes[i]]; if (prevCnlData[i] != curCnlData) { pointQueue.EnqueuePoint(CnlNums[i], curData.Timestamp, curCnlData); prevCnlData[i] = curCnlData; changesCnt++; } } } if (changesCnt > 0) { pointQueue.RemoveExcessPoints(); stopwatch.Stop(); arcLog?.WriteAction(ServerPhrases.QueueingPointsCompleted, changesCnt, stopwatch.ElapsedMilliseconds); return(true); } else { stopwatch.Stop(); } } return(false); }
/// <summary> /// Converts the current tag data with a numeric data type to a string value. /// </summary> private string FormatNumericData(DeviceTag deviceTag, CnlData cnlData) { if (cnlData.IsUndefined) { return(CommonPhrases.UndefinedSign); } const string DefaultFormat = "N3"; try { TagFormat tagFormat = deviceTag.Format; if (tagFormat == null) { return(deviceTag.DataType == TagDataType.Int64 ? BitConverter.DoubleToInt64Bits(cnlData.Val).ToString() : cnlData.Val.ToString(DefaultFormat)); } else { string FormatEnum(int val) { string[] enumValues = tagFormat.EnumValues; if (enumValues == null) { return(val.ToString()); } else if (val < 0) { return(enumValues[0]); } else if (val >= enumValues.Length) { return(enumValues[enumValues.Length - 1]); } else { return(enumValues[val]); } } if (deviceTag.DataType == TagDataType.Int64) { long longVal = BitConverter.DoubleToInt64Bits(cnlData.Val); switch (tagFormat.FormatType) { case TagFormatType.Enum: return(FormatEnum((int)longVal)); case TagFormatType.Date: DateTime dt = new DateTime(longVal, DateTimeKind.Utc).ToLocalTime(); return(string.IsNullOrEmpty(tagFormat.Format) ? dt.ToLocalizedString() : dt.ToString(tagFormat.Format)); default: return(string.IsNullOrEmpty(tagFormat.Format) ? longVal.ToString() : longVal.ToString(tagFormat.Format)); } } else { double doubleVal = cnlData.Val; switch (tagFormat.FormatType) { case TagFormatType.Enum: return(FormatEnum((int)doubleVal)); case TagFormatType.Date: DateTime dt = DateTime.FromOADate(doubleVal); return(string.IsNullOrEmpty(tagFormat.Format) ? dt.ToLocalizedString() : dt.ToString(tagFormat.Format)); default: return(string.IsNullOrEmpty(tagFormat.Format) ? doubleVal.ToString() : doubleVal.ToString(tagFormat.Format)); } } } } catch { return(cnlData.Val.ToString(DefaultFormat)); } }
/// <summary> /// Merges the trends providing a single timeline. /// </summary> public static TrendBundle MergeTrends(IList <Trend> trends) { if (trends == null) { throw new ArgumentNullException(nameof(trends)); } // simple cases first int cnlCnt = trends.Count; if (cnlCnt == 0) { return(new TrendBundle(0, 0)); } if (cnlCnt == 1) { return(CreateTrendBundle(trends[0])); } // full case int maxTrendCapacity = 0; int[] cnlNums = new int[cnlCnt]; int[] trendPositions = new int[cnlCnt]; // trend reading positions for (int i = 0; i < cnlCnt; i++) { Trend trend = trends[i]; cnlNums[i] = trend.CnlNum; trendPositions[i] = 0; if (maxTrendCapacity < trend.Points.Count) { maxTrendCapacity = trend.Points.Count; } } const double CapacityRatio = 1.1; TrendBundle trendBundle = new TrendBundle(cnlNums, (int)(maxTrendCapacity * CapacityRatio)); while (true) { // determine the minimum timestamp at trend reading positions DateTime minTimestamp = DateTime.MaxValue; bool endReached = true; for (int i = 0; i < cnlCnt; i++) { List <TrendPoint> trendPoints = trends[i].Points; int trendPos = trendPositions[i]; if (trendPos < trendPoints.Count) { endReached = false; DateTime pointTimestamp = trendPoints[trendPos].Timestamp; if (minTimestamp > pointTimestamp) { minTimestamp = pointTimestamp; } } } if (endReached) { break; } // copy data with found timestamp trendBundle.Timestamps.Add(minTimestamp); for (int i = 0; i < cnlCnt; i++) { Trend trend = trends[i]; int trendPos = trendPositions[i]; CnlData cnlData = CnlData.Empty; if (trendPos < trend.Points.Count) { TrendPoint trendPoint = trend.Points[trendPos]; if ((trendPoint.Timestamp - minTimestamp).TotalMilliseconds < TimeDiscreteness) { cnlData = new CnlData(trendPoint.Val, trendPoint.Stat); trendPositions[i]++; } } trendBundle.Trends[i].Add(cnlData); } } return(trendBundle); }
/// <summary> /// Gets the floating point value of the tag. /// </summary> public double Get(int tagIndex) { CnlData cnlData = this[tagIndex]; return(cnlData.IsDefined ? cnlData.Val : 0.0); }
/// <summary> /// Formats the channel data according to the channel properties. /// </summary> public CnlDataFormatted FormatCnlData(CnlData cnlData, int cnlNum, bool appendUnit) { return(FormatCnlData(cnlData, cnlNum > 0 ? configDataset.CnlTable.GetItem(cnlNum) : null, appendUnit)); }
/// <summary> /// Gets the floating point value of the tag. /// </summary> public double Get(string tagCode) { CnlData cnlData = this[tagCode]; return(cnlData.IsDefined ? cnlData.Val : 0.0); }
/// <summary> /// Performs the necessary actions after the calculation of the channel data. /// </summary> public void EndCalcCnlData() { cnlNum = 0; cnl = null; initialCnlData = CnlData.Empty; }
/// <summary> /// Gets the integer value of the tag. /// </summary> public long GetInt64(int tagIndex) { CnlData cnlData = this[tagIndex]; return(cnlData.IsDefined ? BitConverter.DoubleToInt64Bits(cnlData.Val) : 0); }
/// <summary> /// Writes the channel data. /// </summary> public override void WriteCnlData(DateTime timestamp, int cnlNum, CnlData cnlData) { adapter.WriteCnlData(GetTrendTable(timestamp), timestamp, cnlNum, cnlData); }
/// <summary> /// Gets the integer value of the tag. /// </summary> public long GetInt64(string tagCode) { CnlData cnlData = this[tagCode]; return(cnlData.IsDefined ? BitConverter.DoubleToInt64Bits(cnlData.Val) : 0); }
/// <summary> /// Gets a 64-bit signed integer from the buffer. /// </summary> public static long GetInt64(CnlData[] buffer, int index) { CnlData cnlData = buffer[index]; return(cnlData.IsDefined ? BitConverter.DoubleToInt64Bits(cnlData.Val) : 0); }
/// <summary> /// Конструктор /// </summary> public Srez(DateTime dateTime, SrezDescr srezDescr) { if (srezDescr == null) throw new ArgumentNullException("srezDescr"); DateTime = dateTime; int cnlCnt = srezDescr.CnlNums.Length; CnlNums = new int[cnlCnt]; srezDescr.CnlNums.CopyTo(CnlNums, 0); CnlData = new CnlData[cnlCnt]; SrezDescr = srezDescr; State = DataRowState.Detached; Position = -1; }