Пример #1
0
        /// <summary>
        /// Converts the specified snapshot table to CSV.
        /// </summary>
        public void ConvertToCsv(SrezTable srezTable)
        {
            if (srezTable == null)
            {
                throw new ArgumentNullException("srezTable");
            }

            Stream       stream = GetStream();
            StreamWriter writer = null;

            try
            {
                int srezCnt = srezTable.SrezList.Count;

                if (srezCnt > 0)
                {
                    // output the channels present in the last snapshot
                    int[] cnlNums = srezTable.SrezList.Values[srezCnt - 1].CnlNums;

                    // prepare a writer
                    writer = new StreamWriter(stream);

                    // output the table header
                    writer.Write("[DateTime]");
                    foreach (int cnlNum in cnlNums)
                    {
                        writer.Write(";[" + cnlNum + "]");
                    }
                    writer.WriteLine();

                    // output the data
                    foreach (SrezTableLight.Srez srez in srezTable.SrezList.Values)
                    {
                        writer.Write(srez.DateTime.ToString(Localization.Culture));

                        foreach (int cnlNum in cnlNums)
                        {
                            writer.Write(";");
                            SrezTableLight.CnlData cnlData = srez.GetCnlData(cnlNum);
                            if (cnlData.Stat > 0)
                            {
                                writer.Write(cnlData.Val.ToString(Localization.Culture));
                            }
                        }

                        writer.WriteLine();
                    }
                }
            }
            finally
            {
                if (fileMode)
                {
                    writer?.Dispose();
                    stream?.Dispose();
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Заполнить объект dest из файла срезов FileName
        /// </summary>
        protected void FillObj(object dest)
        {
            Stream       stream   = null;
            BinaryReader reader   = null;
            DateTime     fillTime = DateTime.Now;

            SrezTableLight srezTableLight = dest as SrezTableLight;
            DataTable      dataTable      = dest as DataTable;
            Trend          trend          = dest as Trend;

            SrezTable srezTable = srezTableLight as SrezTable;

            SrezTableLight.Srez lastStoredSrez = null;

            try
            {
                if (srezTableLight == null && dataTable == null && trend == null)
                {
                    throw new ScadaException("Destination object is invalid.");
                }

                // подготовка объекта для хранения данных
                if (srezTableLight != null)
                {
                    srezTableLight.Clear();
                    srezTableLight.TableName = tableName;

                    if (srezTable != null)
                    {
                        srezTable.BeginLoadData();
                    }
                }
                else if (dataTable != null)
                {
                    // формирование структуры таблицы
                    dataTable.BeginLoadData();
                    dataTable.DefaultView.Sort = "";

                    if (dataTable.Columns.Count == 0)
                    {
                        dataTable.Columns.Add("DateTime", typeof(DateTime));
                        dataTable.Columns.Add("CnlNum", typeof(int));
                        dataTable.Columns.Add("Val", typeof(double));
                        dataTable.Columns.Add("Stat", typeof(int));
                        dataTable.DefaultView.AllowNew    = false;
                        dataTable.DefaultView.AllowEdit   = false;
                        dataTable.DefaultView.AllowDelete = false;
                    }
                    else
                    {
                        dataTable.Rows.Clear();
                    }
                }
                else // trend != null
                {
                    trend.Clear();
                    trend.TableName = tableName;
                }

                // заполнение объекта данными
                stream = ioStream == null ?
                         new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) :
                         ioStream;
                reader = new BinaryReader(stream);

                DateTime            date      = ExtractDate(tableName); // определение даты срезов
                SrezTable.SrezDescr srezDescr = null;                   // описание среза
                int[] cnlNums = null;                                   // ссылка на номера входных каналов из описания среза
                while (stream.Position < stream.Length)
                {
                    // считывание списка номеров каналов и КС
                    int cnlNumCnt = reader.ReadUInt16();
                    if (cnlNumCnt > 0)
                    {
                        // загрузка номеров каналов в буфер для увеличения скорости работы
                        int    cnlNumSize = cnlNumCnt * 2;
                        byte[] buf        = new byte[cnlNumSize];
                        int    readSize   = reader.Read(buf, 0, cnlNumSize);

                        // создание описания среза и заполнение номеров каналов из буфера
                        // с проверкой их уникальности и упорядоченности
                        if (readSize == cnlNumSize)
                        {
                            int prevCnlNum = -1;
                            srezDescr = new SrezTable.SrezDescr(cnlNumCnt);
                            cnlNums   = srezDescr.CnlNums;
                            for (int i = 0; i < cnlNumCnt; i++)
                            {
                                int cnlNum = BitConverter.ToUInt16(buf, i * 2);
                                if (prevCnlNum >= cnlNum)
                                {
                                    throw new ScadaException("Table is incorrect.");
                                }
                                cnlNums[i] = prevCnlNum = cnlNum;
                            }
                            srezDescr.CalcCS();
                        }
                    }
                    else if (srezDescr == null)
                    {
                        throw new Exception("Table is incorrect.");
                    }

                    // считывание и проверка КС
                    ushort cs   = reader.ReadUInt16();
                    bool   csOk = cnlNumCnt > 0 ? srezDescr.CS == cs : cs == 1;

                    // считывание данных среза
                    int cnlCnt       = cnlNums.Length; // количество каналов в срезе
                    int srezDataSize = cnlCnt * 9;     // размер данных среза
                    if (csOk)
                    {
                        long   srezPos = stream.Position;
                        double time = reader.ReadDouble();
                        int    hour, min, sec;
                        ScadaUtils.DecodeTime(time, out hour, out min, out sec);
                        DateTime srezDT = new DateTime(date.Year, date.Month, date.Day, hour, min, sec);

                        // инициализация нового среза
                        SrezTableLight.Srez srez;
                        if (srezTable != null)
                        {
                            srez = new SrezTable.Srez(srezDT, srezDescr)
                            {
                                State    = DataRowState.Unchanged,
                                Position = srezPos
                            };
                        }
                        else if (srezTableLight != null)
                        {
                            srez = new SrezTableLight.Srez(srezDT, cnlCnt);
                            cnlNums.CopyTo(srez.CnlNums, 0);
                        }
                        else // srezTableLight == null
                        {
                            srez = null;
                        }

                        // считывание данных входных каналов
                        int    bufInd = 0;
                        double val;
                        byte   stat;
                        if (trend != null)
                        {
                            // выбор данных требуемого канала для тренда
                            int index = Array.BinarySearch <int>(cnlNums, trend.CnlNum);
                            if (index >= 0)
                            {
                                stream.Seek(index * 9, SeekOrigin.Current);
                                byte[] buf      = new byte[9];
                                int    readSize = reader.Read(buf, 0, 9);
                                if (readSize == 9)
                                {
                                    ExtractCnlData(buf, ref bufInd, out val, out stat);
                                    Trend.Point point = new Trend.Point(srezDT, val, stat);
                                    trend.Points.Add(point);
                                    stream.Seek(srezDataSize - (index + 1) * 9, SeekOrigin.Current);
                                }
                            }
                            else
                            {
                                stream.Seek(srezDataSize, SeekOrigin.Current);
                            }
                        }
                        else
                        {
                            // загрузка данных среза в буфер для увеличения скорости работы
                            byte[] buf      = new byte[srezDataSize];
                            int    readSize = reader.Read(buf, 0, srezDataSize);

                            // заполение таблицы срезов из буфера
                            if (srezTableLight != null)
                            {
                                for (int i = 0; i < cnlCnt; i++)
                                {
                                    ExtractCnlData(buf, ref bufInd, out val, out stat);

                                    srez.CnlNums[i]      = cnlNums[i];
                                    srez.CnlData[i].Val  = val;
                                    srez.CnlData[i].Stat = stat;

                                    if (bufInd >= readSize)
                                    {
                                        break;
                                    }
                                }

                                srezTableLight.AddSrez(srez);
                                lastStoredSrez = srez;
                            }
                            else // dataTable != null
                            {
                                for (int i = 0; i < cnlCnt; i++)
                                {
                                    ExtractCnlData(buf, ref bufInd, out val, out stat);

                                    DataRow row = dataTable.NewRow();
                                    row["DateTime"] = srezDT;
                                    row["CnlNum"]   = cnlNums[i];
                                    row["Val"]      = val;
                                    row["Stat"]     = stat;
                                    dataTable.Rows.Add(row);

                                    if (bufInd >= readSize)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // пропустить срез, считая его размер так, как при повторяющемся списке номеров каналов
                        stream.Seek(srezDataSize + 8, SeekOrigin.Current);
                    }
                }
            }
            catch (EndOfStreamException)
            {
                // нормальная ситуация окончания файла
            }
            catch
            {
                fillTime = DateTime.MinValue;
                throw;
            }
            finally
            {
                if (fileMode)
                {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                    if (stream != null)
                    {
                        stream.Close();
                    }
                }

                if (srezTableLight != null)
                {
                    srezTableLight.LastFillTime = fillTime;
                    if (srezTable != null)
                    {
                        srezTable.LastStoredSrez = (SrezTable.Srez)lastStoredSrez;
                        srezTable.EndLoadData();
                    }
                }
                else if (dataTable != null)
                {
                    dataTable.EndLoadData();
                    dataTable.AcceptChanges();
                    dataTable.DefaultView.Sort = "DateTime, CnlNum";
                }
                else if (trend != null)
                {
                    trend.LastFillTime = fillTime;
                    trend.Sort();
                }
            }
        }
Пример #3
0
        /// <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();
                    }
                }
            }
        }
Пример #4
0
        /// <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();
                }
            }
        }