4 Commits

Author SHA1 Message Date
62554d7fd6 God mode non optional on final test 2025-12-12 11:22:46 +00:00
03dfb3414b V4.7 2025-12-09 09:00:16 +00:00
760987fa75 Merged colours 2025-12-02 13:08:08 +00:00
4c624d7e29 V4.6 2025-12-02 11:02:24 +00:00
13 changed files with 223 additions and 103 deletions

63
AiQ_GUI.Designer.cs generated
View File

@@ -141,6 +141,7 @@ namespace AiQ_GUI
groupBox3 = new GroupBox();
groupBox2 = new GroupBox();
groupBox1 = new GroupBox();
BtnBaudModules = new Button();
BtnZoom8000 = new Button();
BtnZoomWide = new Button();
TabSettings = new TabPage();
@@ -160,6 +161,7 @@ namespace AiQ_GUI
LblGUIVers = new Label();
timerTypeIP = new System.Windows.Forms.Timer(components);
TimerFlash = new System.Windows.Forms.Timer(components);
BtnOpenMoba = new Button();
((System.ComponentModel.ISupportInitialize)PicBxMAV).BeginInit();
((System.ComponentModel.ISupportInitialize)PicBxAiQ).BeginInit();
((System.ComponentModel.ISupportInitialize)PicBxIRF2).BeginInit();
@@ -820,7 +822,7 @@ namespace AiQ_GUI
BtnCancel.Location = new Point(201, 185);
BtnCancel.Margin = new Padding(4, 3, 4, 3);
BtnCancel.Name = "BtnCancel";
BtnCancel.Size = new Size(181, 37);
BtnCancel.Size = new Size(180, 37);
BtnCancel.TabIndex = 174;
BtnCancel.Text = "Cancel";
BtnCancel.UseVisualStyleBackColor = false;
@@ -836,7 +838,7 @@ namespace AiQ_GUI
BtnSave.Location = new Point(10, 185);
BtnSave.Margin = new Padding(4, 3, 4, 3);
BtnSave.Name = "BtnSave";
BtnSave.Size = new Size(181, 37);
BtnSave.Size = new Size(180, 37);
BtnSave.TabIndex = 173;
BtnSave.Text = "Save && Check";
BtnSave.UseVisualStyleBackColor = false;
@@ -1254,7 +1256,7 @@ namespace AiQ_GUI
CbBxType.ForeColor = SystemColors.Control;
CbBxType.FormattingEnabled = true;
CbBxType.IntegralHeight = false;
CbBxType.Items.AddRange(new object[] { "Store & Forward", "Streaming", "Audit" });
CbBxType.Items.AddRange(new object[] { "Store & Forward", "Streaming", "Audit", "XML Server" });
CbBxType.Location = new Point(177, 62);
CbBxType.Margin = new Padding(4, 3, 4, 3);
CbBxType.MaxDropDownItems = 30;
@@ -1781,6 +1783,7 @@ namespace AiQ_GUI
//
// groupBox1
//
groupBox1.Controls.Add(BtnBaudModules);
groupBox1.Controls.Add(BtnZoom8000);
groupBox1.Controls.Add(BtnZoomWide);
groupBox1.Controls.Add(BtnLicVaxtor);
@@ -1801,18 +1804,35 @@ namespace AiQ_GUI
groupBox1.TabStop = false;
groupBox1.Text = "Controls";
//
// BtnBaudModules
//
BtnBaudModules.BackColor = Color.FromArgb(70, 65, 80);
BtnBaudModules.Enabled = false;
BtnBaudModules.FlatAppearance.BorderSize = 0;
BtnBaudModules.FlatStyle = FlatStyle.Flat;
BtnBaudModules.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
BtnBaudModules.ForeColor = SystemColors.Control;
BtnBaudModules.Location = new Point(12, 155);
BtnBaudModules.Margin = new Padding(4, 3, 4, 3);
BtnBaudModules.Name = "BtnBaudModules";
BtnBaudModules.Size = new Size(180, 37);
BtnBaudModules.TabIndex = 237;
BtnBaudModules.Text = "Set baudrate to 115200";
BtnBaudModules.UseVisualStyleBackColor = false;
BtnBaudModules.Click += BtnBaudModules_Click;
//
// BtnZoom8000
//
BtnZoom8000.BackColor = Color.FromArgb(70, 65, 80);
BtnZoom8000.Enabled = false;
BtnZoom8000.FlatAppearance.BorderSize = 0;
BtnZoom8000.FlatStyle = FlatStyle.Flat;
BtnZoom8000.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
BtnZoom8000.Font = new Font("Segoe UI Semibold", 8F, FontStyle.Bold);
BtnZoom8000.ForeColor = SystemColors.Control;
BtnZoom8000.Location = new Point(204, 155);
BtnZoom8000.Location = new Point(299, 155);
BtnZoom8000.Margin = new Padding(4, 3, 4, 3);
BtnZoom8000.Name = "BtnZoom8000";
BtnZoom8000.Size = new Size(180, 37);
BtnZoom8000.Size = new Size(85, 37);
BtnZoom8000.TabIndex = 236;
BtnZoom8000.Text = "Zoom to 8000";
BtnZoom8000.UseVisualStyleBackColor = false;
@@ -1824,12 +1844,12 @@ namespace AiQ_GUI
BtnZoomWide.Enabled = false;
BtnZoomWide.FlatAppearance.BorderSize = 0;
BtnZoomWide.FlatStyle = FlatStyle.Flat;
BtnZoomWide.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
BtnZoomWide.Font = new Font("Segoe UI Semibold", 8F, FontStyle.Bold);
BtnZoomWide.ForeColor = SystemColors.Control;
BtnZoomWide.Location = new Point(12, 154);
BtnZoomWide.Location = new Point(204, 155);
BtnZoomWide.Margin = new Padding(4, 3, 4, 3);
BtnZoomWide.Name = "BtnZoomWide";
BtnZoomWide.Size = new Size(180, 37);
BtnZoomWide.Size = new Size(85, 37);
BtnZoomWide.TabIndex = 235;
BtnZoomWide.Text = "Zoom Full Wide";
BtnZoomWide.UseVisualStyleBackColor = false;
@@ -1838,6 +1858,7 @@ namespace AiQ_GUI
// TabSettings
//
TabSettings.BackColor = Color.FromArgb(39, 37, 55);
TabSettings.Controls.Add(BtnOpenMoba);
TabSettings.Controls.Add(BtnUploadWonwooSetIR);
TabSettings.Controls.Add(BtnUploadWonwooSetOV);
TabSettings.Controls.Add(BtnAdminStart);
@@ -1878,7 +1899,7 @@ namespace AiQ_GUI
BtnUploadWonwooSetOV.Location = new Point(19, 304);
BtnUploadWonwooSetOV.Margin = new Padding(4, 3, 4, 3);
BtnUploadWonwooSetOV.Name = "BtnUploadWonwooSetOV";
BtnUploadWonwooSetOV.Size = new Size(181, 49);
BtnUploadWonwooSetOV.Size = new Size(180, 49);
BtnUploadWonwooSetOV.TabIndex = 243;
BtnUploadWonwooSetOV.Text = "Upload Wonwoo Settings OV";
BtnUploadWonwooSetOV.UseVisualStyleBackColor = false;
@@ -1894,7 +1915,7 @@ namespace AiQ_GUI
BtnAdminStart.Location = new Point(210, 261);
BtnAdminStart.Margin = new Padding(4, 3, 4, 3);
BtnAdminStart.Name = "BtnAdminStart";
BtnAdminStart.Size = new Size(181, 37);
BtnAdminStart.Size = new Size(180, 37);
BtnAdminStart.TabIndex = 241;
BtnAdminStart.Text = "Start in admin mode";
BtnAdminStart.UseVisualStyleBackColor = false;
@@ -1910,7 +1931,7 @@ namespace AiQ_GUI
BtnFirewall.Location = new Point(19, 261);
BtnFirewall.Margin = new Padding(4, 3, 4, 3);
BtnFirewall.Name = "BtnFirewall";
BtnFirewall.Size = new Size(181, 37);
BtnFirewall.Size = new Size(180, 37);
BtnFirewall.TabIndex = 240;
BtnFirewall.Text = "Update Firewall";
BtnFirewall.UseVisualStyleBackColor = false;
@@ -2057,6 +2078,22 @@ namespace AiQ_GUI
timerTypeIP.Interval = 2000;
timerTypeIP.Tick += timerTypeIP_Tick;
//
// BtnOpenMoba
//
BtnOpenMoba.BackColor = Color.FromArgb(70, 65, 80);
BtnOpenMoba.FlatAppearance.BorderSize = 0;
BtnOpenMoba.FlatStyle = FlatStyle.Flat;
BtnOpenMoba.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
BtnOpenMoba.ForeColor = SystemColors.Control;
BtnOpenMoba.Location = new Point(210, 359);
BtnOpenMoba.Margin = new Padding(4, 3, 4, 3);
BtnOpenMoba.Name = "BtnOpenMoba";
BtnOpenMoba.Size = new Size(180, 37);
BtnOpenMoba.TabIndex = 245;
BtnOpenMoba.Text = "Open Moba";
BtnOpenMoba.UseVisualStyleBackColor = false;
BtnOpenMoba.Click += BtnOpenMoba_Click;
//
// MainForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
@@ -2251,5 +2288,7 @@ namespace AiQ_GUI
private Button BtnFactoryDefault;
private Button BtnUploadWonwooSetOV;
private Button BtnUploadWonwooSetIR;
private Button BtnBaudModules;
private Button BtnOpenMoba;
}
}

View File

@@ -48,7 +48,7 @@ namespace AiQ_GUI
Task<LocalDataStore> LDSWAIT = Task.Run(() => LDS.GetLDS()); // Get and deserialise LDS.json
Task<string> guiVerTask = Task.Run(() => GUIUpdate.FindGUIVersion()); // Get GUI Version
Network.Initialize("admin", "admin"); // Initialise HTTP client
Network.Initialize("admin", "admin"); // Initialise HTTP client with basic auth creds.
if (await Network.PingIP("8.8.8.8")) // Ping to check if we're online
{
@@ -74,7 +74,6 @@ 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)
{
@@ -82,6 +81,9 @@ namespace AiQ_GUI
return;
}
Logging.LogMessage("Opening GUI"); // Done after LDS to make sure directory exists.
this.Location = new Point(localDataStore.GUIPosX, localDataStore.GUIPosY);
Task CheckHWOnline = PingCheck(); // Async check all hardware is online
PopulateUIWithLDS(localDataStore); // Update fields that depend on LDS
CbBxCameraType.Text = localDataStore.LastModel; // Set last model that was tested into combobox
@@ -146,10 +148,10 @@ namespace AiQ_GUI
Task VisCheck = Helper.VisualCheck(BtnStartTest);
if (!await FlexiAPI.ZoomModules("1F40", CamOnTest.IP)) // Zoom to 8000 (1F40h) at the same time.
if (!await CameraModules.ZoomModules("1F40", CamOnTest.IP)) // Zoom to 8000 (1F40h) at the same time.
await TestFailed(BtnStartTest, "Could not zoom modules to 8000");
if (!await FlexiAPI.SetZoomLockOn(CamOnTest.IP))
if (!await CameraModules.SetZoomLockOn(CamOnTest.IP))
Helper.RestartApp();
await Task.Delay(1000); // Without sleep it kept failing the factory reset as camera modules were not ready yet
@@ -158,7 +160,7 @@ namespace AiQ_GUI
string VISCAReply = await FlexiAPI.APIHTTPVISCA(CamOnTest.IP, "8101043903FF", true); // Manual mode to be able to manipulate the SIG settings.
if (VISCAReply != "9041FF9051FF")
AddToActionsList("Couldn't set to manual mode",Level.ERROR);
AddToActionsList("Couldn't set to manual mode", Level.ERROR);
await CameraModules.SetSIG(CbBxShutter, CbBxIris, CbBxGain, CamOnTest.IP); // Set SIG according to the drop downs in settings for a good picture ready for image check
await ImageProcessing.ImageCheck(PicBxOV, PicBxIRF2, PicBxIRF16, LblIRImageF2, LblIRImageF16, CamOnTest); // Populates the picture boxes and checks iris changes
@@ -189,7 +191,7 @@ namespace AiQ_GUI
await Wait; // Finished to 5s wait
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 CameraModules.ZoomModules("0000", CamOnTest.IP)) // Zoom 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.
@@ -236,7 +238,7 @@ namespace AiQ_GUI
BtnPreTest.Enabled = BtnStartTest.Enabled = false; // Disable buttons to stop user rnning multiple tests at the same time.
Logging.LogMessage("Pre Test Started");
if (!await FlexiAPI.SetZoomLockOn(CamOnTest.IP))
if (!await CameraModules.SetZoomLockOn(CamOnTest.IP))
Helper.RestartApp();
string LEDreply = await FlexiAPI.APIHTTPLED(CamOnTest.IP, LEDPOWER.MID); // Set LED's to medium (0x30)
@@ -274,7 +276,7 @@ namespace AiQ_GUI
if (await DisplayQuestion($"Would you like to allocate a serial number to this camera?"))
await AllocateSerial();
else if (GoogleAPI.UpdateSpreadSheetRePreTest(CameraAccessInfo.SpreadsheetID, Vers) != "OK") // If rerun might be different values so update SS
AddToActionsList("Failed to write to spreadsheet, please check manually",Level.WARNING);
AddToActionsList("Failed to write to spreadsheet, please check manually", Level.WARNING);
// else if (Excel.UpdateSpreadSheetPreTest(CameraAccessInfo.SpreadsheetID, Vers, CamOnTest.GetCamDesc(), CamOnTest.Model) != "OK")
// AddToActionsList("Failed to write to spreadsheet, please check manually");
}
@@ -302,14 +304,14 @@ namespace AiQ_GUI
// Purge camera of all reads
await FlexiAPI.APIHTTPRequest("/api/purge-all", CamOnTest.IP);
if (await DisplayQuestion("Do you want to set this camera to 211 and God mode off?"))
{
// Turn off God mode
string[,] GOD_JSON = { { "propGodMode", "false" } };
string IntConf = await FlexiAPI.HTTP_Update("GLOBAL--FlexiApplication", CamOnTest.IP, GOD_JSON);
if (!IntConf.Contains("\"propGodMode\": {\"value\": \"false\", \"datatype\": \"boolean\"},"))
AddToActionsList("Could not turn off God mode", Level.WARNING);
if (await DisplayQuestion("Do you want to set this camera to 211?"))
{
Thread Thr211 = new(async () =>
{
if (!await FlexiAPI.ChangeNetwork211(CamOnTest.IP)) // Change camera IP to 192.168.1.211. Waits for camera to come back.
@@ -709,7 +711,7 @@ namespace AiQ_GUI
if (!JSONResponse.Contains(NewSerial) || !JSONResponse.Contains(CamOnTest.Model))
{
AddToActionsList("Could not set model or serial numbers into camera.",Level.ERROR);
AddToActionsList("Could not set model or serial numbers into camera.", Level.ERROR);
await PreTestFailed("Failed To Set Model Or Serial Number");
}
@@ -730,6 +732,8 @@ namespace AiQ_GUI
// Save user settings in LDS for next time if values are valid
if (CbBxUserName.Text.Length > 2 && CbBxCameraType.Text.Length > 6)
{
localDataStore.GUIPosX = this.Location.X;
localDataStore.GUIPosY = this.Location.Y;
localDataStore.User = CbBxUserName.Text;
localDataStore.LastModel = CbBxCameraType.Text;
LDS.SetLDS(localDataStore);
@@ -1124,6 +1128,26 @@ namespace AiQ_GUI
Windows.StartAsAdmin(ExeLoc);
}
private void BtnBaudModules_Click(object sender, EventArgs e)
{
SSH.SetTo115200(CamOnTest.IP);
}
private void BtnOpenMoba_Click(object sender, EventArgs e)
{
const string mobaPath = @"C:\Program Files (x86)\Mobatek\MobaXterm\MobaXterm.exe";
string sshCommand = $"ssh -o StrictHostKeyChecking=no -p 22 mav@{CamOnTest.IP}"; // optional: skip host check
var psi = new ProcessStartInfo
{
FileName = mobaPath,
Arguments = $"-newtab \"{sshCommand}\"",
UseShellExecute = false,
};
Process.Start(psi);
}
// Flips between setting camera to 211 and DHCP
private async void BtnSet211_Click(object sender, EventArgs e)
{
@@ -1282,6 +1306,8 @@ namespace AiQ_GUI
CbBxType.SelectedIndex = 1;
else if (type == "A") // Audit
CbBxType.SelectedIndex = 2;
else if (type == "X") // XML Server
CbBxType.SelectedIndex = 3;
BtnGenerate.Enabled = true;
}
@@ -1471,7 +1497,7 @@ namespace AiQ_GUI
private async void BtnZoomWide_Click(object sender, EventArgs e)
{
if (await FlexiAPI.ZoomModules("0000", CamOnTest.IP))
if (await CameraModules.ZoomModules("0000", CamOnTest.IP))
BtnZoomWide.BackColor = Color.Green;
else
BtnZoomWide.BackColor = Color.Red;
@@ -1481,7 +1507,7 @@ namespace AiQ_GUI
private async void BtnZoom8000_Click(object sender, EventArgs e)
{
if (await FlexiAPI.ZoomModules("1F40", CamOnTest.IP))
if (await CameraModules.ZoomModules("1F40", CamOnTest.IP))
BtnZoom8000.BackColor = Color.Green;
else
BtnZoom8000.BackColor = Color.Red;
@@ -1585,20 +1611,22 @@ namespace AiQ_GUI
CancellationTokenSource cts = new();
soakCtsList.Add(cts);
soakTasks.Add(SoakTest.StartSoak(SCL, SCL.CheckBox, cts.Token));
soakTasks.Add(SoakTest.StartSoak(SCL, cts));
await Task.Delay(10000);
}
}
else
{
BtnSoak.BackColor = BtnColour; // Reset button colour
BtnSoak.Text = "Start Soak";
BtnSoak.BackColor = Color.Red;
BtnSoak.Text = "Please Wait";
foreach (CancellationTokenSource cts in soakCtsList)
cts.Cancel();
soakCtsList.Clear();
soakTasks.Clear();
int i = soakCameraList.Count + 1; // Add 1 for 211 itself staying in the list
RhTxBxActions.Clear();
string[,] Network_JSON = { { "propDHCP", "false" }, { "propHost", "192.168.1.211" }, { "propNetmask", "255.255.255.0" }, { "propGateway", "192.168.1.1" } };
string[,] GOD_JSON = { { "propGodMode", "false" } };
foreach (Camera SCL in soakCameraList.Where(c => c.IsChecked)) // only checked cameras
@@ -1615,8 +1643,8 @@ namespace AiQ_GUI
if (GOD.Contains("Error"))
throw new Exception("Could not set God mode off");
// Update GLOBAL--NetworkConfig with fixed IP and turn off DHCP
await FlexiAPI.HTTP_Update("GLOBAL--NetworkConfig", SCL.IP, Network_JSON);
// Update GLOBAL--NetworkConfig with fixed IP and turn off DHCP. Don't await to save time.
FlexiAPI.HTTP_Update("GLOBAL--NetworkConfig", SCL.IP, Network_JSON);
i--; // Decriment count becuase they will stack into 211
}
catch (Exception ex)
@@ -1643,6 +1671,9 @@ namespace AiQ_GUI
{
AddToActionsList($"Some cameras failed: Found {FoundCams.Count}, expected {i}.", Level.ERROR);
}
BtnSoak.BackColor = BtnColour; // Reset button colour
BtnSoak.Text = "Start Soak";
}
}
@@ -1709,7 +1740,7 @@ namespace AiQ_GUI
}
// ***** Test & Debug *****
private void BtnTest_Click(object sender, EventArgs e)
private async void BtnTest_Click(object sender, EventArgs e)
{
Stopwatch stopWatchTest = Stopwatch.StartNew();

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows10.0.17763.0</TargetFramework>
<TargetFramework>net10.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
@@ -16,7 +16,7 @@
<Product>AiQ GUI</Product>
<Authors>MAV Systems Ltd</Authors>
<PackageId>AiQ GUI</PackageId>
<Version>4.5.0</Version>
<Version>4.7.0</Version>
<Description>A GUI to control and test the AiQ</Description>
<Copyright>MAV Systems Ltd 2025</Copyright>
<PackageIcon>MAV - Plain - Blue.png</PackageIcon>
@@ -55,14 +55,13 @@
<PackageReference Include="ClosedXML" Version="0.105.0" />
<PackageReference Include="Emgu.CV" 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.Gmail.v1" Version="1.70.0.3833" />
<PackageReference Include="Google.Apis.Sheets.v4" Version="1.70.0.3819" />
<PackageReference Include="Google.Apis.Auth" Version="1.73.0" />
<PackageReference Include="Google.Apis.Sheets.v4" Version="1.72.0.3966" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="PDFsharp-MigraDoc-gdi" Version="6.2.2" />
<PackageReference Include="Selenium.Support" Version="4.38.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.38.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="142.0.7444.6100" />
<PackageReference Include="PDFsharp-MigraDoc-gdi" Version="6.2.3" />
<PackageReference Include="Selenium.Support" Version="4.39.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.39.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="143.0.7499.4000" />
<PackageReference Include="SSH.NET" Version="2025.1.0" />
<PackageReference Include="System.Data.OleDb" Version="10.0.0" />
</ItemGroup>

View File

@@ -28,10 +28,10 @@ namespace AiQ_GUI
MainForm.Instance.AddToActionsList($"{CamMod.firmwareVer} or {UniversalData.WonwooFirmware} could not be converted to a double", Level.ERROR);
}
if (CamOnTest.RMANum > 0 && LessTanOrEqualTo)
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)
else if (CamOnTest.RMANum < 1 && CamMod.firmwareVer != UniversalData.WonwooFirmware)
errMssg += $"Firmware: {CamMod.firmwareVer} should be {UniversalData.WonwooFirmware} ";
if (CamMod.expMode != 0) // Auto 0=0x00
@@ -107,5 +107,33 @@ namespace AiQ_GUI
// Build the final VISCA command string using the input characters split as p and q
return $"8101044{command}00000{hex[0]}0{hex[1]}FF";
}
public static async Task<bool> SetZoomLockOn(string IP)
{
// Set Zoomlock on and if it fails ask user to set it manually
if (!(await FlexiAPI.APIHTTPRequest("/api/zoomLock?enable=true", IP)).Contains("Zoom lock enabled.")
&& !await MainForm.Instance.DisplayQuestion("Could not set zoomlock on" + Environment.NewLine + "Set Zoomlock to on then click YES. Click NO to restart."))
{
return false;
}
return true;
}
public static async Task<bool> ZoomModules(string VISCAInput, string IPAddress)
{
// Populate the VISCA command with the four zoom characters
string VISCA = $"810104470{VISCAInput[0]}0{VISCAInput[1]}0{VISCAInput[2]}0{VISCAInput[3]}FF";
Task<string> TS1 = FlexiAPI.APIHTTPVISCA(IPAddress, VISCA, true);
Task<string> TS2 = FlexiAPI.APIHTTPVISCA(IPAddress, VISCA, false);
await Task.WhenAll(TS1, TS2);
const string ExpReply = "9041FF9051FF";
if (TS1.Result == ExpReply && TS1.Result == ExpReply)
return true;
return false;
}
}
}

View File

@@ -174,13 +174,13 @@ namespace AiQ_GUI
// 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).{Level.WARNING}");
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{Level.WARNING}");
MainForm.Instance.DisplayQuestion($"SetVaxtorMinMaxPlate: failed - Please set manually");
return false;
}
@@ -188,39 +188,11 @@ namespace AiQ_GUI
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Could not set Vaxtor Plate height and min confidence: {ex.Message}{Level.ERROR}");
MainForm.Instance.AddToActionsList($"Could not set Vaxtor Plate height and min confidence: {ex.Message}", Level.ERROR);
return false;
}
}
public static async Task<bool> SetZoomLockOn(string IP)
{
// Set Zoomlock on and if it fails ask user to set it manually
if (!(await APIHTTPRequest("/api/zoomLock?enable=true", IP)).Contains("Zoom lock enabled.")
&& !await MainForm.Instance.DisplayQuestion($"Could not set zoomlock on{Level.WARNING}" + Environment.NewLine + $"Set Zoomlock to on then click YES. Click NO to restart. {Level.WARNING}"))
{
return false;
}
return true;
}
public static async Task<bool> ZoomModules(string VISCAInput, string IPAddress)
{
// Populate the VISCA command with the four zoom characters
string VISCA = $"810104470{VISCAInput[0]}0{VISCAInput[1]}0{VISCAInput[2]}0{VISCAInput[3]}FF";
Task<string> TS1 = APIHTTPVISCA(IPAddress, VISCA, true);
Task<string> TS2 = APIHTTPVISCA(IPAddress, VISCA, false);
await Task.WhenAll(TS1, TS2);
const string ExpReply = "9041FF9051FF";
if (TS1.Result == ExpReply && TS1.Result == ExpReply)
return true;
return false;
}
public static async Task SetTrim(string IPAddress, string LblTxt, int RetryCount = 0) // Sets trim by getting plate postion as metric
{
Trim trim;
@@ -270,7 +242,7 @@ namespace AiQ_GUI
}
else // Ask user to centre the plate in the field of view
{
await MainForm.Instance.DisplayOK($"Please centralise plate in view THEN press OK {Level.WARNING}"); // Awaited till OK has been clicked
await MainForm.Instance.DisplayOK($"Please centralise plate in view THEN press OK"); // Awaited till OK has been clicked
if (RetryCount >= 3)
{
@@ -558,6 +530,12 @@ namespace AiQ_GUI
public int colourY { get; set; }
}
public class SysStatus
{
public int gpsState { get; set; } = 0;
public string gpsPresent { get; set; } = string.Empty;
}
public class NetworkConfig
{
public Property propDHCP { get; set; } = new Property();

View File

@@ -11,20 +11,22 @@ namespace AiQ_GUI
const string SAFsalt = "F7W?wbD#'[+:v44]tA<:_iK4hQ}+$R{U";
const string Streamsalt = "*;5WPsR5i/$8s1I(M)K5=z3fms{_8x4U";
const string Auditsalt = "4t5e[E06:dXWf:C09Z[h)}V*n>}t0POP";
const string XMLsalt = "ap(r]oN?t V@WvI=IX=[+$n(<5J,&Ygd";
const string PasswordSalt = "eP@4^4T2@e@^h12oqf!590";
// Generates the license response based on the challenge and type of license
public static string GenerateLicCode(string challenge, string Type)
{
string salt; // Different salts for differnet licenses
string? salt = Type switch
{
"Store & Forward" => SAFsalt,
"Streaming" => Streamsalt,
"Audit" => Auditsalt,
"XML Server" => XMLsalt,
_ => null
};
if (Type == "Store & Forward")
salt = SAFsalt;
else if (Type == "Streaming")
salt = Streamsalt;
else if (Type == "Audit")
salt = Auditsalt;
else
if (salt == null)
return $"Unrecognised challenge type:{Level.ERROR}" + Type;
if (string.IsNullOrEmpty(challenge) || challenge.Length != 6) // Check challenge format

View File

@@ -323,7 +323,7 @@ namespace AiQ_GUI
if (checkDevice.Result.Trim() != "OK") // Device not found
{
MainForm.Instance.AddToActionsList($"Block device {device} not found. {Level.WARNING}");
MainForm.Instance.AddToActionsList($"Block device {device} not found.", Level.WARNING);
return false;
}
@@ -378,7 +378,7 @@ namespace AiQ_GUI
if (checkDevice.Result.Trim().Length > 1) // Device not found
{
MainForm.Instance.AddToActionsList($"Cannot sync files to disk. Replied: {checkDevice.Result}. DO NOT TURN OFF, GET SUPERVISOR {Level.ERROR}");
MainForm.Instance.AddToActionsList($"Cannot sync files to disk. Replied: {checkDevice.Result}. DO NOT TURN OFF, GET SUPERVISOR", Level.ERROR);
return;
}
@@ -387,7 +387,33 @@ namespace AiQ_GUI
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Cannot sync becuase: {ex.Message}. DO NOT TURN OFF, GET SUPERVISOR {Level.ERROR}");
MainForm.Instance.AddToActionsList($"Cannot sync becuase: {ex.Message}. DO NOT TURN OFF, GET SUPERVISOR", Level.ERROR);
}
}
public static void SetTo115200(string IPAddress)
{
try
{
string Cmd = "sudo sh -c \"stty -F /dev/ttyInfrared 9600 cs8 -cstopb -parenb -ixon -ixoff -crtscts -icanon -echo -opost; echo '81 01 04 01 03 FF' | xxd -r -p > /dev/ttyInfrared\"";
SshClient client = SshConnect(IPAddress);
SshCommand checkDevice = client.RunCommand(Cmd);
if (!string.IsNullOrWhiteSpace(checkDevice.Error))
throw new Exception(checkDevice.Error);
Cmd = Cmd.Replace("Infrared", "Colour");
checkDevice = client.RunCommand(Cmd);
if (!string.IsNullOrWhiteSpace(checkDevice.Error))
throw new Exception(checkDevice.Error);
client.Disconnect();
client.Dispose();
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Cannot set cameras to 115200 becuase: {ex.Message}", Level.ERROR);
}
}
}

View File

@@ -46,7 +46,7 @@ namespace AiQ_GUI
{
if (ComapreVersions()) // Checks if the current version is older than the latest version
{
const string GUIPath = $"{GoogleAPI.DrivePath}AiQ\\GUI's\\AiQ_Final_Test\\AiQ_GUI.application";
const string GUIPath = $"{GoogleAPI.DrivePath}AiQ\\GUI's\\AiQ_Final_Test\\setup.exe";
// Check if path is real
if (!File.Exists(GUIPath))

View File

@@ -220,7 +220,7 @@ namespace AiQ_GUI
[GeneratedRegex(@"^[A-Z]{2}\d{2}[A-Z]{2}$", RegexOptions.Compiled)]
internal static partial Regex ModelRegex();
[GeneratedRegex(@"^(?:[FSA])?\d{6}$", RegexOptions.Compiled)]
[GeneratedRegex(@"^(?:[FSAX])?\d{6}$", RegexOptions.Compiled)]
internal static partial Regex LicCodeRegex();
[GeneratedRegex(@"^(?<value>[\d\.]+)(?<unit>[KMGTP]?)(?<suffix>B?)$", RegexOptions.Compiled | RegexOptions.IgnoreCase)]

10
LDS.cs
View File

@@ -10,7 +10,7 @@ namespace AiQ_GUI
public const string IROpensavePath = "IR_Open_image.jpg"; // Path to save the downloaded image
public const string IRTightsavePath = "IR_Tight_image.jpg"; // Path to save the downloaded image
public const string LDSFileName = "LDS.json"; // Local Data Store file name
const string DefaultJSON = "{\r\n \"User\": \"\",\r\n \"LastModel\": \"\",\r\n \"PSUIP\": \"\",\r\n \"EzIP\": \"\",\r\n \"ZebraIP\": \"\",\r\n \"TestTubeIP\": \"\",\r\n \"Shutter\": 0,\r\n \"Iris\": 0,\r\n \"Gain\": 0\r\n}";
const string DefaultJSON = "{\r\n \"User\": \"\",\r\n \"LastModel\": \"\",\r\n \"PSUIP\": \"\",\r\n \"EzIP\": \"\",\r\n \"ZebraIP\": \"\",\r\n \"TestTubeIP\": \"\",\r\n \"Shutter\": 0,\r\n \"Iris\": 0,\r\n \"Gain\": 0\r\n \"GUIPosX\": 0\r\n \"GUIPosY\": 0\r\n}";
public static LocalDataStore GetLDS()
{
@@ -58,8 +58,10 @@ namespace AiQ_GUI
public string EzIP { get; set; } = string.Empty;
public string ZebraIP { get; set; } = string.Empty;
public string TestTubeIP { get; set; } = string.Empty;
public int Shutter { get; set; }
public int Iris { get; set; }
public int Gain { get; set; }
public int Shutter { get; set; } = 0;
public int Iris { get; set; } = 0;
public int Gain { get; set; } = 0;
public int GUIPosX { get; set; } = 0;
public int GUIPosY { get; set; } = 0;
}
}

View File

@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Security.Principal;
namespace AiQ_GUI
{
@@ -25,6 +26,10 @@ namespace AiQ_GUI
{
try
{
WindowsPrincipal wp = new(WindowsIdentity.GetCurrent()); // Log in a seperate file when admin
if (wp.IsInRole(WindowsBuiltInRole.Administrator))
FileName = FileName.Replace(".log", "_ADMIN.log");
string logFilePath = LDS.MAVPath + FileName;
FileInfo fi = new(logFilePath);
@@ -43,7 +48,7 @@ namespace AiQ_GUI
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Error logging message: {ex.Message}{Level.ERROR}");
MessageBox.Show($"Error logging message: {ex.Message}");
}
}
}

View File

@@ -106,8 +106,6 @@ namespace AiQ_GUI
// Initialises and opens a ChromeDriver with specific options
public static ChromeDriver OpenDriver()
{
string tempProfile = null;
try
{
ChromeOptions options = new();
@@ -121,7 +119,7 @@ namespace AiQ_GUI
"--disable-features=BrowserAddPersonFeature,InterestFeedContentSuggestions");
// Use a unique temporary profile to avoid conflicts
tempProfile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
string tempProfile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
options.AddArguments($"--user-data-dir={tempProfile}");
// manual driver path

View File

@@ -7,8 +7,9 @@ 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, CheckBox CkBx, CancellationToken token)
public static async Task StartSoak(Camera CamInfo, CancellationTokenSource CTS)
{
CancellationToken token = CTS.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.
@@ -18,6 +19,7 @@ namespace AiQ_GUI
try
{
driver = Selenium.OpenDriver();
Logging.LogMessage("----- Soak test started -----", SoakLogFile);
await Task.Delay(1000); // Small delay to ensure driver is ready
// Keep retrying until connected or cancelled
@@ -58,6 +60,16 @@ namespace AiQ_GUI
while (!token.IsCancellationRequested)
{
try
{
string TheString = "Selenium string: " + driver.Manage().Window.Size; // Fails out if Window doesn't exist.
}
catch
{
CTS.Cancel();
continue;
}
int currentHour = DateTime.Now.Hour;
// At 7am, power cycle the camera