using System; using System.Collections.Generic; using System.Linq; using DTS.Common.Classes.Sensors; namespace DTS.SensorDB.TSF { /// /// handles the sensor channel information section of the TSF /// can contain /// datachan,rack,mod,chan,descrip,s/n,offsetlow,offsethigh,calmode,calstep(ohm/volt),shuntval(eu),proptoext,sens(mv/eu or mv/v/eu),gain,extvolt,EU,filter,invert,zeroref,desiredmaxrange,commentfield,caldate,Offset?,InitialEU,sensorID,ISOcode,IRTRACC exponent,sensor category,desired max range scaling,C0,C1,C2,C3,C4,C5 /// these appear to be only analog sensors /// public class TSFSensorChannelInformationSection { private const string SECTION_START_HEADER = "---- Start Sensor Channel Information ----"; private const string COLUMNS_HEADER = "datachan,rack,mod,chan,descrip,s/n,offsetlow,offsethigh,calmode,calstep(ohm/volt),shuntval(eu),proptoext,sens(mv/eu or mv/v/eu),gain,extvolt,EU,filter,invert,zeroref,desiredmaxrange,commentfield,caldate,Offset?,InitialEU,sensorID"; private const string COLUMNS_HEADER_POLY = "C0,C1,C2,C3,C4,C5"; private const string SECTION_END_HEADER = "---- End Sensor Channel Information ----"; private List _entries = new List(); public TSFSensorEntry[] Entries { get => _entries.ToArray(); set => _entries = new List(value); } public TSFSensorChannelInformationSection() { } /// /// reads the section from the TSF /// assumes currentline points to the start of the section /// /// /// /// public void ReadFrom(List lines, ref int currentLine, ref List errors) { // READ IN SENSOR CHANNEL VALUES if (currentLine == lines.Count) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_UNEXPECTED_EOF, currentLine)); return; } var sectionHeader = lines[currentLine++]; if (sectionHeader != SECTION_START_HEADER) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.SENSORCHANNELSECTION_INVALIDHEADER, currentLine, sectionHeader)); return; } if (currentLine == lines.Count) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_UNEXPECTED_EOF, currentLine)); return; } var columnHeader = lines[currentLine++]; var hasPolynomials = false; if (columnHeader.Contains(COLUMNS_HEADER)) { // Valid header hasPolynomials = columnHeader.Contains(COLUMNS_HEADER_POLY); } else { // Invalid Header errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.SENSORCHANNELSECTION_INVALIDCOLUMNHEADER, currentLine, columnHeader)); return; } var done = false; var sensorEntries = new List(); var invariant = System.Globalization.CultureInfo.InvariantCulture; #region Process entries while (!done) { if (currentLine == lines.Count) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_UNEXPECTED_EOF, currentLine)); return; } var line = lines[currentLine++]; if (!line.Contains("End Sensor Channel Information")) { var tokens = line.Split(','); var entry = new TSFSensorEntry(); for (var iCurField = 0; iCurField < tokens.Length; iCurField++) { var s = tokens[iCurField]; try { var field = (TSFSensorEntry.Fields)iCurField; switch (field) { case TSFSensorEntry.Fields.caldate: try { var dateTokens = s.Split('_'); entry.CalDate = new DateTime(Convert.ToInt32(dateTokens[2], invariant), Convert.ToInt32(dateTokens[0], invariant), Convert.ToInt32(dateTokens[1], invariant)); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_CALDATE, currentLine, s)); } break; case TSFSensorEntry.Fields.calmode: { entry.CalMode = new CalMode(s); } break; case TSFSensorEntry.Fields.calstep: try { entry.CalStep = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_CALSTEP, currentLine, s)); } break; case TSFSensorEntry.Fields.chan: try { entry.Chan = Convert.ToInt32(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_CHAN, currentLine, s)); } break; case TSFSensorEntry.Fields.commentfield: entry.CommentField = s; break; case TSFSensorEntry.Fields.datachan: try { entry.DataChan = Convert.ToInt32(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_DATACHAN, currentLine, s)); } break; case TSFSensorEntry.Fields.descrip: entry.Description = s; break; case TSFSensorEntry.Fields.desiredmaxrange: try { entry.DesiredMaxRange = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_DESIREDMAXRANGE, currentLine, s)); } break; case TSFSensorEntry.Fields.desiredmaxrangescaling: try { entry.DesiredMaxRangeScaling = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_DESIREDMAXRANGESCALING, currentLine, s)); } break; case TSFSensorEntry.Fields.EU: entry.EU = s; break; case TSFSensorEntry.Fields.extvolt: try { entry.ExtVolt = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_EXTVOLT, currentLine, s)); } break; case TSFSensorEntry.Fields.filter: { double d; if (!double.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out d)) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_FILTER, currentLine, s)); } else { entry.Filter = d; } } break; case TSFSensorEntry.Fields.gain: try { entry.Gain = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_GAIN, currentLine, s)); } break; case TSFSensorEntry.Fields.InitialEU: try { entry.InitialEU = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_INITIALEU, currentLine, s)); } break; case TSFSensorEntry.Fields.invert: entry.Invert = !(s == "0" || s == "N" || s == "F"); break; case TSFSensorEntry.Fields.IRTRACCexponent: try { entry.IRTRACCexponent = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_IRTRACCEXPONENT, currentLine, s)); } break; case TSFSensorEntry.Fields.ISOcode: // The TDC SIF ISOcode feild is notoriously abused with holding non-iso information and cannot be trusted to be unique // This if statement catches some easy to identify signs of abuse and an empty ISO code if (s.Count() != (new IsoCode(string.Empty)).StringRepresentation.Count() // http://fogbugz/fogbugz/default.asp?9254 || s.Equals("0000000000000000")) { // Stomp on the incorrect ISO Code from the import because we cant trust it. s = string.Empty; } entry.ISOCode = s; break; case TSFSensorEntry.Fields.mod: try { entry.Module = Convert.ToInt32(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_MODULE, currentLine, s)); } break; case TSFSensorEntry.Fields.Offset: { switch (s) { case "0": case "F": case "N": entry.RemoveOffset = false; break; case "1": case "T": case "Y": entry.RemoveOffset = true; break; default: { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_OFFSET, currentLine, s)); } break; } } break; case TSFSensorEntry.Fields.offsethigh: try { entry.OffsetHigh = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_OFFSETHIGH, currentLine, s)); } break; case TSFSensorEntry.Fields.offsetlow: try { entry.OffsetLow = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_OFFSETLOW, currentLine, s)); } break; case TSFSensorEntry.Fields.proptoext: entry.ProportionalToExcitation = !(s == "0" || s == "N" || s == "F"); break; case TSFSensorEntry.Fields.rack: try { entry.Rack = Convert.ToInt32(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_RACK, currentLine, s)); } break; case TSFSensorEntry.Fields.sens: try { entry.Sensitivity = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_SENSITIVITY, currentLine, s)); } break; case TSFSensorEntry.Fields.sensorcategory: { switch (s) { case "0": entry.SensorCategory = SensorInformationFile.TDCSensorCategory.Normal; break; case "1": entry.SensorCategory = SensorInformationFile.TDCSensorCategory.POT; break; case "2": entry.SensorCategory = SensorInformationFile.TDCSensorCategory.IRTracc; break; case "3": entry.SensorCategory = SensorInformationFile.TDCSensorCategory.Polynomial; break; default: { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_SENSORCATEGORY, currentLine, s)); break; } } } break; case TSFSensorEntry.Fields.sensorID: if (s.Equals("NONE")) { s = string.Empty; } entry.SensorId = s; break; case TSFSensorEntry.Fields.serialNumber: if (sensorEntries.Select(x => x.SerialNumber).Contains(s)) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_DUPLICATESERIALNUMBER, currentLine, s)); } if (string.IsNullOrEmpty(entry.Description)) { entry.Description = s; } entry.SerialNumber = s; break; case TSFSensorEntry.Fields.shuntval: try { entry.ShuntValue = Convert.ToDouble(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_SHUNTVALUE, currentLine, s)); } break; case TSFSensorEntry.Fields.zeroref: try { entry.ZeroRef = new ZeroRef(s); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALID_ZEROREF, currentLine, s)); } break; case TSFSensorEntry.Fields.C0: case TSFSensorEntry.Fields.C1: case TSFSensorEntry.Fields.C2: case TSFSensorEntry.Fields.C3: case TSFSensorEntry.Fields.C4: case TSFSensorEntry.Fields.C5: // Nothing to do yet. break; default: throw new NotSupportedException("TSFFile::ReadTSF unknown field: " + field); } if (true == hasPolynomials) { switch (field) { case TSFSensorEntry.Fields.C0: try { entry.C0 = double.Parse(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_C0, currentLine, s)); } break; case TSFSensorEntry.Fields.C1: try { entry.C1 = double.Parse(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_C1, currentLine, s)); } break; case TSFSensorEntry.Fields.C2: try { entry.C2 = double.Parse(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_C2, currentLine, s)); } break; case TSFSensorEntry.Fields.C3: try { entry.C3 = double.Parse(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_C3, currentLine, s)); } break; case TSFSensorEntry.Fields.C4: try { entry.C4 = double.Parse(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_C4, currentLine, s)); } break; case TSFSensorEntry.Fields.C5: try { entry.C5 = double.Parse(s, invariant); } catch (Exception) { errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSORCHANNEL_INVALID_C5, currentLine, s)); } break; } } } catch (Exception) { //errors.Add("TSF_INVALID_SENSOR_CHANNEL_INFO_FIELD" + iCurField.ToString()); errors.Add(new ReadTSFError(ReadTSFError.TSF_ERRORS.TSF_SENSOR_CHANNEL_INVALIDFIELD, currentLine, iCurField.ToString())); continue; } } sensorEntries.Add(entry); //tdc has some additional logic to do some scaling over what the desired max range is ... we don't do that yet ... /* // Store unscaled desired max range values, and then scale. Sensor_UnscaledDesiredMaxRange[r][m][c] = Sensor_DesiredMaxRange[r][m][c]; Sensor_DesiredMaxRange[r][m][c] *= Sensor_DesiredMaxRangeScaling; if (0.0 == Sensor_IRTRACC_Exponent[r][m][c]) { Sensor_IRTRACC_Exponent[r][m][c] = IRTRACC_DEFAULT_EXPONENT; } // DETERMINE GAIN BASED ON DESIRED MAX RANGE DetermineMaxRangeandGain(r, m, c, Sensor_DesiredMaxRange[r][m][c], &gain[3], &gain[5], &range[3], &range[5]); if(IsG5 (Rack_SN[r])) //G5 { Sensor_Gain[r][m][c]=gain[5]; } else //PRO { Sensor_Gain[r][m][c]=gain[3]; } */ } else { done = true; } } #endregion Entries = sensorEntries.ToArray(); } } }