/// <summary> /// Add event to file or stream /// </summary> public void AppendEvent(EventTableLight.Event ev) { if (ev == null) { throw new ArgumentNullException(nameof(ev)); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream ?? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); writer = new BinaryWriter(stream); // setting the recording position to a multiple of the size of the event data stream.Seek(0, SeekOrigin.End); long evInd = stream.Position / EventDataSize; long offset = evInd * EventDataSize; stream.Seek(offset, SeekOrigin.Begin); // event recording writer.Write(CreateEventBuffer(ev)); ev.Number = (int)evInd + 1; } finally { if (fileMode) { writer?.Close(); stream?.Close(); } } }
/// <summary> /// Создать данные события на основе строки таблицы /// </summary> protected EventTableLight.Event CreateEvent(DataRowView rowView) { EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = ConvertToInt(rowView["Number"]); ev.DateTime = ConvertToDateTime(rowView["DateTime"]); ev.ObjNum = ConvertToInt(rowView["ObjNum"]); ev.KPNum = ConvertToInt(rowView["KPNum"]); ev.ParamID = ConvertToInt(rowView["ParamID"]); ev.CnlNum = ConvertToInt(rowView["CnlNum"]); ev.OldCnlVal = ConvertToDouble(rowView["OldCnlVal"]); ev.OldCnlStat = ConvertToInt(rowView["OldCnlStat"]); ev.NewCnlVal = ConvertToDouble(rowView["NewCnlVal"]); ev.NewCnlStat = ConvertToInt(rowView["NewCnlStat"]); ev.Checked = ConvertToBoolean(rowView["Checked"]); ev.UserID = ConvertToInt(rowView["UserID"]); ev.Descr = Convert.ToString(rowView["Descr"]); ev.Data = Convert.ToString(rowView["Data"]); return(ev); }
/// <summary> /// Добавить событие в файл или поток /// </summary> public void AppendEvent(EventTableLight.Event ev) { if (ev == null) { throw new ArgumentNullException("ev"); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream == null ? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) : ioStream; writer = new BinaryWriter(stream); // установка позиции записи кратной размеру данных события stream.Seek(0, SeekOrigin.End); long evInd = stream.Position / EventDataSize; long offset = evInd * EventDataSize; stream.Seek(offset, SeekOrigin.Begin); // запись события writer.Write(CreateEventBuffer(ev)); ev.Number = (int)evInd + 1; } finally { if (fileMode) { if (writer != null) { writer.Close(); } if (stream != null) { stream.Close(); } } } }
/// <summary> /// Create event data based on table row /// </summary> protected EventTableLight.Event CreateEvent(DataRowView rowView) { var ev = new EventTableLight.Event { Number = ConvertToInt(rowView["Number"]), DateTime = ConvertToDateTime(rowView["DateTime"]), ObjNum = ConvertToInt(rowView["ObjNum"]), KPNum = ConvertToInt(rowView["KPNum"]), ParamID = ConvertToInt(rowView["ParamID"]), CnlNum = ConvertToInt(rowView["CnlNum"]), OldCnlVal = ConvertToDouble(rowView["OldCnlVal"]), OldCnlStat = ConvertToInt(rowView["OldCnlStat"]), NewCnlVal = ConvertToDouble(rowView["NewCnlVal"]), NewCnlStat = ConvertToInt(rowView["NewCnlStat"]), Checked = ConvertToBoolean(rowView["Checked"]), UserID = ConvertToInt(rowView["UserID"]), Descr = Convert.ToString(rowView["Descr"]), Data = Convert.ToString(rowView["Data"]) }; return(ev); }
/// <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> /// Записать изменения таблицы 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.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) : ioStream; writer = new BinaryWriter(stream); // запись изменённых событий DataView dataView = new DataView(dataTable, "", "", DataViewRowState.ModifiedCurrent); foreach (DataRowView rowView in dataView) { EventTableLight.Event ev = CreateEvent(rowView); if (ev.Number > 0) { stream.Seek((ev.Number - 1) * EventDataSize, SeekOrigin.Begin); writer.Write(CreateEventBuffer(ev)); } } // запись добавленных событий dataView = new DataView(dataTable, "", "", DataViewRowState.Added); if (dataView.Count > 0) { // установка позиции записи кратной размеру данных события stream.Seek(0, SeekOrigin.End); int evInd = (int)(stream.Position / EventDataSize); int evNum = evInd + 1; stream.Seek(evInd * EventDataSize, SeekOrigin.Begin); // запись событий и установка номеров событий foreach (DataRowView rowView in dataView) { EventTableLight.Event ev = CreateEvent(rowView); writer.Write(CreateEventBuffer(ev)); rowView["Number"] = evNum++; } } // подтверждение успешного сохранения изменений dataTable.AcceptChanges(); } finally { if (fileMode) { if (writer != null) { writer.Close(); } if (stream != null) { stream.Close(); } } } }
/// <summary> /// Заполнить объект dest из файла событий FileName /// </summary> protected void FillObj(object dest) { Stream stream = null; BinaryReader reader = null; DateTime fillTime = DateTime.Now; EventTableLight eventTableLight = null; DataTable dataTable = null; try { if (dest is EventTableLight) { eventTableLight = dest as EventTableLight; } else if (dest is DataTable) { dataTable = dest as DataTable; } else { throw new ScadaException("Destination object is invalid."); } // определение даты событий в таблице DateTime date = ExtractDate(tableName); // подготовка объекта для хранения данных if (eventTableLight != null) { eventTableLight.Clear(); eventTableLight.TableName = tableName; } else // dataTable != null { // формирование структуры таблицы dataTable.BeginLoadData(); dataTable.DefaultView.Sort = ""; if (dataTable.Columns.Count == 0) { dataTable.Columns.Add("Number", typeof(int)); dataTable.Columns.Add("DateTime", typeof(DateTime)).DefaultValue = date; dataTable.Columns.Add("ObjNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("KPNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("ParamID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("CnlNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("OldCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("OldCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("NewCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("NewCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Checked", typeof(bool)).DefaultValue = false; dataTable.Columns.Add("UserID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Descr", typeof(string)); dataTable.Columns.Add("Data", typeof(string)); dataTable.DefaultView.AllowNew = false; dataTable.DefaultView.AllowEdit = false; dataTable.DefaultView.AllowDelete = false; } else { DataColumn colDateTime = dataTable.Columns["DateTime"]; if (colDateTime != null) { colDateTime.DefaultValue = date; } dataTable.Rows.Clear(); } } // заполнение таблицы из файла stream = ioStream == null ? new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) : ioStream; reader = new BinaryReader(stream); Byte[] eventBuf = new byte[EventDataSize]; // буфер данных события int evNum = 1; // порядковый номер события while (stream.Position < stream.Length) { int readSize = reader.Read(eventBuf, 0, EventDataSize); if (readSize == EventDataSize) { // создание события на основе считанных данных EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = evNum; evNum++; double time = BitConverter.ToDouble(eventBuf, 0); ev.DateTime = ScadaUtils.CombineDateTime(date, time); ev.ObjNum = BitConverter.ToUInt16(eventBuf, 8); ev.KPNum = BitConverter.ToUInt16(eventBuf, 10); ev.ParamID = BitConverter.ToUInt16(eventBuf, 12); ev.CnlNum = BitConverter.ToUInt16(eventBuf, 14); ev.OldCnlVal = BitConverter.ToDouble(eventBuf, 16); ev.OldCnlStat = eventBuf[24]; ev.NewCnlVal = BitConverter.ToDouble(eventBuf, 25); ev.NewCnlStat = eventBuf[33]; ev.Checked = eventBuf[34] > 0; ev.UserID = BitConverter.ToUInt16(eventBuf, 35); ev.Descr = BytesToStr(eventBuf, 37); ev.Data = BytesToStr(eventBuf, 138); // создание строки заполняемой таблицы if (eventTableLight != null) { eventTableLight.AllEvents.Add(ev); // быстрее, чем eventTableLight.AddEvent(ev) } else // dataTable != null { DataRow row = dataTable.NewRow(); row["Number"] = ev.Number; row["DateTime"] = ev.DateTime; row["ObjNum"] = ev.ObjNum; row["KPNum"] = ev.KPNum; row["ParamID"] = ev.ParamID; row["CnlNum"] = ev.CnlNum; row["OldCnlVal"] = ev.OldCnlVal; row["OldCnlStat"] = ev.OldCnlStat; row["NewCnlVal"] = ev.NewCnlVal; row["NewCnlStat"] = ev.NewCnlStat; row["Checked"] = ev.Checked; row["UserID"] = ev.UserID; row["Descr"] = ev.Descr; row["Data"] = ev.Data; dataTable.Rows.Add(row); } } } } catch (EndOfStreamException) { // нормальная ситуация окончания файла } catch { fillTime = DateTime.MinValue; throw; } finally { if (fileMode) { if (reader != null) { reader.Close(); } if (stream != null) { stream.Close(); } } if (eventTableLight != null) { eventTableLight.LastFillTime = fillTime; } else if (dataTable != null) { dataTable.EndLoadData(); dataTable.AcceptChanges(); dataTable.DefaultView.Sort = "Number"; } } }
/// <summary> /// Populate the dest object from the FileName event file. /// </summary> protected void FillObj(object dest) { Stream stream = null; BinaryReader reader = null; var fillTime = DateTime.Now; EventTableLight eventTableLight = null; DataTable dataTable = null; try { if (dest is EventTableLight) { eventTableLight = dest as EventTableLight; } else if (dest is DataTable) { dataTable = dest as DataTable; } else { throw new ScadaException("Destination object is invalid."); } // determining the date of events in the table var date = ExtractDate(tableName); // storage facility preparation if (eventTableLight != null) { eventTableLight.Clear(); eventTableLight.TableName = tableName; } else // dataTable != null // forming the table structure { dataTable.BeginLoadData(); dataTable.DefaultView.Sort = ""; if (dataTable.Columns.Count == 0) { dataTable.Columns.Add("Number", typeof(int)); dataTable.Columns.Add("DateTime", typeof(DateTime)).DefaultValue = date; dataTable.Columns.Add("ObjNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("KPNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("ParamID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("CnlNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("OldCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("OldCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("NewCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("NewCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Checked", typeof(bool)).DefaultValue = false; dataTable.Columns.Add("UserID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Descr", typeof(string)); dataTable.Columns.Add("Data", typeof(string)); dataTable.DefaultView.AllowNew = false; dataTable.DefaultView.AllowEdit = false; dataTable.DefaultView.AllowDelete = false; } else { var colDateTime = dataTable.Columns["DateTime"]; if (colDateTime != null) { colDateTime.DefaultValue = date; } dataTable.Rows.Clear(); } } // filling a table from a file stream = ioStream ?? new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); reader = new BinaryReader(stream); var eventBuf = new byte[EventDataSize]; // event data buffer var evNum = 1; // event sequence number while (stream.Position < stream.Length) { int readSize = reader.Read(eventBuf, 0, EventDataSize); if (readSize == EventDataSize) { // create event based on read data var ev = new EventTableLight.Event { Number = evNum }; evNum++; double time = BitConverter.ToDouble(eventBuf, 0); ev.DateTime = ScadaUtils.CombineDateTime(date, time); ev.ObjNum = BitConverter.ToUInt16(eventBuf, 8); ev.KPNum = BitConverter.ToUInt16(eventBuf, 10); ev.ParamID = BitConverter.ToUInt16(eventBuf, 12); ev.CnlNum = BitConverter.ToUInt16(eventBuf, 14); ev.OldCnlVal = BitConverter.ToDouble(eventBuf, 16); ev.OldCnlStat = eventBuf[24]; ev.NewCnlVal = BitConverter.ToDouble(eventBuf, 25); ev.NewCnlStat = eventBuf[33]; ev.Checked = eventBuf[34] > 0; ev.UserID = BitConverter.ToUInt16(eventBuf, 35); ev.Descr = BytesToStr(eventBuf, 37); ev.Data = BytesToStr(eventBuf, 138); // create row of filled table if (eventTableLight != null) { eventTableLight.AllEvents.Add(ev); // faster than eventTableLight.AddEvent (ev) } else // dataTable != null { var row = dataTable.NewRow(); row["Number"] = ev.Number; row["DateTime"] = ev.DateTime; row["ObjNum"] = ev.ObjNum; row["KPNum"] = ev.KPNum; row["ParamID"] = ev.ParamID; row["CnlNum"] = ev.CnlNum; row["OldCnlVal"] = ev.OldCnlVal; row["OldCnlStat"] = ev.OldCnlStat; row["NewCnlVal"] = ev.NewCnlVal; row["NewCnlStat"] = ev.NewCnlStat; row["Checked"] = ev.Checked; row["UserID"] = ev.UserID; row["Descr"] = ev.Descr; row["Data"] = ev.Data; dataTable.Rows.Add(row); } } } } catch (EndOfStreamException) { // normal file end situation } catch { fillTime = DateTime.MinValue; throw; } finally { if (fileMode) { reader?.Close(); stream?.Close(); } if (eventTableLight != null) { eventTableLight.LastFillTime = fillTime; } if (dataTable != null) { dataTable.EndLoadData(); dataTable.AcceptChanges(); dataTable.DefaultView.Sort = "Number"; } } }