public List <DataPoint> GetDataPoints(IPsnProtocolConfiguration protocol, IPsnProtocolCommandPartConfiguration commandPart, IPsnProtocolParameterConfiguration paramInfo, DateTime beginTime) { // Если конфигурация была изменена: if (_lastPsnProtocolId != null && _lastPsnProtocolId.IdentyString != protocol.Information.Id.IdentyString) { FreeResources(); } if (_areResourcesFree) { FillResources(protocol, beginTime, protocol.CycleCommandParts, protocol.CommandParts); } var result = new List <DataPoint>(); bool isWatchForRequestNeeded; Func <IPsnMapRecord, IPsnMapSubrecord> funcGetPart; if (commandPart.PartType == PsnProtocolCommandPartType.Request) { funcGetPart = FuncGetPartRequest; isWatchForRequestNeeded = false; } else if (commandPart.PartType == PsnProtocolCommandPartType.Reply) { funcGetPart = FuncGetPartReply; isWatchForRequestNeeded = false; } else /*if (commandPart.PartType == PsnProtocolCommandPartType.ReplyWithRequiredRequest)*/ { funcGetPart = FuncGetPartReply; isWatchForRequestNeeded = true; } // поток данных нужен для извлечения самих данных (т.к. изначально их нет в карте (есть только информация о местоположении и времени команд протокола ПСН) // можно разделить алгоритм на две части: выборку из карты инфомрации об интересующем сигнале, а затем - заполнение значений из потока данных for (int i = 0; i < _commandsMap.Count; ++i) { if (_commandsMap[i].CommandId.IdentyString == commandPart.CommandId.IdentyString) { IPsnMapSubrecord needRec = funcGetPart.Invoke(_commandsMap[i]); if (needRec != null) { if (isWatchForRequestNeeded && _commandsMap[i].RequestRecordInfo != null || !isWatchForRequestNeeded) { // CRC ok int positionInGoodData = needRec.LocationInfo.Position; result.Add(new DataPoint(paramInfo.GetValue(_goodPagesOnlyGoodBytes, positionInGoodData), needRec.LocationInfo.Time, true, positionInGoodData)); } } } } return(result); }
private BigList <IPsnMapRecord> BuildCommandsMap(IPsnProtocolCommandPartConfiguration[] cmdParts, IEnumerable <IPsnProtocolCommandPartConfigurationCycle> cycleCmdPartInfos, byte[] dataBytes, DateTime psnLogBeginTime, List <IPsnPageIndexRecord> pagesIndex) { // Структура записи будет: // Запись: // Запрос: // - позиция // - кусок команды // Ответ: // - позиция // - кусок команды var result = new BigList <IPsnMapRecord>(); var time = psnLogBeginTime; var cycleCmdPartInfoArray = cycleCmdPartInfos as IPsnProtocolCommandPartConfigurationCycle[] ?? cycleCmdPartInfos.ToArray(); IPsnMapSubrecord prevRequestSubrec = null; // Запрос из предыдущей итерации (изначально его нет) RunThroughDataAndExectueCustomActionOnCommandPartsFound( cmdParts, dataBytes, partsPosition => { try { IPsnCommandPartsPosition currPtLocInfo = new PsnCommandPartsAndPosition(partsPosition.DataPosition, partsPosition.CrcOkPartLocationInfo); var pageIndex = currPtLocInfo.DataPosition / (_extractor.PsnPageSize - _extractor.PsnPageHeaderLength); var pageWhereCmdPartLocated = pagesIndex[pageIndex]; // Подгонка времени до страничного, если время теущей страницы больше времени if (pageWhereCmdPartLocated.PageTime.HasValue) { if (pageWhereCmdPartLocated.PageTime.Value > time) { time = pageWhereCmdPartLocated.PageTime.Value; } } // -1. Если среди текущих найденных кусков команд есть циклическай кусок с правильной контрольной суммой, то время инкрементируется: for (int j = 0; j < cycleCmdPartInfoArray.Length; ++j) { if (currPtLocInfo.CrcOkPartLocationInfo.Id.IdentyString == cycleCmdPartInfoArray[j].Id.IdentyString) { time = time.Add(cycleCmdPartInfoArray[j].CyclePeriod); break; } } // 0. К этой точке есть готовое время для текущей части команды - переменная time var currentTruelyFoundCommandPart = currPtLocInfo.CrcOkPartLocationInfo; bool isCurrentTruelyFoundCommandPartRepliedOnPrevRequest = false; // является ли точно найденная команда ответом на предыдущий запрос // Если предыдущий запрос есть, то вероятно надо искать ответ на него: if (prevRequestSubrec != null) { if (currentTruelyFoundCommandPart.PartType == PsnProtocolCommandPartType.Reply || currentTruelyFoundCommandPart.PartType == PsnProtocolCommandPartType.ReplyWithRequiredRequest) { if (prevRequestSubrec.CommandPart.CommandId.IdentyString == currentTruelyFoundCommandPart.CommandId.IdentyString) { isCurrentTruelyFoundCommandPartRepliedOnPrevRequest = true; } } } if (currentTruelyFoundCommandPart.PartType == PsnProtocolCommandPartType.Request) { // Если до этого уже был запрос, то он сохраняется в карту как безответная запись: if (prevRequestSubrec != null) { result.Add(new PsnMapRecord( prevRequestSubrec.CommandPart.CommandId, prevRequestSubrec, null)); } // Текущий запрос сохраняется, для дальнейшего поиска ответа на него: prevRequestSubrec = new PsnMapSubrecord( new PsnCommandPartLocation( currPtLocInfo.DataPosition, time), currentTruelyFoundCommandPart); } else { // Если найден ответ - проверить, является ли ответ ответом на пердыдущий запрос, или это какой-то другой ответ: if (isCurrentTruelyFoundCommandPartRepliedOnPrevRequest) { // Является, нужно сделать одну целую запись: result.Add(new PsnMapRecord( prevRequestSubrec.CommandPart.CommandId, prevRequestSubrec, new PsnMapSubrecord( new PsnCommandPartLocation( currPtLocInfo.DataPosition, time), currentTruelyFoundCommandPart))); prevRequestSubrec = null; } else { // Не является, нужно сделать две записи: // (1) запрос if (prevRequestSubrec != null) { result.Add(new PsnMapRecord( prevRequestSubrec.CommandPart.CommandId, prevRequestSubrec, null)); prevRequestSubrec = null; // Обнуляем запрос после добавления в карту } // (2) ответ result.Add( new PsnMapRecord( currentTruelyFoundCommandPart.CommandId, null, new PsnMapSubrecord( new PsnCommandPartLocation( currPtLocInfo.DataPosition, time), currentTruelyFoundCommandPart) )); } } return(partsPosition.CrcOkPartLocationInfo .Length); // Следующий поиск будем проводить с позиции конца хорошей части команды } catch (OutOfMemoryException ex) { throw new Exception("В системе не достаточно памяти для построения командной карты лога", ex); } catch (Exception ex) { throw new Exception( "Ошибка алгоритма постоения командной карты лога, обратитесь к разработчикам программы", ex); } }); return(result); }
public PsnMapRecord(IIdentifier commandId, IPsnMapSubrecord requestRecordInfo, IPsnMapSubrecord replyRecordInfo) { CommandId = commandId; RequestRecordInfo = requestRecordInfo; ReplyRecordInfo = replyRecordInfo; }