From e29d104d47c3cdcf8c1e28607c151a4c37eb99d2 Mon Sep 17 00:00:00 2001 From: Bradley Relyea Date: Wed, 26 Nov 2025 14:39:07 +0000 Subject: [PATCH] V4.5 --- AiQ_GUI.cs | 200 ++++++++++++++++++---------------------- AiQ_GUI.resx | 5 +- AiQ_GUI_NET_Test.csproj | 2 +- Camera/CameraModules.cs | 18 +++- Camera/FlexiAPI.cs | 83 +++++++++++++---- GoogleAPI.cs | 132 +++++++++++++------------- Helper.cs | 4 +- LDS.cs | 8 +- Logging.cs | 6 +- Microsoft/Access.cs | 12 +-- Microsoft/StatsExcel.cs | 37 ++++---- Network.cs | 4 +- PDF.cs | 13 ++- Soak/Selenium.cs | 3 - Soak/SoakTest.cs | 45 +++++---- 15 files changed, 304 insertions(+), 268 deletions(-) diff --git a/AiQ_GUI.cs b/AiQ_GUI.cs index f038e49..b1dce52 100644 --- a/AiQ_GUI.cs +++ b/AiQ_GUI.cs @@ -5,6 +5,13 @@ using System.Reflection; namespace AiQ_GUI { + public enum Level + { + ERROR, + WARNING, + LOG + } + public partial class MainForm : Form { // Classes @@ -19,8 +26,6 @@ namespace AiQ_GUI private List soakCtsList = []; private List soakTasks = []; - public const string GoogleDrivePath = @"G:\Shared drives\MAV Production GUI's\AiQ\GUI's\"; - // Colours public static readonly Color BtnColour = Color.FromArgb(70, 65, 80); public static readonly Color TxBxColour = Color.FromArgb(53, 51, 64); @@ -36,20 +41,18 @@ namespace AiQ_GUI private async void AiQGUI_Load(object sender, EventArgs e) { - Stopwatch stopwatch = Stopwatch.StartNew(); - Task? closeProcessesTask = Windows.CloseProcesses(); // Fire and forget closing other apps Windows.UpdateFirewall(); Task UniDataTask = Task.Run(() => Access.ReadUniData()); // Get universal data - Task LDSWAIT = Task.Run(() => LDS.GetLDS()); // Get and deserialise LDS.json - Task guiVerTask = Task.Run(() => GUIUpdate.FindGUIVersion()); // Get GUI Version + Task LDSWAIT = Task.Run(() => LDS.GetLDS()); // Get and deserialise LDS.json + Task guiVerTask = Task.Run(() => GUIUpdate.FindGUIVersion()); // Get GUI Version Network.Initialize("admin", "admin"); // Initialise HTTP client if (await Network.PingIP("8.8.8.8")) // Ping to check if we're online { if (!GoogleAPI.Setup()) - AddToActionsList("Cannot setup Google API"); + AddToActionsList("Cannot setup Google API", Level.WARNING); } else { @@ -71,6 +74,7 @@ namespace AiQ_GUI // Load local data store localDataStore = await LDSWAIT; Logging.LogMessage("Opening GUI"); // Done after LDS to make sure directory exists. + if (localDataStore == null) { AddToActionsList("Could not deserialise LDS.json please help!"); @@ -89,9 +93,6 @@ namespace AiQ_GUI await CheckHWOnline; Flags.Start = false; - - stopwatch.Stop(); - Debug.WriteLine("RunTime " + stopwatch.Elapsed.ToString(@"hh\:mm\:ss\.ff")); } private void PopulateUIWithLDS(LocalDataStore lds) @@ -209,8 +210,8 @@ namespace AiQ_GUI await CheckDiagsAPIPt2(); // For only final test parts // Check module has gone to default config - CameraModules.CheckCamModule(DiagsAPI.IRmodule, LblIRModule); // IR - CameraModules.CheckCamModule(DiagsAPI.OVmodule, LblOVModule); // OV + CameraModules.CheckCamModule(DiagsAPI.IRmodule, LblIRModule, CamOnTest); // IR + CameraModules.CheckCamModule(DiagsAPI.OVmodule, LblOVModule, CamOnTest); // OV // Check voltage and current are OK. LED.CheckLEDs(DiagsAPI.LedVoltage, LblLEDV, "V", CameraAccessInfo.LED_V); // Voltage @@ -253,8 +254,8 @@ namespace AiQ_GUI await CheckDiagsAPIPt1(); // Check module has gone to default config - CameraModules.CheckCamModule(DiagsAPI.IRmodule, LblIRModule); // IR - CameraModules.CheckCamModule(DiagsAPI.OVmodule, LblOVModule); // OV + CameraModules.CheckCamModule(DiagsAPI.IRmodule, LblIRModule, CamOnTest); // IR + CameraModules.CheckCamModule(DiagsAPI.OVmodule, LblOVModule, CamOnTest); // OV // Check voltage and current are OK. LED.CheckLEDs(DiagsAPI.LedVoltage, LblLEDV, "V", CameraAccessInfo.LED_V); // Voltage @@ -286,8 +287,6 @@ namespace AiQ_GUI { await PreTestFailed("Diagnostic Failure"); } - - } // ***** Pass/Fails ***** @@ -336,15 +335,11 @@ namespace AiQ_GUI BtnStartTest.Text = "Test Passed"; PnlQuestion.Visible = false; // just in case this came from an override Logging.LogMessage("Final Test Passed"); - if (CamOnTest.RMANum == 0) // Yap to check if it is not a RMA - { - Access.Stats("Final Tests Passed", CamOnTest.Model); - } - else - { - Access.Stats("RMA Final Tests Passed", CamOnTest.Model); - } + if (CamOnTest.RMANum == 0) // Yap to check if it is not a RMA + Access.Stats("Final Tests Passed", CamOnTest.Model); + else + Access.Stats("RMA Final Tests Passed", CamOnTest.Model); } public async Task TestFailed(Button Btn, string ErrMssg) @@ -354,13 +349,10 @@ namespace AiQ_GUI Btn.Text = "Test Failed"; if (!(CamOnTest.RMANum != 0)) // Yap to check if it is not a RMA - { Access.Stats(["Final Tests Failed", ErrMssg], CamOnTest.Model); - } else - { Access.Stats("RMA Final Tests Failed", CamOnTest.Model); - } + AddToActionsList(ErrMssg); string RedLbls = string.Join(Environment.NewLine, PnlLbls.Controls @@ -400,7 +392,6 @@ namespace AiQ_GUI GoogleAPI.WriteToSS(oblistCD, "'Approval'!C" + nextRow + ":D" + nextRow, GoogleAPI.spreadsheetId_ModelInfo); await Teams.SendMssg(Convert.ToString(nextRow), CbBxUserName.Text); - //GoogleAPI.EmailApproval(Convert.ToString(nextRow), CbBxUserName.Text); string Approved = ""; @@ -514,7 +505,10 @@ namespace AiQ_GUI AddToActionsList($"{DiagsAPI.MAC} not recognised as NVIDIA MAC address"); } else + { lblMac.ForeColor = Color.Red; + AddToActionsList($"{DiagsAPI.MAC} not recognised as a MAC address"); + } // Check timestamp DateTime dateTime = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); @@ -597,9 +591,7 @@ namespace AiQ_GUI CamOnTest.RMANum = Convert.ToInt32(await DisplayInput("What is the RMA number?")); if (CamOnTest.RMANum == -1) // Means they chose the 'I don't know' option - { await TestFailed(BtnStartTest, "Please get RMA number from operations team before continuing"); - } } } } @@ -638,11 +630,7 @@ namespace AiQ_GUI double CPUround = Math.Round(DiagsAPI.CPUusage); // Check CPU usage isn't near max LblCPUusage.Text += CPUround + "%"; - if (CPUround < 98 && CPUround > 50) - { - LblCPUusage.ForeColor = Color.LightGreen; - } - else if (CPUround <= 50) + if (CPUround <= 50) { LblCPUusage.Text += " Unexpectedly low CPU usage"; LblCPUusage.ForeColor = Color.Red; @@ -652,6 +640,10 @@ namespace AiQ_GUI LblCPUusage.Text += " Unexpectedly high CPU usage"; LblCPUusage.ForeColor = Color.Red; } + else + { + LblCPUusage.ForeColor = Color.LightGreen; + } // Check Vaxtor if it doesn't need or have license OR has and wants one then pass if (CameraAccessInfo.VaxtorLic == false && DiagsAPI.licenses.raptorKeyID == "Not Licensed" || CameraAccessInfo.VaxtorLic == true && DiagsAPI.licenses.raptorKeyID != "Not Licensed") @@ -727,7 +719,6 @@ namespace AiQ_GUI lblSerial.Text += DiagsAPI.serialNumber; Printer.ZebraIP = localDataStore.ZebraIP; - Printer.PrintGBLbl(); // Print GB label Printer.PrintSerialLbl(CamOnTest.Model, NewSerial, CameraAccessInfo.Processor); // Print model/serial label } @@ -804,7 +795,9 @@ namespace AiQ_GUI foreach (Camera soakInfo in soakCameraList) { - TabSoak.Controls.Add(SoakTest.MakeNewCheckbox(soakInfo, YLoc)); + CheckBox chkBox = SoakTest.MakeNewCheckbox(soakInfo, YLoc); + TabSoak.Controls.Add(chkBox); + soakInfo.CheckBox = chkBox; YLoc += 24; } @@ -937,15 +930,27 @@ namespace AiQ_GUI } // ***** Helper functions ***** - public void AddToActionsList(string Mssg, bool IsErr = true) + public void AddToActionsList(string Mssg, Level Lvl = Level.LOG) { - if (IsErr) + if (Lvl == Level.ERROR) + { Logging.LogErrorMessage(Mssg); - else + RhTxBxActions.SelectionColor = Color.IndianRed; + } + else if (Lvl == Level.WARNING) + { + Logging.LogWarningMessage(Mssg); + RhTxBxActions.SelectionColor = Color.Orange; + } + else if (Lvl == Level.LOG) + { Logging.LogMessage(Mssg); + RhTxBxActions.SelectionColor = Color.LightGreen; + } RhTxBxActions.AppendText(Mssg + Environment.NewLine); RhTxBxActions.SelectionStart = RhTxBxActions.Text.Length; + RhTxBxActions.SelectionColor = SystemColors.Control; RhTxBxActions.ScrollToCaret(); } @@ -1146,7 +1151,7 @@ namespace AiQ_GUI { Network.Initialize("developer", SCL.DevPass); // Ensure network is initialized to the right camera await FlexiAPI.HTTP_Update("GLOBAL--NetworkConfig", SCL.IP, Network_JSON); - Instance.AddToActionsList($"Setting 211 for camera {SCL.IP}", false); + Instance.AddToActionsList($"Setting 211 for camera {SCL.IP}", Level.LOG); } catch (Exception ex) { @@ -1173,7 +1178,7 @@ namespace AiQ_GUI { Network.Initialize("developer", SCL.DevPass); // Ensure network is initialized to the right camera string RESP = await FlexiAPI.HTTP_Update("GLOBAL--FlexiApplication", SCL.IP, GOD_JSON); - Instance.AddToActionsList($"Setting God mode for camera {SCL.IP} to {newGodModeValue}", false); + Instance.AddToActionsList($"Setting God mode for camera {SCL.IP} to {newGodModeValue}", Level.LOG); } catch (Exception ex) { @@ -1313,7 +1318,11 @@ namespace AiQ_GUI { VaxtorLicResp = JsonConvert.DeserializeObject(ALresponse); - if (VaxtorLicResp.protectionKeyId != string.Empty) + if (VaxtorLicResp.error != string.Empty) + { + AddToActionsList(VaxtorLicResp.error, Level.ERROR); + } + else if (VaxtorLicResp.protectionKeyId != string.Empty) { string err = GoogleAPI.UpdateSpreadSheetVaxtor(VaxtorLicResp, Vers.Serial, CamOnTest.Model); @@ -1327,18 +1336,14 @@ namespace AiQ_GUI await DisplayOK("Please wait at least a minute before turning off the unit."); } - else if (VaxtorLicResp.error != string.Empty) - { - RhTxBxCode.AppendText(VaxtorLicResp.error); - } else { - AddToActionsList($"Error reading JSON - {ALresponse}"); + AddToActionsList($"Error reading JSON - {ALresponse}", Level.ERROR); } } catch { - AddToActionsList($"Error reading JSON - {ALresponse}"); + AddToActionsList($"Error reading JSON - {ALresponse}", Level.ERROR); return; } } @@ -1574,7 +1579,7 @@ namespace AiQ_GUI CancellationTokenSource cts = new(); soakCtsList.Add(cts); - soakTasks.Add(SoakTest.StartSoak(SCL, cts.Token)); + soakTasks.Add(SoakTest.StartSoak(SCL, SCL.CheckBox, cts.Token)); await Task.Delay(10000); } } @@ -1596,7 +1601,7 @@ namespace AiQ_GUI continue; try { - AddToActionsList($"Setting 211 & God Mode off for camera {SCL.IP}", false); + AddToActionsList($"Setting 211 & God Mode off for camera {SCL.IP}", Level.LOG); Network.Initialize("developer", SCL.DevPass); // Ensure network is initialized to the right camera await CameraModules.FactoryResetModules(SCL.IP); // Reset camera modules @@ -1612,6 +1617,13 @@ namespace AiQ_GUI { AddToActionsList("Failed to set all cameras to 211 and god mode off. Reason: " + ex.Message); // In case non AiQ's get caught up } + + if (SCL.CheckBox.ForeColor == Color.Red) + { + DialogResult DR = MessageBox.Show($"CAMERA {SCL.Serial} {SCL.Model} DID NOT PASS SOAK TEST. Check soak test report to see error. Do you want to open the test report", "SOAK TEST FAILED", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + if (DR == DialogResult.Yes) + File.Open(SCL.TestReportLoc, FileMode.Open); + } } await Task.Delay(5000); // Wait for 5 seconds to allow the camera to restart @@ -1619,11 +1631,11 @@ namespace AiQ_GUI if ((FoundCams.Count == i && FoundCams.Contains("192.168.1.211")) || FoundCams.Count == 1) { - AddToActionsList("All cameras successfully changed to 211.", false); + AddToActionsList("All cameras successfully changed to 211.", Level.LOG); } else { - AddToActionsList($"Some cameras failed: Found {FoundCams.Count}, expected {i}.", true); + AddToActionsList($"Some cameras failed: Found {FoundCams.Count}, expected {i}.", Level.ERROR); } } } @@ -1671,59 +1683,7 @@ namespace AiQ_GUI private async void BtnUploadBlob_Click(object sender, EventArgs e) { BtnUploadBlob.BackColor = BtnColour; - const string networkFolderPath = @"G:\Shared drives\MAV Production\MAV_146_AiQ_Mk2\Flexi"; - string fileToUpload = null; - - if (await DisplayQuestion("Do you want the latest Flexi version from the MAV Production folder?")) - { - fileToUpload = Directory.GetFiles(networkFolderPath, "*.blob").OrderByDescending(File.GetLastWriteTime).FirstOrDefault(); - - if (fileToUpload == null) - { - AddToActionsList("No .blob file found in the directory.", false); - return; - } - } - else - { - using OpenFileDialog openFileDialog1 = new() - { - InitialDirectory = networkFolderPath, - Filter = "Blob files (*.blob)|*.blob", - FilterIndex = 0 - }; - - if (openFileDialog1.ShowDialog() == DialogResult.OK) - fileToUpload = openFileDialog1.FileName; - else - { - AddToActionsList("File selection cancelled.", false); - return; - } - } - - string fileName = Path.GetFileName(fileToUpload); - AddToActionsList($"Selected file to upload: {fileToUpload}", false); - - foreach (Camera? cam in soakCameraList.Where(c => c.IsChecked)) - { - string apiUrl = $"http://{cam.IP}/upload/software-update/2"; - Network.Initialize("developer", cam.DevPass); - await Task.Delay(1000); // Gives extra time to allow for Network to initialize - AddToActionsList($"Uploading to {cam.IP}...", false); - string result = await FlexiAPI.SendBlobFileUpload(apiUrl, fileToUpload, fileName); - - // Retry once on transient errors - if (result.Contains("Error while copying content to a stream") || result.Contains("Timeout")) - { - AddToActionsList($"Retrying upload to {cam.IP}...", false); - await Task.Delay(1000); - result = await FlexiAPI.SendBlobFileUpload(apiUrl, fileToUpload, fileName); - } - - AddToActionsList($"Upload result for {cam.IP}: {result}", false); - await Task.Delay(500); - } + FlexiAPI.UploadBlob(soakCameraList); BtnUploadBlob.BackColor = Color.Green; } @@ -1743,19 +1703,37 @@ namespace AiQ_GUI } // ***** Test & Debug ***** - private async void BtnTest_Click(object sender, EventArgs e) + private void BtnTest_Click(object sender, EventArgs e) { Stopwatch stopWatchTest = Stopwatch.StartNew(); //StatsExcel excelExporter = new(); //excelExporter.ExportDatabaseToExcel(); - string ans = await FlexiAPI.HTTP_Fetch("GLOBAL--Device", "192.168.0.71"); - AddToActionsList(ans); // /api/config-ids - For getting all available config IDs + // Make every log file in the soak log directory into a soak test report PDF + var files = from file in Directory.EnumerateFiles("C:\\ProgramData\\MAV\\AiQ_GUI") select file; + + foreach (var file in files) + { + if (file.Contains("SoakLog")) + { + // File name: SoakLog_{Serial}_{Model}.log + string[] parts = file.Split('_', '.').Select(p => p.Trim()).ToArray(); + + Camera NewCam = new() + { + Model = parts[3], + Serial = parts[2], + }; + + PDF.CreateSoakTestReport(NewCam, "SoakTestRig", DateTime.Now, file); + } + } + stopWatchTest.Stop(); - AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff")); + AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff"), Level.LOG); } } } diff --git a/AiQ_GUI.resx b/AiQ_GUI.resx index d93c5df..3ba17b2 100644 --- a/AiQ_GUI.resx +++ b/AiQ_GUI.resx @@ -123,11 +123,8 @@ 159, 17 - - 17, 17 - - 690, 19 + 531, 18 305, 17 diff --git a/AiQ_GUI_NET_Test.csproj b/AiQ_GUI_NET_Test.csproj index 42a72f2..4aa24f2 100644 --- a/AiQ_GUI_NET_Test.csproj +++ b/AiQ_GUI_NET_Test.csproj @@ -16,7 +16,7 @@ AiQ GUI MAV Systems Ltd AiQ GUI - 4.4.0 + 4.5.0 A GUI to control and test the AiQ MAV Systems Ltd 2025 MAV - Plain - Blue.png diff --git a/Camera/CameraModules.cs b/Camera/CameraModules.cs index c85f436..176fc3e 100644 --- a/Camera/CameraModules.cs +++ b/Camera/CameraModules.cs @@ -4,7 +4,7 @@ namespace AiQ_GUI internal class CameraModules { // Chack camera modules are in default state according to what the diagnostics API. - public static void CheckCamModule(Module CamMod, Label Lbl) + public static void CheckCamModule(Module CamMod, Label Lbl, Camera CamOnTest) { if (CamMod == null || Lbl == null) { @@ -17,7 +17,21 @@ namespace AiQ_GUI if (CamMod.zoom != 0) // Check camera module is at full wide errMssg += $"Zoom not at 0 - {CamMod.zoom} "; - if (CamMod.firmwareVer != UniversalData.WonwooFirmware) // Check camera module firmware version is up to date. + bool LessTanOrEqualTo = false; + + try + { + LessTanOrEqualTo = Convert.ToDouble(CamMod.firmwareVer) <= Convert.ToDouble(UniversalData.WonwooFirmware); + } + catch + { + MainForm.Instance.AddToActionsList($"{CamMod.firmwareVer} or {UniversalData.WonwooFirmware} could not be converted to a double"); + } + + if (CamOnTest.RMANum > 0 && LessTanOrEqualTo) + errMssg += $"Firmware: {CamMod.firmwareVer} should be less than or equal to {UniversalData.WonwooFirmware} for RMA {CamOnTest.RMANum}"; + + else if ((CamOnTest.RMANum == 0 || CamOnTest.RMANum == -1) && CamMod.firmwareVer != UniversalData.WonwooFirmware) errMssg += $"Firmware: {CamMod.firmwareVer} should be {UniversalData.WonwooFirmware} "; if (CamMod.expMode != 0) // Auto 0=0x00 diff --git a/Camera/FlexiAPI.cs b/Camera/FlexiAPI.cs index aabf9f0..db39ab2 100644 --- a/Camera/FlexiAPI.cs +++ b/Camera/FlexiAPI.cs @@ -378,7 +378,7 @@ namespace AiQ_GUI using OpenFileDialog openFileDialog1 = new() { - InitialDirectory = MainForm.GoogleDrivePath, + InitialDirectory = GoogleAPI.GoogleDrivePath, Filter = "CSV files (*.csv)|*.csv", FilterIndex = 0 }; @@ -387,7 +387,7 @@ namespace AiQ_GUI fileToUpload = openFileDialog1.FileName; else { - MainForm.Instance.AddToActionsList("File selection cancelled.", false); + MainForm.Instance.AddToActionsList("File selection cancelled.", Level.WARNING); return; } @@ -396,7 +396,7 @@ namespace AiQ_GUI if ((isIR && !filename.Contains("IR")) || (!isIR && !filename.Contains("OV"))) { - MainForm.Instance.AddToActionsList($"Incorrect file selected. Expected {(isIR ? "IR" : "OV")} file", false); + MainForm.Instance.AddToActionsList($"Incorrect file selected. Expected {(isIR ? "IR" : "OV")} file", Level.WARNING); return; } @@ -408,7 +408,7 @@ namespace AiQ_GUI if (parts.Length < 3) { - MainForm.Instance.AddToActionsList($"Invalid row format at line {i + 1}", false); + MainForm.Instance.AddToActionsList($"Invalid row format at line {i + 1}", Level.WARNING); continue; } @@ -419,21 +419,78 @@ namespace AiQ_GUI // VISCA format check if (!RegexCache.VISCAAPIRegex().IsMatch(command)) { - MainForm.Instance.AddToActionsList($"{name}: Invalid VISCA command ({command})", false); + MainForm.Instance.AddToActionsList($"{name}: Invalid VISCA command ({command})", Level.WARNING); continue; // do not send it if bad } string result = await APIHTTPVISCA(ipAddress, command, isIR); if (result.Contains(expectedResponse)) - MainForm.Instance.AddToActionsList($"{name}: Success ({(isIR ? "IR" : "Colour")})", true); + MainForm.Instance.AddToActionsList($"{name}: Success ({(isIR ? "IR" : "Colour")})", Level.LOG); else - MainForm.Instance.AddToActionsList($"{name}: Unexpected response ({result})", false); + MainForm.Instance.AddToActionsList($"{name}: Unexpected response ({result})", Level.ERROR); await Task.Delay(150); } - MainForm.Instance.AddToActionsList($"Upload complete ({(isIR ? "IR" : "Colour")}).", true); + MainForm.Instance.AddToActionsList($"Upload complete ({(isIR ? "IR" : "Colour")}).", Level.LOG); + } + + public static async void UploadBlob(List soakCameraList) + { + const string networkFolderPath = @"G:\Shared drives\MAV Production\MAV_146_AiQ_Mk2\Flexi"; + string fileToUpload = null; + + if (await MainForm.Instance.DisplayQuestion("Do you want the latest Flexi version from the MAV Production folder?")) + { + fileToUpload = Directory.GetFiles(networkFolderPath, "*.blob").OrderByDescending(File.GetLastWriteTime).FirstOrDefault(); + + if (fileToUpload == null) + { + MainForm.Instance.AddToActionsList("No .blob file found in the directory.", Level.ERROR); + return; + } + } + else + { + using OpenFileDialog openFileDialog1 = new() + { + InitialDirectory = networkFolderPath, + Filter = "Blob files (*.blob)|*.blob", + FilterIndex = 0 + }; + + if (openFileDialog1.ShowDialog() == DialogResult.OK) + fileToUpload = openFileDialog1.FileName; + else + { + MainForm.Instance.AddToActionsList("File selection cancelled.", Level.WARNING); + return; + } + } + + string fileName = Path.GetFileName(fileToUpload); + MainForm.Instance.AddToActionsList($"Selected file to upload: {fileToUpload}", Level.LOG); + + foreach (Camera? cam in soakCameraList.Where(c => c.IsChecked)) + { + string apiUrl = $"http://{cam.IP}/upload/software-update/2"; + Network.Initialize("developer", cam.DevPass); + await Task.Delay(1000); // Gives extra time to allow for Network to initialize + MainForm.Instance.AddToActionsList($"Uploading to {cam.IP}...", Level.LOG); + string result = await SendBlobFileUpload(apiUrl, fileToUpload, fileName); + + // Retry once on transient errors + if (result.Contains("Error while copying content to a stream") || result.Contains("Timeout")) + { + MainForm.Instance.AddToActionsList($"Retrying upload to {cam.IP}...", Level.WARNING); + await Task.Delay(1000); + result = await SendBlobFileUpload(apiUrl, fileToUpload, fileName); + } + + MainForm.Instance.AddToActionsList($"Upload result for {cam.IP}: {result}", Level.LOG); + await Task.Delay(500); + } } } @@ -443,10 +500,8 @@ namespace AiQ_GUI public string version { get; set; } = string.Empty; public string revision { get; set; } = string.Empty; public string buildtime { get; set; } = string.Empty; - public string appname { get; set; } = string.Empty; public string MAC { get; set; } = string.Empty; public int timeStamp { get; set; } - public string UUID { get; set; } = string.Empty; public string proquint { get; set; } = string.Empty; [JsonProperty("Serial No.")] @@ -510,13 +565,5 @@ namespace AiQ_GUI public class Property { public string Value { get; set; } = string.Empty; - public string datatype { get; set; } - } - public class VaxtorConfig - { - public string id { get; set; } - public long configHash { get; set; } - public Property propMinCharHeight { get; set; } - public Property propMinGlobalConfidence { get; set; } } } diff --git a/GoogleAPI.cs b/GoogleAPI.cs index df807e9..5724c45 100644 --- a/GoogleAPI.cs +++ b/GoogleAPI.cs @@ -1,12 +1,12 @@ using Google.Apis.Auth.OAuth2; -using Google.Apis.Gmail.v1; +//using Google.Apis.Gmail.v1; using Google.Apis.Services; using Google.Apis.Sheets.v4; using Google.Apis.Sheets.v4.Data; using Google.Apis.Util.Store; -using System.Net.Mail; -using System.Net.Mime; -using System.Reflection; +//using System.Net.Mail; +//using System.Net.Mime; +//using System.Reflection; namespace AiQ_GUI { @@ -18,6 +18,7 @@ namespace AiQ_GUI static readonly string credPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); public const string spreadsheetId_ModelInfo = "1bCcCr4OYqfjmydt6UqtmN4FQETezXmZRSStJdCCcqZM"; public const string DrivePath = @"G:\Shared drives\MAV Production GUI's\"; // Path to google shared drive + public const string GoogleDrivePath = @"G:\Shared drives\MAV Production GUI's\AiQ\GUI's\"; // Startup and make necessary connections to Google servers and make sure user is logged in public static bool Setup() @@ -284,75 +285,76 @@ namespace AiQ_GUI return valuesRMA.Count + 2; // Gets the amount of rows, offsets for start from 1 error and adds one to be next row } - public static void EmailApproval(string ApprovalRow, string User) - { - FileStream GmailStream = new($"{DrivePath}R50IQ\\creds.json", FileMode.Open, FileAccess.Read); - string[] ScopesGmail = [GmailService.Scope.GmailSend]; + // DEPRECATED + //public static void EmailApproval(string ApprovalRow, string User) + //{ + // FileStream GmailStream = new($"{DrivePath}R50IQ\\creds.json", FileMode.Open, FileAccess.Read); + // string[] ScopesGmail = [GmailService.Scope.GmailSend]; - using (GmailStream) - { - string credPathGmail = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.json"); - credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(GmailStream).Secrets, ScopesGmail, "user", CancellationToken.None, new FileDataStore(credPathGmail, true)).Result; - GmailStream.Close(); - } + // using (GmailStream) + // { + // string credPathGmail = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.json"); + // credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(GmailStream).Secrets, ScopesGmail, "user", CancellationToken.None, new FileDataStore(credPathGmail, true)).Result; + // GmailStream.Close(); + // } - // Build the MIME message with attachment - using MailMessage mail = new(); - mail.From = new MailAddress("me"); - mail.To.Add("richard.porter@mav-systems.com"); - mail.To.Add("bradley.relyea@mav-systems.com"); - mail.To.Add("bradley.born@mav-systems.com"); - mail.Subject = "Approval required"; - mail.Body = $"Dear Rich,

Camera needs approval
" + - $"https://docs.google.com/spreadsheets/d/1bCcCr4OYqfjmydt6UqtmN4FQETezXmZRSStJdCCcqZM/edit#gid=1931079354&range=A{ApprovalRow}" + - $"


Thanks,

{User}"; - mail.IsBodyHtml = true; + // // Build the MIME message with attachment + // using MailMessage mail = new(); + // mail.From = new MailAddress("me"); + // mail.To.Add("richard.porter@mav-systems.com"); + // mail.To.Add("bradley.relyea@mav-systems.com"); + // mail.To.Add("bradley.born@mav-systems.com"); + // mail.Subject = "Approval required"; + // mail.Body = $"Dear Rich,

Camera needs approval
" + + // $"https://docs.google.com/spreadsheets/d/1bCcCr4OYqfjmydt6UqtmN4FQETezXmZRSStJdCCcqZM/edit#gid=1931079354&range=A{ApprovalRow}" + + // $"


Thanks,

{User}"; + // mail.IsBodyHtml = true; - // Attach the log file if it exists - string logFilePath = LDS.MAVPath + Logging.LogFileName; - if (File.Exists(logFilePath)) - { - Attachment logAttachment = new(logFilePath, MediaTypeNames.Text.Plain); - logAttachment.Name = Logging.LogFileName; - mail.Attachments.Add(logAttachment); - } + // // Attach the log file if it exists + // string logFilePath = LDS.MAVPath + Logging.LogFileName; + // if (File.Exists(logFilePath)) + // { + // Attachment logAttachment = new(logFilePath, MediaTypeNames.Text.Plain); + // logAttachment.Name = Logging.LogFileName; + // mail.Attachments.Add(logAttachment); + // } - // Save the MIME message to a stream - using MemoryStream ms = new(); - SmtpClient smtpClient = new(); // Only used to access the internal Write method - Type mailWriterType = typeof(SmtpClient).Assembly.GetType("System.Net.Mail.MailWriter"); - object? mailWriter = Activator.CreateInstance( - mailWriterType, - BindingFlags.Instance | BindingFlags.NonPublic, - null, - [ms, true], - null); + // // Save the MIME message to a stream + // using MemoryStream ms = new(); + // SmtpClient smtpClient = new(); // Only used to access the internal Write method + // Type mailWriterType = typeof(SmtpClient).Assembly.GetType("System.Net.Mail.MailWriter"); + // object? mailWriter = Activator.CreateInstance( + // mailWriterType, + // BindingFlags.Instance | BindingFlags.NonPublic, + // null, + // [ms, true], + // null); - typeof(MailMessage).InvokeMember( - "Send", - BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, - null, - mail, - [mailWriter, true, true]); + // typeof(MailMessage).InvokeMember( + // "Send", + // BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, + // null, + // mail, + // [mailWriter, true, true]); - ms.Position = 0; - byte[] rawBytes = ms.ToArray(); + // ms.Position = 0; + // byte[] rawBytes = ms.ToArray(); - GmailService service = new(new BaseClientService.Initializer() - { - HttpClientInitializer = credential, - ApplicationName = ApplicationName, - }); + // GmailService service = new(new BaseClientService.Initializer() + // { + // HttpClientInitializer = credential, + // ApplicationName = ApplicationName, + // }); - Google.Apis.Gmail.v1.Data.Message newMsg = new() - { - Raw = Convert.ToBase64String(rawBytes) - .Replace("+", "-") - .Replace("/", "_") - .Replace("=", "") - }; + // Google.Apis.Gmail.v1.Data.Message newMsg = new() + // { + // Raw = Convert.ToBase64String(rawBytes) + // .Replace("+", "-") + // .Replace("/", "_") + // .Replace("=", "") + // }; - service.Users.Messages.Send(newMsg, "me").Execute(); - } + // service.Users.Messages.Send(newMsg, "me").Execute(); + //} } } diff --git a/Helper.cs b/Helper.cs index 9e54331..dc3bc1b 100644 --- a/Helper.cs +++ b/Helper.cs @@ -184,9 +184,9 @@ namespace AiQ_GUI public string IP { get; set; } = string.Empty; public int RMANum { get; set; } = 0; public string FlexiVersion { get; set; } = string.Empty; // Flexi version - public string Processor { get; set; } = string.Empty; // Nano, Xavier, Orin or Pi? - public string ModuleManufacturer { get; set; } = string.Empty; // KT&C or Wonwoo public bool IsChecked { get; set; } // Is it checked for soak test? + public CheckBox CheckBox { get; set; } = new CheckBox(); + public string TestReportLoc { get; set; } = string.Empty; // Location of test report file } // Static class for global flags diff --git a/LDS.cs b/LDS.cs index 6ab47bc..ae853b0 100644 --- a/LDS.cs +++ b/LDS.cs @@ -17,15 +17,10 @@ namespace AiQ_GUI try { if (!Directory.Exists(MAVPath)) // Check the AiQ folder exists in ProgramData and if it doesn't then create it - { Directory.CreateDirectory(MAVPath); - } if (!File.Exists(MAVPath + LDSFileName)) // Check the LDS file exists and if it doesn't then create it - { - // Save a blank version of the JSON - File.WriteAllText(MAVPath + LDSFileName, DefaultJSON); - } + File.WriteAllText(MAVPath + LDSFileName, DefaultJSON); // Save a blank version of the JSON StreamReader file = new(MAVPath + LDSFileName); string Content = file.ReadToEnd(); @@ -37,7 +32,6 @@ namespace AiQ_GUI { MainForm.Instance.AddToActionsList("Error loading Local Data Store"); return null; // Return null to indicate failure - } } diff --git a/Logging.cs b/Logging.cs index 871408e..3d371d4 100644 --- a/Logging.cs +++ b/Logging.cs @@ -1,6 +1,4 @@ -using System.Diagnostics; - -namespace AiQ_GUI +namespace AiQ_GUI { internal class Logging { @@ -43,7 +41,7 @@ namespace AiQ_GUI } catch (Exception ex) { - Debug.WriteLine($"Error logging message: {ex.Message}"); + MainForm.Instance.AddToActionsList($"Error logging message: {ex.Message}"); } } } diff --git a/Microsoft/Access.cs b/Microsoft/Access.cs index 660b03e..1391c69 100644 --- a/Microsoft/Access.cs +++ b/Microsoft/Access.cs @@ -122,10 +122,8 @@ namespace AiQ_GUI int rowsAffected = cmd.ExecuteNonQuery(); // Execute the command and get the number of rows affected - //if (rowsAffected > 0) // If one or more rows were updated - // AddToActionsList($"Updated {TypeOfTest} for {modelNumber}"); - //else - // AddToActionsList($"No rows found for {modelNumber}"); + if (rowsAffected == 0) // If one or more rows were updated + MainForm.Instance.AddToActionsList($"No rows affected for {modelNumber}"); } conn.Close(); } @@ -162,10 +160,8 @@ namespace AiQ_GUI int rows = cmd.ExecuteNonQuery(); conn.Close(); - //if (rows > 0) - // AddToActionsList($"DiagsStats inserted ({rows} row) for model '{model}' on {DateTime.Now:yyyy-MM-dd}"); - //else - // AddToActionsList("No rows inserted into DiagsStats (unexpected)."); + if (rows == 0) + MainForm.Instance.AddToActionsList("No rows inserted into DiagsStats (unexpected)."); } } diff --git a/Microsoft/StatsExcel.cs b/Microsoft/StatsExcel.cs index 95c134f..0a49c43 100644 --- a/Microsoft/StatsExcel.cs +++ b/Microsoft/StatsExcel.cs @@ -23,7 +23,7 @@ namespace AiQ_GUI DateTime? lastStatsRun = null; try { - using (OleDbCommand cmdPeriod = new OleDbCommand("SELECT LastStatsRun FROM UniversalData", conn)) + using (OleDbCommand cmdPeriod = new("SELECT LastStatsRun FROM UniversalData", conn)) { object res = cmdPeriod.ExecuteScalar(); if (res != null && res != DBNull.Value) @@ -37,7 +37,7 @@ namespace AiQ_GUI } // ==================== MAIN STATS EXPORT ==================== - string selectColumns = @" + const string selectColumns = @" ModelNumber, [Total Tests Run], [Pre Tests Passed], @@ -125,7 +125,7 @@ namespace AiQ_GUI DateTime monthStart = new(now.Year, now.Month, 1); DateTime nextMonth = monthStart.AddMonths(1); - string diagsQuery = @" + const string diagsQuery = @" SELECT [Date], [Model], @@ -136,36 +136,33 @@ namespace AiQ_GUI FROM DiagsStats WHERE [Date] >= ? AND [Date] < ?"; - using (OleDbCommand diagsCmd = new OleDbCommand(diagsQuery, conn)) + using (OleDbCommand diagsCmd = new(diagsQuery, conn)) { diagsCmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = monthStart }); diagsCmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = nextMonth }); - using (OleDbDataAdapter diagsAdapter = new OleDbDataAdapter(diagsCmd)) + using OleDbDataAdapter diagsAdapter = new(diagsCmd); + DataTable diagsTable = new(); + diagsAdapter.Fill(diagsTable); + + if (diagsTable.Rows.Count > 0) { - DataTable diagsTable = new(); - diagsAdapter.Fill(diagsTable); + int startRow = (ws.LastRowUsed()?.RowNumber() ?? 0) + 3; - if (diagsTable.Rows.Count > 0) - { - int startRow = (ws.LastRowUsed()?.RowNumber() ?? 0) + 3; + ws.Cell(startRow, 1).Value = "Diags Stats (Current Month)"; + ws.Cell(startRow, 1).Style.Font.Bold = true; + ws.Cell(startRow, 1).Style.Font.FontSize = 12; - ws.Cell(startRow, 1).Value = "Diags Stats (Current Month)"; - ws.Cell(startRow, 1).Style.Font.Bold = true; - ws.Cell(startRow, 1).Style.Font.FontSize = 12; + ws.Cell(startRow + 1, 1).InsertTable(diagsTable, "Diags_Stats", true); + ws.Columns().AdjustToContents(); - ws.Cell(startRow + 1, 1).InsertTable(diagsTable, "Diags_Stats", true); - ws.Columns().AdjustToContents(); - - MainForm.Instance.AddToActionsList($"Added DiagsStats ({diagsTable.Rows.Count} rows) starting at row {startRow}."); - } + MainForm.Instance.AddToActionsList($"Added DiagsStats ({diagsTable.Rows.Count} rows) starting at row {startRow}."); } } // ==================== SAVE MAIN SHEET ==================== workbook.SaveAs(exportPath); MainForm.Instance.AddToActionsList($"Added {sheetName} to workbook: {exportPath}"); - workbook.Dispose(); // ==================== BACKUP TABLE (ALWAYS, BEFORE RESET) ==================== @@ -199,7 +196,7 @@ namespace AiQ_GUI { try { - string resetSql = @" + const string resetSql = @" UPDATE AiQ SET [Total Tests Run] = 0, [Pre Tests Passed] = 0, diff --git a/Network.cs b/Network.cs index 71f0110..b09807d 100644 --- a/Network.cs +++ b/Network.cs @@ -32,10 +32,8 @@ namespace AiQ_GUI UP = await PingIP("10.10.10.137"); await Task.Delay(500); if (i >= 5) - { - //MainForm.Instance.AddToActionsList($"Could not initialise new network with USER: {username} & PSWD: {password}"); return; // Try 5 times max - } + i++; } } diff --git a/PDF.cs b/PDF.cs index 3f63257..84de986 100644 --- a/PDF.cs +++ b/PDF.cs @@ -167,7 +167,6 @@ namespace AiQ_GUI } List logLines = File.Exists(logFilePath) ? File.ReadAllLines(logFilePath).ToList() : new List(); - List errorLines = logLines.Where(l => l.Contains("[ERROR]")).ToList(); List warningLines = logLines.Where(l => l.Contains("[WARNING]")).ToList(); @@ -337,7 +336,17 @@ namespace AiQ_GUI renderer.PdfDocument.Options.Layout = PdfWriterLayout.Compact; // Construct save path - string fullPath = TestRecordDir + CamSoak.Model + $"\\SoakTestReport_{CamSoak.Model}_{CamSoak.Serial}_{pcTime:dd-MM-yyyy_HH-mm-ss}" + (CamSoak.RMANum != 0 ? $" RMA{CamSoak.RMANum}" : "") + ".pdf"; + string SaveDir = TestRecordDir + CamSoak.Model; + + if (!Directory.Exists(TestRecordDir)) + { + SaveDir = Path.Combine(LDS.MAVPath, "SoakTestRecords"); // Gets local folder if the main TestRecordDir is not found (no google drive). + if (!Directory.Exists(SaveDir)) + Directory.CreateDirectory(SaveDir); + } + + string fullPath = Path.Combine(SaveDir, $"SoakTestReport_{CamSoak.Model}_{CamSoak.Serial}_{pcTime:dd-MM-yyyy_HH-mm-ss}" + (CamSoak.RMANum != 0 ? $" RMA{CamSoak.RMANum}" : "") + ".pdf"); + //string fullPath = TestRecordDir + CamSoak.Model + $"\\SoakTestReport_{CamSoak.Model}_{CamSoak.Serial}_{pcTime:dd-MM-yyyy_HH-mm-ss}" + (CamSoak.RMANum != 0 ? $" RMA{CamSoak.RMANum}" : "") + ".pdf"; renderer.PdfDocument.Save(fullPath); Logging.LogMessage("Soak Test PDF saved to " + fullPath); diff --git a/Soak/Selenium.cs b/Soak/Selenium.cs index 8fdb859..aef7084 100644 --- a/Soak/Selenium.cs +++ b/Soak/Selenium.cs @@ -159,10 +159,7 @@ namespace AiQ_GUI await Task.Delay(500); // Wait for the change to take effect if (!await Checkflashline(driver, CamAct)) - { Logging.LogWarningMessage("Bad flashline after changing: " + fullId, SoakLogFile); - MainForm.Instance.AddToActionsList("Bad flashline after changing: " + fullId); - } } // Monitors the flashline element's color to determine success (green) or failure (red) of a camera diff --git a/Soak/SoakTest.cs b/Soak/SoakTest.cs index 604efea..5d8e36c 100644 --- a/Soak/SoakTest.cs +++ b/Soak/SoakTest.cs @@ -7,7 +7,7 @@ namespace AiQ_GUI internal class SoakTest { // Main soak test loop: Randomise dropdowns, run luminance test every hour, power cycle at 7am - public static async Task StartSoak(Camera CamInfo, CancellationToken token) + public static async Task StartSoak(Camera CamInfo, CheckBox CkBx, CancellationToken token) { if (CamInfo.Serial == "N/A") CamInfo.Serial = "UNKNOWN"; // If serial is not set, set it to UNKNOWN. Cannot have N/A in file names. @@ -34,7 +34,7 @@ namespace AiQ_GUI } catch (Exception ex) { - Logging.LogErrorMessage($"Initial connection failed: {ex.Message}", SoakLogFile); + SoakError($"Initial connection failed: {ex.Message}", SoakLogFile, CamInfo.CheckBox); MainForm.Instance.AddToActionsList($"[{CamInfo.IP}] Initial connection failed: {ex.Message}"); // Wait 10 seconds before trying again @@ -50,7 +50,7 @@ namespace AiQ_GUI } catch (Exception ex) { - Logging.LogErrorMessage($"Failed to get element IDs: {ex.Message}", SoakLogFile); + SoakError($"Failed to get element IDs: {ex.Message}", SoakLogFile, CamInfo.CheckBox); return; } @@ -72,7 +72,7 @@ namespace AiQ_GUI // Retry ping until camera responds or cancelled while (!await Network.PingIP(CamInfo.IP) && !token.IsCancellationRequested) { - Logging.LogErrorMessage($"Camera did not respond after restart.", SoakLogFile); + SoakError($"Camera did not respond after restart.", SoakLogFile, CamInfo.CheckBox); await Task.Delay(TimeSpan.FromMinutes(1), token); // Retry after delay of 1 minute } @@ -86,7 +86,7 @@ namespace AiQ_GUI } catch (Exception ex) { - Logging.LogErrorMessage($"Error during power cycle: {ex.Message}", SoakLogFile); + SoakError($"Error during power cycle: {ex.Message}", SoakLogFile, CamInfo.CheckBox); } } @@ -96,11 +96,11 @@ namespace AiQ_GUI Logging.LogMessage($"Hour changed to {currentHour}, running ImageCheck.", SoakLogFile); try { - ImageCheck(driver, SoakLogFile, CamInfo.IP, CamInfo.DevPass, elementID); + ImageCheck(driver, SoakLogFile, CamInfo, elementID); } catch (Exception ex) { - Logging.LogErrorMessage($"ImageCheck failed: {ex.Message}", SoakLogFile); + SoakError($"ImageCheck failed: {ex.Message}", SoakLogFile, CamInfo.CheckBox); } lastHour = currentHour; } @@ -119,7 +119,7 @@ namespace AiQ_GUI } catch (Exception ex) { - Logging.LogErrorMessage($"ChangeRandomDropdown failed: {ex.Message}", SoakLogFile); + SoakError($"ChangeRandomDropdown failed: {ex.Message}", SoakLogFile, CamInfo.CheckBox); } try @@ -144,6 +144,8 @@ namespace AiQ_GUI if (SoakTestPath != null) { + CamInfo.TestReportLoc = SoakTestPath; + // Delete the soak test log file if the report was created successfully try { @@ -152,7 +154,7 @@ namespace AiQ_GUI } catch (Exception ex) { - Logging.LogErrorMessage($"Failed to delete soak log file: {ex.Message}{Environment.NewLine}Please delete if you find this.", SoakLogFile); + SoakError($"Failed to delete soak log file: {ex.Message}{Environment.NewLine}Please delete if you find this.", SoakLogFile, CamInfo.CheckBox); } // Find the final test report PDF for this camera @@ -198,7 +200,7 @@ namespace AiQ_GUI } // Capture's bright and dark images, then compares their luminance to verify sufficient contrast and adds results to the log - public static async Task LuminescenceMean(string FullID, ChromeDriver driver, string[] SettingMinMax, string SoakLogFile, string IP, string DevPass, string CamAct) + public static async Task LuminescenceMean(string FullID, ChromeDriver driver, string[] SettingMinMax, string SoakLogFile, Camera CamInfo, string CamAct) { string controlType = FullID.Split('_')[0]; // Extract control type from FullID (e.g. "Shutter_1234" → "Shutter") @@ -208,7 +210,7 @@ namespace AiQ_GUI await Task.Delay(500); // Take bright image - Image ImageBright = await ImageProcessing.GetProcessedImage("Infrared", IP, DevPass); + Image ImageBright = await ImageProcessing.GetProcessedImage("Infrared", CamInfo.IP, CamInfo.DevPass); if (ImageBright == null) { Logging.LogWarningMessage($"Bright image is null for {controlType} at setting {SettingMinMax[0]}", SoakLogFile); @@ -222,7 +224,7 @@ namespace AiQ_GUI await Task.Delay(500); // Take dark image - Image ImageDark = await ImageProcessing.GetProcessedImage("Infrared", IP, DevPass); + Image ImageDark = await ImageProcessing.GetProcessedImage("Infrared", CamInfo.IP, CamInfo.DevPass); if (ImageDark == null) { Logging.LogWarningMessage($"Dark image is null for {controlType} at setting {SettingMinMax[1]}", SoakLogFile); @@ -236,9 +238,10 @@ namespace AiQ_GUI if (Bright_Lum < Dark_Lum * 1.01) { - Logging.LogErrorMessage( + SoakError( $"Insufficient luminance contrast. Bright: {Bright_Lum:F2}, Dark: {Dark_Lum:F2} | Type: {controlType} | Bright Setting: {SettingMinMax[0]}, Dark Setting: {SettingMinMax[1]}", - SoakLogFile + SoakLogFile, + CamInfo.CheckBox ); } else @@ -251,7 +254,7 @@ namespace AiQ_GUI } // Performs a series of camera control adjustments and luminance checks to verify image settings functionality - public async static void ImageCheck(ChromeDriver driver, string SoakLogFile, string IP, string DevPass, ElementID elementID) + public async static void ImageCheck(ChromeDriver driver, string SoakLogFile, Camera CamInfo, ElementID elementID) { await Selenium.Dropdown_Change(elementID.modeId, "Manual", driver, SoakLogFile, elementID.CamAct); await Selenium.Dropdown_Change(elementID.shutterId, "1/1000", driver, SoakLogFile, elementID.CamAct); @@ -259,11 +262,11 @@ namespace AiQ_GUI await Selenium.Dropdown_Change(elementID.irisId, "F4.0", driver, SoakLogFile, elementID.CamAct); await Selenium.Dropdown_Change(elementID.irLevelId, "Safe", driver, SoakLogFile, elementID.CamAct); - await LuminescenceMean(elementID.shutterId, driver, ["1/100", "1/10000"], SoakLogFile, IP, DevPass, elementID.CamAct); // Check Shutter goes from min to max + await LuminescenceMean(elementID.shutterId, driver, ["1/100", "1/10000"], SoakLogFile, CamInfo, elementID.CamAct); // Check Shutter goes from min to max await Selenium.Dropdown_Change(elementID.shutterId, "1/1000", driver, SoakLogFile, elementID.CamAct); // Reset to default - await LuminescenceMean(elementID.irisId, driver, ["F2.0", "F16"], SoakLogFile, IP, DevPass, elementID.CamAct); // Check iris goes from min to max + await LuminescenceMean(elementID.irisId, driver, ["F2.0", "F16"], SoakLogFile, CamInfo, elementID.CamAct); // Check iris goes from min to max await Selenium.Dropdown_Change(elementID.irisId, "F4.0", driver, SoakLogFile, elementID.CamAct); // Reset to default - await LuminescenceMean(elementID.gainId, driver, ["20dB", "0dB"], SoakLogFile, IP, DevPass, elementID.CamAct); // Check gain goes from min to max + await LuminescenceMean(elementID.gainId, driver, ["20dB", "0dB"], SoakLogFile, CamInfo, elementID.CamAct); // Check gain goes from min to max } public async static Task ChangeRandomDropdown(ChromeDriver driver, string SoakLogFile, ElementID elementID) @@ -319,6 +322,12 @@ namespace AiQ_GUI return dynamicButton; } + + private static void SoakError(string ErrMssg, string LogFile, CheckBox CkBx) + { + Logging.LogErrorMessage(ErrMssg, LogFile); + CkBx.ForeColor = Color.Red; + } } public class ElementID