/// <summary> /// Decodes the received tag value and returns the tag type. /// </summary> private double DecodeItemVal(object val, out TagType tagType) { try { if (val is string) { tagType = TagType.String; return(ScadaUtils.EncodeAscii((string)val)); } else if (val is DateTime) { tagType = TagType.DateTime; return(ScadaUtils.EncodeDateTime((DateTime)val)); } else { tagType = TagType.Number; return(Convert.ToDouble(val)); } } catch (Exception ex) { WriteToLog((Localization.UseRussian ? "Ошибка при декодировании элемента: " : "Error decoding item: ") + ex); tagType = TagType.Number; return(0.0); } }
/// <summary> /// Decodes the specified object and converts it to a tag data. /// </summary> private SrezTableLight.CnlData DecodeTag(object val, out TagType tagType) { try { if (val == DBNull.Value) { tagType = TagType.Number; return(SrezTableLight.CnlData.Empty); } else if (val is string) { tagType = TagType.String; return(new SrezTableLight.CnlData(ScadaUtils.EncodeAscii((string)val), BaseValues.CnlStatuses.Defined)); } else if (val is DateTime) { tagType = TagType.DateTime; return(new SrezTableLight.CnlData(ScadaUtils.EncodeDateTime((DateTime)val), BaseValues.CnlStatuses.Defined)); } else { tagType = TagType.Number; return(new SrezTableLight.CnlData(Convert.ToDouble(val), BaseValues.CnlStatuses.Defined)); } } catch { tagType = TagType.Number; return(SrezTableLight.CnlData.Empty); } }
/// <summary> /// Create a single-slice table in a file or stream /// </summary> /// <remarks>To record the current slice table</remarks> public void Create(SrezTable.Srez srez, DateTime srezDT) { if (srez == null) { throw new ArgumentNullException(nameof(srez)); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream ?? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); writer = new BinaryWriter(stream); writer.Write(GetSrezDescrBuf(srez.SrezDescr)); writer.Write(ScadaUtils.EncodeDateTime(srezDT)); writer.Write(GetCnlDataBuf(srez.CnlData)); stream.SetLength(stream.Position); } finally { if (fileMode) { writer?.Close(); stream?.Close(); } } }
/// <summary> /// Decodes the received array and returns the tag type. /// </summary> private double[] DecodeArray(object val, int len, out TagType tagType) { double[] outArr = new double[len]; tagType = TagType.Number; try { // get the type of the 1st element Array inArr = (Array)val; if (inArr.Length > 0) { object firstItem = inArr.GetValue(0); if (firstItem is string) { tagType = TagType.String; } else if (firstItem is DateTime) { tagType = TagType.DateTime; } } // decode array elements for (int i = 0, n = Math.Min(inArr.Length, len); i < n; i++) { object inVal = inArr.GetValue(i); double outVal; switch (tagType) { case TagType.String: outVal = ScadaUtils.EncodeAscii((string)inVal); break; case TagType.DateTime: outVal = ScadaUtils.EncodeDateTime((DateTime)inVal); break; default: outVal = Convert.ToDouble(inVal); break; } outArr[i] = outVal; } } catch (Exception ex) { WriteToLog((Localization.UseRussian ? "Ошибка при декодировании массива: " : "Error decoding array: ") + ex); } return(outArr); }
/// <summary> /// Получить метки времени одиночного тренда в виде JavaScript. /// </summary> protected string GetTimePointsJs(Trend trend) { StringBuilder sbTimePoints = new StringBuilder("["); if (trend != null) { foreach (Trend.Point point in trend.Points) { sbTimePoints.Append(ScadaUtils.EncodeDateTime(point.DateTime) .ToString(CultureInfo.InvariantCulture)).Append(", "); } } sbTimePoints.Append("]"); return(sbTimePoints.ToString()); }
/// <summary> /// Converts the chart data to JavaScript. /// </summary> public void ToJs(StringBuilder stringBuilder) { // интервал времени int startDateEnc = (int)ScadaUtils.EncodeDateTime(startDate); stringBuilder .AppendLine("var timeRange = new scada.chart.TimeRange();") .AppendFormat("timeRange.startTime = {0};", startDateEnc).AppendLine() .AppendFormat("timeRange.endTime = {0};", startDateEnc + period).AppendLine() .AppendLine(); // данные графика StringBuilder sbTrends = new StringBuilder("["); bool isSingle = singleTrend != null; for (int i = 0; i < cnlCnt; i++) { string trendName = "trend" + i; InCnlProps cnlProps = cnlPropsArr[i] ?? new InCnlProps() { CnlNum = cnlNums[i] }; sbTrends.Append(trendName).Append(", "); stringBuilder .Append("var ").Append(trendName).AppendLine(" = new scada.chart.Trend();") .Append(trendName).AppendFormat(".cnlNum = {0};", cnlProps.CnlNum).AppendLine() .Append(trendName).AppendFormat(".cnlName = '{0}';", HttpUtility.JavaScriptStringEncode(cnlProps.CnlName)).AppendLine() .Append(trendName).AppendFormat(".quantityID = {0};", cnlProps.ParamID).AppendLine() .Append(trendName).AppendFormat(".quantityName = '{0}';", HttpUtility.JavaScriptStringEncode(GetQuantityName(cnlProps))).AppendLine() .Append(trendName).AppendFormat(".trendPoints = {0};", isSingle ? GetTrendPointsJs(singleTrend, cnlPropsArr[i]) : GetTrendPointsJs(trendBundle, i)) .AppendLine() .AppendLine(); } sbTrends.Append("];"); stringBuilder .AppendLine("var chartData = new scada.chart.ChartData();") .Append("chartData.timePoints = ") .Append(isSingle ? GetTimePointsJs(singleTrend) : GetTimePointsJs(trendBundle)).AppendLine(";") .Append("chartData.trends = ").Append(sbTrends).AppendLine() .AppendLine(); }
/// <summary> /// Получить метки времени связки трендов в виде JavaScript. /// </summary> protected string GetTimePointsJs(TrendBundle trendBundle) { StringBuilder sbTimePoints = new StringBuilder("["); if (trendBundle != null) { foreach (TrendBundle.Point point in trendBundle.Series) { double time = point.DateTime.TimeOfDay.TotalDays; sbTimePoints.Append(ScadaUtils.EncodeDateTime(point.DateTime) .ToString(CultureInfo.InvariantCulture)).Append(", "); } } sbTimePoints.Append("]"); return(sbTimePoints.ToString()); }
/// <summary> /// Записать значение в буффер строки таблицы /// </summary> protected void WriteValueToRowBuffer(FieldDef fieldDef, object val, byte[] rowBuf, ref int bufInd) { bool isNull = val == null || val == DBNull.Value; if (fieldDef.AllowNull) { rowBuf[bufInd++] = isNull ? (byte)1 : (byte)0; } switch (fieldDef.DataType) { case DataTypes.Integer: int intVal = isNull ? 0 : (int)val; Array.Copy(BitConverter.GetBytes(intVal), 0, rowBuf, bufInd, fieldDef.DataSize); break; case DataTypes.Double: double dblVal = isNull ? 0.0 : (double)val; Array.Copy(BitConverter.GetBytes(dblVal), 0, rowBuf, bufInd, fieldDef.DataSize); break; case DataTypes.Boolean: rowBuf[bufInd] = (byte)(isNull ? 0 : (bool)val ? 1 : 0); break; case DataTypes.DateTime: double dtVal = isNull ? 0.0 : ScadaUtils.EncodeDateTime((DateTime)val); Array.Copy(BitConverter.GetBytes(dtVal), 0, rowBuf, bufInd, fieldDef.DataSize); break; default: string strVal = isNull ? "" : val.ToString(); ConvertStr(strVal, fieldDef.MaxStrLen, fieldDef.DataSize, rowBuf, bufInd, Encoding.UTF8); break; } bufInd += fieldDef.DataSize; }
/// <summary> /// Create buffer for event recording /// </summary> protected byte[] CreateEventBuffer(EventTableLight.Event ev) { var evBuf = new byte[EventDataSize]; Array.Copy(BitConverter.GetBytes(ScadaUtils.EncodeDateTime(ev.DateTime)), 0, evBuf, 0, 8); evBuf[8] = (byte)(ev.ObjNum % 256); evBuf[9] = (byte)(ev.ObjNum / 256); evBuf[10] = (byte)(ev.KPNum % 256); evBuf[11] = (byte)(ev.KPNum / 256); evBuf[12] = (byte)(ev.ParamID % 256); evBuf[13] = (byte)(ev.ParamID / 256); evBuf[14] = (byte)(ev.CnlNum % 256); evBuf[15] = (byte)(ev.CnlNum / 256); Array.Copy(BitConverter.GetBytes(ev.OldCnlVal), 0, evBuf, 16, 8); evBuf[24] = (byte)ev.OldCnlStat; Array.Copy(BitConverter.GetBytes(ev.NewCnlVal), 0, evBuf, 25, 8); evBuf[33] = (byte)ev.NewCnlStat; evBuf[34] = ev.Checked ? (byte)1 : (byte)0; evBuf[35] = (byte)(ev.UserID % 256); evBuf[36] = (byte)(ev.UserID / 256); string descr = ev.Descr ?? ""; if (descr.Length > MaxDescrLen) { descr = descr.Substring(0, MaxDescrLen); } evBuf[37] = (byte)descr.Length; Array.Copy(Encoding.Default.GetBytes(descr), 0, evBuf, 38, descr.Length); string data = ev.Data ?? ""; if (data.Length > MaxDataLen) { data = data.Substring(0, MaxDataLen); } evBuf[138] = (byte)data.Length; Array.Copy(Encoding.Default.GetBytes(data), 0, evBuf, 139, data.Length); return(evBuf); }
/// <summary> /// Создать буфер для записи события /// </summary> protected byte[] CreateEventBuffer(EventTableLight.Event ev) { byte[] evBuf = new byte[EventDataSize]; Array.Copy(BitConverter.GetBytes(ScadaUtils.EncodeDateTime(ev.DateTime)), 0, evBuf, 0, 8); evBuf[8] = (byte)(ev.ObjNum % 256); evBuf[9] = (byte)(ev.ObjNum / 256); evBuf[10] = (byte)(ev.KPNum % 256); evBuf[11] = (byte)(ev.KPNum / 256); evBuf[12] = (byte)(ev.ParamID % 256); evBuf[13] = (byte)(ev.ParamID / 256); evBuf[14] = (byte)(ev.CnlNum % 256); evBuf[15] = (byte)(ev.CnlNum / 256); Array.Copy(BitConverter.GetBytes(ev.OldCnlVal), 0, evBuf, 16, 8); evBuf[24] = (byte)ev.OldCnlStat; Array.Copy(BitConverter.GetBytes(ev.NewCnlVal), 0, evBuf, 25, 8); evBuf[33] = (byte)ev.NewCnlStat; evBuf[34] = ev.Checked ? (byte)1 : (byte)0; evBuf[35] = (byte)(ev.UserID % 256); evBuf[36] = (byte)(ev.UserID / 256); StrToBytes(ev.Descr, evBuf, 37, MaxDescrLen); StrToBytes(ev.Data, evBuf, 138, MaxDataLen); return(evBuf); }
/// <summary> /// Записать изменения таблицы срезов в файл или поток /// </summary> public void Update(SrezTable srezTable) { if (srezTable == null) { throw new ArgumentNullException("srezTable"); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream == null ? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) : ioStream; writer = new BinaryWriter(stream); // запись изменённых срезов foreach (SrezTable.Srez srez in srezTable.ModifiedSrezList) { stream.Seek(srez.Position + 8, SeekOrigin.Begin); writer.Write(GetCnlDataBuf(srez.CnlData)); } // установка позиции записи добавленных срезов в поток, // восстановление таблицы срезов в случае необходимости SrezTable.Srez lastSrez = srezTable.LastStoredSrez; if (lastSrez == null) { stream.Seek(0, SeekOrigin.Begin); } else { stream.Seek(0, SeekOrigin.End); long offset = lastSrez.Position + lastSrez.CnlNums.Length * 9 + 8; if (stream.Position < offset) { byte[] buf = new byte[offset - stream.Position]; stream.Write(buf, 0, buf.Length); } else { stream.Seek(offset, SeekOrigin.Begin); } } // запись добавленных срезов SrezTable.SrezDescr prevSrezDescr = lastSrez == null ? null : lastSrez.SrezDescr; foreach (SrezTable.Srez srez in srezTable.AddedSrezList) { // запись номеров каналов среза if (srez.SrezDescr.Equals(prevSrezDescr)) { writer.Write(EmptyCnlNumsBuf); } else { writer.Write(GetSrezDescrBuf(srez.SrezDescr)); } prevSrezDescr = srez.SrezDescr; // запись данных среза srez.Position = stream.Position; writer.Write(ScadaUtils.EncodeDateTime(srez.DateTime)); writer.Write(GetCnlDataBuf(srez.CnlData)); lastSrez = srez; } // подтверждение успешного сохранения изменений srezTable.AcceptChanges(); srezTable.LastStoredSrez = lastSrez; } finally { if (fileMode) { if (writer != null) { writer.Close(); } if (stream != null) { stream.Close(); } } } }
/// <summary> /// Write changes to the slicing table to a file or stream. /// </summary> public void Update(SrezTable srezTable) { if (srezTable == null) { throw new ArgumentNullException(nameof(srezTable)); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream ?? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); writer = new BinaryWriter(stream); // record modified slices foreach (var srez in srezTable.ModifiedSrezList) { stream.Seek(srez.Position + 8, SeekOrigin.Begin); writer.Write(GetCnlDataBuf(srez.CnlData)); } // setting the recording position of the added slices to the stream, // restore slice table if necessary var lastSrez = srezTable.LastStoredSrez; if (lastSrez == null) { stream.Seek(0, SeekOrigin.Begin); } else { stream.Seek(0, SeekOrigin.End); long offset = lastSrez.Position + lastSrez.CnlNums.Length * 9 + 8; if (stream.Position < offset) { var buf = new byte[offset - stream.Position]; stream.Write(buf, 0, buf.Length); } else { stream.Seek(offset, SeekOrigin.Begin); } } // record added slices var prevSrezDescr = lastSrez?.SrezDescr; foreach (var srez in srezTable.AddedSrezList) { // recording cutoff channel numbers writer.Write(srez.SrezDescr.Equals(prevSrezDescr) ? EmptyCnlNumsBuf : GetSrezDescrBuf(srez.SrezDescr)); prevSrezDescr = srez.SrezDescr; // slice data entry srez.Position = stream.Position; writer.Write(ScadaUtils.EncodeDateTime(srez.DateTime)); writer.Write(GetCnlDataBuf(srez.CnlData)); lastSrez = srez; } // confirmation of successful saving of changes srezTable.AcceptChanges(); srezTable.LastStoredSrez = lastSrez; } finally { if (fileMode) { writer?.Close(); stream?.Close(); } } }
/// <summary> /// Записать таблицу dataTable в файл или поток /// </summary> public void Update(DataTable dataTable) { if (dataTable == null) { throw new ArgumentNullException("dataTable"); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream == null ? new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite) : ioStream; writer = new BinaryWriter(stream, Encoding.Default); // запись заголовка byte fieldCnt = dataTable.Columns.Count > byte.MaxValue ? byte.MaxValue : (byte)dataTable.Columns.Count; writer.Write(fieldCnt); writer.Write((ushort)0); // резерв if (fieldCnt > 0) { // формирование и запись определений полей FieldDef[] fieldDefs = new FieldDef[fieldCnt]; int recSize = 2; // размер строки в файле byte[] fieldDefBuf = new byte[FieldDefSize]; fieldDefBuf[FieldDefSize - 1] = fieldDefBuf[FieldDefSize - 2] = 0; // резерв for (int i = 0; i < fieldCnt; i++) { FieldDef fieldDef = new FieldDef(); DataColumn col = dataTable.Columns[i]; Type type = col.DataType; if (type == typeof(int)) { fieldDef.DataType = DataTypes.Integer; fieldDef.DataSize = sizeof(int); fieldDef.MaxStrLen = 0; } else if (type == typeof(double)) { fieldDef.DataType = DataTypes.Double; fieldDef.DataSize = sizeof(double); fieldDef.MaxStrLen = 0; } else if (type == typeof(bool)) { fieldDef.DataType = DataTypes.Boolean; fieldDef.DataSize = 1; fieldDef.MaxStrLen = 0; } else if (type == typeof(DateTime)) { fieldDef.DataType = DataTypes.DateTime; fieldDef.DataSize = sizeof(double); fieldDef.MaxStrLen = 0; } else // String { fieldDef.DataType = DataTypes.String; int maxLen = Math.Min(col.MaxLength, MaxStringLen); fieldDef.DataSize = 2 /*запись длины*/ + Encoding.UTF8.GetMaxByteCount(maxLen); fieldDef.MaxStrLen = maxLen; } fieldDef.Name = col.ColumnName; fieldDef.AllowNull = col.AllowDBNull; recSize += fieldDef.DataSize; if (fieldDef.AllowNull) { recSize++; } fieldDefs[i] = fieldDef; fieldDefBuf[0] = (byte)fieldDef.DataType; Array.Copy(BitConverter.GetBytes((ushort)fieldDef.DataSize), 0, fieldDefBuf, 1, 2); Array.Copy(BitConverter.GetBytes((ushort)fieldDef.MaxStrLen), 0, fieldDefBuf, 3, 2); fieldDefBuf[5] = fieldDef.AllowNull ? (byte)1 : (byte)0; ConvertStr(fieldDef.Name, MaxFieldNameLen, MaxFieldNameDataSize, fieldDefBuf, 6, Encoding.ASCII); writer.Write(fieldDefBuf); } // запись строк byte[] rowBuf = new byte[recSize]; rowBuf[0] = rowBuf[1] = 0; // резерв foreach (DataRowView rowView in dataTable.DefaultView) { DataRow row = rowView.Row; int bufInd = 2; foreach (FieldDef fieldDef in fieldDefs) { int colInd = dataTable.Columns.IndexOf(fieldDef.Name); object val = colInd >= 0 ? row[colInd] : null; bool isNull = val == null || val == DBNull.Value; if (fieldDef.AllowNull) { rowBuf[bufInd++] = isNull ? (byte)1 : (byte)0; } switch (fieldDef.DataType) { case DataTypes.Integer: int intVal = isNull ? 0 : (int)val; Array.Copy(BitConverter.GetBytes(intVal), 0, rowBuf, bufInd, fieldDef.DataSize); break; case DataTypes.Double: double dblVal = isNull ? 0.0 : (double)val; Array.Copy(BitConverter.GetBytes(dblVal), 0, rowBuf, bufInd, fieldDef.DataSize); break; case DataTypes.Boolean: rowBuf[bufInd] = (byte)(isNull ? 0 : (bool)val ? 1 : 0); break; case DataTypes.DateTime: double dtVal = isNull ? 0.0 : ScadaUtils.EncodeDateTime((DateTime)val); Array.Copy(BitConverter.GetBytes(dtVal), 0, rowBuf, bufInd, fieldDef.DataSize); break; default: string strVal = isNull ? "" : val.ToString(); ConvertStr(strVal, fieldDef.MaxStrLen, fieldDef.DataSize, rowBuf, bufInd, Encoding.UTF8); break; } bufInd += fieldDef.DataSize; } writer.Write(rowBuf); } } } finally { if (fileMode) { if (writer != null) { writer.Close(); } if (stream != null) { stream.Close(); } } } }