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> sensorValues; private Dictionary sensorAttempts = new Dictionary(); // 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 cabinets = new List{ // 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 rthSensors = new List { 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 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 projects = new List(); try { isLoadingData = true; dgvProjects.Rows.Clear(); List 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 if (string.IsNullOrEmpty(name)) { MessageBox.Show("Geen waarde gevonden in 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 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>(); // Dictionary per sensor List sensorWithDatalist = new List(); List selectedSensorList = new List(); 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(); // 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>(); // 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(); } 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 sensorname = new List(); if (chamber != null) { Console.WriteLine("Checking chamber " + chamber.MIDS); List 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>(); // Dictionary per sensor List sensorWithDatalist = new List(); 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(); 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 sensorname = new List(); if (chamber != null) { Console.WriteLine("Checking chamber " + chamber.MIDS); List 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>(); // Dictionary per sensor List sensorWithDatalist = new List(); 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(); 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 airTemperatures = new List(); 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() .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 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().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