2284 lines
104 KiB
C#
2284 lines
104 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using Maser.Feanor.Model;
|
|
using Maser.Feanor.Biz;
|
|
using Maser.Feanor.MIDSInterface;
|
|
using System.IO;
|
|
using MySqlConnector;
|
|
|
|
using System.Data.SqlClient;
|
|
|
|
using OxyPlot;
|
|
using OxyPlot.Series;
|
|
using OxyPlot.WindowsForms;
|
|
using OxyPlot.Legends;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml.Linq;
|
|
using OxyPlot.Annotations;
|
|
|
|
using System;
|
|
using System.Net.Http;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks; // Nodig voor async/await
|
|
|
|
|
|
|
|
/*
|
|
* Transparant --> geen test in kast
|
|
* Groen --> test in kast, alles OK
|
|
* EUrofins-donker-oranje --> test in kast, iets niet OK
|
|
* Eurofins-licht-oranje --> Kast heeft general data error!
|
|
* Paars --> Kast heeft geen status!? (dit is niet te bedoeling)
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
namespace HalCheck
|
|
{
|
|
public partial class HalControle : Form
|
|
{
|
|
private PlotModel plotModel;
|
|
private PlotView plotView;
|
|
private Dictionary<int, List<SensorReading>> sensorValues;
|
|
private Dictionary<object, int> sensorAttempts = new Dictionary<object, int>();
|
|
|
|
// save location for dgvProjects information xml file
|
|
string filePath = @"Z:\projects\2025\P250082\sub1\dgvProjects.xml";
|
|
|
|
bool isLoadingData = true; // Vlag om aan te geven of data wordt geladen
|
|
|
|
bool lbSensorChanged = false;
|
|
|
|
bool humidityLOW = false;
|
|
|
|
List<CabinetStatus> cabinets = new List<CabinetStatus>{ // links/recht , hoogte Color.Purple/Orange/Red
|
|
new CabinetStatus { Name = "1120", Position = new Point(430, 470), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3094", Position = new Point(520, 470), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1865", Position = new Point(620,470), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2750", Position = new Point(250, 470), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3097", Position = new Point(160, 470), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "986", Position = new Point(340, 470), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "1593", Position = new Point(260, 330), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1586", Position = new Point(260, 380), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2249", Position = new Point(340, 330), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2250", Position = new Point(340, 380), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2798", Position = new Point(415, 330), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2799", Position = new Point(415, 380), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2443", Position = new Point(490, 370), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "77", Position = new Point(560, 370), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "526", Position = new Point(630, 370), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "18", Position = new Point(710, 260), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "2318", Position = new Point(220, 630), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2319", Position = new Point(285, 630), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2599", Position = new Point(345, 630), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3096", Position = new Point(430, 630), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3095", Position = new Point(530, 630), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1056", Position = new Point(620, 630), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "3098", Position = new Point(530, 700), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3140", Position = new Point(430, 700), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "38", Position = new Point(830, 300), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1232", Position = new Point(830, 400), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1233", Position = new Point(830, 500), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "1238", Position = new Point(1020, 50), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1728", Position = new Point(1020, 150), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2222", Position = new Point(1020, 260), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2546", Position = new Point(1020, 360), StatusColor = Color.Purple },//
|
|
new CabinetStatus { Name = "2547", Position = new Point(1020, 410), StatusColor = Color.Purple },//
|
|
new CabinetStatus { Name = "3050", Position = new Point(1020,490), StatusColor = Color.Purple },//
|
|
new CabinetStatus { Name = "3051", Position = new Point(1020,540), StatusColor = Color.Purple },//
|
|
|
|
new CabinetStatus { Name = "1880", Position = new Point(1120, 80), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "987", Position = new Point(1120, 160), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "847", Position = new Point(1120, 230), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "947", Position = new Point(1120, 310), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "680", Position = new Point(1120,380), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1281", Position = new Point(1120, 440), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "1282", Position = new Point(1120,500), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "1991", Position = new Point(1280, 80), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2183", Position = new Point(1280, 160), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2420", Position = new Point(1280, 250), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3111", Position = new Point(1280, 330), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "3112", Position = new Point(1280, 380), StatusColor = Color.Purple },
|
|
|
|
|
|
new CabinetStatus { Name = "2745", Position = new Point(1380, 250), StatusColor = Color.Purple },
|
|
new CabinetStatus { Name = "2998", Position = new Point(1380, 160), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "1999", Position = new Point(1185, 630), StatusColor = Color.Purple },
|
|
|
|
new CabinetStatus { Name = "2325", Position = new Point(1215, 710), StatusColor = Color.Purple },
|
|
};
|
|
|
|
List<RTHSensor> rthSensors = new List<RTHSensor>
|
|
{
|
|
new RTHSensor { Id = 35, Position = new Point(400, 250) }, // linksboven IP .191
|
|
new RTHSensor { Id = 8, Position = new Point(1200, 40) }, // compressor IP .166
|
|
new RTHSensor { Id = 31, Position = new Point(1400, 40) }, // rechtsboven IP .187
|
|
new RTHSensor { Id = 9, Position = new Point(940, 635) } // cms2 pc IP .167
|
|
};
|
|
|
|
|
|
public HalControle()
|
|
{
|
|
InitializeComponent();
|
|
|
|
System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly(); // report build version
|
|
string exe = System.IO.Path.GetFullPath(ass.Location);
|
|
DateTime dt = new System.IO.FileInfo(exe).LastWriteTimeUtc;
|
|
this.Text = String.Format("Feanor - Halcontrole" + " v{0:0000}{1:00}{2:00}", dt.Year, dt.Month, dt.Day);
|
|
|
|
obtainActiveProjects();
|
|
obtainActiveChambers();
|
|
LoadDataFromXML();
|
|
|
|
tabControl.SelectedTab = tpHal;
|
|
|
|
timerProjectDataCheck_Tick(null, null); // Direct de eerste tick uitvoeren
|
|
}
|
|
|
|
|
|
[STAThread]
|
|
static void Main()
|
|
{
|
|
Application.EnableVisualStyles();
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
Application.Run(new HalControle());
|
|
}
|
|
|
|
void obtainActiveChambers()
|
|
{
|
|
try
|
|
{
|
|
List<Chamber> chambers;
|
|
chambers = new Chambers().GetAllActive();
|
|
|
|
lbChambers.Items.Clear();
|
|
|
|
foreach (Chamber chamber in chambers)
|
|
{
|
|
lbChambers.Items.Add(chamber.MIDSandDescription); // MD
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Chambers", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void fixedChambers() // chambers with fixed values, project is not started in CMS --> dummy projects which are invisible (3 LHU chamber + 2 bake ovens)
|
|
{
|
|
int rowIndex1 = dgvProjects.Rows.Add();
|
|
dgvProjects.Rows[rowIndex1].Cells[0].Value = "LHU chamber 2318";
|
|
dgvProjects.Rows[rowIndex1].Cells[3].Value = "02318";
|
|
dgvProjects.Rows[rowIndex1].Cells[6].Value = "30"; // temp
|
|
dgvProjects.Rows[rowIndex1].Cells[7].Value = "60"; // rh
|
|
dgvProjects.Rows[rowIndex1].Cells[8].Value = "Climate"; // chamber type
|
|
dgvProjects.Rows[rowIndex1].Cells[9].Value = true; // check
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.BackColor = Color.LightGray;
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.ForeColor = Color.Black;
|
|
//dgvProjects.Rows[rowIndex1].Visible = false;
|
|
|
|
rowIndex1 = dgvProjects.Rows.Add();
|
|
dgvProjects.Rows[rowIndex1].Cells[0].Value = "LHU chamber 2319";
|
|
dgvProjects.Rows[rowIndex1].Cells[3].Value = "02319";
|
|
dgvProjects.Rows[rowIndex1].Cells[6].Value = "30"; // temp
|
|
dgvProjects.Rows[rowIndex1].Cells[7].Value = "60"; // rh
|
|
dgvProjects.Rows[rowIndex1].Cells[8].Value = "Climate"; // chamber type
|
|
dgvProjects.Rows[rowIndex1].Cells[9].Value = true; // check
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.BackColor = Color.LightGray;
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.ForeColor = Color.Black;
|
|
//dgvProjects.Rows[rowIndex1].Visible = false;
|
|
|
|
rowIndex1 = dgvProjects.Rows.Add();
|
|
dgvProjects.Rows[rowIndex1].Cells[0].Value = "LHU chamber 2599";
|
|
dgvProjects.Rows[rowIndex1].Cells[3].Value = "02599";
|
|
dgvProjects.Rows[rowIndex1].Cells[6].Value = "30"; // temp
|
|
dgvProjects.Rows[rowIndex1].Cells[7].Value = "60"; // rh
|
|
dgvProjects.Rows[rowIndex1].Cells[8].Value = "Climate"; // chamber type
|
|
dgvProjects.Rows[rowIndex1].Cells[9].Value = true; // check
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.BackColor = Color.LightGray;
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.ForeColor = Color.Black;
|
|
//dgvProjects.Rows[rowIndex1].Visible = false;
|
|
|
|
rowIndex1 = dgvProjects.Rows.Add();
|
|
dgvProjects.Rows[rowIndex1].Cells[0].Value = "Oven 1281";
|
|
dgvProjects.Rows[rowIndex1].Cells[3].Value = "01281";
|
|
dgvProjects.Rows[rowIndex1].Cells[6].Value = "125"; // temp
|
|
dgvProjects.Rows[rowIndex1].Cells[7].Value = "N/A"; // rh
|
|
dgvProjects.Rows[rowIndex1].Cells[8].Value = "HTOL"; // chamber type
|
|
dgvProjects.Rows[rowIndex1].Cells[9].Value = true; // check
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.BackColor = Color.LightGray;
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.ForeColor = Color.Black;
|
|
//dgvProjects.Rows[rowIndex1].Visible = false;
|
|
|
|
rowIndex1 = dgvProjects.Rows.Add();
|
|
dgvProjects.Rows[rowIndex1].Cells[0].Value = "Oven 1282";
|
|
dgvProjects.Rows[rowIndex1].Cells[3].Value = "01282";
|
|
dgvProjects.Rows[rowIndex1].Cells[6].Value = "150"; // temp
|
|
dgvProjects.Rows[rowIndex1].Cells[7].Value = "N/A"; // rh
|
|
dgvProjects.Rows[rowIndex1].Cells[8].Value = "HTOL"; // chamber type
|
|
dgvProjects.Rows[rowIndex1].Cells[9].Value = true; // check
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.BackColor = Color.LightGray;
|
|
dgvProjects.Rows[rowIndex1].DefaultCellStyle.ForeColor = Color.Black;
|
|
//dgvProjects.Rows[rowIndex1].Visible = false;
|
|
}
|
|
|
|
void obtainActiveProjects()
|
|
{
|
|
|
|
List<Project> projects = new List<Project>();
|
|
try
|
|
{
|
|
isLoadingData = true;
|
|
dgvProjects.Rows.Clear();
|
|
List<Project> list;
|
|
list = new Projects().GetAllActive();
|
|
|
|
Chambers cBiz = new Chambers();
|
|
String c = "";
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
Project p = list[i];
|
|
|
|
if (p.ProjectDescription == "Maintenance and calibration" )
|
|
{
|
|
dgvProjects.Rows.Add();
|
|
dgvProjects[0, i].Value = String.Format("I{0:00000} sub {1:00} step {2:00}", p.ProjectID, p.SubProject, p.Step);
|
|
|
|
}
|
|
else
|
|
{
|
|
dgvProjects.Rows.Add();
|
|
dgvProjects[0, i].Value = String.Format("P{0:00000} sub {1:00} step {2:00}", p.ProjectID, p.SubProject, p.Step);
|
|
}
|
|
dgvProjects[8, i].Value = "Unknown";
|
|
|
|
dgvProjects[2, i].Value = p.StepDescription;
|
|
dgvProjects[4, i].Value = p.Customer;
|
|
double min = p.Stop == null ? (Time.UTC - p.Start).TotalMinutes : ((DateTime)p.Stop - p.Start).TotalMinutes;
|
|
double hrs = Math.Floor(min / 60);
|
|
min -= hrs * 60;
|
|
dgvProjects[1, i].Value = String.Format("{0:0}h{1:0}", hrs, min);
|
|
|
|
// Chamber description
|
|
try { c = cBiz.GetByPK(p.Chamber).MIDSandDescription; } catch { c = "Chamber not found!"; }
|
|
dgvProjects[3, i].Value = c;
|
|
|
|
dgvProjects.Rows[i].DefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText;
|
|
|
|
System.Drawing.Color rowColor = MIDSinterface.RowColor(cBiz.GetByPK(p.Chamber).MIDS); // obtain row color (from MIDS) for each chamber
|
|
dgvProjects.Rows[i].DefaultCellStyle.BackColor = rowColor;
|
|
|
|
try
|
|
{
|
|
var xml = XElement.Load(filePath);
|
|
|
|
if (xml.Elements("Project").FirstOrDefault(k => k.Element("Project")?.Value == dgvProjects[0, i].Value) == null)
|
|
{
|
|
var result = AnalyzeProject(p.StepDescription, rowColor);
|
|
string testtype = result[3].ToString();
|
|
|
|
dgvProjects[5, i].Value = result[2];
|
|
dgvProjects[6, i].Value = result[0];
|
|
dgvProjects[7, i].Value = result[1];
|
|
dgvProjects[8, i].Value = testtype;
|
|
dgvProjects[10, i].Value = result[4];
|
|
dgvProjects[11, i].Value = result[5];
|
|
// if (row.Cells[9].Value.ToString() == "True") // only check project data if check == True
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
// only enable check checkbox for P-projects, not for I-projects
|
|
if (p.ProjectDescription == "Maintenance and calibration")
|
|
dgvProjects[9, i].Value = false;
|
|
else
|
|
dgvProjects[9, i].Value = true;
|
|
}
|
|
|
|
try
|
|
{
|
|
foreach (DataGridViewRow row in dgvProjects.Rows)
|
|
{
|
|
// Controleer of de eerste kolom (bijv. index 0) leeg is
|
|
if (row.Cells[0].Value == null || string.IsNullOrEmpty(row.Cells[0].Value.ToString()))
|
|
{
|
|
// Verwijder de rij
|
|
dgvProjects.Rows.Remove(row);
|
|
}
|
|
}
|
|
}
|
|
catch {}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show("Could not retrieve projects from database!" + ex.Message, "Projects", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
finally
|
|
{
|
|
dgvProjects.ClearSelection();
|
|
fixedChambers();
|
|
LoadDataFromXML();
|
|
isLoadingData = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void LoadDataFromXML()
|
|
{
|
|
try
|
|
{
|
|
isLoadingData = true;
|
|
if (!System.IO.File.Exists(filePath))
|
|
{
|
|
MessageBox.Show($"XML-bestand '{filePath}' niet gevonden.", "Fout", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
var xml = XElement.Load(filePath);
|
|
foreach (var project in xml.Elements("Project"))
|
|
{
|
|
string name = project.Element("Project")?.Value; // Child <Project>
|
|
|
|
if (string.IsNullOrEmpty(name))
|
|
{
|
|
MessageBox.Show("Geen waarde gevonden in <Project> tag.", "Waarschuwing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
continue;
|
|
}
|
|
foreach (DataGridViewRow row in dgvProjects.Rows)
|
|
{
|
|
if (row.Cells[0].Value?.ToString() == name) // Kolom 1 (Name)
|
|
{
|
|
row.Cells[5].Value = project.Element("Hours")?.Value ?? string.Empty;
|
|
row.Cells[6].Value = project.Element("Temperature")?.Value ?? string.Empty;
|
|
row.Cells[7].Value = project.Element("Humidity")?.Value ?? string.Empty;
|
|
row.Cells[8].Value = project.Element("Testtype")?.Value ?? string.Empty;
|
|
row.Cells[9].Value = project.Element("Check")?.Value ?? string.Empty;
|
|
row.Cells[10].Value = project.Element("TempHigh")?.Value ?? string.Empty;
|
|
row.Cells[11].Value = project.Element("TempLow")?.Value ?? string.Empty;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Fout bij het laden van XML: {ex.Message}", "Fout", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
finally
|
|
{
|
|
isLoadingData = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
private void lbChambers_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
|
|
private double ParseValidDouble(object value)
|
|
{
|
|
if (value == null) return 0.0;
|
|
|
|
string strValue = value.ToString().Trim();
|
|
if (string.IsNullOrEmpty(strValue) || strValue == "N/A") return 0.0;
|
|
|
|
if (double.TryParse(strValue, out double result))
|
|
return result;
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void updateLiveView()
|
|
{
|
|
if (lbChambers.SelectedItems.Count == 0)
|
|
return;
|
|
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
Chamber chamber;
|
|
try
|
|
{
|
|
chamber = new Chambers().GetAll().ToList().Find(delegate (Chamber c) { return (c.MIDSandDescription == (string)lbChambers.SelectedItem); });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
// Fill Sensors
|
|
if (lbSensorChanged == false)
|
|
lbSensors.Items.Clear();
|
|
List<Sensor> sensors;
|
|
try
|
|
{
|
|
sensors = new Sensors().GetByChamber(chamber.PK);
|
|
if (sensors.Count > 0)
|
|
{
|
|
lbSensors.SelectedIndexChanged -= lbSensors_SelectedIndexChanged;
|
|
int index = 0;
|
|
foreach (Sensor s in sensors)
|
|
{
|
|
|
|
if (lbSensorChanged == false)
|
|
{
|
|
lbSensors.Items.Add(s.ToString());
|
|
lbSensors.SetSelected(index, true); // Selecteer dit item direct
|
|
}
|
|
|
|
index++;
|
|
}
|
|
lbSensors.SelectedIndexChanged += lbSensors_SelectedIndexChanged;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
return;
|
|
}
|
|
lbSensorChanged = false;
|
|
|
|
int lastHours = 0;
|
|
if (int.TryParse(tbLastHours.Text, out lastHours))
|
|
{ }
|
|
else
|
|
{
|
|
MessageBox.Show("Voer een geldig aantal uren in.");
|
|
}
|
|
|
|
var sensorValues = new Dictionary<int, List<SensorReading>>(); // Dictionary per sensor
|
|
|
|
|
|
List<string> sensorWithDatalist = new List<string>();
|
|
List<string> selectedSensorList = new List<string>();
|
|
int sensorid = 0;
|
|
foreach (var sensor in sensors)
|
|
{
|
|
if(!sensor.ToString().Contains("Air"))
|
|
if (!lbSensors.SelectedItems.Contains(sensor.ToString()))
|
|
{
|
|
sensorid++;
|
|
continue;
|
|
}
|
|
|
|
if (lbSensors.SelectedItems.Contains(sensor.ToString()))
|
|
selectedSensorList.Add(sensor.PK.ToString());
|
|
|
|
|
|
SqlConnection connection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");
|
|
try
|
|
{
|
|
using (connection)
|
|
{
|
|
string query = string.Empty;
|
|
|
|
if (chamber.Humidity)
|
|
{
|
|
query = "SELECT Value, TimeStamp FROM Results WHERE SensorPK = @SensorPK AND TimeStamp >= DATEADD(HOUR, -@lasthours, GETUTCDATE()) ORDER BY TimeStamp ASC";
|
|
}
|
|
else
|
|
{
|
|
query = "SELECT Value, TimeStamp FROM ResultsOudeHal WHERE SensorPK = @SensorPK AND TimeStamp >= DATEADD(HOUR, -@lasthours, GETUTCDATE()) ORDER BY TimeStamp ASC";
|
|
}
|
|
|
|
SqlCommand command = new SqlCommand(query, connection);
|
|
command.Parameters.AddWithValue("@SensorPK", sensor.PK);
|
|
command.Parameters.AddWithValue("@lasthours", lastHours);
|
|
|
|
connection.Open();
|
|
|
|
|
|
using (SqlDataReader reader = command.ExecuteReader())
|
|
{
|
|
var readings = new List<SensorReading>(); // Lijst voor de readings van de huidige sensor
|
|
|
|
while (reader.Read())
|
|
{
|
|
float resultValue = reader.IsDBNull(0) ? 0.0f : reader.GetFloat(0); // Haal de waarde op, standaard 0 als null
|
|
DateTime timestamp = reader.IsDBNull(1) ? DateTime.MinValue : reader.GetDateTime(1); // Haal de timestamp op
|
|
|
|
readings.Add(new SensorReading
|
|
{
|
|
Value = resultValue,
|
|
Timestamp = timestamp
|
|
});
|
|
}
|
|
if (readings.Count > 0)
|
|
{
|
|
sensorWithDatalist.Add(lbSensors.Items[sensorid].ToString());
|
|
sensorValues[sensor.PK] = readings;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error for Sensor {sensor.PK}: {ex.Message}");
|
|
}
|
|
finally { sensorid++; }
|
|
}
|
|
|
|
int viewHours = lastHours;
|
|
|
|
|
|
if (panelPlot.Controls.Count > 0)
|
|
{
|
|
panelPlot.Controls.Clear();
|
|
}
|
|
plotModel = new PlotModel
|
|
{
|
|
Title = "CMS 2 Sensor Data",
|
|
};
|
|
|
|
plotModel.Legends.Add(new Legend
|
|
{
|
|
LegendPosition = LegendPosition.RightTop, // Plaats de legenda rechtsboven
|
|
LegendOrientation = LegendOrientation.Vertical, // Oriëntatie van de legenda
|
|
LegendPlacement = LegendPlacement.Outside, // Plaats de legenda buiten de plot
|
|
LegendBackground = OxyColors.White, // Achtergrondkleur van de legenda
|
|
LegendBorder = OxyColors.Black // Randkleur van de legenda
|
|
});
|
|
|
|
|
|
var plotView = new PlotView
|
|
{
|
|
Model = plotModel,
|
|
Dock = DockStyle.Fill
|
|
};
|
|
panelPlot.Controls.Add(plotView);
|
|
plotModel.Series.Clear();
|
|
|
|
plotModel.Axes.Add(new OxyPlot.Axes.LinearAxis // x-as
|
|
{
|
|
Position = OxyPlot.Axes.AxisPosition.Bottom,
|
|
Title = "Hours since last point [h]",
|
|
MajorGridlineStyle = LineStyle.Solid,
|
|
MinorGridlineStyle = LineStyle.Dot,
|
|
StartPosition = 1, // Begin van de as rechts
|
|
EndPosition = 0, // Eind van de as links
|
|
Minimum = 0, // Begin bij 0 uur (laatste punt)
|
|
Maximum = viewHours, // Toon slechts 24 uur in de view
|
|
IsPanEnabled = true, // Schakel scrollen/pannen in
|
|
IsZoomEnabled = true, // Schakel in- en uitzoomen in
|
|
AbsoluteMinimum = 0, // Minimum waarde voor pannen
|
|
AbsoluteMaximum = lastHours // Maximum waarde voor pannen
|
|
});
|
|
|
|
var yAxis1 = new OxyPlot.Axes.LinearAxis // y-as 1 voor temp en RH
|
|
{
|
|
Position = OxyPlot.Axes.AxisPosition.Left,
|
|
Title = "Temperature [°C] / RH [%]",
|
|
MajorGridlineStyle = LineStyle.Solid,
|
|
MinorGridlineStyle = LineStyle.Dot,
|
|
Minimum = 0,
|
|
Maximum = 110,
|
|
Key = "TempRH"
|
|
};
|
|
|
|
|
|
var yAxis2 = new OxyPlot.Axes.LinearAxis// y-as 1 voor spanning en stroom
|
|
{
|
|
Position = OxyPlot.Axes.AxisPosition.Right,
|
|
Title = "Voltage [V]",
|
|
MajorGridlineStyle = LineStyle.Solid,
|
|
MinorGridlineStyle = LineStyle.Dot,
|
|
Minimum = 0,
|
|
Maximum = 30,
|
|
Key = "Volt"
|
|
};
|
|
|
|
int sensorCount = 0;
|
|
DateTime? lastTimestamp = null;
|
|
|
|
double maxVoltage = 0.0;
|
|
double minVoltage = 0.0;
|
|
double maxTempRH = 0.0;
|
|
double minTempRH = 0.0;
|
|
|
|
var sensorValuesSync = new Dictionary<int, List<SensorReading>>(); // Dictionary per sensor
|
|
|
|
|
|
try
|
|
{
|
|
// Selecteer de eerste sensor als referentie
|
|
var referenceSensor = sensorValues.First();
|
|
int referenceKey = referenceSensor.Key;
|
|
var referenceTimestamps = referenceSensor.Value.Select(r => r.Timestamp).ToList();
|
|
|
|
|
|
// Ga per tijdstip in de referentiesensor door alle andere sensoren heen
|
|
foreach (var timestamp in referenceTimestamps)
|
|
{
|
|
foreach (var sensor in sensorValues)
|
|
{
|
|
var sensorKey = sensor.Key;
|
|
|
|
// Maak een nieuwe lijst voor sensorwaarden als deze nog niet bestaat
|
|
if (!sensorValuesSync.ContainsKey(sensorKey))
|
|
{
|
|
sensorValuesSync[sensorKey] = new List<SensorReading>();
|
|
}
|
|
|
|
if (sensorKey == referenceKey)
|
|
{
|
|
var referenceValue = referenceSensor.Value.First(r => r.Timestamp == timestamp).Value;
|
|
|
|
sensorValuesSync[sensorKey].Add(new SensorReading
|
|
{
|
|
Value = referenceValue,
|
|
Timestamp = timestamp
|
|
});
|
|
}
|
|
else
|
|
{
|
|
// Zoek de dichtstbijzijnde waarde binnen 20 seconden
|
|
var closestReading = sensor.Value
|
|
.Where(r => Math.Abs((r.Timestamp - timestamp).TotalSeconds) <= 20)
|
|
.OrderBy(r => Math.Abs((r.Timestamp - timestamp).TotalSeconds))
|
|
.FirstOrDefault();
|
|
|
|
double value = closestReading != null ? closestReading.Value : 0;
|
|
|
|
// Voeg de gevonden waarde toe aan de sync dictionary
|
|
sensorValuesSync[sensorKey].Add(new SensorReading
|
|
{
|
|
Value = (float)value,
|
|
Timestamp = timestamp
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch{}
|
|
|
|
|
|
|
|
sensorValues = sensorValuesSync;
|
|
|
|
foreach (var sensor in sensorValues.Keys.ToList())
|
|
{
|
|
var readings = sensorValues[sensor];
|
|
if (readings.Count > 1)
|
|
readings.RemoveAt(readings.Count - 1);
|
|
else
|
|
readings.Clear();
|
|
}
|
|
|
|
foreach (var sensor in sensorValues)
|
|
{
|
|
if(!selectedSensorList.Contains(sensor.Key.ToString()))
|
|
{
|
|
sensorCount++;
|
|
continue;
|
|
}
|
|
|
|
// calibration correction!
|
|
var sensorPK = sensor.Key; // Haal de sensor.PK op
|
|
double a = 1.0;
|
|
double b = 0.0;
|
|
try
|
|
{
|
|
Calibration t = new Calibrations().GetLastCreatedBySensorPK(sensorPK);
|
|
if (t != null) // calibration found
|
|
{
|
|
a = t.Coefficients[1]; // gain
|
|
b = t.Coefficients[0]; // offset
|
|
}
|
|
else // no calibration found
|
|
{
|
|
a = 1.0; // gain
|
|
b = 0.0; // offset
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
string msg = "Could not retrieve calibrations for sensor ";
|
|
}
|
|
|
|
|
|
var series = new LineSeries
|
|
{
|
|
Title = $"Sensor {sensorCount}",
|
|
StrokeThickness = 2,
|
|
MarkerType = MarkerType.Circle, // Punt zichtbaar maken
|
|
MarkerSize = 2, // Grootte van de punten
|
|
};
|
|
|
|
foreach (var reading in sensor.Value)
|
|
{
|
|
if (lastTimestamp == null || reading.Timestamp > lastTimestamp)
|
|
{
|
|
lastTimestamp = reading.Timestamp;
|
|
}
|
|
}
|
|
|
|
double hoursSinceNow = 0;
|
|
if (lastTimestamp.HasValue)
|
|
{
|
|
TimeSpan timeSinceLast = DateTime.UtcNow - lastTimestamp.Value;
|
|
hoursSinceNow = timeSinceLast.TotalHours;
|
|
|
|
if (timeSinceLast > TimeSpan.FromMinutes(10))
|
|
Console.WriteLine("Laatste meting is meer dan 10 minuten geleden.");
|
|
|
|
}
|
|
|
|
if (sensorCount ==0)
|
|
{
|
|
int cycleCount = 0;
|
|
bool upCrossed = false;
|
|
bool downCrossed = false;
|
|
double uppercountvalue = Double.Parse(tbHighTC.Text);
|
|
double lowercountvalue = Double.Parse(tbLowTC.Text);
|
|
|
|
foreach (var reading in sensor.Value)
|
|
{
|
|
double hoursSinceLast = (lastTimestamp.Value - reading.Timestamp).TotalHours + hoursSinceNow;
|
|
double temperature = (double)(reading.Value * a + b); // Correctie toegepast
|
|
|
|
series.Points.Add(new DataPoint(hoursSinceLast, temperature));
|
|
|
|
if (temperature >= uppercountvalue)
|
|
upCrossed = true; // Opgaande overgang
|
|
|
|
if (temperature <= lowercountvalue && upCrossed)
|
|
downCrossed = true; // Neergaande overgang
|
|
|
|
if (upCrossed && downCrossed)
|
|
{
|
|
cycleCount++; // Volledige cyclus geteld
|
|
upCrossed = false;
|
|
downCrossed = false;
|
|
}
|
|
}
|
|
lblCycles.Text = string.Format(cycleCount.ToString() + " cycles in last " + tbLastHours.Text + " hours");
|
|
}
|
|
else
|
|
{
|
|
foreach (var reading in sensor.Value)
|
|
{
|
|
double hoursSinceLast = (lastTimestamp.Value - reading.Timestamp).TotalHours + hoursSinceNow;
|
|
series.Points.Add(new DataPoint(hoursSinceLast, (double)(reading.Value * a + b))); // CORRECTION!!!!!!!!!!!!!!!!!!!!
|
|
}
|
|
}
|
|
|
|
|
|
|
|
series.Title = sensorWithDatalist[sensorCount];
|
|
|
|
if (sensorWithDatalist[sensorCount].ToLower().Contains("rh"))
|
|
series.Color = OxyColors.DarkBlue;
|
|
else if (sensorWithDatalist[sensorCount].ToLower().Contains("air"))
|
|
series.Color = OxyColors.Red;
|
|
else if (sensorWithDatalist[sensorCount].ToLower().Contains("water"))
|
|
series.Color = OxyColors.LightBlue;
|
|
|
|
if (sensorWithDatalist[sensorCount].ToLower().Contains("voltage")) // koppel sensordata aan juiste as
|
|
{
|
|
maxVoltage = Math.Max(maxVoltage, series.Points.Max(point => point.Y));
|
|
minVoltage = Math.Min(minVoltage, series.Points.Min(point => point.Y));
|
|
series.YAxisKey = "Volt";
|
|
}
|
|
else
|
|
{
|
|
maxTempRH = Math.Max(maxTempRH, series.Points.Max(point => point.Y));
|
|
minTempRH = Math.Min(minTempRH, series.Points.Min(point => point.Y));
|
|
series.YAxisKey = "TempRH";
|
|
}
|
|
plotModel.Series.Add(series);
|
|
sensorCount++;
|
|
}
|
|
//Console.WriteLine("max temp/RH " + maxTempRH.ToString() + " min temp/RH " + minTempRH.ToString());
|
|
yAxis1.Maximum = (int)maxTempRH + 10;
|
|
yAxis1.Minimum = (int)minTempRH - 10;
|
|
yAxis1.AbsoluteMaximum = yAxis1.Maximum;
|
|
yAxis1.AbsoluteMinimum = yAxis1.Minimum;
|
|
|
|
// Console.WriteLine("max voltage " + maxVoltage.ToString() + " min voltage " + minVoltage.ToString());
|
|
if (cbVoltageScale.Checked == false)
|
|
{
|
|
yAxis2.Maximum = (int)maxVoltage + 1;
|
|
yAxis2.Minimum = (int)minVoltage - 1;
|
|
yAxis2.AbsoluteMaximum = yAxis2.Maximum;
|
|
yAxis2.AbsoluteMinimum = yAxis2.Minimum;
|
|
}
|
|
else
|
|
{
|
|
yAxis2.Maximum = yAxis1.Maximum;
|
|
yAxis2.Minimum = yAxis1.Minimum;
|
|
yAxis2.AbsoluteMaximum = yAxis1.AbsoluteMaximum;
|
|
yAxis2.AbsoluteMinimum = yAxis1.AbsoluteMinimum;
|
|
}
|
|
|
|
|
|
plotModel.Axes.Add(yAxis1);
|
|
plotModel.Axes.Add(yAxis2);
|
|
|
|
if (cbShowEnvelope.Checked == true)
|
|
{
|
|
if (dgvProjects.Rows.Count > 0)
|
|
{
|
|
foreach (DataGridViewRow row in dgvProjects.Rows)
|
|
{
|
|
if (!row.IsNewRow)
|
|
{
|
|
var chamberValue = row.Cells["dgvProjects_Chamber"].Value;
|
|
if (chamberValue != null)
|
|
{
|
|
if (chamberValue.ToString() == (string)lbChambers.SelectedItem) // chamber has an active project running --> show envelope!
|
|
{
|
|
Console.WriteLine("project found for " + chamber.MIDS.ToString());
|
|
|
|
string testtype = row.Cells[8].Value.ToString();
|
|
|
|
double tempdiff = ParseValidDouble(tbTempDev.Text);
|
|
double rhdiff = ParseValidDouble(tbHumidityDev.Text);
|
|
double testtemp = ParseValidDouble(row.Cells[6].Value);
|
|
double testrh = ParseValidDouble(row.Cells[7].Value);
|
|
double settempH = ParseValidDouble(row.Cells["CTempHigh"].Value);
|
|
double settempL = ParseValidDouble(row.Cells["CTempLow"].Value);
|
|
|
|
// steady temperature + humidity
|
|
if (testtype.Contains("HAST") || testtype.Contains("THB") || testtype.Contains("THB_cycledbias") || testtype.Contains("Climate"))
|
|
{
|
|
var tempBand = new RectangleAnnotation
|
|
{
|
|
MinimumY = testtemp - tempdiff,
|
|
MaximumY = testtemp + tempdiff,
|
|
MinimumX = double.NegativeInfinity, // Volledige breedte
|
|
MaximumX = double.PositiveInfinity, // Volledige breedte
|
|
Fill = OxyColor.FromAColor(20, OxyColors.Red) // Doorzichtige rode band
|
|
};
|
|
plotModel.Annotations.Add(tempBand);
|
|
|
|
var rhBand = new RectangleAnnotation
|
|
{
|
|
MinimumY = testrh - rhdiff,
|
|
MaximumY = testrh + rhdiff,
|
|
MinimumX = double.NegativeInfinity, // Volledige breedte
|
|
MaximumX = double.PositiveInfinity, // Volledige breedte
|
|
Fill = OxyColor.FromAColor(20, OxyColors.Blue) // Doorzichtige blauwe band
|
|
};
|
|
plotModel.Annotations.Add(rhBand);
|
|
}
|
|
|
|
// steady temperature
|
|
else if (testtype.Contains("HTOL") || testtype.Contains("Bake"))
|
|
{
|
|
var tempBand = new RectangleAnnotation
|
|
{
|
|
MinimumY = testtemp - tempdiff,
|
|
MaximumY = testtemp + tempdiff,
|
|
MinimumX = double.NegativeInfinity, // Volledige breedte
|
|
MaximumX = double.PositiveInfinity, // Volledige breedte
|
|
Fill = OxyColor.FromAColor(20, OxyColors.Red) // Doorzichtige blauwe band
|
|
};
|
|
plotModel.Annotations.Add(tempBand);
|
|
}
|
|
|
|
|
|
// temperature cycling
|
|
else if (testtype.Contains("TC") || testtype.Contains("PTC"))
|
|
{
|
|
try
|
|
{
|
|
var tempBandH = new RectangleAnnotation
|
|
{
|
|
MinimumY = settempH - tempdiff,
|
|
MaximumY = settempH + tempdiff,
|
|
MinimumX = double.NegativeInfinity, // Volledige breedte
|
|
MaximumX = double.PositiveInfinity, // Volledige breedte
|
|
Fill = OxyColor.FromAColor(20, OxyColors.Red) // Doorzichtige band
|
|
};
|
|
plotModel.Annotations.Add(tempBandH);
|
|
|
|
var tempBandL = new RectangleAnnotation
|
|
{
|
|
MinimumY = settempL - tempdiff,
|
|
MaximumY = settempL + tempdiff,
|
|
MinimumX = double.NegativeInfinity, // Volledige breedte
|
|
MaximumX = double.PositiveInfinity, // Volledige breedte
|
|
Fill = OxyColor.FromAColor(20, OxyColors.Red) // Doorzichtige band
|
|
};
|
|
plotModel.Annotations.Add(tempBandL);
|
|
}
|
|
catch {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
|
|
private void HalControle_Load(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void GeneralDataCheck()
|
|
{
|
|
Console.WriteLine("general data check started...");
|
|
|
|
sensorAttempts.Clear();
|
|
|
|
double Tmin = Double.Parse(tbTmin.Text);
|
|
double Tmax = Double.Parse(tbTmax.Text);
|
|
double RHmin = Double.Parse(tbRHmin.Text);
|
|
double RHmax = Double.Parse(tbRHmax.Text);
|
|
double Vmin = Double.Parse(tbVmin.Text);
|
|
double Vmax = Double.Parse(tbVmax.Text);
|
|
|
|
|
|
try
|
|
{
|
|
foreach (var Item in lbChambers.Items)
|
|
{
|
|
Chamber chamber = new Chambers().GetAll().ToList().Find(c => c.MIDSandDescription == (string)Item);
|
|
List<string> sensorname = new List<string>();
|
|
if (chamber != null)
|
|
{
|
|
Console.WriteLine("Checking chamber " + chamber.MIDS);
|
|
List<Sensor> sensors;
|
|
try
|
|
{
|
|
sensors = new Sensors().GetByChamber(chamber.PK);
|
|
if (sensors.Count > 0)
|
|
{
|
|
foreach (Sensor s in sensors)
|
|
{
|
|
sensorname.Add(s.Description);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, String.Format("Sensors in chamber {0:00000}", chamber.MIDS), MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
var sensorValues = new Dictionary<int, List<SensorReading>>(); // Dictionary per sensor
|
|
|
|
List<string> sensorWithDatalist = new List<string>();
|
|
int sensorid = 0;
|
|
|
|
foreach (var sensor in sensors)
|
|
{
|
|
SqlConnection connection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");
|
|
try
|
|
{
|
|
using (connection)
|
|
{
|
|
string query = string.Empty;
|
|
|
|
if (chamber.Humidity)
|
|
{
|
|
query = "SELECT Value, TimeStamp FROM Results WHERE SensorPK = @SensorPK AND TimeStamp >= DATEADD(HOUR, -@lasthours, GETUTCDATE()) ORDER BY TimeStamp ASC";
|
|
}
|
|
else
|
|
{
|
|
query = "SELECT Value, TimeStamp FROM ResultsOudeHal WHERE SensorPK = @SensorPK AND TimeStamp >= DATEADD(HOUR, -@lasthours, GETUTCDATE()) ORDER BY TimeStamp ASC";
|
|
}
|
|
|
|
SqlCommand command = new SqlCommand(query, connection);
|
|
command.Parameters.AddWithValue("@SensorPK", sensor.PK);
|
|
command.Parameters.AddWithValue("@lasthours", Int32.Parse(tbCheckLastHour.Text));
|
|
|
|
connection.Open();
|
|
|
|
using (SqlDataReader reader = command.ExecuteReader())
|
|
{
|
|
var readings = new List<SensorReading>();
|
|
|
|
while (reader.Read())
|
|
{
|
|
float resultValue = reader.IsDBNull(0) ? 0.0f : reader.GetFloat(0); // Haal de waarde op, standaard 0 als null
|
|
DateTime timestamp = reader.IsDBNull(1) ? DateTime.MinValue : reader.GetDateTime(1); // Haal de timestamp op
|
|
|
|
readings.Add(new SensorReading
|
|
{
|
|
Value = resultValue,
|
|
Timestamp = timestamp
|
|
});
|
|
}
|
|
if (readings.Count > 0)
|
|
{
|
|
//sensorWithDatalist.Add(lbSensors.Items[sensorid].ToString());
|
|
sensorValues[sensor.PK] = readings;
|
|
|
|
}
|
|
|
|
|
|
// calibration correction!
|
|
var sensorPK = sensor.PK; // Haal de sensor.PK op
|
|
double a = 1.0;
|
|
double b = 0.0;
|
|
try
|
|
{
|
|
Calibration t = new Calibrations().GetLastCreatedBySensorPK(sensorPK);
|
|
if (t != null) // calibration found
|
|
{
|
|
a = t.Coefficients[1]; // gain
|
|
b = t.Coefficients[0]; // offset
|
|
}
|
|
else // no calibration found
|
|
{
|
|
a = 1.0; // gain
|
|
b = 0.0; // offset
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
string msg = "Could not retrieve calibrations for sensor ";
|
|
}
|
|
|
|
foreach (var reading in readings)
|
|
{
|
|
double value = (double)(reading.Value * a + b);
|
|
//Console.WriteLine("SENSORPK " + sensor.PK +" type " + sensorname[sensorid] + $" Value: value}, Timestamp: {reading.Timestamp}");
|
|
|
|
if (sensorname[sensorid].ToLower().Contains("temperature"))
|
|
{
|
|
if (value < Tmin || value > Tmax)
|
|
{
|
|
if (!RowExists(dgvGeneralErrors, sensorPK))
|
|
dgvGeneralErrors.Rows.Add(chamber.MIDS, sensorPK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
else if (sensorname[sensorid].ToLower().Contains("rh"))
|
|
{
|
|
if (value < RHmin || value > RHmax)
|
|
{
|
|
if (!RowExists(dgvGeneralErrors, sensorPK))
|
|
dgvGeneralErrors.Rows.Add(chamber.MIDS, sensorPK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
else if (sensorname[sensorid].ToLower().Contains("voltage"))
|
|
{
|
|
if (value < Vmin || value > Vmax)
|
|
{
|
|
if (!RowExists(dgvGeneralErrors, sensorPK))
|
|
dgvGeneralErrors.Rows.Add(chamber.MIDS, sensorPK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
//if (sensorValues.Count > 0 && sensorname[sensorid].ToLower().Contains("air temperature"))
|
|
if (sensorname[sensorid].ToLower().Contains("air temperature"))
|
|
{
|
|
DateTime meestRecenteUtc = sensorValues
|
|
.SelectMany(kvp => kvp.Value)
|
|
.Max(r => r.Timestamp);
|
|
|
|
TimeZoneInfo nlTz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
|
|
DateTime meestRecenteLocal = TimeZoneInfo.ConvertTimeFromUtc(meestRecenteUtc, nlTz);
|
|
TimeSpan verschil = DateTime.Now - meestRecenteLocal;
|
|
bool ouderDan20Min = verschil.TotalMinutes > 20;
|
|
|
|
if (ouderDan20Min == true)
|
|
{
|
|
Console.WriteLine("Meer dan 20 minuten geen data!");
|
|
if (!RowExists(dgvGeneralErrors, sensorPK))
|
|
dgvGeneralErrors.Rows.Add(chamber.MIDS, sensorPK, 0, 0, sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine("Geen data gevonden voor deze kamer");
|
|
if (!RowExists(dgvGeneralErrors, sensorPK))
|
|
dgvGeneralErrors.Rows.Add(chamber.MIDS, sensorPK, 0, 0, sensorname[sensorid], 1);
|
|
}
|
|
|
|
|
|
sensorid++;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error for Sensor {sensor.PK}: {ex.Message}");
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
// Lees uitgesloten kamernummers vanuit bestand
|
|
var excludedChambers = File.ReadAllLines(@"Z:\projects\2020\P201339\sub1\4. Software\1. Feanor\excluded_chambers.txt")
|
|
.Select(line => line.Trim())
|
|
.Where(line => !string.IsNullOrEmpty(line))
|
|
.ToHashSet(); // Snelle lookup
|
|
|
|
foreach (var cabinet in cabinets)
|
|
{
|
|
bool generalerror = false;
|
|
foreach (DataGridViewRow row in dgvGeneralErrors.Rows)
|
|
{
|
|
string chambernumber = row.Cells[0].Value?.ToString();
|
|
if (!string.IsNullOrEmpty(chambernumber) &&
|
|
Int32.TryParse(cabinet.Name, out int cabinetNr) &&
|
|
Int32.TryParse(chambernumber, out int chamberNr))
|
|
{
|
|
// Check of er een error is én het kamernummer NIET is uitgesloten
|
|
if (cabinetNr == chamberNr && !excludedChambers.Contains(chambernumber))
|
|
{
|
|
generalerror = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (generalerror)
|
|
cabinet.StatusColor = Color.FromArgb(247, 180, 116);
|
|
}
|
|
|
|
updateOverview();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("Fout bij het verwerken van fouten: " + ex.Message);
|
|
}
|
|
Console.WriteLine("general data check finished");
|
|
}
|
|
|
|
int HaalUrenUitTijdsduur(string tijdsduur)
|
|
{
|
|
if (tijdsduur == null)
|
|
return 0;
|
|
|
|
int indexH = tijdsduur.IndexOf('h');
|
|
|
|
if (indexH > 0)
|
|
{
|
|
string urenString = tijdsduur.Substring(0, indexH);
|
|
if (int.TryParse(urenString, out int uren))
|
|
{
|
|
return uren;
|
|
}
|
|
}
|
|
|
|
// Als iets misgaat, bijvoorbeeld geen 'h' of geen geldig getal
|
|
throw new FormatException("Ongeldige tijdsduurstring. Verwacht formaat '22h50'.");
|
|
}
|
|
|
|
void projectDataCheck()
|
|
{
|
|
Console.WriteLine("project data check started...");
|
|
|
|
sensorAttempts.Clear();
|
|
|
|
try
|
|
{
|
|
foreach (DataGridViewRow row in dgvProjects.Rows)
|
|
{
|
|
string chambernumber = row.Cells[3].Value.ToString();
|
|
|
|
if (row.Cells[9].Value.ToString() == "True") // only check project data if check == True
|
|
{
|
|
int uren = HaalUrenUitTijdsduur(row.Cells["dgvProjects_Duration"].Value?.ToString()); // haal duration op in volle uren (getal voor de "h")
|
|
|
|
Chamber chamber = new Chambers().GetAll().ToList().Find(c => c.MIDSandDescription == chambernumber);
|
|
List<string> sensorname = new List<string>();
|
|
if (chamber != null)
|
|
{
|
|
Console.WriteLine("Checking chamber " + chamber.MIDS);
|
|
List<Sensor> sensors;
|
|
try
|
|
{
|
|
sensors = new Sensors().GetByChamber(chamber.PK);
|
|
if (sensors.Count > 0)
|
|
{
|
|
foreach (Sensor s in sensors)
|
|
{
|
|
sensorname.Add(s.Description);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, String.Format("Sensors in chamber {0:00000}", chamber.MIDS), MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
var sensorValues = new Dictionary<int, List<SensorReading>>(); // Dictionary per sensor
|
|
|
|
List<string> sensorWithDatalist = new List<string>();
|
|
int sensorid = 0;
|
|
SensorReading mostRecentReading = null;
|
|
|
|
foreach (var sensor in sensors)
|
|
{
|
|
SqlConnection connection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");
|
|
try
|
|
{
|
|
using (connection)
|
|
{
|
|
string query = string.Empty;
|
|
|
|
if (chamber.Humidity)
|
|
{
|
|
query = "SELECT Value, TimeStamp FROM Results WHERE SensorPK = @SensorPK AND TimeStamp >= DATEADD(HOUR, -@lasthours, GETUTCDATE()) ORDER BY TimeStamp ASC";
|
|
}
|
|
else
|
|
{
|
|
query = "SELECT Value, TimeStamp FROM ResultsOudeHal WHERE SensorPK = @SensorPK AND TimeStamp >= DATEADD(HOUR, -@lasthours, GETUTCDATE()) ORDER BY TimeStamp ASC";
|
|
}
|
|
|
|
SqlCommand command = new SqlCommand(query, connection);
|
|
command.Parameters.AddWithValue("@SensorPK", sensor.PK);
|
|
command.Parameters.AddWithValue("@lasthours", Int32.Parse(tbCheckLastProjectData.Text));
|
|
|
|
connection.Open();
|
|
|
|
using (SqlDataReader reader = command.ExecuteReader())
|
|
{
|
|
var readings = new List<SensorReading>();
|
|
|
|
while (reader.Read())
|
|
{
|
|
float resultValue = reader.IsDBNull(0) ? 0.0f : reader.GetFloat(0); // Haal de waarde op, standaard 0 als null
|
|
DateTime timestamp = reader.IsDBNull(1) ? DateTime.MinValue : reader.GetDateTime(1); // Haal de timestamp op
|
|
|
|
readings.Add(new SensorReading
|
|
{
|
|
Value = resultValue,
|
|
Timestamp = timestamp
|
|
});
|
|
}
|
|
if (sensorname[sensorid].ToLower().Contains("air temperature"))
|
|
mostRecentReading = readings.OrderByDescending(r => r.Timestamp).FirstOrDefault();
|
|
|
|
|
|
if (readings.Count > 0)
|
|
{
|
|
//sensorWithDatalist.Add(lbSensors.Items[sensorid].ToString());
|
|
sensorValues[sensor.PK] = readings;
|
|
}
|
|
|
|
// calibration correction!
|
|
double a = 1.0;
|
|
double b = 0.0;
|
|
try
|
|
{
|
|
Calibration t = new Calibrations().GetLastCreatedBySensorPK(sensor.PK);
|
|
if (t != null) // calibration found
|
|
{
|
|
a = t.Coefficients[1]; // gain
|
|
b = t.Coefficients[0]; // offset
|
|
}
|
|
else // no calibration found
|
|
{
|
|
a = 1.0; // gain
|
|
b = 0.0; // offset
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
string msg = "Could not retrieve calibrations for sensor ";
|
|
}
|
|
|
|
string testtype = row.Cells[8].Value.ToString();
|
|
|
|
double tempdiff = ParseValidDouble(tbTempDev.Text);
|
|
double rhdiff = ParseValidDouble(tbHumidityDev.Text);
|
|
double testtemp = ParseValidDouble(row.Cells[6].Value);
|
|
double testrh = ParseValidDouble(row.Cells[7].Value);
|
|
|
|
|
|
// only detect project data after the project runs for 1 hour
|
|
|
|
int onlyhours = 1;
|
|
if(row.Cells[1].Value!= null)
|
|
{
|
|
Match match = Regex.Match(row.Cells[1].Value.ToString(), @"^(\d+)h");
|
|
onlyhours = int.Parse(match.Groups[1].Value);
|
|
}
|
|
|
|
|
|
if(onlyhours>=1)
|
|
{
|
|
// steady temperature + humidity
|
|
if (testtype.Contains("HAST") || testtype.Contains("Climate") || testtype.Contains("THB") || testtype.Contains("THB_cycledbias"))
|
|
{
|
|
foreach (var reading in readings)
|
|
{
|
|
double value = reading.Value * a + b; // gecorrigeerde waarde!
|
|
//Console.WriteLine("SENSORPK " + sensor.PK + " type " + sensorname[sensorid] + $" Value: {value}, Timestamp: {reading.Timestamp}");
|
|
if (sensorname[sensorid].ToLower().Contains("air temperature")) // don't check water temperature (not neccessary, only air temp + rh)
|
|
{
|
|
if (value > (testtemp + tempdiff) || value < (testtemp - tempdiff))
|
|
{
|
|
//Console.WriteLine("temperature too high/low --> SENSORPK " + sensor.PK + " type " + sensorname[sensorid] + " Value: " + value + " Refvalue: " + testtemp + " +/- " + tempdiff + " Timestamp: " + reading.Timestamp);
|
|
if (!RowExists(dgvProjectErrors, sensor.PK))
|
|
dgvProjectErrors.Rows.Add(chamber.MIDS, sensor.PK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
else if (sensorname[sensorid].ToLower().Contains("rh"))
|
|
{
|
|
if (row.Cells[7].Value.ToString() == "N/A")
|
|
{
|
|
//MessageBox.Show("Invalid RH for " + row.Cells[0].Value.ToString());
|
|
break;
|
|
}
|
|
if (value > (testrh + rhdiff) || value < (testrh - rhdiff))
|
|
{
|
|
//Console.WriteLine("rh too high/low --> SENSORPK " + sensor.PK + " type " + sensorname[sensorid] + " Value: " + value + " Refvalue: " + testrh + " +/- " + rhdiff + " Timestamp: " + reading.Timestamp);
|
|
if (!RowExists(dgvProjectErrors, sensor.PK))
|
|
dgvProjectErrors.Rows.Add(chamber.MIDS, sensor.PK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// steady temperature
|
|
else if (testtype.Contains("HTOL") || testtype.Contains("Bake"))
|
|
{
|
|
foreach (var reading in readings)
|
|
{
|
|
double value = reading.Value * a + b; // gecorrigeerde waarde!
|
|
//Console.WriteLine("SENSORPK " + sensor.PK + " type " + sensorname[sensorid] + $" Value: {value}, Timestamp: {reading.Timestamp}");
|
|
if (sensorname[sensorid].ToLower().Contains("air temperature")) //
|
|
{
|
|
if (value > (testtemp + tempdiff) || value < (testtemp - tempdiff))
|
|
{
|
|
//Console.WriteLine("temperature too high/low --> SENSORPK " + sensor.PK + " type " + sensorname[sensorid] + " Value: " + value + " Refvalue: " + testtemp + " +/- " + tempdiff + " Timestamp: " + reading.Timestamp);
|
|
if (!RowExists(dgvProjectErrors, sensor.PK))
|
|
dgvProjectErrors.Rows.Add(chamber.MIDS, sensor.PK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// temperature cycling
|
|
// voor TC en PTC wordt er naar de air temp gekeken of de min en max waarde gehaald worden (1 min en 1 max = 1 cycle), wordt er 1 of meer cycles gevonden, goedgekeurd!
|
|
else if ((testtype.Contains("TC") || testtype.Contains("PTC")) && sensorname[sensorid].Contains("Air"))
|
|
{
|
|
// Alle Air-sensormetingen verzamelen
|
|
List<double> airTemperatures = new List<double>();
|
|
foreach (var reading in readings)
|
|
{
|
|
double value = reading.Value * a + b; // gecorrigeerde waarde
|
|
airTemperatures.Add(value);
|
|
}
|
|
// Analyseer op cycles: detecteer of beide extremen zijn bereikt
|
|
double minThreshold = Double.Parse(row.Cells["CTempLow"].Value.ToString());
|
|
double maxThreshold = Double.Parse(row.Cells["CTempHigh"].Value.ToString());
|
|
|
|
bool minReached = false;
|
|
bool maxReached = false;
|
|
int cycleCount = 0;
|
|
|
|
foreach (var value in airTemperatures)
|
|
{
|
|
if (value <= minThreshold)
|
|
minReached = true;
|
|
|
|
if (value >= maxThreshold)
|
|
maxReached = true;
|
|
|
|
if (minReached && maxReached)
|
|
{
|
|
cycleCount++;
|
|
//Console.WriteLine($"Cycle {cycleCount}: Beide extremen bereikt.");
|
|
minReached = false;
|
|
maxReached = false;
|
|
}
|
|
}
|
|
|
|
if (cycleCount == 0)
|
|
{
|
|
//Console.WriteLine("Geen volledige cycles met beide extremen gevonden.");
|
|
if (!RowExists(dgvProjectErrors, sensor.PK))
|
|
dgvProjectErrors.Rows.Add(chamber.MIDS, sensor.PK, readings[0].Timestamp, Math.Round(readings[0].Value, 2), sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check for falling voltages for all tests except for PTC and THB_cycledbias tests ofcourse (drops with 50%)
|
|
double previousValue = 0.0;
|
|
// Check voor elke test (behalve PTC-tests)
|
|
if (!testtype.Contains("PTC") && !testtype.Contains("THB_cycledbias"))
|
|
{
|
|
if (sensorname[sensorid].ToLower().Contains("voltage")) // alleen voor spanningskanalen
|
|
{
|
|
foreach (var reading in readings)
|
|
{
|
|
double value = reading.Value * a + b; // gecorrigeerde waarde!
|
|
//Console.WriteLine("voltage " + value.ToString() + " prevValue " + previousValue.ToString() +" timestamp " + reading.Timestamp.ToString());
|
|
|
|
// controleer of spanning met meer dan 50% daalt
|
|
if (value < previousValue * 0.5)
|
|
{
|
|
Console.WriteLine("Spanning is meer dan 50% gedaald: " + value);
|
|
if (!RowExists(dgvProjectErrors, sensor.PK))
|
|
dgvProjectErrors.Rows.Add(chamber.MIDS, sensor.PK, reading.Timestamp, Math.Round(value, 2), sensorname[sensorid], 1);
|
|
}
|
|
|
|
previousValue = value;
|
|
}
|
|
try
|
|
{
|
|
DateTime mostRecentTimestamp = mostRecentReading.Timestamp;
|
|
|
|
// controleer of spanning wegzakt naar 0
|
|
|
|
if (readings.Count > 0)
|
|
{
|
|
DateTime lastTimestamp = readings.Last().Timestamp; // Haal de timestamp van de laatste reading
|
|
TimeSpan timeDifference = lastTimestamp - mostRecentTimestamp;
|
|
if (timeDifference.TotalMinutes < -5)
|
|
{
|
|
Console.WriteLine("Spanning gedaald naar 0!");
|
|
if (!RowExists(dgvProjectErrors, sensor.PK))
|
|
dgvProjectErrors.Rows.Add(chamber.MIDS, sensor.PK, lastTimestamp, 0.0, sensorname[sensorid], 1);
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sensorid++;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error for Sensor {sensor.PK}: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
|
|
|
|
|
|
try
|
|
{
|
|
foreach (var cabinet in cabinets)
|
|
{
|
|
Boolean projecterror = false;
|
|
Boolean projectprogress = false;
|
|
foreach (DataGridViewRow row in dgvProjectErrors.Rows)
|
|
{
|
|
string chambernumber = row.Cells[0].Value.ToString();
|
|
if (Int32.Parse(cabinet.Name) == Int32.Parse(chambernumber))
|
|
{
|
|
Console.WriteLine("project error in chamber " + cabinet.Name);
|
|
|
|
#warning controle of test binnen uur geleden gestart is
|
|
projecterror = true;
|
|
}
|
|
}
|
|
foreach (DataGridViewRow row in dgvProjects.Rows)
|
|
{
|
|
string chambernumber = row.Cells[3].Value.ToString();
|
|
if (Int32.Parse(cabinet.Name) == Int32.Parse(chambernumber))
|
|
{
|
|
projectprogress = true;
|
|
}
|
|
}
|
|
|
|
|
|
if (cabinet.StatusColor != Color.FromArgb(247, 180, 116))
|
|
{
|
|
if (projecterror == true)
|
|
cabinet.StatusColor = Color.FromArgb(238, 126, 16); // eurofins oranje
|
|
else if (projectprogress == true)
|
|
{
|
|
cabinet.StatusColor = Color.FromArgb(34, 177, 76); // bijpassende groene kleur
|
|
|
|
}
|
|
else
|
|
{
|
|
cabinet.StatusColor = Color.Transparent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
Console.WriteLine("project data check finished");
|
|
}
|
|
|
|
|
|
|
|
private bool RowExists(DataGridView dgv, object sensorPK)
|
|
{
|
|
if (sensorAttempts.ContainsKey(sensorPK))
|
|
{
|
|
sensorAttempts[sensorPK]++;
|
|
}
|
|
else
|
|
{
|
|
sensorAttempts[sensorPK] = 1;
|
|
}
|
|
|
|
foreach (DataGridViewRow row in dgv.Rows)
|
|
{
|
|
if (row.IsNewRow) continue;
|
|
if (row.Cells[1].Value?.Equals(sensorPK) == true)
|
|
{
|
|
row.Cells[dgv.Columns.Count - 1].Value = sensorAttempts[sensorPK];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
private void tbGeneralDataInterval_TextChanged(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
//timerGeneralDataCheck.Interval = Int32.Parse(tbGeneralDataInterval.Text) * 60 * 1000;
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Invalid interval value");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private void btnGeneralCheck_Click(object sender, EventArgs e)
|
|
{
|
|
GeneralDataCheck();
|
|
}
|
|
|
|
private void dgvGeneralErrors_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
private void dgvGeneralErrors_Click(object sender, EventArgs e)
|
|
{
|
|
if (dgvGeneralErrors.SelectedRows.Count > 0)
|
|
{
|
|
DataGridViewRow selectedRow = dgvGeneralErrors.SelectedRows[0];
|
|
tabControl.SelectedTab = tpDataView;
|
|
|
|
var roomNumber = selectedRow.Cells[0].Value?.ToString();
|
|
if (roomNumber != null)
|
|
{
|
|
string formattedRoomNumber = int.TryParse(roomNumber, out int roomNum) ? roomNum.ToString("D5") : roomNumber;
|
|
|
|
if (lbChambers.Items.Contains(formattedRoomNumber))
|
|
lbChambers.SelectedItem = formattedRoomNumber;
|
|
else
|
|
lbChambers.ClearSelected();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dgvProjects_CellClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (dgvProjects.SelectedRows.Count > 0)
|
|
{
|
|
DataGridViewRow selectedRow = dgvProjects.SelectedRows[0];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static string[] AnalyzeProject(string stepstring, Color backColor)
|
|
{
|
|
//Console.WriteLine(stepstring);
|
|
string temperature = "N/A";
|
|
string rh = "N/A";
|
|
string duration = "N/A";
|
|
string testtype = "N/A";
|
|
string tempH = "N/A";
|
|
string tempL = "N/A";
|
|
|
|
if (backColor == Color.FromArgb(191, 226, 248))
|
|
testtype = "HAST";
|
|
else if (backColor == Color.FromArgb(196, 249, 235))
|
|
testtype = "HTOL";
|
|
else if (backColor == Color.FromArgb(235, 243, 253))
|
|
testtype = "Unknown";
|
|
else if (backColor == Color.FromArgb(197, 249, 199)) // Green TC 2 chamber
|
|
testtype = "TC";
|
|
else if (backColor == Color.Pink) // Pink
|
|
testtype = "Unknown";
|
|
else if (backColor == Color.FromArgb(208, 195, 249)) // Purple
|
|
testtype = "Climate";
|
|
else if (backColor == Color.FromArgb(249, 243, 195)) // Yellow TC 1 chamber
|
|
testtype = "TC";
|
|
else
|
|
testtype = "Unknown";
|
|
|
|
|
|
|
|
|
|
if(testtype=="TC")
|
|
{
|
|
|
|
// Regex om temperaturen zoals "-40 °C" of "+150°C" te vinden
|
|
Regex regex = new Regex(@"([-+]?\d+)\s?°C", RegexOptions.IgnoreCase);
|
|
MatchCollection matches = regex.Matches(stepstring);
|
|
|
|
if (matches.Count >= 2)
|
|
{
|
|
double t1 = double.Parse(matches[0].Groups[1].Value);
|
|
double t2 = double.Parse(matches[1].Groups[1].Value);
|
|
|
|
// Sorteer zodat de laagste waarde tempL is en de hoogste tempH
|
|
if (t1 < t2)
|
|
{
|
|
tempL = t1.ToString();
|
|
tempH = t2.ToString();
|
|
}
|
|
else
|
|
{
|
|
tempL = t2.ToString();
|
|
tempH = t1.ToString();
|
|
}
|
|
return new string[] { temperature, rh, duration, testtype, tempH, tempL };
|
|
}
|
|
}
|
|
|
|
// Regex voor temperatuur (bijv. 125°C, 110±2 °C)
|
|
string tempPattern = @"(\d+)(?:±\d+)?\s*°C";
|
|
Match tempMatch = Regex.Match(stepstring, tempPattern);
|
|
|
|
if (tempMatch.Success)
|
|
{
|
|
temperature = tempMatch.Groups[1].Value;
|
|
}
|
|
|
|
// Regex voor relatieve luchtvochtigheid (bijv. 85% R.H., 85±5% R.H.)
|
|
string rhPattern = @"(\d+)(?:±\d+)?\s*%\s*(?:R\.?H\.?|rh)";
|
|
|
|
Match rhMatch = Regex.Match(stepstring, rhPattern);
|
|
if (rhMatch.Success)
|
|
{
|
|
rh = rhMatch.Groups[1].Value;
|
|
}
|
|
|
|
// Regex voor duur (bijv. 24h, 68 hours, 1 hour)
|
|
string durationPattern = @"(\d+)(?:\s*\(\+?-?\d+/-?\d+\))?\s*(?:hours?|hrs?|h)";
|
|
Match durationMatch = Regex.Match(stepstring, durationPattern);
|
|
if (durationMatch.Success)
|
|
{
|
|
duration = durationMatch.Groups[1].Value;
|
|
}
|
|
// Retourneer de resultaten als een array
|
|
return new string[] { temperature, rh, duration, testtype, tempH, tempL };
|
|
}
|
|
|
|
|
|
|
|
private void dgvProjects_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void tpProjectData_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void btnProjectDataCheck_Click(object sender, EventArgs e)
|
|
{
|
|
projectDataCheck();
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1x per 3 minuten ProjectdataCheck en 1x per 30 minuten GeneralDataCheck
|
|
private int timerCount = 0;
|
|
private void timerProjectDataCheck_Tick(object sender, EventArgs e)
|
|
{
|
|
Cursor = Cursors.WaitCursor;
|
|
|
|
obtainActiveProjects();
|
|
|
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
if ( timerCount % 3 == 0)
|
|
projectDataCheck();
|
|
|
|
if (timerCount % 30 == 0)
|
|
GeneralDataCheck();
|
|
|
|
Cursor = Cursors.Default;
|
|
updateOverview();
|
|
|
|
// Teller verhogen en resetten bij 30 om oneindige groei te voorkomen
|
|
timerCount = (timerCount + 1) % 30;
|
|
}
|
|
|
|
|
|
private void dgvProjects_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (isLoadingData)
|
|
return;
|
|
|
|
Console.WriteLine("save");
|
|
|
|
try
|
|
{
|
|
var xml = new XElement("Projects",
|
|
from DataGridViewRow row in dgvProjects.Rows
|
|
where !row.IsNewRow // Sla lege rijen over
|
|
select new XElement("Project",
|
|
dgvProjects.Columns.Cast<DataGridViewColumn>()
|
|
.Where(col => row.Cells[col.Index].Value != null) // Voorkom null waarden
|
|
.Select(col => new XElement(col.HeaderText, row.Cells[col.Index].Value?.ToString() ?? ""))
|
|
)
|
|
);
|
|
xml.Save(filePath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Fout bij het opslaan van XML: {ex.Message}", "Fout", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
private void dgvProjects_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (dgvProjects.SelectedRows.Count > 0)
|
|
{
|
|
DataGridViewRow selectedRow = dgvProjects.SelectedRows[0];
|
|
|
|
var roomNumber = selectedRow.Cells[3].Value?.ToString();
|
|
if (roomNumber != null)
|
|
{
|
|
string formattedRoomNumber = int.TryParse(roomNumber, out int roomNum) ? roomNum.ToString("D5") : roomNumber;
|
|
|
|
if (lbChambers.Items.Contains(formattedRoomNumber))
|
|
lbChambers.SelectedItem = formattedRoomNumber;
|
|
else
|
|
lbChambers.ClearSelected();
|
|
}
|
|
tabControl.SelectedTab = tpDataView;
|
|
updateLiveView();
|
|
}
|
|
}
|
|
|
|
private void timerLiveData_Tick(object sender, EventArgs e)
|
|
{
|
|
if (cbLiveData.Checked == true)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
}
|
|
|
|
private void btnUpdateOverview_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void StatusIndicator_Click(object sender, MouseEventArgs e)
|
|
{
|
|
CabinetStatus cabinet = null;
|
|
|
|
if (sender is Panel panel && panel.Tag is CabinetStatus cab1)
|
|
{
|
|
cabinet = cab1;
|
|
}
|
|
else if (sender is Label label && label.Parent is Panel parentPanel && parentPanel.Tag is CabinetStatus cab2)
|
|
{
|
|
cabinet = cab2;
|
|
}
|
|
|
|
if (cabinet != null)
|
|
{
|
|
// MessageBox.Show($"Je hebt geklikt op: {cabinet.Name}, Positie: {cabinet.Position}, Kleur: {cabinet.StatusColor}");
|
|
string roomNumber = cabinet.Name;
|
|
string formattedRoomNumber = int.TryParse(roomNumber, out int roomNum) ? roomNum.ToString("D5") : roomNumber;
|
|
|
|
if (lbChambers.Items.Contains(formattedRoomNumber))
|
|
lbChambers.SelectedItem = formattedRoomNumber;
|
|
else
|
|
lbChambers.ClearSelected();
|
|
|
|
tabControl.SelectedTab = tpDataView;
|
|
}
|
|
}
|
|
|
|
private System.Drawing.Drawing2D.GraphicsPath RoundedRect(Rectangle bounds, int radius)
|
|
{
|
|
int diameter = radius * 2;
|
|
var path = new System.Drawing.Drawing2D.GraphicsPath();
|
|
|
|
path.AddArc(bounds.Left, bounds.Top, diameter, diameter, 180, 90);
|
|
path.AddArc(bounds.Right - diameter, bounds.Top, diameter, diameter, 270, 90);
|
|
path.AddArc(bounds.Right - diameter, bounds.Bottom - diameter, diameter, diameter, 0, 90);
|
|
path.AddArc(bounds.Left, bounds.Bottom - diameter, diameter, diameter, 90, 90);
|
|
path.CloseFigure();
|
|
return path;
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateOverview()
|
|
{
|
|
// Update RTH-sensoren
|
|
List<int> sensorIds = rthSensors.Select(s => s.Id).ToList();
|
|
List<(double temperature, double humidity)> sensorData = GetTemperaturesAndHumidity(sensorIds);
|
|
|
|
for (int i = 0; i < sensorData.Count; i++)
|
|
{
|
|
rthSensors[i].Temperature = sensorData[i].temperature;
|
|
rthSensors[i].Humidity = sensorData[i].humidity;
|
|
}
|
|
|
|
humidityLOW = false;
|
|
|
|
foreach (var sensor in rthSensors)
|
|
{
|
|
// Controleer of er al een panel voor deze sensor bestaat
|
|
Panel statusIndicator = pcHal.Controls.OfType<Panel>().FirstOrDefault(p => p.Tag is RTHSensor s && s.Id == sensor.Id);
|
|
|
|
if (statusIndicator == null)
|
|
{
|
|
// Nieuw statuspanel voor RTH-sensor aanmaken
|
|
statusIndicator = new Panel
|
|
{
|
|
Size = new Size(55, 55),
|
|
BackColor = GetColorFromHumidity(sensor.Humidity),
|
|
Location = sensor.Position,
|
|
Cursor = Cursors.Hand,
|
|
Tag = sensor
|
|
};
|
|
|
|
// Maak cirkelvorm
|
|
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
|
|
path.AddEllipse(0, 0, statusIndicator.Width, statusIndicator.Height);
|
|
statusIndicator.Region = new Region(path);
|
|
|
|
statusIndicator.Paint += (sender, e) =>
|
|
{
|
|
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
e.Graphics.DrawEllipse(Pens.Black, 0, 0, statusIndicator.Width - 1, statusIndicator.Height - 1);
|
|
};
|
|
|
|
// Label
|
|
Label sensorLabel = new Label
|
|
{
|
|
Text = $"{sensor.Temperature:F1}\n{sensor.Humidity:F1}",
|
|
ForeColor = Color.Black,
|
|
BackColor = Color.Transparent,
|
|
TextAlign = ContentAlignment.MiddleCenter,
|
|
Dock = DockStyle.Fill,
|
|
Font = new Font("Arial", 12, FontStyle.Bold)
|
|
};
|
|
|
|
statusIndicator.Controls.Add(sensorLabel);
|
|
pcHal.Controls.Add(statusIndicator);
|
|
}
|
|
else
|
|
{
|
|
// Alleen kleur en tekst updaten
|
|
statusIndicator.BackColor = GetColorFromHumidity(sensor.Humidity);
|
|
Label label = statusIndicator.Controls.OfType<Label>().FirstOrDefault();
|
|
if (label != null)
|
|
{
|
|
label.Text = $"{sensor.Temperature:F1}\n{sensor.Humidity:F1}";
|
|
}
|
|
}
|
|
|
|
// Klik-event altijd toevoegen
|
|
statusIndicator.MouseClick -= StatusIndicator_Click;
|
|
statusIndicator.MouseClick += StatusIndicator_Click;
|
|
}
|
|
|
|
if(humidityLOW==true)
|
|
pnlESDwarning.Visible = true;
|
|
else
|
|
pnlESDwarning.Visible = false;
|
|
|
|
|
|
// Update cabinets
|
|
foreach (var cabinet in cabinets)
|
|
{
|
|
Panel statusIndicator = pcHal.Controls.OfType<Panel>().FirstOrDefault(p => p.Tag is CabinetStatus cab && cab.Name == cabinet.Name);
|
|
|
|
if (statusIndicator == null)
|
|
{
|
|
statusIndicator = new Panel
|
|
{
|
|
Size = new Size(55, 55),
|
|
BackColor = Color.Transparent, // <--- Zet BACKGROUND transparant
|
|
Location = cabinet.Position,
|
|
Cursor = Cursors.Hand,
|
|
Tag = cabinet
|
|
};
|
|
/*
|
|
statusIndicator = new Panel
|
|
{
|
|
Size = new Size(55, 55),
|
|
BackColor = cabinet.StatusColor,
|
|
Location = cabinet.Position,
|
|
Cursor = Cursors.Hand,
|
|
Tag = cabinet
|
|
};
|
|
|
|
|
|
statusIndicator.Paint += (sender, e) =>
|
|
{
|
|
e.Graphics.DrawRectangle(Pens.Black, 0, 0, statusIndicator.Width - 1, statusIndicator.Height - 1);
|
|
};
|
|
*/
|
|
|
|
//
|
|
statusIndicator.Paint += (sender, e) =>
|
|
{
|
|
var panel = sender as Panel;
|
|
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
|
|
int radius = 15; // Rondingsstraal
|
|
var rect = new Rectangle(0, 0, panel.Width - 1, panel.Height - 1);
|
|
|
|
using (var path = RoundedRect(rect, radius))
|
|
{
|
|
using (var brush = new SolidBrush(cabinet.StatusColor))
|
|
{
|
|
e.Graphics.FillPath(brush, path); // <-- TEKEN GEKLEURDE GEVULDE VORM
|
|
}
|
|
|
|
e.Graphics.DrawPath(Pens.Black, path); // <-- TEKEN RAND
|
|
}
|
|
};
|
|
|
|
//
|
|
|
|
Label numberLabel = new Label
|
|
{
|
|
Text = cabinet.Name,
|
|
ForeColor = Color.Black,
|
|
BackColor = Color.Transparent,
|
|
TextAlign = ContentAlignment.MiddleCenter,
|
|
Dock = DockStyle.Fill,
|
|
Font = new Font("Arial", 14, FontStyle.Bold)
|
|
};
|
|
numberLabel.MouseClick += StatusIndicator_Click; // <- toevoegen
|
|
|
|
statusIndicator.Controls.Add(numberLabel);
|
|
pcHal.Controls.Add(statusIndicator);
|
|
}
|
|
else
|
|
{
|
|
//statusIndicator.BackColor = cabinet.StatusColor;
|
|
}
|
|
|
|
statusIndicator.MouseClick -= StatusIndicator_Click;
|
|
statusIndicator.MouseClick += StatusIndicator_Click;
|
|
}
|
|
|
|
pcHal.BringToFront();
|
|
pcHal.Invalidate();
|
|
}
|
|
|
|
|
|
|
|
Color GetColorFromHumidity(double humidity)
|
|
{
|
|
if (humidity < 30)
|
|
{
|
|
humidityLOW = true;
|
|
return Color.FromArgb(205, 45, 45); // rth rood
|
|
}
|
|
if (humidity >=30) return Color.FromArgb(34, 177, 76); // rth groen
|
|
return Color.Red;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (tabControl.SelectedTab == tpHal)
|
|
{
|
|
updateOverview();
|
|
}
|
|
}
|
|
|
|
private void pcHal_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (false)
|
|
Console.WriteLine($"X: {e.X}, Y: {e.Y}");
|
|
}
|
|
|
|
private void bgwGeneralDataCheck_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
GeneralDataCheck();
|
|
}
|
|
|
|
private void bgwProjectDataCheck_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
projectDataCheck();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void tbLastHours_TextChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void tbHourView_TextChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void cbLiveData_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void cbShowEnvelope_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
|
|
private void cbVoltageScale_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
|
|
private void tbLastHours_Leave(object sender, EventArgs e)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
|
|
private void tbHourView_Leave(object sender, EventArgs e)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
|
|
private void tbLastHours_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
public class SensorReading
|
|
{
|
|
public float Value { get; set; }
|
|
public DateTime Timestamp { get; set; }
|
|
}
|
|
|
|
public class RTHSensor
|
|
{
|
|
public int Id { get; set; }
|
|
public double Temperature { get; set; }
|
|
public double Humidity { get; set; }
|
|
public Point Position { get; set; } // Positie in de PictureBox
|
|
}
|
|
|
|
public class CabinetStatus
|
|
{
|
|
public string Name { get; set; }
|
|
public Point Position { get; set; }
|
|
public Color StatusColor { get; set; }
|
|
}
|
|
|
|
|
|
|
|
private void tbHourView_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
updateLiveView();
|
|
}
|
|
|
|
}
|
|
|
|
private void button1_Click(object sender, EventArgs e)
|
|
{
|
|
tbLastHours.Text = "10";
|
|
updateLiveView();
|
|
}
|
|
|
|
private void btn1d_Click(object sender, EventArgs e)
|
|
{
|
|
tbLastHours.Text = "24";
|
|
updateLiveView();
|
|
}
|
|
|
|
private void btn2d_Click(object sender, EventArgs e)
|
|
{
|
|
tbLastHours.Text = "48";
|
|
updateLiveView();
|
|
}
|
|
|
|
private void btn1w_Click(object sender, EventArgs e)
|
|
{
|
|
tbLastHours.Text = "168";
|
|
updateLiveView();
|
|
}
|
|
|
|
// Server acces parameters
|
|
const string UserID = "mids_userquery";
|
|
const string Password = "23uRUVfq6dXXHMWN";
|
|
const string Catalog = "mids_maser";
|
|
const string Server = "meeu001sqvp007.itiz-me-eu.local";
|
|
|
|
private static MySqlConnection GetConnection()
|
|
{
|
|
try
|
|
{
|
|
string ConnectionString = String.Format("DataSource={0};Persist Security Info=False;Initial Catalog={1};Connect Timeout=30;Username={2}; Password={3};", Server, Catalog, UserID, Password);
|
|
MySqlConnection myConnection = new MySqlConnection();
|
|
myConnection.ConnectionString = ConnectionString;
|
|
return myConnection;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
private void button2_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private List<(double temperature, double humidity)> GetTemperaturesAndHumidity(List<int> sensorIds)
|
|
{
|
|
MySqlCommand cmd;
|
|
MySqlConnection connection = null;
|
|
var results = new List<(double temperature, double humidity)>(); // Lijst om de resultaten op te slaan
|
|
|
|
try
|
|
{
|
|
foreach (int sensorId in sensorIds)
|
|
{
|
|
string query = $"SELECT temperature, humidity FROM `sensor_data` WHERE sensor_id = {sensorId} ORDER BY timestamp DESC LIMIT 1";
|
|
|
|
// Verbinding maken
|
|
connection = GetConnection();
|
|
if (connection == null)
|
|
{
|
|
return results; // Geen verbinding, lege lijst retourneren
|
|
}
|
|
|
|
cmd = new MySqlCommand(query, connection);
|
|
|
|
connection.Open();
|
|
|
|
// Voer de query uit
|
|
MySqlDataReader reader = cmd.ExecuteReader();
|
|
|
|
if (reader.HasRows)
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
double temperature = reader.IsDBNull(0) ? 0.0 : reader.GetDouble(0);
|
|
double humidity = reader.IsDBNull(1) ? 0.0 : reader.GetDouble(1);
|
|
|
|
// Voeg de opgehaalde waarden toe aan de lijst
|
|
results.Add((temperature, humidity));
|
|
}
|
|
}
|
|
|
|
reader.Close();
|
|
connection.Close();
|
|
}
|
|
}
|
|
catch (MySqlException ex)
|
|
{
|
|
// Foutmelding voor MySQL
|
|
Console.WriteLine("MySQL fout: " + ex.Message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Algemene foutmelding voor andere fouten
|
|
Console.WriteLine("Fout: " + ex.Message);
|
|
}
|
|
finally
|
|
{
|
|
if (connection != null)
|
|
{
|
|
connection.Close();
|
|
}
|
|
}
|
|
|
|
return results; // Retourneer de lijst met de opgehaalde waarden
|
|
}
|
|
|
|
private void lbSensors_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
lbSensorChanged = true;
|
|
updateLiveView();
|
|
}
|
|
}
|
|
}
|