/// <summary> /// Read the content of a TAG file and routes it to the provided sink /// </summary> /// <param name="fileName"></param> /// <param name="sink"></param> /// <returns></returns> public TAGReadResult Read(string fileName, TAGValueSinkBase sink) { using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { using (var reader = new TAGReader(fs)) { return(Read(reader, sink)); } } }
/// <summary> /// Reads the context of a TAG file using the provided reader and sink /// </summary> /// <param name="reader"></param> /// <param name="sink"></param> /// <returns></returns> public TAGReadResult Read(TAGReader reader, TAGValueSinkBase sink) { try { if (reader.StreamSizeInNybbles == 0) { return(TAGReadResult.ZeroLengthFile); } try { Header.Read(reader); } catch (Exception E) { Log.LogError(E, "Invalid tag file. Exception in TTagFile.ReadStream - Header.LoadFromStream:"); return(TAGReadResult.InvalidDictionary); } // If the offset to the dictionary is zero, then it follows immediately after the header long DataEndPos; try { if (Header.FieldAndTypeTableOffset != 0) { long StreamPos = reader.NybblePosition; reader.NybblePosition = Header.FieldAndTypeTableOffset * 2; // FieldAndTypeTableOffset is in bytes if (!Dictionary.Read(reader)) { return(TAGReadResult.InvalidDictionary); } reader.NybblePosition = StreamPos; DataEndPos = Header.FieldAndTypeTableOffset * 2; // FieldAndTypeTableOffset is in bytes } else { if (!Dictionary.Read(reader)) { return(TAGReadResult.InvalidDictionary); } DataEndPos = reader.StreamSizeInNybbles; } } catch (Exception E) { Log.LogWarning(E, "Exception in TagFile.ReadFile:"); return(TAGReadResult.InvalidDictionary); } // Now read in the data from the file if (!sink.Starting()) { return(TAGReadResult.SinkStartingFailure); } while (!sink.Aborting() && reader.NybblePosition < DataEndPos) { if (!reader.ReadVarInt(out short ValueTypeID)) { if (reader.NybblePosition >= DataEndPos) { break; // We have finished } return(TAGReadResult.InvalidValueTypeID); // This is an invalid tag file } if (Dictionary.Entries.Keys.Count == 0) { return(TAGReadResult.InvalidDictionary); } if (!Dictionary.Entries.TryGetValue(ValueTypeID, out TAGDictionaryItem DictionaryEntry)) { return(TAGReadResult.InvalidValueTypeID); } try { switch (DictionaryEntry.Type) { case TAGDataType.t4bitInt: case TAGDataType.t8bitInt: case TAGDataType.t12bitInt: case TAGDataType.t16bitInt: case TAGDataType.t32bitInt: sink.ReadIntegerValue(DictionaryEntry, reader.ReadSignedIntegerValue(IntegerNybbleSizes.Nybbles[(byte)DictionaryEntry.Type])); break; case TAGDataType.t4bitUInt: case TAGDataType.t8bitUInt: case TAGDataType.t12bitUInt: case TAGDataType.t16bitUInt: case TAGDataType.t32bitUInt: sink.ReadUnsignedIntegerValue(DictionaryEntry, reader.ReadUnSignedIntegerValue(IntegerNybbleSizes.Nybbles[(byte)DictionaryEntry.Type])); break; case TAGDataType.tIEEESingle: sink.ReadIEEESingleValue(DictionaryEntry, reader.ReadSinglePrecisionIEEEValue()); break; case TAGDataType.tIEEEDouble: sink.ReadIEEEDoubleValue(DictionaryEntry, reader.ReadDoublePrecisionIEEEValue()); break; case TAGDataType.tANSIString: sink.ReadANSIStringValue(DictionaryEntry, reader.ReadANSIString()); break; case TAGDataType.tUnicodeString: sink.ReadUnicodeStringValue(DictionaryEntry, reader.ReadUnicodeString()); break; case TAGDataType.tEmptyType: sink.ReadEmptyValue(DictionaryEntry); break; } } catch (Exception E) { Log.LogError(E, "Exception in TagFile.ReadFile while reading field value:"); return(TAGReadResult.InvalidValue); } } if (!sink.Finishing()) { return(TAGReadResult.SinkFinishingFailure); } } catch (IOException E) { Log.LogDebug(E, "Exception in TagFile.ReadFile:"); return(TAGReadResult.CouldNotOpenFile); } return(TAGReadResult.NoError); }
/// <summary> /// Reads the context of a Volvo earthworks CSV file using the provided sink to send data to /// Note: LastEDV value is not handled as it has no corresponding value in TRex /// </summary> public TAGReadResult Read(TAGValueSinkBase sink, TAGProcessor processor) { using var streamReader = new StreamReader(_stream, Encoding.ASCII); var headerLine = streamReader.ReadLine(); var headerIndex = 0; _headerLocations = headerLine.Split(',').Select(x => new KeyValuePair <string, int>(x, headerIndex++)).ToDictionary(k => k.Key, v => v.Value); // Read all remaining lines into an array for easy access var lines = ReadLines(streamReader).ToList(); var swather = new VolvoEarthworksCSVGridSwather(processor, processor.MachineTargetValueChangesAggregator, processor.SiteModel, processor.SiteModelGridAggregator, null) { ProcessedEpochNumber = processor.ProcessedEpochCount }; var currentTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc); //var firstDataTime = // For each line, locate the TRex cell that fall within the cell and add a cell pass for it lines.ForEach(line => { var cellPass = ParseLine(line); if (!cellPass.lineParsedOK) { // Each cell is parsed independently, so we can short circuit processing if a line did not parse return; } processor.DataTime = DateTime.SpecifyKind(cellPass.Time, DateTimeKind.Utc); // There is no RMV in the CSV file - set on ground to be true all the time. processor.SetOnGround(OnGroundState.YesLegacy); // Default Volvo machine to MC024 sensor returning CMV values // TODO: understand if this is a special sensor for Volvo // TODO: understand meaning of the ICMVType field processor.ICSensorType = CompactionSensorType.MC024; // TODO: Understand the relationship of Volvo CMV value to internal CMV value processor.SetICCCVValue((short)Math.Round(cellPass.LastCMV)); processor.MachineType = VolvoEarthworksCSVRecord.MachineTypeFromString(cellPass.Machine); if (processor.MachineType == MachineType.Unknown) { _log.LogDebug($"Machine type name {cellPass.Machine} generated an unknown machine type"); } // Add the events for this line if (currentTime < processor.DataTime) { // Fill in the machine events for this epoch processor.Design = cellPass.DesignName; } // Convert mph to cs/s. 44.704 is the magic mph to cm/s conversion factor var speedInCentimetersPerSecond = (int)Math.Round(cellPass.Speed_mph * 44.704); processor.SetICMachineSpeedValue(speedInCentimetersPerSecond); processor.ICPassTargetValue = (ushort)cellPass.TargetPassCount; processor.ValidPosition = cellPass.ValidPos ? (byte)1 : (byte)0; processor.ICLayerIDValue = (ushort)cellPass.Lift; processor.SetICFrequency((ushort)cellPass.LastFreq_Hz); processor.SetICAmplitude(cellPass.LastAmp_mm == -1000 ? CellPassConsts.NullAmplitude : (ushort)Math.Round(cellPass.LastAmp_mm * 100)); processor.ICTargetLiftThickness = (float)(cellPass.TargThickness_FT / 3.048); processor.ICGear = VolvoEarthworksCSVRecord.MachineGearFromString(cellPass.MachineGear); if (processor.ICGear == MachineGear.Null) { _log.LogDebug($"Machine gear name {cellPass.MachineGear} generated a null machine gear"); } processor.SetICTemperatureValue((ushort)cellPass.LastTemp_f); processor.ICMode = (byte)((cellPass.VibeState == "On" ? 1 : 0) << ICModeFlags.IC_TEMPERATURE_VIBRATION_STATE_SHIFT); // Add the cell pass for this line. // Note: Half pass is hardwired to false, and pass type is hardwired to front drum/blade swather.SwathSingleCell(false, PassType.Front, cellPass.CellE_m, cellPass.CellN_m, VOLVO_EARTHWORKS_GRID_CELL_SIZE, cellPass); processor.ProcessedEpochCount = swather.ProcessedEpochNumber; }); return(TAGReadResult.NoError); }