555 lines
21 KiB
C#
555 lines
21 KiB
C#
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<List<Result>> _Results = new List<List<Result>>();
|
|
|
|
public static void Create(Project Project, Chamber Chamber)
|
|
{
|
|
_Project = Project;
|
|
_Chamber = Chamber;
|
|
_Sensors = new List<Sensor>();
|
|
_File = "";
|
|
|
|
// Set project stop to UTC for current object
|
|
_Project.Stop = _Project.Stop == null ? Time.UTC : (DateTime)_Project.Stop;
|
|
|
|
}
|
|
|
|
|
|
public static List<Sensor> Sensors
|
|
{
|
|
get { return _Sensors; }
|
|
set { _Sensors = value; }
|
|
}
|
|
private static List<Sensor> _Sensors = new List<Sensor>();
|
|
|
|
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<ExportDataItem> exportDataItems = new List<ExportDataItem>();
|
|
|
|
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<Result> 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<Int32> calibrationPKs = new List<int>();
|
|
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<Result> 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<List<Result>>();
|
|
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<Int32> calibrationPKs = new List<int>();
|
|
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();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|