using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Maser.Feanor.Model; using Maser.Feanor.Biz; using System.IO; using System.Globalization; namespace FeanorProjects { public static class Export { private static StringBuilder _Content; // File content private static List> _Results = new List>(); public static void Create(Project Project, Chamber Chamber) { _Project = Project; _Chamber = Chamber; _Sensors = new List(); _File = ""; // Set project stop to UTC for current object _Project.Stop = _Project.Stop == null ? Time.UTC : (DateTime)_Project.Stop; } public static List Sensors { get { return _Sensors; } set { _Sensors = value; } } private static List _Sensors = new List(); public static Project Project { get { return _Project; } } private static Project _Project; public static Chamber Chamber { get { return _Chamber; } } private static Chamber _Chamber; public static String File { get { return _File; } set { _File = value; } } private static String _File; public static Boolean ToFile() { try { GetResults(); } catch(Exception ex) { string msg = "Exception in Export.ToFile() during GetResults() -> " + ex.Message; throw new Exception(msg); } _Content = new StringBuilder(); _Content.AppendLine(ProjectHeader); _Content.AppendLine(ChamberHeader); _Content.AppendLine(SensorHeader); _Content.AppendLine(UncertaintyHeader); AppendDataField(); _Content.AppendLine(FileStamp); // Write the file try { FileStream fileStream = new FileStream(_File, FileMode.Create); StreamWriter MyStreamWriter = new StreamWriter(fileStream); MyStreamWriter.WriteLine(_Content); MyStreamWriter.Close(); fileStream.Close(); return true; } catch (Exception ex) { string msg = "Exception in Export.ToFile() during writing of file -> " + ex.Message; throw new Exception(msg); } } private static void AppendDataField() { List exportDataItems = new List(); String[,] dataField = new String[_Results[0].Count, _Sensors.Count + 1]; DateTime start = _Results[0][0].TimeStamp; // sensor0 primary sensor (with timestamp) for (int i = 1; i < _Sensors.Count; i++) //sensor1,sensor2,.... (without timestamp) { Sensor sensor = _Sensors[i]; List results = _Results[i]; } int count = 0; TimeSpan maxDifference = new TimeSpan(0, 0, 20); // max difference in time from sensor 0 timestamp TimeSpan minDifference = new TimeSpan(0, 0, -20); // min difference in time from sensor 0 timestamp //Console.WriteLine("count 0 and 1 "+ _Results[0].Count.ToString() + " " +_Results[2].Count.ToString()); //foreach (Result r in _Results[2]) // Itereer door elke rij van de eerste sensor //Console.WriteLine("v ch1 " + r.TimeStamp.ToString() + " | " + r.Value.ToString()); Int32 foundsensorpk = 0; double[] CalibrCoeff = new double[40]; for (int i = 0; i < _Sensors.Count; i++) { try { List calibrationPKs = new List(); foreach (Result r in _Results[i]) { if (!calibrationPKs.Contains(r.CalibrationPK)) { calibrationPKs.Add(r.CalibrationPK); foundsensorpk = r.SensorPK; } } Calibration t = new Calibrations().GetLastCreatedBySensorPK(foundsensorpk); if (t != null) // calibration found { CalibrCoeff[2*i] = t.Coefficients[1]; // gain CalibrCoeff[2*i+1] = t.Coefficients[0]; // offset } else // no calibration found { CalibrCoeff[2 * i] = 1.0; // gain CalibrCoeff[2 * i + 1] = 0.0; // offset } } catch { string msg = "Could not retrieve calibrations for sensor "; } } int[] shift = new int[_Sensors.Count]; int[] skipcount = new int[_Sensors.Count]; #region oldExportSorter /* // Primary sensor is sensor with lowest ID (the first object in _Sensors) foreach (Result r in _Results[0]) // for each row (first sensor) { ExportDataItem item = new ExportDataItem(r.TimeStamp, (r.Value*CalibrCoeff[0]+CalibrCoeff[1]), _Results.Count, start); // for sensor 0 export value and timestamp first sensor exportDataItems.Add(item); Console.Write(r.TimeStamp.ToString() + " " + r.Value.ToString() + " "); for (int i = 1; i < _Sensors.Count; i++) // for the sensor1, sensor2, .... { try { TimeSpan difference = r.TimeStamp - _Results[i][count-shift[i]].TimeStamp; // Calculate difference between sensor 0 and sensor X Console.Write(difference.TotalSeconds.ToString() + " "); if (difference <= maxDifference && difference >= minDifference) // If difference is between min and max { // difference between sensor0 and sensor X is between max and min difference --> ADD value to file } else { // difference between sensor0 and sensor X is not between max and min difference --> DO NOT ADD VALUE to file shift[i]++; } if (_Results[i][count - shift[i]].Value == 9999.99) { item.AddValue(_Results[i][count-shift[i]].Value, i); } else { _Results[i][count - shift[i]].Value = _Results[i][count-shift[i]].Value * CalibrCoeff[2*i] + CalibrCoeff[2*i+1]; item.AddValue(_Results[i][count-shift[i]].Value, i); } Console.Write(_Results[i][count - shift[i]].Value.ToString() + " "); } catch { } } count++; // next row Console.WriteLine(); } */ #endregion bool debug = true; foreach (Result r in _Results[0]) { //Console.WriteLine("timestamp "+ r.TimeStamp.ToString()); ExportDataItem item = new ExportDataItem( r.TimeStamp, (r.Value * CalibrCoeff[0] + CalibrCoeff[1]), _Results.Count, start ); exportDataItems.Add(item); for (int i = 1; i < _Sensors.Count; i++) // Itereren over andere sensoren (o.a. sensor 2) { bool dataAdded = false; int index = BinarySearchClosestTimestamp(_Results[i], r.TimeStamp); if (index != -1) { TimeSpan diff = _Results[i][index].TimeStamp - r.TimeStamp; if (diff <= maxDifference && diff >= minDifference) { double calibratedValue = (_Results[i][index].Value != 9999.99) ? _Results[i][index].Value * CalibrCoeff[2 * i] + CalibrCoeff[2 * i + 1] : _Results[i][index].Value; item.AddValue(calibratedValue, i); dataAdded = true; } } // Voeg 0 toe als er geen match was if (!dataAdded) { item.AddValue(0.0, i); } } } foreach (ExportDataItem exportDataItem in exportDataItems) // for each line of .csv file { _Content.AppendLine(exportDataItem.ToString()); // add line to content } } private static int BinarySearchClosestTimestamp(List results, DateTime targetTimestamp) { int left = 0, right = results.Count - 1; while (left <= right) { int mid = left + (right - left) / 2; if (results[mid].TimeStamp == targetTimestamp) return mid; else if (results[mid].TimeStamp < targetTimestamp) left = mid + 1; else right = mid - 1; } int closestIndex = Math.Max(0, Math.Min(left, results.Count - 1)); return closestIndex; } private static void GetResults() { _Results = new List>(); foreach (Sensor sensor in _Sensors) { if(Chamber.Humidity == true) { _Results.Add(new Results().GetByProjectWindow(_Project.PK, sensor.PK)); } else { _Results.Add(new Results().GetByProjectWindowOudeHal(_Project.PK, sensor.PK)); } } } private static string UncertaintyHeader { get { String uncertainty; uncertainty = String.Format("Uncertainty (k=2), {0:0}, ", Math.Ceiling((double)_Chamber.Interval / 2)); double U = 0; Int32 foundsensorpk = 0; for (int i = 0; i < _Sensors.Count; i++) { try { List calibrationPKs = new List(); foreach (Result r in _Results[i]) { if (!calibrationPKs.Contains(r.CalibrationPK)) { //Console.WriteLine(r.SensorPK.ToString()); // 21 dit gaat goed calibrationPKs.Add(r.CalibrationPK); //Console.WriteLine(r.CalibrationPK.ToString()); foundsensorpk = r.SensorPK; } } Console.Write("Found sensor PK = "); Console.WriteLine(foundsensorpk.ToString()); Calibration t = new Calibrations().GetLastCreatedBySensorPK(foundsensorpk); if (t != null) // calibration found { U = t.Uncertainty; Console.Write("a = "); Console.Write(t.Coefficients[1]); // gain Console.Write(" "); Console.Write("b = "); Console.WriteLine(t.Coefficients[0]); // offset } else // no calibration found { Console.WriteLine("No calibration found for this sensor ( a = 0 and b = 0 )"); U = 0.0; } } catch { string msg = "Could not retrieve calibrations for sensor "; msg += string.Format("PK={0:0} ChamberPK={1:0) ID={2:00} [{3}]", _Sensors[i].PK, _Sensors[i].ChamberPK, _Sensors[i].ID, _Sensors[i].Description); throw new Exception(msg); } uncertainty += String.Format("{0:0.00},", U); } // Remove last comma of line uncertainty = uncertainty.Remove(uncertainty.Length - 1, 1); Console.WriteLine(uncertainty); return uncertainty; } } private static string SensorHeader { get { String sensorHeader; // Are sensors from other chambers linked to project's chamber? bool linked = false; foreach (Sensor sensor in _Sensors) { if (sensor.ChamberPK != _Chamber.PK) { linked = true; break; } } sensorHeader = "Timestamp, Duration,"; foreach (Sensor sensor in _Sensors) { if(linked) { try { Chamber c = new Chambers().GetByPK(sensor.ChamberPK); sensorHeader = string.Format("{0:00000}.{1:00} {2}", c.MIDS, sensor.ID, sensor.Description); } catch { sensorHeader += String.Format("\"#{0:00} {1}\",", sensor.ID, sensor.Description); } } else sensorHeader += String.Format("\"#{0:00} {1}\",", sensor.ID, sensor.Description); } // Remove last comma of line sensorHeader = sensorHeader.Remove(sensorHeader.Length - 1, 1); // Add newline sensorHeader += "\n"; // Units sensorHeader += "YYYY/MM/DD @ hh:mm:ss, s,"; foreach (Sensor sensor in _Sensors) sensorHeader += String.Format("{0},", sensor.Units); // Remove last comma of line sensorHeader = sensorHeader.Remove(sensorHeader.Length - 1, 1); return sensorHeader; } } private static string ProjectHeader { get { DateTime stop = (DateTime)_Project.Stop; // Cast to non-nullable string projectHeader; projectHeader = "Project details\r\n"; projectHeader += String.Format(",Customer, \"{0}\"\r\n", _Project.Customer); projectHeader += String.Format(",P{0:000000} , \"{1}\"\r\n", _Project.ProjectID, _Project.ProjectDescription); projectHeader += String.Format(",Sub {0:00} , \"{1}\"\r\n", _Project.SubProject, _Project.SubProjectDescription); String stepD = _Project.StepDescription; stepD = stepD.Replace(System.Environment.NewLine, " "); Console.WriteLine(stepD); projectHeader += String.Format(",Step {0:00} , \"{1}\"\r\n", _Project.Step, stepD); projectHeader += String.Format(",Start, {0:0000}/{1:00}/{2:00} @ {3:00}:{4:00}\r\n", _Project.Start.Year, _Project.Start.Month, _Project.Start.Day, _Project.Start.Hour+1, _Project.Start.Minute); projectHeader += String.Format(",Stop, {0:0000}/{1:00}/{2:00} @ {3:00}:{4:00}\r\n", stop.Year, stop.Month, stop.Day, stop.Hour+1, stop.Minute); projectHeader += "\r\n"; projectHeader += ",Note: Time is observed in Central European Time+1 (UTC+1).\r\n"; return projectHeader; } } private static string ChamberHeader { get { // return String.Format("Apparatus, \"{0:00000} {1}\"\r\n", _Chamber.MIDS, _Chamber.Description); return String.Format("Apparatus, \"{0:00000}\"\r\n", _Chamber.MIDSandDescription); } } public static string FileStamp { get { string str = "Maser Engineering B.V. Central Monitoring System"; //return String.Format("\r\n{0}{1}{2} {3}", Time.UTC.Year, Time.UTC.Month, Time.UTC.Day, str); // <-- original \r\n zorgt voor witregel wat problemen met META geeft return String.Format("{0}{1}{2} {3}", Time.UTC.Year, Time.UTC.Month, Time.UTC.Day, str); } } public static string DefaultExportFileName { get { return String.Format("P{0:00000}-{1:00}-{2:00} measurements in {3:00000}.csv", _Project.ProjectID, _Project.SubProject, _Project.Step, _Chamber.MIDS); } } } public class ExportDataItem { public DateTime TimeStamp { get { return _timeStamp; } } private DateTime _timeStamp; private Double[] _sensorData; private DateTime _startOfProject; public ExportDataItem(DateTime timeStamp, Double firstValue, Int32 sensorCount, DateTime startOfProject) { _timeStamp = timeStamp; _sensorData = new Double[sensorCount]; _sensorData[0] = firstValue; _startOfProject = startOfProject; } public void AddValue(Double value, Int32 SensorNr) { try { if (SensorNr < _sensorData.Length) _sensorData[SensorNr] = value; } catch { } } public override string ToString() { StringBuilder result = new StringBuilder(); var culture = CultureInfo.InvariantCulture; // Zorgt ervoor dat het decimaalteken altijd een punt is. // exported time is UTC + 1 !!!! // onderstaande regel zorgde voor fouten rond middernacht data zoals 00h01 werd geexporteerd als 24h01 // result.AppendFormat("{0:0000}/{1:00}/{2:00} @ {3:00}:{4:00}:{5:00},", TimeStamp.Year, TimeStamp.Month, TimeStamp.Day, TimeStamp.Hour+1, TimeStamp.Minute, TimeStamp.Second); DateTime localTime = TimeStamp.AddHours(1); // UTC +1 correct verwerken result.AppendFormat("{0:0000}/{1:00}/{2:00} @ {3:00}:{4:00}:{5:00},", localTime.Year, localTime.Month, localTime.Day, localTime.Hour, localTime.Minute, localTime.Second); result.AppendFormat("{0}", ((TimeSpan)TimeStamp.Subtract(_startOfProject)).TotalSeconds); foreach (Double value in _sensorData) { if (Math.Abs(value) < 1 && value != 0) { int k = 0; Double v = Math.Abs(value); while (v < 10 && k < 10) { v = v * 10; k++; } string s = ",{0:0."; for (int i = 0; i < k; i++) { s += "0"; } s += "000}"; result.AppendFormat(culture,s, value); } else { result.AppendFormat(culture,",{0:0.00}", value); } } //Console.WriteLine(result.ToString()); return result.ToString(); } } }