Esempio n. 1
0
 private static PsnPageNumberAndTime GetLastPageNumberWithGoodDate(PsnBinLogLocationInfo locationInfo, Func <byte[], PsnPageHeader> timeReceiveMethod)
 {
     using (var br = new AdvancedBinaryReader(File.OpenRead(locationInfo.PsnBinFileName), false)) {
         var extractor = PsnPageExtractorFactory.Extractor;
         var buf       = new byte[extractor.PsnPageHeaderLength];
         for (int i = locationInfo.LastPageIndex; i >= locationInfo.FirstPageIndex; --i)
         {
             try {
                 br.BaseStream.Seek(extractor.PsnPageSize * i, SeekOrigin.Begin);
                 br.Read(buf, 0, buf.Length);
                 var header = timeReceiveMethod(buf);                         //PsnBinPageExtractor.GetHeaderFromRealDevice(buf);
                 br.Close();
                 return(new PsnPageNumberAndTime(i, header.CreatedAt));
             }
             catch {
                 // в случае ошибки цикл продолжается, т.к. нужная страница не найдена
             }
         }
     }
     throw new Exception("Cannot find any dated page");
 }
Esempio n. 2
0
        /// <summary>
        /// Прочитать тренд из бинарника
        /// </summary>
        /// <param name="channel">Канал, для которого грузится тренд</param>
        public ReadChannelTrendResult ReadChannelTrendFromBinaryFile(/*string filePath,*/ RpdChannel channel)
        {
            var result = new ReadChannelTrendResult {
                Result = ((RpdMeter)channel.OwnerMeter).CloneAndLinkWithFault(null)
            };

            // Запишем в результат измеритель (родитель для channel)
            result.Result.Channels.Clear();                                           //каналы тоже склонировались!!1
            result.Result.Channels.Add(channel.CloneAndLinkWithMeter(result.Result)); //добавим результирующему измерителю канал
            try {
                result.Result.Channels[0].Trend.Clear();                              //очистим тренд канала, вдруг там что-то есть!
                //using (AdvancedBinaryReader reader = new AdvancedBinaryReader(new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read), false))
                using (var reader = new AdvancedBinaryReader(new FileStream(BinFilePath.FullName, FileMode.Open, FileAccess.Read), false))
                {
                    // запомним количество страниц в файле
                    long pagesCount = reader.BaseStream.Length / 2048;

                    // постраничное перемещение i
                    int timePosition = 0;

                    for (long i = 0; i < pagesCount; ++i)
                    {
                        try {
                            var pageRaw = new byte[2048];                             //ряд байтов, представляющих собой страницу
                            reader.Read(pageRaw, 0, 2048);                            //считываем страницу
                            // тут не надо проверять псн! // && pageRaw[0] != 0x80) //если это не заголовок аварии и не данные по ПСН (по идее заголовок - это >= 0x55) fixed
                            if (pageRaw[0] < 0x55)
                            {
                                int meterAddrFromPage = pageRaw[0];                                    //номер/адрес измерителя хранится в первом байте страницы
                                if (meterAddrFromPage == result.Result.Channels[0].OwnerMeter.Address) //если страница принадлежит нужному измерителю, то:
                                {
                                    var currentPage = new FaultArchivePage(pageRaw, this);             //сформируем страницу как объект
                                    var neededMeter = (RpdMeter)result.Result.Channels[0].OwnerMeter;

                                    //если настройки не считаны - считываем:
                                    if (!neededMeter.SettingsReaded)
                                    {
                                        neededMeter.ReadSettings(currentPage);                                         // Настройки измерителя хранятся в первой послезаголовочной странице ( TODO: а если это измеритель № 10 и его настройки не влезли в первую послезаголовочную страницу?)
                                    }

                                    // В любом случае удаляем информационные строки с настройками по измерителю
                                    RemoveMeterSettingLines(currentPage);
                                    // Зачем пытаться удалять то, чего возможно и нет? (не лучше ли будет перенести под условие if (!neededMeter.SettingsReaded)
                                    // Не лучше, т.к. нужно в люом случае проверять строки на нулевой номер (вдруг в системе куча измерителей? и т.п.)
                                    // Можно не удалять, а работать только со строками, номер которых больше нуля (нулевые - это строки настроек измерителей)


                                    // Теперь необходимо прочесать строки и найти строки для нашего канала
                                    foreach (VariableLengthPageLine currentLine in currentPage.Lines)
                                    {
                                        if (currentLine.ChannelNumber + 1 == result.Result.Channels[0].Number)                                         //ввбираем строки для нужного канала
                                        {
                                            foreach (int val in currentLine.Values)
                                            {
                                                ChannelCalibration chT = neededMeter.Settings.Calibrations.Channels[result.Result.Channels[0].Number - 1];
                                                //формула вычисления значения с учетом настроек измерителя: (см. ТЗ)
                                                var point = new DataPointSimple((val - chT.Zero) * chT.Kkor * chT.Kper * 1.0, AccuredAt.AddTicks((long)(timePosition * (10000000.0 / neededMeter.Settings.Time) - neededMeter.TrendsTimeOffset * 10)), true, 0, null); // TODO
                                                result.Result.Channels[0].Trend.Add(point);                                                                                                                                                                            // *10 is microseconds in ticks//timePosition * 25 - neededMeter.TrendsTimeOffset));
                                                timePosition++;
                                            }
                                            //else пропускаем, такого канала в системе нету :(
                                        }
                                    }
                                }
                            }
                        }
                        catch {
                            // TODO: remove empty catch
                        }
                    }
                    //sw.Close();//DEBUG
                    reader.Close();                     //ридер нужно закрыть
                }
            }
            catch             // (Exception ex)
            {
                result = null;
            }

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Прочитать информацию об аварии из бинарника вида AVR*.bin
        /// Переопределяет название аварии из бинарника
        /// Переопределяет время аварии
        /// Переопределяет FileHash
        /// Переопределяет BinFileInfo
        /// </summary>
        /// <param name="sourceFile">Путь к бинарнику</param>
        /// <returns>Результат операции</returns>
        public bool ReadInfoFromBinaryFile(FileInfo sourceFile)
        {
            //Log.Global.Info("Попытка чтения информации об аварии из файла: " + sourceFile.FullName);
            bool result = true;

            sourceFile.Refresh();
            if (sourceFile.Exists)
            {
                //Log.Global.Info("Файл лога аварии существует");
                using (var reader = new AdvancedBinaryReader(new FileStream(sourceFile.FullName, FileMode.Open, FileAccess.Read), false))
                {
                    long pagesCount = reader.BaseStream.Length / 2048;
                    //Log.Global.Info("Количество страниц в файле = " + pagesCount);
                    bool startPageFound = false;
                    //int startPageIndex = 0;
                    bool firstNonstartPageFound = false;
                    for (long i = 0; i < pagesCount; ++i)
                    {
                        reader.BaseStream.Seek(i * 2048, SeekOrigin.Begin);
                        byte firstPageByte = reader.ReadByte();            // считаем первый байт
                        if (firstPageByte == 0x55)                         // заголовок найден!
                        {
                            //Log.Global.Info("Заголовочная страница найдена, её номер = " + i);
                            startPageFound  = true;
                            HeaderPageIndex = i;                             // запомнить индекс страницы-заголовка аварии (но в реальности страниц может быть много!)
                            // следующие 6 байт - дата (dd|MM|yy|HH|mm|ss)
                            byte day   = reader.ReadByte();
                            byte month = reader.ReadByte();
                            byte year  = reader.ReadByte();

                            byte hour   = reader.ReadByte();
                            byte minute = reader.ReadByte();
                            byte second = reader.ReadByte();
                            try {
                                AccuredAt = new DateTime(2000 + year, month, day, hour, minute, second);                                 // соберем байты в удобный вид
                            }
                            catch {
                                //Log.Global.Info("Не удалось распарсить дату и время аварии из байт: " + year + " " + month + " " + day + " " + hour + " " + minute + " " + second);
                                AccuredAt = DateTime.MinValue;
                            }
                            //Log.Global.Info("Дата аварии = " + AccuredAt.ToString("yyyy.MM.dd HH:mm:ss"));
                            _faultNumberFromHeader = reader.ReadByte();        // прочитаем номер аварии (байт №8)
                            _metersCount           = reader.ReadByte();        // прочитаем число измерителей (байт №9)
                        }
                        else if (firstPageByte < 0x55)                         // Первую незаголовочную страницу нужно прочитать для получения настроек измерителя:
                        {
                            if (startPageFound)
                            {
                                firstNonstartPageFound = true;
                            }
                            //Log.Global.Info("Незаголовочная страница, её индекс=" + i + " RpdMeters.Count=" + RpdMeters.Count);
                            reader.BaseStream.Seek(i * 2048, SeekOrigin.Begin);

                            var pageRaw = new byte[2048];
                            reader.Read(pageRaw, 0, 2048);                             //считываем страницу
                            var currentPage = new FaultArchivePage(pageRaw, this);

                            // Считываем настройки всех измерителей:
                            for (int j = 0; j < _metersCount; ++j)
                            {
                                var neededMeter = (RpdMeter)RpdMeters[j];
                                if (!neededMeter.SettingsReaded)
                                {
                                    neededMeter.ReadSettings(currentPage);
                                }
                            }
                        }


                        if (startPageFound && firstNonstartPageFound)
                        {
                            break;
                        }
                    }



                    if (startPageFound && firstNonstartPageFound)
                    {
                        //reader.BaseStream.Seek(startPageIndex * 2048, SeekOrigin.Begin);
                        // После чтения информации по измерителям РПД необходимо вернуться в начало и прочитать текущие данные:
                        var rpdCurrentData = new List <RpdChannelCurrentData>();
                        int rpdChannelCurrentDataOffset = 9;
                        // В этом цикле считываем текущие данные каналов РПД, заодно на выходе получая позицию текущих данных ПСН
                        for (int i = 0; i < _metersCount; ++i)
                        {
                            rpdChannelCurrentDataOffset += MeterHeaderCurrentDataRecordLength;

                            foreach (RpdChannel ch in RpdMeters[i].Channels)
                            {
                                //Log.Global.Info("Channel=" + ch.Name + ".IsEnabled = " + ch.IsEnabled);
                                if (ch.IsEnabled)
                                {
                                    rpdChannelCurrentDataOffset += ChannelCurrentDataRecordLength;
                                    //Log.Global.Info("rpdChannelCurrentDataOffset = " + rpdChannelCurrentDataOffset);
                                    // Если настройки были прочитаны:
                                    // Нельзя выносить на верхний уровень, т.к. тогда не правильно отработает смещение rpdChannelCurrentDataOffset
                                    var neededMeter = (RpdMeter)RpdMeters[i];
                                    if (neededMeter.Settings != null && neededMeter.SettingsReaded)
                                    {
                                        //Log.Global.Info(neededMeter.Name + " настроки были прочитаны");
                                        reader.BaseStream.Seek(HeaderPageIndex * 2048 + rpdChannelCurrentDataOffset, SeekOrigin.Begin);

                                        var chT = neededMeter.Settings.Calibrations.Channels[ch.Number - 1];
                                        var b1  = reader.ReadByte();                                        // По суте первый байт не нужен, но нужно сдвинуть текущее положение в файле на 1 байт
                                        var b2  = reader.ReadByte();
                                        var b3  = reader.ReadByte();
                                        //Log.Global.Info("b1 = " + b1);
                                        //Log.Global.Info("b2 = " + b2);
                                        //Log.Global.Info("b3 = " + b3);
                                        double channelCurrentValue = b2 + b3 * 256.0;
                                        //Log.Global.Info("ChCurrValue = " + channelCurrentValue);
                                        double modifiedCurValue = (channelCurrentValue - chT.Zero) * chT.Kkor * chT.Kper * 1.0;
                                        //Log.Global.Info("ResultValue = " + modifiedCurValue);
                                        rpdCurrentData.Add(new RpdChannelCurrentData(ch, modifiedCurValue));
                                    }
                                }
                            }
                        }
                        int psnCurrentDataOffset = rpdChannelCurrentDataOffset;                         // На самом деле № позиции текущих данных ПСН определяется так: сумма числа разрешённых каналов рпд по каждому измерителю:
                        //Log.Global.Info("Смещение текущих данных магистрали ПСН: psnCurrentDataOffset=" + psnCurrentDataOffset);

                        var psnReasonRaw = new byte[FaultReason.PsnGaugesCount * FaultReason.PsnReplyMaxLength];
                        reader.BaseStream.Seek(HeaderPageIndex * 2048 + psnCurrentDataOffset, SeekOrigin.Begin);
                        reader.Read(psnReasonRaw, 0, psnReasonRaw.Length);
                        // TODO: whre to get PsnChannelSimple
                        //Reason = new FaultReason(rpdCurrentData, PsnPagesParser.GetPsnCurrentData(psnReasonRaw, _deviceConfig));
                        reader.Close();
                    }
                    else
                    {
                        reader.Close();
                        throw new Exception("Ошибка, не удалось найти начальную страницу или первую страницу с данными");
                    }
                    //reader.Close();


                    FileHash    = DTHasher.GetMD5Hash(sourceFile.FullName, string.Empty);
                    BinFilePath = sourceFile;
                    //this.Name = sourceFile.Name; // Имя исходного файла всегда корявое,
                    UpdateName();
                    //Log.Global.Info("Информация об аварии {" + Name + "} успешно прочитана");
                    //Log.Global.Info(BinFilePath.FullName);
                    //Log.Global.Info(Reason.ToString);
                }
            }
            else
            {
                result = false;
                //Log.Global.Info("Файл лога аварии не существует! result = " + result);
            }

            return(result);
        }