Compare commits

..

3 Commits

Author SHA1 Message Date
cfe8a57a9d Merged ready for V4 2025-10-21 14:28:45 +01:00
01268ddda5 Changes to SSH including new password 2025-10-21 14:01:27 +01:00
e39a36183a V3.15 iterim BR changes 2025-10-17 14:26:33 +01:00
16 changed files with 227 additions and 402 deletions

3
AiQ_GUI.Designer.cs generated
View File

@@ -270,9 +270,10 @@ namespace AiQ_GUI
CbBxUserName.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold); CbBxUserName.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
CbBxUserName.ForeColor = SystemColors.Control; CbBxUserName.ForeColor = SystemColors.Control;
CbBxUserName.FormattingEnabled = true; CbBxUserName.FormattingEnabled = true;
CbBxUserName.Items.AddRange(new object[] { "Guest", "Clive", "Conor", "Charlie", "Henry", "Sam C", "Sam L", "Simon", "Sophie", "Toby", "Tom" }); CbBxUserName.Items.AddRange(new object[] { "Guest", "Clive", "Conor", "Charlie", "Henry", "Sam C", "Sam L", "Simon", "Toby", "Tom" });
CbBxUserName.Location = new Point(10, 262); CbBxUserName.Location = new Point(10, 262);
CbBxUserName.Margin = new Padding(4, 3, 4, 3); CbBxUserName.Margin = new Padding(4, 3, 4, 3);
CbBxUserName.MaxDropDownItems = 20;
CbBxUserName.Name = "CbBxUserName"; CbBxUserName.Name = "CbBxUserName";
CbBxUserName.Size = new Size(233, 25); CbBxUserName.Size = new Size(233, 25);
CbBxUserName.TabIndex = 159; CbBxUserName.TabIndex = 159;

View File

@@ -108,7 +108,7 @@ namespace AiQ_GUI
CbBxIris.SelectedIndex = lds.Iris; CbBxIris.SelectedIndex = lds.Iris;
CbBxGain.SelectedIndex = lds.Gain; CbBxGain.SelectedIndex = lds.Gain;
if (lds.User == "Bradley" || lds.User == "Sophie") if (lds.User == "Bradley")
BtnTest.Visible = true; BtnTest.Visible = true;
TxBxCheckValid(TxBxPsuIP); // Set save button color if valid TxBxCheckValid(TxBxPsuIP); // Set save button color if valid
@@ -143,16 +143,13 @@ namespace AiQ_GUI
AddToActionsList($"LED level could not be set: {LEDreply}"); AddToActionsList($"LED level could not be set: {LEDreply}");
} }
else if (!await TestTube.CheckInTestTube(CamOnTest.IP)) // Sets LED's to medium power after checking it is in the test tube else if (!await TestTube.CheckInTestTube(CamOnTest.IP)) // Sets LED's to medium power after checking it is in the test tube
{
await TestFailed(BtnStartTest, "Camera not in test tube"); await TestFailed(BtnStartTest, "Camera not in test tube");
}
Task VisCheck = Helper.VisualCheck(BtnStartTest); Task VisCheck = Helper.VisualCheck(BtnStartTest);
if (!await FlexiAPI.ZoomModules("1F40", CamOnTest.IP)) // Zoom to 8000 (1F40h) at the same time. if (!await FlexiAPI.ZoomModules("1F40", CamOnTest.IP)) // Zoom to 8000 (1F40h) at the same time.
await TestFailed(BtnStartTest, "Could not zoom modules to 8000"); await TestFailed(BtnStartTest, "Could not zoom modules to 8000");
if (!await FlexiAPI.SetZoomLockOn(CamOnTest.IP)) if (!await FlexiAPI.SetZoomLockOn(CamOnTest.IP))
Helper.RestartApp(); Helper.RestartApp();
@@ -194,9 +191,7 @@ namespace AiQ_GUI
await FlexiAPI.SetTrim(CamOnTest.IP, LblTestTubePing.Text); // Auto trims the cameras, some plates should have been captured in the meantime await FlexiAPI.SetTrim(CamOnTest.IP, LblTestTubePing.Text); // Auto trims the cameras, some plates should have been captured in the meantime
if (!await FlexiAPI.ZoomModules("0000", CamOnTest.IP)) // Zoom to full wide if (!await FlexiAPI.ZoomModules("0000", CamOnTest.IP)) // Zoom to full wide
{
await TestFailed(BtnStartTest, "Could not zoom modules to full wide"); await TestFailed(BtnStartTest, "Could not zoom modules to full wide");
}
await Task.Delay(1000); // Wait to be sure cameras are zoomed out. await Task.Delay(1000); // Wait to be sure cameras are zoomed out.
@@ -209,7 +204,6 @@ namespace AiQ_GUI
if (!LEDreply.Contains("Power levels set successfully")) if (!LEDreply.Contains("Power levels set successfully"))
AddToActionsList($"LED level could not be set: {LEDreply}"); AddToActionsList($"LED level could not be set: {LEDreply}");
} }
await FlexiAPI.SetVaxtorMinMaxPlate(CamOnTest.IP);
DateTime PCTime = DateTime.Now; // Grab PC time as close to the API as possible to pass onto PDF later DateTime PCTime = DateTime.Now; // Grab PC time as close to the API as possible to pass onto PDF later
@@ -229,6 +223,7 @@ namespace AiQ_GUI
// If there are any actions identified then fail the test. // If there are any actions identified then fail the test.
// If any labels are red then fail. Only labels in panel so can foreach on labels not controls // If any labels are red then fail. Only labels in panel so can foreach on labels not controls
if (RhTxBxActions.Text.Length > 2 || PnlLbls.Controls.OfType<Label>().Any(c => c.ForeColor == Color.Red) == true) if (RhTxBxActions.Text.Length > 2 || PnlLbls.Controls.OfType<Label>().Any(c => c.ForeColor == Color.Red) == true)
await TestFailed(BtnStartTest, "Failed due to action box text and/or red label");// If approved then pass otherwise GUI would have restarted before getting to TestPassed.
{ {
await TestFailed(BtnStartTest, "Diagnostic Failure");// If approved then pass otherwise GUI would have restarted before getting to TestPassed. await TestFailed(BtnStartTest, "Diagnostic Failure");// If approved then pass otherwise GUI would have restarted before getting to TestPassed.
} }
@@ -270,7 +265,7 @@ namespace AiQ_GUI
} }
} }
public void StatsDiags(string redDiagLabels, string RhTxBxActionsText, string IsRMA, int RMA) public void StatsDiags(string redDiagLabels, string RhTxBxActionsText)
{ {
using OleDbConnection conn = new(connString); using OleDbConnection conn = new(connString);
conn.Open(); conn.Open();
@@ -281,20 +276,26 @@ namespace AiQ_GUI
string model = string.IsNullOrWhiteSpace(CamOnTest?.Model) ? "-" : CamOnTest.Model; string model = string.IsNullOrWhiteSpace(CamOnTest?.Model) ? "-" : CamOnTest.Model;
string sql = @" string sql = @"
INSERT INTO DiagsStats ([Date], [Model], [Red Diags Labels], [RhTxBxActions Contents],[IsRMA],[RMA]) INSERT INTO DiagsStats ([Date], [Model], [Red Diags Labels], [RhTxBxActions Contents])
VALUES (?, ?, ?, ?, ?, ?)"; VALUES (?, ?, ?, ?)";
using OleDbCommand cmd = new(sql, conn); using OleDbCommand cmd = new(sql, conn);
// OleDb uses positional parameters — order must match the VALUES list above cmd.Parameters.Add(new OleDbParameter
cmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = DateTime.Now }); {
cmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.VarWChar, Value = model }); OleDbType = OleDbType.Date,
cmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.VarWChar, Value = redVal }); Value = DateTime.Now
cmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.VarWChar, Value = actVal }); });
cmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Boolean, Value = IsRMA }); cmd.Parameters.AddWithValue("?", model);
cmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.VarWChar, Value = RMA }); cmd.Parameters.AddWithValue("?", redVal);
cmd.Parameters.AddWithValue("?", actVal);
cmd.ExecuteNonQuery(); int rows = cmd.ExecuteNonQuery();
//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).");
} }
@@ -423,6 +424,15 @@ namespace AiQ_GUI
// Indicators to the user the test has failed // Indicators to the user the test has failed
Btn.BackColor = Color.Maroon; Btn.BackColor = Color.Maroon;
Btn.Text = "Test Failed"; Btn.Text = "Test Failed";
if (!(CamOnTest.RMANum != 0)) // Yap to check if it is not a RMA
{
Stats( ["Final Tests Failed", ErrMssg]);
}
else
{
Stats("RMA Final Tests Failed");
}
AddToActionsList(ErrMssg);
string RedLbls = string.Join(Environment.NewLine, PnlLbls.Controls string RedLbls = string.Join(Environment.NewLine, PnlLbls.Controls
.OfType<Label>() .OfType<Label>()
@@ -430,18 +440,7 @@ namespace AiQ_GUI
.Select(lbl => lbl.Text)); // Extract text .Select(lbl => lbl.Text)); // Extract text
string FullFailureValues = RhTxBxActions.Text + Environment.NewLine + RedLbls; string FullFailureValues = RhTxBxActions.Text + Environment.NewLine + RedLbls;
StatsDiags(RedLbls, RhTxBxActions.Text); // Log to Access database
// Database logging \\
if (!(CamOnTest.RMANum != 0)) // Yap to check if it is not a RMA
{
Stats(["Final Tests Failed", ErrMssg]);
StatsDiags(RedLbls, RhTxBxActions.Text, "FALSE", CamOnTest.RMANum);
}
else
{
Stats("RMA Final Tests Failed");
StatsDiags(RedLbls, RhTxBxActions.Text, "TRUE", CamOnTest.RMANum);
}
if (await DisplayQuestion("Test failed, appeal?" + Environment.NewLine + "See Actions textbox for details.")) if (await DisplayQuestion("Test failed, appeal?" + Environment.NewLine + "See Actions textbox for details."))
@@ -461,6 +460,7 @@ namespace AiQ_GUI
Logging.LogErrorMessage(FullFailureValues); Logging.LogErrorMessage(FullFailureValues);
Logging.LogErrorMessage(FullFailureValues);
IList<IList<object>> values = GoogleAPI.service.Spreadsheets.Values.Get(GoogleAPI.spreadsheetId_ModelInfo, "'Approval'!A1:A").Execute().Values; IList<IList<object>> values = GoogleAPI.service.Spreadsheets.Values.Get(GoogleAPI.spreadsheetId_ModelInfo, "'Approval'!A1:A").Execute().Values;
@@ -535,24 +535,22 @@ namespace AiQ_GUI
BtnNo.Visible = false; BtnNo.Visible = false;
Logging.LogMessage("Pre Test Failed"); Logging.LogMessage("Pre Test Failed");
if (CamOnTest.RMANum == 0) // Yap to check if it is not a RMA
{
Stats(["Pre Tests Failed", ErrMssg]);
}
else
{
Stats("RMA Pre Tests Failed");
}
string RedLbls = string.Join(Environment.NewLine, PnlLbls.Controls string RedLbls = string.Join(Environment.NewLine, PnlLbls.Controls
.OfType<Label>() .OfType<Label>()
.Where(lbl => lbl.ForeColor == Color.Red) // Only include red labels .Where(lbl => lbl.ForeColor == Color.Red) // Only include red labels
.Select(lbl => lbl.Text)); // Extract text .Select(lbl => lbl.Text)); // Extract text
string FullFailureValues = RhTxBxActions.Text + Environment.NewLine + RedLbls; string FullFailureValues = RhTxBxActions.Text + Environment.NewLine + RedLbls;
if (CamOnTest.RMANum == 0) // Yap to check if it is not a RMA StatsDiags(RedLbls, RhTxBxActions.Text); // Log to Access database
{
Stats(["Pre Tests Failed", ErrMssg]);
StatsDiags(RedLbls, RhTxBxActions.Text, "FALSE", CamOnTest.RMANum);
}
else
{
Stats("RMA Pre Tests Failed");
StatsDiags(RedLbls, RhTxBxActions.Text, "TRUE", CamOnTest.RMANum);
}
// Log to Access database
if (await DisplayQuestion("Test failed, restart?" + Environment.NewLine + "See Actions textbox for details.")) if (await DisplayQuestion("Test failed, restart?" + Environment.NewLine + "See Actions textbox for details."))
Helper.RestartApp(); Helper.RestartApp();
@@ -674,9 +672,7 @@ namespace AiQ_GUI
CamOnTest.RMANum = Convert.ToInt32(await DisplayInput("What is the RMA number?")); CamOnTest.RMANum = Convert.ToInt32(await DisplayInput("What is the RMA number?"));
if (CamOnTest.RMANum == -1) // Means they chose the 'I don't know' option 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"); await TestFailed(BtnStartTest, "Please get RMA number from operations team before continuing");
}
} }
// Found RMA num and want to verify it with user // Found RMA num and want to verify it with user
else if (!await DisplayQuestion($"Is {CamOnTest.RMANum} the RMA Number?")) // '!' because if its not the right RMA number let the user to it manually else if (!await DisplayQuestion($"Is {CamOnTest.RMANum} the RMA Number?")) // '!' because if its not the right RMA number let the user to it manually
@@ -771,8 +767,8 @@ namespace AiQ_GUI
lblTrim.Text += "H: " + DiagsAPI.trim[0] + " V: " + DiagsAPI.trim[1]; lblTrim.Text += "H: " + DiagsAPI.trim[0] + " V: " + DiagsAPI.trim[1];
// Offset accounted for in the SetTrim function, so value should be close to 0,0. // Offset accounted for in the SetTrim function, so value should be close to 0,0.
int HMax = 96; // 5% of 1920 each way = ±96 const int HMax = 96; // 5% of 1920 each way = ±96
int VMax = 54; // 5% of 1080 each way = ±54 const int VMax = 54; // 5% of 1080 each way = ±54
if (Math.Abs(DiagsAPI.trim[0]) <= HMax && Math.Abs(DiagsAPI.trim[1]) <= VMax) if (Math.Abs(DiagsAPI.trim[0]) <= HMax && Math.Abs(DiagsAPI.trim[1]) <= VMax)
lblTrim.ForeColor = Color.LightGreen; lblTrim.ForeColor = Color.LightGreen;
@@ -1136,9 +1132,8 @@ namespace AiQ_GUI
PnlInputValue.Visible = true; PnlInputValue.Visible = true;
while (Flags.Done == false) // Waiting for user input in RMA Num panel while (Flags.Done == false) // Waiting for user input in RMA Num panel
{
await Task.Delay(100); // Check every 100ms await Task.Delay(100); // Check every 100ms
}
Flags.Done = false; // Reset flag Flags.Done = false; // Reset flag
PnlInputValue.Visible = false; PnlInputValue.Visible = false;
@@ -1822,11 +1817,11 @@ namespace AiQ_GUI
return speedMph; return speedMph;
} }
// ***** Test & Debug ***** // ***** Test & Debug *****
private async void BtnTest_Click(object sender, EventArgs e) private async void BtnTest_Click(object sender, EventArgs e)
{ {
Stopwatch stopWatchTest = Stopwatch.StartNew(); Stopwatch stopWatchTest = Stopwatch.StartNew();
//string[,] GOD_JSON = { { "propURI", "rtsp://ADMIN:1234@192.168.0.49:554/live/main" } }; //string[,] GOD_JSON = { { "propURI", "rtsp://ADMIN:1234@192.168.0.49:554/live/main" } };
//string str = FlexiAPI.BuildJsonUpdate(GOD_JSON, "CameraA"); //string str = FlexiAPI.BuildJsonUpdate(GOD_JSON, "CameraA");
//AddToActionsList(str); //AddToActionsList(str);
@@ -1855,36 +1850,37 @@ namespace AiQ_GUI
//double Spd = EstimateSpeed(frames); //double Spd = EstimateSpeed(frames);
//AddToActionsList("Estimated Speed: " + Spd.ToString("F2") + " MPH"); //AddToActionsList("Estimated Speed: " + Spd.ToString("F2") + " MPH");
await FlexiAPI.SetVaxtorMinMaxPlate(CamOnTest.IP);
//StatsExcel excelExporter = new();
//excelExporter.ExportDatabaseToExcel();
//FakeCamera fakeCamera = new FakeCamera(80); // Create an instance of FakeCamera StatsExcel excelExporter = new();
excelExporter.ExportDatabaseToExcel();
////CamOnTest.IP = CbBxFoundCams.Text; // FakeCamera fakeCamera = new FakeCamera(80); // Create an instance of FakeCamera
//_ = fakeCamera.StartAsync(CAMTYPE.GOOD).ContinueWith(task =>
//{
// //Network.Initialize("developer", "Pass123");
// if (task.IsFaulted) // //CamOnTest.IP = CbBxFoundCams.Text;
// { // _ = fakeCamera.StartAsync(CAMTYPE.BAD).ContinueWith(task =>
// AddToActionsList("Error starting FakeCamera: " + task.Exception?.Message); // {
// } // //Network.Initialize("developer", "Pass123");
// else
// {
// AddToActionsList($"FakeCamera started successfully. IP: {fakeCamera}", false);
// }
//});
//await Task.Delay(3000); // Wait for server to start // if (task.IsFaulted)
//CbBxFoundCams.Text = "localhost"; // Should force update in creds an network reinit // {
//CmBoFoundCams_TextChanged(sender, e); // AddToActionsList("Error starting FakeCamera: " + task.Exception?.Message);
//CbBxCameraType.SelectedIndex = CbBxCameraType.Items.Count - 1; // Selects AB12CD as model number // }
// else
// {
// AddToActionsList($"FakeCamera started successfully. IP: {fakeCamera}", false);
// }
// });
//await Task.Delay(3000); // Wait for server to start // await Task.Delay(3000); // Wait for server to start
// CbBxFoundCams.Text = "localhost"; // Should force update in creds an network reinit
// CmBoFoundCams_TextChanged(sender, e);
// CbBxCameraType.SelectedIndex = CbBxCameraType.Items.Count - 1; // Selects AB12CD as model number
//BtnStartTest_Click(sender, e); // await Task.Delay(3000); // Wait for server to start
//BtnPreTest_Click(sender, e);
AddToActionsList("Estimated Speed: " + Spd.ToString("F2") + " MPH");
stopWatchTest.Stop(); stopWatchTest.Stop();
//AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff")); //AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff"));

View File

@@ -42,7 +42,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="ClosedXML" Version="0.105.0" /> <PackageReference Include="ClosedXML" Version="0.105.0" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Emgu.CV" Version="4.12.0.5764" /> <PackageReference Include="Emgu.CV" Version="4.12.0.5764" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.12.0.5764" /> <PackageReference Include="Emgu.CV.runtime.windows" Version="4.12.0.5764" />
<PackageReference Include="Google.Apis.Auth" Version="1.72.0" /> <PackageReference Include="Google.Apis.Auth" Version="1.72.0" />
@@ -50,11 +49,11 @@
<PackageReference Include="Google.Apis.Sheets.v4" Version="1.70.0.3819" /> <PackageReference Include="Google.Apis.Sheets.v4" Version="1.70.0.3819" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="PDFsharp-MigraDoc-gdi" Version="6.2.2" /> <PackageReference Include="PDFsharp-MigraDoc-gdi" Version="6.2.2" />
<PackageReference Include="Selenium.Support" Version="4.36.0" /> <PackageReference Include="Selenium.Support" Version="4.37.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.36.0" /> <PackageReference Include="Selenium.WebDriver" Version="4.37.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="141.0.7390.7600" /> <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="141.0.7390.7800" />
<PackageReference Include="SSH.NET" Version="2025.0.0" /> <PackageReference Include="SSH.NET" Version="2025.0.0" />
<PackageReference Include="System.Data.OleDb" Version="9.0.9" /> <PackageReference Include="System.Data.OleDb" Version="9.0.10" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -35,6 +35,8 @@ namespace AiQ_GUI
try try
{ {
string JSONdata = BuildJsonUpdate(jsonArrayData, ID); string JSONdata = BuildJsonUpdate(jsonArrayData, ID);
JSONdata = JSONdata.Replace("\"14\"", "14").Replace("\"30\"", "30"); // Fixes & encoding issue
MainForm.Instance.AddToActionsList(JSONdata);
string url = $"http://{IPAddress}/api/update-config"; string url = $"http://{IPAddress}/api/update-config";
return await Network.SendHttpRequest(url, HttpMethod.Post, 2, JSONdata); return await Network.SendHttpRequest(url, HttpMethod.Post, 2, JSONdata);
} }
@@ -159,37 +161,6 @@ namespace AiQ_GUI
return null; // If it fails to parse the JSON return null; // If it fails to parse the JSON
} }
} }
public static async Task<bool> SetVaxtorMinMaxPlate(string IP)
{
try
{
// Build JSON array for Vaxtor min/max plate configuration
string[,] Vaxtor_JSON = { { "propMinCharHeight", "18" }, { "propMinGlobalConfidence", "30" } };
string response = await HTTP_Update("RaptorOCR".Trim(), IP, Vaxtor_JSON);
// Treat "operation was canceled" as a successful apply
if (response.Contains("The operation was canceled", StringComparison.OrdinalIgnoreCase))
{
Logging.LogMessage("SetVaxtorMinMaxPlate: Camera applied config but closed connection early (safe to ignore).");
return true;
}
if (response.Contains("error", StringComparison.OrdinalIgnoreCase))
{
MainForm.Instance.DisplayQuestion($"SetVaxtorMinMaxPlate: failed - Please set manually");
return false;
}
return true;
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Could not set Vaxtor Plate height and min confidence: {ex.Message}");
return false;
}
}
public static async Task<bool> SetZoomLockOn(string IP) public static async Task<bool> SetZoomLockOn(string IP)
{ {
@@ -435,13 +406,5 @@ namespace AiQ_GUI
public class Property public class Property
{ {
public string Value { get; set; } = string.Empty; 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; }
} }
} }

View File

@@ -10,11 +10,11 @@ namespace AiQ_GUI
internal class ImageProcessing internal class ImageProcessing
{ {
// API to get snapshot then downsize and downscale image to save size. // API to get snapshot then downsize and downscale image to save size.
public static async Task<Image?> GetProcessedImage(string suffix, string IPAddress, string DevPass, string? savePath = null, PictureBox? PcBx = null, bool SaveDisplay = false) public static async Task<Image?> GetProcessedImage(string Module, string IPAddress, string DevPass, string? savePath = null, PictureBox? PcBx = null, bool SaveDisplay = false)
{ {
try try
{ {
string requestUrl = $"http://{IPAddress}/{suffix}"; string requestUrl = $"http://{IPAddress}/{Module}-snapshot";
HttpClientHandler handler = new() HttpClientHandler handler = new()
{ {
@@ -85,7 +85,7 @@ namespace AiQ_GUI
public static async Task ImageCheck(PictureBox PicBxOV, PictureBox PicBxF2, PictureBox PicBxF16, Label LblF2, Label LblF16, Camera CamOnTest) public static async Task ImageCheck(PictureBox PicBxOV, PictureBox PicBxF2, PictureBox PicBxF16, Label LblF2, Label LblF16, Camera CamOnTest)
{ {
// Take OV snapshot // Take OV snapshot
Task<Image?> Colour_Response = GetProcessedImage("Colour-snapshot", CamOnTest.IP, CamOnTest.DevPass, LDS.MAVPath + LDS.OVsavePath, PicBxOV, true); Task<Image?> Colour_Response = GetProcessedImage("Colour", CamOnTest.IP, CamOnTest.DevPass, LDS.MAVPath + LDS.OVsavePath, PicBxOV, true);
// Change to wide iris F2.0 // Change to wide iris F2.0
await FlexiAPI.APIHTTPVISCA(CamOnTest.IP, "8101044B00000100FF", true); await FlexiAPI.APIHTTPVISCA(CamOnTest.IP, "8101044B00000100FF", true);
@@ -93,7 +93,7 @@ namespace AiQ_GUI
await Task.Delay(200); // Wait for iris to settle before taking IR image await Task.Delay(200); // Wait for iris to settle before taking IR image
// Take IR bright light image // Take IR bright light image
Image? F2_Response = await GetProcessedImage("Infrared-snapshot", CamOnTest.IP, CamOnTest.DevPass, LDS.MAVPath + LDS.IROpensavePath, PicBxF2, true); Image? F2_Response = await GetProcessedImage("Infrared", CamOnTest.IP, CamOnTest.DevPass, LDS.MAVPath + LDS.IROpensavePath, PicBxF2, true);
if (F2_Response == null) if (F2_Response == null)
{ {
MainForm.Instance.AddToActionsList("IR F2.0 image response is blank."); MainForm.Instance.AddToActionsList("IR F2.0 image response is blank.");
@@ -106,7 +106,7 @@ namespace AiQ_GUI
await Task.Delay(200); // Wait for iris to settle before taking IR image await Task.Delay(200); // Wait for iris to settle before taking IR image
// Take IR low light image // Take IR low light image
Image? F16_Response = await GetProcessedImage("Infrared-snapshot", CamOnTest.IP, CamOnTest.DevPass, LDS.MAVPath + LDS.IRTightsavePath, PicBxF16, true); Image? F16_Response = await GetProcessedImage("Infrared", CamOnTest.IP, CamOnTest.DevPass, LDS.MAVPath + LDS.IRTightsavePath, PicBxF16, true);
if (F16_Response == null) if (F16_Response == null)
{ {
MainForm.Instance.AddToActionsList("IR F16.0 image response is blank."); MainForm.Instance.AddToActionsList("IR F16.0 image response is blank.");

View File

@@ -1,4 +1,5 @@
using Renci.SshNet; using Renci.SshNet;
using Renci.SshNet.Common;
namespace AiQ_GUI namespace AiQ_GUI
{ {
@@ -6,6 +7,29 @@ namespace AiQ_GUI
{ {
public const string SSHUsername = "mav"; public const string SSHUsername = "mav";
public const string SSHPassword = "mavPA$$"; public const string SSHPassword = "mavPA$$";
public const string SSHPasswordNEW = "#!mavsoftMESA19"; // New password for SSH after last one got leaked
private static SshClient SshConnect(string IPAddress)
{
SshClient client = new(IPAddress, SSHUsername, SSHPasswordNEW);
try
{
client.Connect();
return client;
}
catch (SshAuthenticationException)
{
client = new(IPAddress, SSHUsername, SSHPassword);
client.Connect();
return client;
}
catch (Exception Ex)
{
MainForm.Instance.AddToActionsList($"SSH connection failed: {Ex.Message}. Check password or network.");
}
return null;
}
// Connects to camera over SSH and collects the Vaxtor packages, filesystem name, filesystem size, and tailscale status. // Connects to camera over SSH and collects the Vaxtor packages, filesystem name, filesystem size, and tailscale status.
public static SSHData CollectSSHData(string IPAddress) public static SSHData CollectSSHData(string IPAddress)
@@ -14,8 +38,7 @@ namespace AiQ_GUI
try try
{ {
using SshClient client = new(IPAddress, SSHUsername, SSHPassword); SshClient client = SshConnect(IPAddress);
client.Connect();
try try
{ {
@@ -34,8 +57,7 @@ namespace AiQ_GUI
catch (Exception ex) catch (Exception ex)
{ {
MainForm.Instance.AddToActionsList($"Failed to get filesystem info: {ex.Message}"); MainForm.Instance.AddToActionsList($"Failed to get filesystem info: {ex.Message}");
Data.FilesystemName = "Unknown"; Data.FilesystemName = Data.FilesystemSize = "Unknown";
Data.FilesystemSize = "Unknown";
} }
try try
@@ -49,6 +71,7 @@ namespace AiQ_GUI
} }
client.Disconnect(); client.Disconnect();
client.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -131,8 +154,7 @@ namespace AiQ_GUI
{ {
try try
{ {
using SshClient client = new SshClient(IPAddress, SSHUsername, SSHPassword); SshClient client = SshConnect(IPAddress);
client.Connect();
try try
{ {
@@ -144,6 +166,7 @@ namespace AiQ_GUI
} }
client.Disconnect(); client.Disconnect();
client.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -191,10 +214,10 @@ namespace AiQ_GUI
{ {
try try
{ {
using SshClient client = new(IPAddress, SSHUsername, SSHPassword); SshClient client = SshConnect(IPAddress);
client.Connect();
(string FilesystemName, string FilesystemSize) = GetRootFilesystemInfo(client); (string FilesystemName, string FilesystemSize) = GetRootFilesystemInfo(client);
client.Disconnect(); client.Disconnect();
client.Dispose();
return (FilesystemName, FilesystemSize); return (FilesystemName, FilesystemSize);
} }
catch (Exception ex) catch (Exception ex)
@@ -207,19 +230,19 @@ namespace AiQ_GUI
// Checks the filesystem size and expands it if necessary, displays on the label how big the SD card is. // Checks the filesystem size and expands it if necessary, displays on the label how big the SD card is.
public static async Task<SSHData> CheckFSSize(string IPAddress, Label LblFSSize, SSHData sshData) public static async Task<SSHData> CheckFSSize(string IPAddress, Label LblFSSize, SSHData sshData)
{ {
const double MinGoodSize = 100.0; // 100GB const double GoodSize = 128.0; // 128GB
const double MaxGoodSize = 150.0; // 150GB const double Deviation = 20.0; // ±20GB
double currentSize = NormaliseFSSize(sshData.FilesystemSize); double currentSize = NormaliseFSSize(sshData.FilesystemSize);
LblFSSize.Text = $"Filesystem Size = {currentSize}GB"; LblFSSize.Text = $"Filesystem Size = {currentSize}GB";
if (currentSize >= MinGoodSize && currentSize <= MaxGoodSize) if (Math.Abs(GoodSize - currentSize) < Deviation)
{ {
LblFSSize.ForeColor = Color.LightGreen; LblFSSize.ForeColor = Color.LightGreen;
return sshData; return sshData;
} }
if (currentSize < MinGoodSize) if (currentSize < GoodSize - Deviation)
{ {
try try
{ {
@@ -230,7 +253,7 @@ namespace AiQ_GUI
double newSize = NormaliseFSSize(sshData.FilesystemSize); double newSize = NormaliseFSSize(sshData.FilesystemSize);
LblFSSize.Text = $"Filesystem Size = {newSize}GB"; LblFSSize.Text = $"Filesystem Size = {newSize}GB";
if (newSize >= MinGoodSize && newSize <= MaxGoodSize) if (Math.Abs(GoodSize - newSize) < Deviation)
{ {
LblFSSize.ForeColor = Color.LightGreen; LblFSSize.ForeColor = Color.LightGreen;
return sshData; return sshData;
@@ -261,10 +284,9 @@ namespace AiQ_GUI
// Extract value & unit // Extract value & unit
System.Text.RegularExpressions.Match match = RegexCache.FileSizeRegex().Match(rootSize.Trim()); System.Text.RegularExpressions.Match match = RegexCache.FileSizeRegex().Match(rootSize.Trim());
if (!match.Success)
return 0;
if (!double.TryParse(match.Groups["value"].Value, out double value)) // Return 0 if no match or invalid number
if (!match.Success || !double.TryParse(match.Groups["value"].Value, out double value))
return 0; return 0;
string unit = match.Groups["unit"].Value.ToUpperInvariant(); string unit = match.Groups["unit"].Value.ToUpperInvariant();
@@ -293,10 +315,9 @@ namespace AiQ_GUI
{ {
try try
{ {
using SshClient ssh = new SshClient(IPAddress, SSHUsername, SSHPassword); SshClient client = SshConnect(IPAddress);
ssh.Connect();
SshCommand checkDevice = ssh.RunCommand($"[ -b {device} ] && echo OK || echo NOT_FOUND"); SshCommand checkDevice = client.RunCommand($"[ -b {device} ] && echo OK || echo NOT_FOUND");
if (!string.IsNullOrWhiteSpace(checkDevice.Error)) if (!string.IsNullOrWhiteSpace(checkDevice.Error))
throw new Exception(checkDevice.Error); throw new Exception(checkDevice.Error);
@@ -306,7 +327,7 @@ namespace AiQ_GUI
return false; return false;
} }
SshCommand umountCmd = ssh.RunCommand($"sudo umount {device}"); SshCommand umountCmd = client.RunCommand($"sudo umount {device}");
if (!string.IsNullOrWhiteSpace(umountCmd.Error) && !umountCmd.Error.Contains("not mounted")) if (!string.IsNullOrWhiteSpace(umountCmd.Error) && !umountCmd.Error.Contains("not mounted"))
{ {
MainForm.Instance.AddToActionsList($"Unmount error: {umountCmd.Error}"); MainForm.Instance.AddToActionsList($"Unmount error: {umountCmd.Error}");
@@ -315,15 +336,16 @@ namespace AiQ_GUI
await Task.Delay(1000); // Wait for mount to settle await Task.Delay(1000); // Wait for mount to settle
SshCommand fsckCmd = ssh.RunCommand($"sudo e2fsck -f -y -v -C 0 {device}"); SshCommand fsckCmd = client.RunCommand($"sudo e2fsck -f -y -v -C 0 {device}");
if (!string.IsNullOrWhiteSpace(fsckCmd.Error)) if (!string.IsNullOrWhiteSpace(fsckCmd.Error))
{ {
MainForm.Instance.AddToActionsList($"e2fsck error: {fsckCmd.Error}"); MainForm.Instance.AddToActionsList($"e2fsck error: {fsckCmd.Error}");
return false; return false;
} }
SshCommand resizeFs = ssh.RunCommand($"sudo resize2fs {device}"); SshCommand resizeFs = client.RunCommand($"sudo resize2fs {device}");
ssh.Disconnect(); client.Disconnect();
client.Dispose();
if (!string.IsNullOrWhiteSpace(resizeFs.Error)) if (!string.IsNullOrWhiteSpace(resizeFs.Error))
{ {
@@ -348,10 +370,9 @@ namespace AiQ_GUI
{ {
try try
{ {
using SshClient ssh = new SshClient(IPAddress, SSHUsername, SSHPassword); SshClient client = SshConnect(IPAddress);
ssh.Connect();
SshCommand checkDevice = ssh.RunCommand("sync"); SshCommand checkDevice = client.RunCommand("sync");
if (!string.IsNullOrWhiteSpace(checkDevice.Error)) if (!string.IsNullOrWhiteSpace(checkDevice.Error))
throw new Exception(checkDevice.Error); throw new Exception(checkDevice.Error);
@@ -360,6 +381,9 @@ namespace AiQ_GUI
MainForm.Instance.AddToActionsList($"Cannot sync files to disk. Replied: {checkDevice.Result}. DO NOT TURN OFF, GET SUPERVISOR"); MainForm.Instance.AddToActionsList($"Cannot sync files to disk. Replied: {checkDevice.Result}. DO NOT TURN OFF, GET SUPERVISOR");
return; return;
} }
client.Disconnect();
client.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -15,9 +15,7 @@ namespace AiQ_GUI
// If there is no dot in the version string, return the version as is // If there is no dot in the version string, return the version as is
if (dotLocation < 0) if (dotLocation < 0)
{
return GUIVersion; return GUIVersion;
}
// Check if the next character after the dot is "0" // Check if the next character after the dot is "0"
if (dotLocation + 1 < GUIVersion.Length && GUIVersion[dotLocation + 1] == '0') if (dotLocation + 1 < GUIVersion.Length && GUIVersion[dotLocation + 1] == '0')
@@ -48,7 +46,7 @@ namespace AiQ_GUI
{ {
if (ComapreVersions()) // Checks if the current version is older than the latest version if (ComapreVersions()) // Checks if the current version is older than the latest version
{ {
string GUIPath = $"{GoogleAPI.DrivePath}AiQ\\GUI's\\AiQ_Final_Test\\AiQ_GUI.application"; const string GUIPath = $"{GoogleAPI.DrivePath}AiQ\\GUI's\\AiQ_Final_Test\\AiQ_GUI.application";
// Check if path is real // Check if path is real
if (!File.Exists(GUIPath)) if (!File.Exists(GUIPath))

View File

@@ -24,7 +24,7 @@ namespace AiQ_GUI
{ {
try try
{ {
string streamPath = $"{DrivePath}R50IQ\\client_secret.json"; const string streamPath = $"{DrivePath}R50IQ\\client_secret.json";
string[] Scopes = [SheetsService.Scope.Spreadsheets]; string[] Scopes = [SheetsService.Scope.Spreadsheets];
FileStream stream = new(streamPath, FileMode.Open, FileAccess.Read); FileStream stream = new(streamPath, FileMode.Open, FileAccess.Read);
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(stream).Secrets, Scopes, "user", CancellationToken.None, new FileDataStore(credPath, true)).Result; credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(stream).Secrets, Scopes, "user", CancellationToken.None, new FileDataStore(credPath, true)).Result;
@@ -231,7 +231,7 @@ namespace AiQ_GUI
// Checks RMA control sheet for a model and serial that match current camera // Checks RMA control sheet for a model and serial that match current camera
public static int CheckRMANum(string serial, string model) public static int CheckRMANum(string serial, string model)
{ {
string spreadsheetId_RMAControl = "1tZhkYrqBQ3BcL7ZS4q3ghzCgHSJ8f5LVSj7nh6fIRC8"; const string spreadsheetId_RMAControl = "1tZhkYrqBQ3BcL7ZS4q3ghzCgHSJ8f5LVSj7nh6fIRC8";
try try
{ {
// Get all info in H and I columns // Get all info in H and I columns

2
LDS.cs
View File

@@ -35,9 +35,7 @@ namespace AiQ_GUI
} }
catch // If file can't deserialise catch // If file can't deserialise
{ {
MainForm.Instance.AddToActionsList("Error loading Local Data Store");
return null; // Return null to indicate failure return null; // Return null to indicate failure
} }
} }

View File

@@ -38,6 +38,7 @@ namespace AiQ_GUI
IOrderedEnumerable<Tuple<string, string>> sorted = modelTuples.OrderBy(t => t.Item1.Equals("AB12CD", StringComparison.OrdinalIgnoreCase) ? 1 : 0) IOrderedEnumerable<Tuple<string, string>> sorted = modelTuples.OrderBy(t => t.Item1.Equals("AB12CD", StringComparison.OrdinalIgnoreCase) ? 1 : 0)
.ThenBy(t => t.Item1, StringComparer.OrdinalIgnoreCase); .ThenBy(t => t.Item1, StringComparer.OrdinalIgnoreCase);
conn.Close();
// Format the sorted tuples as "ModelNumber - Description" strings and return as array // Format the sorted tuples as "ModelNumber - Description" strings and return as array
return sorted.Select(t => $"{t.Item1} - {t.Item2}").ToArray(); return sorted.Select(t => $"{t.Item1} - {t.Item2}").ToArray();
} }
@@ -67,6 +68,7 @@ namespace AiQ_GUI
UniversalData.LatestVersion = Convert.ToString(reader["AiQGUIVersion"]); UniversalData.LatestVersion = Convert.ToString(reader["AiQGUIVersion"]);
UniversalData.PowerConsumption = Convert.ToInt16(reader["PowerConsumption"]); UniversalData.PowerConsumption = Convert.ToInt16(reader["PowerConsumption"]);
UniversalData.LicencingServerURL = Convert.ToString(reader["LicencingServerURL"]); UniversalData.LicencingServerURL = Convert.ToString(reader["LicencingServerURL"]);
conn.Close();
} }
// Knowing the model number on test, this function reads the database and populates the Camera class with the values. // Knowing the model number on test, this function reads the database and populates the Camera class with the values.
@@ -97,6 +99,7 @@ namespace AiQ_GUI
CameraAccessInfo.LED_V = Convert.ToDouble(reader["LEDVoltage"]); CameraAccessInfo.LED_V = Convert.ToDouble(reader["LEDVoltage"]);
CameraAccessInfo.LED_I = Convert.ToInt32(reader["LEDCurrent"]); CameraAccessInfo.LED_I = Convert.ToInt32(reader["LEDCurrent"]);
CameraAccessInfo.SpreadsheetID = Convert.ToString(reader["SSID"]); CameraAccessInfo.SpreadsheetID = Convert.ToString(reader["SSID"]);
conn.Close();
} }
} }

View File

@@ -417,7 +417,6 @@ namespace AiQ_GUI
// int nextFree = Excel.CheckNextFree(filePath); // int nextFree = Excel.CheckNextFree(filePath);
// Debug.WriteLine("Next free row in Vaxtor sheet (Column C): " + nextFree); // Debug.WriteLine("Next free row in Vaxtor sheet (Column C): " + nextFree);
//} //}
} }
} }
} }

View File

@@ -11,7 +11,7 @@ namespace AiQ_GUI.Microsoft
@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\Shared drives\MAV Production GUI's\AiQ\GUI's\AiQ_Final_Test.accdb;Persist Security Info=False;OLE DB Services=-1;"; @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\Shared drives\MAV Production GUI's\AiQ\GUI's\AiQ_Final_Test.accdb;Persist Security Info=False;OLE DB Services=-1;";
private readonly string exportPath = private readonly string exportPath =
@"G:\Shared drives\MAV Production GUI's\AiQ\GUI's\AiQ_Test_Stats.xlsx"; @"C:\Users\BradleyBorn\OneDrive - MAV Systems Ltd\Desktop\AiQ_Test_Stats.xlsx";
public void ExportDatabaseToExcel() public void ExportDatabaseToExcel()
{ {
@@ -26,52 +26,35 @@ namespace AiQ_GUI.Microsoft
DateTime now = DateTime.Now; DateTime now = DateTime.Now;
// Read LastStatsRun from UniversalData (if any)
DateTime? lastStatsRun = null;
try
{
using (var cmdPeriod = new OleDbCommand("SELECT LastStatsRun FROM UniversalData", conn))
{
object res = cmdPeriod.ExecuteScalar();
if (res != null && res != DBNull.Value)
lastStatsRun = (DateTime)res;
}
MainForm.Instance.AddToActionsList($"Fetched LastStatsRun: {(lastStatsRun.HasValue ? lastStatsRun.Value.ToString("yyyy-MM-dd HH:mm:ss") : "none")}");
}
catch (Exception periodEx)
{
MainForm.Instance.AddToActionsList($"Warning: could not read LastStatsRun. Details: {periodEx.Message}");
}
// ==================== MAIN STATS EXPORT ==================== // ==================== MAIN STATS EXPORT ====================
string selectColumns = @" string selectColumns = @"
ModelNumber, ModelNumber,
[Total Tests Run], [Total Tests Run],
[Pre Tests Passed], [Pre Tests Passed],
[Pre Tests Failed], [Pre Tests Failed],
[Final Tests Passed], [Final Tests Passed],
[Final Tests Failed], [Final Tests Failed],
[RMA Total Tests Run], [RMA Total Tests Run],
[RMA Pre Tests Passed], [RMA Pre Tests Passed],
[RMA Pre Tests Failed], [RMA Pre Tests Failed],
[RMA Final Tests Passed], [RMA Final Tests Passed],
[RMA Final Tests Failed], [RMA Final Tests Failed],
[Diagnostic Failure], [Diagnostic Failure],
[Failed To Set Model Or Serial Number], [Failed To Set Model Or Serial Number],
[Camera Not In Test Tube], [Camera Not In Test Tube],
[Could Not Zoom Modules To 8000], [Could Not Zoom Modules To 8000],
[Could Not Zoom Modules To Full Wide], [Could Not Zoom Modules To Full Wide],
[Please Get RMA Number From Operations Team Before Continuing], [Please Get RMA Number From Operations Team Before Continuing],
[Please Get A Valid Vaxtor Product Key Before Continuing], [Please Get A Valid Vaxtor Product Key Before Continuing],
[Visual Test Fail - Sleeve Not Aligned], [Visual Test Fail - Sleeve Not Aligned],
[Visual Test Fail - Not All Front Screws Fitted], [Visual Test Fail - Not All Front Screws Fitted],
[Visual Test Fail - Not All Rear Screws Fitted], [Visual Test Fail - Not All Rear Screws Fitted],
[Visual Test Fail - Unit rattles]"; [Visual Test Fail - Unit rattles]";
string query = $@" string query = $@"
SELECT SELECT
{selectColumns} {selectColumns}
FROM AiQ"; FROM AiQ";
OleDbDataAdapter adapter = new(query, conn); OleDbDataAdapter adapter = new(query, conn);
DataTable dataTable = new(); DataTable dataTable = new();
@@ -110,21 +93,8 @@ namespace AiQ_GUI.Microsoft
ws.Cell(1, 1).InsertTable(dataTable, "AiQ_Stats", true); ws.Cell(1, 1).InsertTable(dataTable, "AiQ_Stats", true);
ws.Columns().AdjustToContents(); ws.Columns().AdjustToContents();
// Write Data Period label and computed period string to the right of the table ws.Cell(1, dataTable.Columns.Count + 2).Value = "Exported:";
int infoCol = dataTable.Columns.Count + 2; ws.Cell(2, dataTable.Columns.Count + 2).Value = now.ToString("yyyy-MM-dd HH:mm:ss");
ws.Cell(1, infoCol).Value = "Data Period";
string periodText;
if (lastStatsRun.HasValue)
{
periodText = $"{lastStatsRun.Value:yyyy-MM-dd HH:mm:ss} - {now:yyyy-MM-dd HH:mm:ss}";
}
else
{
periodText = $"Up to {now:yyyy-MM-dd HH:mm:ss}";
}
ws.Cell(2, infoCol).Value = periodText;
// ==================== DIAGS STATS EXPORT (CURRENT MONTH ONLY) ==================== // ==================== DIAGS STATS EXPORT (CURRENT MONTH ONLY) ====================
MainForm.Instance.AddToActionsList("Exporting DiagsStats for current month..."); MainForm.Instance.AddToActionsList("Exporting DiagsStats for current month...");
@@ -137,36 +107,33 @@ namespace AiQ_GUI.Microsoft
[Date], [Date],
[Model], [Model],
[Red Diags Labels], [Red Diags Labels],
[RhTxBxActions Contents], [RhTxBxActions Contents]
[IsRma],
[RMA]
FROM DiagsStats FROM DiagsStats
WHERE [Date] >= ? AND [Date] < ?"; WHERE [Date] >= ? AND [Date] < ?";
using (var diagsCmd = new OleDbCommand(diagsQuery, conn)) OleDbDataAdapter diagsAdapter = new(diagsQuery, conn);
diagsAdapter.SelectCommand.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = monthStart });
diagsAdapter.SelectCommand.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = nextMonth });
DataTable diagsTable = new();
diagsAdapter.Fill(diagsTable);
if (diagsTable.Rows.Count > 0)
{ {
diagsCmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = monthStart }); int startRow = ws.LastRowUsed().RowNumber() + 3;
diagsCmd.Parameters.Add(new OleDbParameter { OleDbType = OleDbType.Date, Value = nextMonth });
using (var diagsAdapter = new OleDbDataAdapter(diagsCmd)) ws.Cell(startRow, 1).Value = "Diags Stats (Current Month)";
{ ws.Cell(startRow, 1).Style.Font.Bold = true;
DataTable diagsTable = new(); ws.Cell(startRow, 1).Style.Font.FontSize = 12;
diagsAdapter.Fill(diagsTable);
if (diagsTable.Rows.Count > 0) ws.Cell(startRow + 1, 1).InsertTable(diagsTable, "Diags_Stats", true);
{ ws.Columns().AdjustToContents();
int startRow = (ws.LastRowUsed()?.RowNumber() ?? 0) + 3;
ws.Cell(startRow, 1).Value = "Diags Stats (Current Month)"; MainForm.Instance.AddToActionsList($"Added DiagsStats ({diagsTable.Rows.Count} rows) starting at row {startRow}.");
ws.Cell(startRow, 1).Style.Font.Bold = true; }
ws.Cell(startRow, 1).Style.Font.FontSize = 12; else
{
ws.Cell(startRow + 1, 1).InsertTable(diagsTable, "Diags_Stats", true); MainForm.Instance.AddToActionsList("No DiagsStats data found for current month.");
ws.Columns().AdjustToContents();
MainForm.Instance.AddToActionsList($"Added DiagsStats ({diagsTable.Rows.Count} rows) starting at row {startRow}.");
}
}
} }
// ==================== SAVE MAIN SHEET ==================== // ==================== SAVE MAIN SHEET ====================
@@ -183,10 +150,10 @@ namespace AiQ_GUI.Microsoft
backupTableName = backupTableName.Substring(0, 64); backupTableName = backupTableName.Substring(0, 64);
string backupSql = $@" string backupSql = $@"
SELECT SELECT
{selectColumns} {selectColumns}
INTO [{backupTableName}] INTO [{backupTableName}]
FROM AiQ"; FROM AiQ";
try try
{ {
using (var cmdBackup = new OleDbCommand(backupSql, conn)) using (var cmdBackup = new OleDbCommand(backupSql, conn))
@@ -207,28 +174,28 @@ namespace AiQ_GUI.Microsoft
try try
{ {
string resetSql = @" string resetSql = @"
UPDATE AiQ SET UPDATE AiQ SET
[Total Tests Run] = 0, [Total Tests Run] = 0,
[Pre Tests Passed] = 0, [Pre Tests Passed] = 0,
[Pre Tests Failed] = 0, [Pre Tests Failed] = 0,
[Final Tests Passed] = 0, [Final Tests Passed] = 0,
[Final Tests Failed] = 0, [Final Tests Failed] = 0,
[RMA Total Tests Run] = 0, [RMA Total Tests Run] = 0,
[RMA Pre Tests Passed] = 0, [RMA Pre Tests Passed] = 0,
[RMA Pre Tests Failed] = 0, [RMA Pre Tests Failed] = 0,
[RMA Final Tests Passed] = 0, [RMA Final Tests Passed] = 0,
[RMA Final Tests Failed] = 0, [RMA Final Tests Failed] = 0,
[Diagnostic Failure] = 0, [Diagnostic Failure] = 0,
[Failed To Set Model Or Serial Number] = 0, [Failed To Set Model Or Serial Number] = 0,
[Camera Not In Test Tube] = 0, [Camera Not In Test Tube] = 0,
[Could Not Zoom Modules To 8000] = 0, [Could Not Zoom Modules To 8000] = 0,
[Could Not Zoom Modules To Full Wide] = 0, [Could Not Zoom Modules To Full Wide] = 0,
[Please Get RMA Number From Operations Team Before Continuing] = 0, [Please Get RMA Number From Operations Team Before Continuing] = 0,
[Please Get A Valid Vaxtor Product Key Before Continuing] = 0, [Please Get A Valid Vaxtor Product Key Before Continuing] = 0,
[Visual Test Fail - Sleeve Not Aligned] = 0, [Visual Test Fail - Sleeve Not Aligned] = 0,
[Visual Test Fail - Not All Front Screws Fitted] = 0, [Visual Test Fail - Not All Front Screws Fitted] = 0,
[Visual Test Fail - Not All Rear Screws Fitted] = 0, [Visual Test Fail - Not All Rear Screws Fitted] = 0,
[Visual Test Fail - Unit rattles] = 0;"; [Visual Test Fail - Unit rattles] = 0;";
using (var cmdReset = new OleDbCommand(resetSql, conn, tx)) using (var cmdReset = new OleDbCommand(resetSql, conn, tx))
{ {

View File

@@ -1,6 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal; using System.Security.Principal;
namespace AiQ_GUI namespace AiQ_GUI
@@ -16,14 +15,11 @@ namespace AiQ_GUI
.Where(p => targetProcesses.Any(tp => p.ProcessName.Contains(tp))) .Where(p => targetProcesses.Any(tp => p.ProcessName.Contains(tp)))
.Select(clsProcess => .Select(clsProcess =>
{ {
using (clsProcess) try
{ {
try clsProcess.CloseMainWindow();
{
clsProcess.CloseMainWindow();
}
catch { }
} }
catch { }
return Task.CompletedTask; return Task.CompletedTask;
}); });
@@ -34,7 +30,7 @@ namespace AiQ_GUI
{ {
Logging.LogMessage($"Starting exe from {ExeLoc}"); Logging.LogMessage($"Starting exe from {ExeLoc}");
ProcessStartInfo processInfo = new ProcessStartInfo(ExeLoc) ProcessStartInfo processInfo = new(ExeLoc)
{ {
UseShellExecute = true, UseShellExecute = true,
Verb = "runas" Verb = "runas"
@@ -64,7 +60,7 @@ namespace AiQ_GUI
{ {
StartAsAdmin(ExeLoc); StartAsAdmin(ExeLoc);
} }
else if (runAsAdmin) else if (Properties.Settings.Default.FirstRun && runAsAdmin)
{ {
try try
{ {
@@ -97,43 +93,4 @@ namespace AiQ_GUI
} }
} }
} }
[ComImport, Guid("AF230D27-BABA-4E42-ACED-F524F22CFCE2")]
public interface INetFwRule
{
string Name { get; set; }
string Description { get; set; }
string ApplicationName { get; set; }
string ServiceName { get; set; }
int Protocol { get; set; }
string LocalPorts { get; set; }
string RemotePorts { get; set; }
string LocalAddresses { get; set; }
string RemoteAddresses { get; set; }
string IcmpTypesAndCodes { get; set; }
int Direction { get; set; }
object Interfaces { get; set; }
string InterfaceTypes { get; set; }
bool Enabled { get; set; }
string Grouping { get; set; }
int Profiles { get; set; }
bool EdgeTraversal { get; set; }
int Action { get; set; }
}
[ComImport, Guid("98325047-C671-4174-8D81-DEFCD3F03186")]
public interface INetFwPolicy2
{
int CurrentProfileTypes { get; }
void get_FirewallEnabled(int profileType, out bool enabled);
void put_FirewallEnabled(int profileType, bool enabled);
void get_ExcludedInterfaces(int profileType, out object interfaces);
void put_ExcludedInterfaces(int profileType, object interfaces);
int BlockAllInboundTraffic { get; set; }
int NotificationsDisabled { get; set; }
int UnicastResponsesToMulticastBroadcastDisabled { get; set; }
object Rules { get; }
object ServiceRestriction { get; }
// ...other members omitted for brevity
}
} }

View File

@@ -39,14 +39,8 @@ namespace AiQ_GUI
return elementID; return elementID;
} }
// Clicks the element with the specified ID using Chromedriver
public static void ClickElementByID(string elementID, ChromeDriver driver)
{
ClickElementByID(elementID, true, driver);
}
// Attempts to click the web element with the specified ID; refreshes the page and retries once if the initial attempt fails // Attempts to click the web element with the specified ID; refreshes the page and retries once if the initial attempt fails
public static void ClickElementByID(string elementID, bool tryagain, ChromeDriver driver) public static void ClickElementByID(string elementID, ChromeDriver driver, bool tryagain = true)
{ {
try try
{ {
@@ -61,7 +55,7 @@ namespace AiQ_GUI
driver.Navigate().Refresh(); driver.Navigate().Refresh();
WebDriverWait wait = new(driver, TimeSpan.FromSeconds(10)); WebDriverWait wait = new(driver, TimeSpan.FromSeconds(10));
wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete")); wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete"));
ClickElementByID(elementID, false, driver); ClickElementByID(elementID, driver, false);
} }
MainForm.Instance.AddToActionsList("Could not click " + elementID); MainForm.Instance.AddToActionsList("Could not click " + elementID);

View File

@@ -138,7 +138,6 @@ namespace AiQ_GUI
// Create Test report in the same directory as the final test reports. // Create Test report in the same directory as the final test reports.
string soakLogPath = LDS.MAVPath + SoakLogFile; string soakLogPath = LDS.MAVPath + SoakLogFile;
string SoakTestPath = PDF.CreateSoakTestReport(CamInfo, MainForm.Instance.CbBxUserName.Text, DateTime.Now, soakLogPath); string SoakTestPath = PDF.CreateSoakTestReport(CamInfo, MainForm.Instance.CbBxUserName.Text, DateTime.Now, soakLogPath);
if (SoakTestPath != null) if (SoakTestPath != null)
@@ -207,7 +206,7 @@ namespace AiQ_GUI
await Task.Delay(500); await Task.Delay(500);
// Take bright image // Take bright image
Image ImageBright = await ImageProcessing.GetProcessedImage("Infrared-snapshot", IP, DevPass); Image ImageBright = await ImageProcessing.GetProcessedImage("Infrared", IP, DevPass);
if (ImageBright == null) if (ImageBright == null)
{ {
Logging.LogWarningMessage($"Bright image is null for {controlType} at setting {SettingMinMax[0]}", SoakLogFile); Logging.LogWarningMessage($"Bright image is null for {controlType} at setting {SettingMinMax[0]}", SoakLogFile);
@@ -221,7 +220,7 @@ namespace AiQ_GUI
await Task.Delay(500); await Task.Delay(500);
// Take dark image // Take dark image
Image ImageDark = await ImageProcessing.GetProcessedImage("Infrared-snapshot", IP, DevPass); Image ImageDark = await ImageProcessing.GetProcessedImage("Infrared", IP, DevPass);
if (ImageDark == null) if (ImageDark == null)
{ {
Logging.LogWarningMessage($"Dark image is null for {controlType} at setting {SettingMinMax[1]}", SoakLogFile); Logging.LogWarningMessage($"Dark image is null for {controlType} at setting {SettingMinMax[1]}", SoakLogFile);

View File

@@ -1,73 +0,0 @@
{
"id": "GLOBAL--Device",
"configHash": "101478235",
"propHardwarePlatform": {
"value": "JETSON_NANO",
"datatype": "mav.flexi.web.pages.SystemConfig$HardwareConfigurationOption",
"accepted": "[NONE, JETSON_NANO, JETSON_XAVIER, RASPBERRY_PI_CM4, RASPBERRY_PI_CM5, DEVELOPER_WORKSTATION]"
},
"propApplicationPlatform": {
"value": "CUSTOM",
"datatype": "mav.flexi.web.pages.SystemConfig$ApplicationConfigurationOption",
"accepted": "[NONE, CUSTOM, MONO_BASIC_ANPR, DUAL_CAMERA_BASIC_ANPR, SINGLE_SAF_DUAL_CAMERA_BASIC_ANPR, DUAL_CAMERA_STREAMING, BAYGUARD, SITE_ACCESS_CONTROL_WITH_MODBUS, WAPOL_IQ50_VRM_CORRECTION, BAYWATCH_MONO_CAM, BAYWATCH_DUAL_CAM, BAYWATCH_TRIPLE_CAM, BAYWATCH_QUADRUPLE_CAM, IN_CAR_ANPR]"
},
"propDeviceName": {
"value": "Test Nano",
"datatype": "java.lang.String"
},
"propLocalTimeZone": {
"value": "Europe/London (UTC+00)",
"datatype": "mav.util.TimeZoneEnum",
"accepted": "[Africa/Cairo (UTC+02), Africa/Johannesburg (UTC+02), Africa/Lagos (UTC+01), Africa/Monrousing (UTC+00), America/Anchorage (UTC-09), America/Chicago (UTC-06), America/Denver (UTC-07), America/Edmonton (UTC-07), America/Jamaica (UTC-05), America/Los Angeles (UTC-08), America/Mexico City (UTC-06), America/Montreal (UTC-05), America/New/York (UTC-05), America/Phoenix (UTC-07), America/Puerto Rico (UTC-04), America/Sao Paulo (UTC-03), America/Toronto (UTC-05), America/Vancouver (UTC-08), Asia/Hong Kong (UTC+08), Asia/Jerusalem (UTC+02), Asia/Manila (UTC+08), Asia/Seoul (UTC+09), Asia/Tokyo (UTC+09), Atlantic/Reykjavik (UTC+00), Australia/Perth (UTC+08), Australia/Sydney (UTC+10), Europe/Athens (UTC+02), Europe/Berlin (UTC+01), Europe/Brussels (UTC+01), Europe/Copenhagen (UTC+01), Europe/London (UTC+00), Europe/Madrid (UTC+01), Europe/Moscow (UTC+04), Europe/Paris (UTC+01), Europe/Prague (UTC+01), Europe/Rome (UTC+01), Europe/Warsaw (UTC+01), Pacific/Guam (UTC+10), Pacific/Honolulu (UTC-10), UTC (UTC-00)]"
},
"propTimeSource": {
"value": "SNTP Only",
"datatype": "mav.flexi.web.pages.SystemConfig$TimeSourceEnum",
"accepted": "[SNTP Only, GPS Only, SNTP + Soft GPS]"
},
"propSNTPServer": {
"value": "1.uk.pool.ntp.org",
"datatype": "java.lang.String"
},
"propSNTPIntervalMinutes": {
"value": "public long mav.flexi.web.pages.SystemConfig$DeviceConfig.propSNTPIntervalMinutes",
"datatype": "long",
"range": {
"minimum": "1.000000",
"maximum": "99999.000000"
}
},
"propOutputsMaxTimeSyncAge": {
"value": "24 hours",
"datatype": "mav.flexi.web.pages.SystemConfig$HoursEnum",
"accepted": "[NO LIMIT, 01 hours, 02 hours, 03 hours, 04 hours, 05 hours, 06 hours, 07 hours, 08 hours, 09 hours, 10 hours, 11 hours, 12 hours, 18 hours, 24 hours, 36 hours, 48 hours, 72 hours, 96 hours]"
},
"propReservedMemoryMegabytes": {
"value": "public long mav.flexi.web.pages.SystemConfig$DeviceConfig.propReservedMemoryMegabytes",
"datatype": "long",
"range": {
"minimum": "1000.000000",
"maximum": "128000.000000"
}
},
"propClientTrustStorePassword": {
"value": "",
"datatype": "java.lang.String"
},
"propFlexiScriptPath": {
"value": "/home/mav/FlexiAI/bin/FlexiAI",
"datatype": "java.lang.String"
},
"propVideo0Tee": {
"value": "video0tee",
"datatype": "java.lang.String"
},
"propVideo1Tee": {
"value": "video1tee",
"datatype": "java.lang.String"
},
"propRestartCameraModulesOnBoot": {
"value": "true",
"datatype": "boolean"
}
}