/// <summary> /// Clear all data to start new tagfile /// </summary> public void Reset() { EpochRec = new EpochRecord(); TagName = String.Empty; TagValue = String.Empty; HaveName = false; HaveValue = false; HeaderRecordCount = 0; HeaderRequired = true; HeaderUpdated = false; TrailerRequired = false; updateCount = 0; EpochCount = 0; TagContent = new TagContentList(); // zero list }
/// <summary> /// /// </summary> /// <param name="txt">Each field from data packet should be in the order RS+Name+Value</param> /// <returns></returns> public bool ParseText(string txt) { // Note STX and ETX, ENQ, ACK, NAK should not enter here as a rule. packetIsHeader = false; // If debugging (causing a ide delay) this can be commented out if (prevEpochTime != DateTime.MinValue) { // this check is here to prevent two epochs seprated by a min time interval being stitched together TimeSpan minSpanAllowed = TimeSpan.FromSeconds(TagConstants.MIN_EPOCH_INTERVAL_SECS); TimeSpan currentSpan = DateTime.Now - prevEpochTime; if (currentSpan > minSpanAllowed) { if (Prev_EpochRec != null) { Prev_EpochRec = null; // stops the previous epoch being associated to this epoch } if (_PrevTagFile_EpochRec != null) { _PrevTagFile_EpochRec = null; } } } prevEpochTime = DateTime.Now; try { byte[] bArray = Encoding.UTF8.GetBytes(txt); if (!ValidateText(ref bArray)) { return(false); } HaveName = false; HaveValue = false; // construct records(tagfile fields) byte by byte for (int i = 0; i < bArray.Length; i++) { switch (bArray[i]) { case TagConstants.STX: continue; case TagConstants.ETX: continue; case TagConstants.ENQ: continue; case TagConstants.ACK: continue; case TagConstants.NAK: continue; case TagConstants.RS: if (HaveName && TagValue != String.Empty) { ProcessField(); } HaveName = false; HaveValue = false; TagValue = String.Empty; TagName = String.Empty; continue; default: if (!HaveName) { TagName = TagName + (char)bArray[i]; HaveName = TagName.Length == TagConstants.TAG_NAME_LENGHT; } else { TagValue = TagValue + (char)bArray[i]; if (!HaveValue) { HaveValue = true; } if (HaveName && i == bArray.Length - 1) // endoftext { if (HaveName && TagValue != String.Empty) { var res = ProcessField(); if (res == false) { return(false); } } } } continue; } } // finally process all fields picked out of the datapacket var newHeader = false; LastStateEpochRecord.EpochCopyLatestValues(ref EpochRec); // Remeber last valid values for each tag if (Prev_EpochRec != null) // test needed { // Check if its the same position and elevation if (packetIsHeader) // if header record { UpdateTagContentList(ref EpochRec, ref newHeader, TagConstants.UpdateReason.NewHeader); } else if (EpochRec.MachineStateDifferent(ref Prev_EpochRec)) { UpdateTagContentList(ref EpochRec, ref newHeader, TagConstants.UpdateReason.ChangeRecord); if (NotSeenNewPosition && updateCount > 1) { NotSeenNewPosition = false; } } else { Log.LogError($"** Same Position ***"); } } else if (packetIsHeader) { UpdateTagContentList(ref EpochRec, ref newHeader, TagConstants.UpdateReason.NewHeader); } else { UpdateTagContentList(ref EpochRec, ref newHeader, TagConstants.UpdateReason.ChangeRecord); } if (newHeader) // Is this the start of a new tagfile { if (_PrevTagFile_EpochRec != null) // epoch from last tagfile { if (_PrevTagFile_EpochRec.IsFullPositionEpoch()) // if it is a new tagfile we use last known epoch to start new tagfile { UpdateTagContentList(ref _PrevTagFile_EpochRec, ref tmpNR, TagConstants.UpdateReason.LastTagFileEpoch); } _PrevTagFile_EpochRec = null; LastStateEpochRecord.ClearEpoch(); } } else { if (Prev_EpochRec == null) { Prev_EpochRec = new EpochRecord(); } Prev_EpochRec.EpochCopy(ref LastStateEpochRecord); } return(true); } catch (Exception e) { Log.LogError($"Unexpected error occured in ParseText. Error:{e.Message}, {e.StackTrace}"); return(false); } }
/// <summary> /// Checks we have enough input data to create a tagfile epoch /// </summary> public void UpdateTagContentList(ref EpochRecord eRecord, ref bool newHeader, TagConstants.UpdateReason reason) { if (DebugTraceToLog) { Log.LogInformation($"* UpdateTagContentList * {reason}"); } newHeader = false; var timeAdded = false; if (!HeaderUpdated & !eRecord.HasMTP) // dont process any epoch before recieving a header { Log.LogWarning("Epoch ignored before recieving header record"); // should not happen return; } if (!eRecord.HasUpdateData() && !TrailerRequired) { return; } if (reason == TagConstants.UpdateReason.ChangeRecord) { updateCount++; } if (!HeaderUpdated) { if (eRecord.HasTime) { TagContent.AddTimeEntry(new TagData_UnsignedInt() { Data = eRecord.Time }); TagContent.AddWeekEntry(new TagData_UnsignedInt() { Data = eRecord.Week }); eRecord.Time = uint.MaxValue; // reset HeaderRecordCount++; HeaderUpdated = true; timeAdded = true; // Some fields are defaulted by Trimble set them up here now // todo add these to appsettings as defaults eRecord.CoordSys = TagConstants.DEFAULT_COORDSYS; // coordinate system if (eRecord.MappingMode == ushort.MaxValue) { eRecord.MappingMode = TagConstants.DEFAULT_MAPPINGMODE; // min elevation defaulted if not supplied to suit marine } eRecord.RadioType = TagConstants.DEFAULT_RADIOTYPE; // torch eRecord.AppVersion = TagConstants.DEFAULT_APPVERSION; // app version eRecord.ValidPosition = TagConstants.DEFAULT_VALID_POSITION; // has valid position newHeader = true; } } if (eRecord.HasCST) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.CST, DataType = TAGDataType.t8bitUInt, Data = eRecord.CST }); eRecord.CST = uint.MaxValue; } if (eRecord.HasFlags) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.Flags, DataType = TAGDataType.t4bitUInt, Data = eRecord.Flags }); eRecord.Flags = uint.MaxValue;; } if (eRecord.HasTargetCCV) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.TargetCCV, DataType = TAGDataType.t12bitUInt, Data = eRecord.TargetCCV }); eRecord.TargetCCV = uint.MaxValue; } if (eRecord.HasTargetMDP) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.TargetMDP, DataType = TAGDataType.t12bitUInt, Data = eRecord.TargetMDP }); eRecord.TargetMDP = uint.MaxValue; } if (eRecord.HasDirection) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.Direction, DataType = TAGDataType.t4bitUInt, Data = eRecord.Direction }); eRecord.Direction = uint.MaxValue; } if (eRecord.HasTemperature) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.Temperature, DataType = TAGDataType.t12bitUInt, Data = eRecord.Temperature }); eRecord.Temperature = uint.MaxValue; } if (eRecord.HasCoordSys) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.CoordSys, DataType = TAGDataType.t4bitUInt, Data = eRecord.CoordSys }); eRecord.CoordSys = ushort.MaxValue;; } if (eRecord.HasValidPosition) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.ValidPosition, DataType = TAGDataType.t4bitUInt, Data = eRecord.ValidPosition }); eRecord.ValidPosition = ushort.MaxValue; } if (eRecord.HasMappingMode) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.MappingMode, DataType = TAGDataType.t8bitUInt, Data = eRecord.MappingMode }); eRecord.MappingMode = ushort.MaxValue;; } if (eRecord.HasDesign) { TagContent.AddEntry(new TagData_Unicode() { DictID = (short)DictionaryItem.Design, DataType = TAGDataType.tUnicodeString, Data = eRecord.Design }); eRecord.Design = String.Empty; } if (eRecord.HasLAT) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Latitude, DataType = TAGDataType.tIEEEDouble, Data = eRecord.LAT }); eRecord.LAT = double.MaxValue; HeaderRecordCount++; } if (eRecord.HasLON) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Longtitude, DataType = TAGDataType.tIEEEDouble, Data = eRecord.LON }); eRecord.LON = double.MaxValue; HeaderRecordCount++; } if (eRecord.HasHGT) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.height, DataType = TAGDataType.tIEEEDouble, Data = eRecord.HGT }); eRecord.HGT = double.MaxValue; } if (eRecord.HasUTM) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.UTMZone, DataType = TAGDataType.t8bitUInt, Data = eRecord.UTM }); eRecord.UTM = byte.MaxValue; } if (eRecord.HasTargetThickness) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.TargetThickness, DataType = TAGDataType.t16bitUInt, Data = eRecord.TargetThickness }); eRecord.TargetThickness = uint.MaxValue; } if (eRecord.HasTargetPasses) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.TargetPasses, DataType = TAGDataType.t12bitUInt, Data = eRecord.TargetPasses }); eRecord.TargetPasses = uint.MaxValue; } if (eRecord.HasTempMin) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.TempMin, DataType = TAGDataType.t12bitUInt, Data = eRecord.TempMin }); eRecord.TempMin = uint.MaxValue; } if (eRecord.HasTempMax) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.TempMax, DataType = TAGDataType.t12bitUInt, Data = eRecord.TempMax }); eRecord.TempMax = uint.MaxValue; } if (TransmissionProtocolVersion < TagConstants.TRANSMISSION_PROTOCOL_VERSION_ONE) { HeaderRequired = HeaderRecordCount < 3; // do we have the key main header values } else { HeaderRequired = !eRecord.HasHeader; } if (eRecord.HasTime & !timeAdded) { if (eRecord.HasDeltaTime) { TagContent.AddTimeDeltaEntry(new TagData_UnsignedInt() { Data = eRecord.DeltaTime }); } else { TagContent.AddTimeEntry(new TagData_UnsignedInt() { Data = eRecord.Time }); } eRecord.DeltaTime = uint.MaxValue; eRecord.Time = uint.MaxValue; // reset EpochCount++; } if (eRecord.HasLEB || eRecord.HasLNB || eRecord.HasLHB) { TagContent.AddEntry(new TagData_Empty() { DictID = (short)DictionaryItem.Left, DataType = TAGDataType.tEmptyType }); if (eRecord.HasLEB) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Easting, DataType = TAGDataType.tIEEEDouble, Data = eRecord.LEB }); eRecord.LEB = double.MaxValue; } if (eRecord.HasLNB) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Northing, DataType = TAGDataType.tIEEEDouble, Data = eRecord.LNB }); eRecord.LNB = double.MaxValue; } if (eRecord.HasLHB) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Elevation, DataType = TAGDataType.tIEEEDouble, Data = eRecord.LHB }); eRecord.LHB = double.MaxValue; } } if (eRecord.HasREB || eRecord.HasRNB || eRecord.HasRHB) { TagContent.AddEntry(new TagData_Empty() { DictID = (short)DictionaryItem.Right, DataType = TAGDataType.tEmptyType }); if (eRecord.HasREB) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Easting, DataType = TAGDataType.tIEEEDouble, Data = eRecord.REB }); eRecord.REB = double.MaxValue; } if (eRecord.HasRNB) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Northing, DataType = TAGDataType.tIEEEDouble, Data = eRecord.RNB }); eRecord.RNB = double.MaxValue; } if (eRecord.HasRHB) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.Elevation, DataType = TAGDataType.tIEEEDouble, Data = eRecord.RHB }); eRecord.RHB = double.MaxValue; } } if (eRecord.HasHDG) { // special field todo. Heading does not go to tagfile. will go somewhere else eventually eRecord.HDG = double.MaxValue; } if (eRecord.HasMSD) { TagContent.AddEntry(new TagData_Double() { DictID = (short)DictionaryItem.MachineSpeed, DataType = TAGDataType.tIEEEDouble, Data = eRecord.MSD }); eRecord.MSD = double.MaxValue; } if (eRecord.HasGPM) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.GPSMode, DataType = TAGDataType.t4bitUInt, Data = eRecord.GPM }); eRecord.GPM = ushort.MaxValue; } if (eRecord.HasBOG) { // writes On_GROUND and BLADE_ON_GROUND together TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.OG, DataType = TAGDataType.t4bitUInt, Data = eRecord.BOG }); TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.BOG, DataType = TAGDataType.t4bitUInt, Data = eRecord.BOG }); eRecord.BOG = ushort.MaxValue; } if (eRecord.HasCCV) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.CCV, DataType = TAGDataType.t12bitUInt, Data = eRecord.CCV }); eRecord.CCV = uint.MaxValue; } if (eRecord.HasMDP) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.MDP, DataType = TAGDataType.t12bitUInt, Data = eRecord.MDP }); eRecord.MDP = uint.MaxValue; } if (TrailerRequired) { if (ForceSerial != string.Empty) { eRecord.RadioSerial = ForceSerial; eRecord.Serial = ForceSerial; } if (eRecord.HasRadioSerial) { TagContent.AddEntry(new TagData_String() { DictID = (short)DictionaryItem.RadioSerial, DataType = TAGDataType.tANSIString, Data = eRecord.RadioSerial }); eRecord.RadioSerial = String.Empty; } if (eRecord.HasRadioType) { TagContent.AddEntry(new TagData_String() { DictID = (short)DictionaryItem.RadioType, DataType = TAGDataType.tANSIString, Data = eRecord.RadioType }); eRecord.RadioType = String.Empty; } if (eRecord.HasSerial) { TagContent.AddEntry(new TagData_String() { DictID = (short)DictionaryItem.FileSerial, DataType = TAGDataType.tANSIString, Data = eRecord.Serial }); eRecord.Serial = String.Empty; } if (eRecord.HasMID) { TagContent.AddEntry(new TagData_String() { DictID = (short)DictionaryItem.MachineID, DataType = TAGDataType.tANSIString, Data = eRecord.MID }); eRecord.MID = String.Empty; } if (eRecord.HasAppVersion) { TagContent.AddEntry(new TagData_String() { DictID = (short)DictionaryItem.ApplicationVersion, DataType = TAGDataType.tANSIString, Data = eRecord.AppVersion }); eRecord.AppVersion = String.Empty; } if (eRecord.HasMTP) { TagContent.AddEntry(new TagData_UnsignedInt() { DictID = (short)DictionaryItem.MachineType, DataType = TAGDataType.t8bitUInt, Data = eRecord.MTP }); eRecord.MTP = byte.MaxValue; } } }
/// <summary> /// Make copy of last epoch to be reused in new tagfile /// </summary> public void CloneLastEpoch() { _PrevTagFile_EpochRec = new EpochRecord(); _PrevTagFile_EpochRec.EpochCopy(ref EpochRec); }