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
14 changed files with 104 additions and 206 deletions

39
AiQ_GUI.Designer.cs generated
View File

@@ -148,6 +148,7 @@ namespace AiQ_GUI
BtnFirewall = new Button(); BtnFirewall = new Button();
TabImages = new TabPage(); TabImages = new TabPage();
TabSoak = new TabPage(); TabSoak = new TabPage();
BtnFactoryDefault = new Button();
SetGodModeAll = new Button(); SetGodModeAll = new Button();
BtnUploadBlob = new Button(); BtnUploadBlob = new Button();
CkBxTickAll = new CheckBox(); CkBxTickAll = new CheckBox();
@@ -157,7 +158,6 @@ namespace AiQ_GUI
LblGUIVers = new Label(); LblGUIVers = new Label();
timerTypeIP = new System.Windows.Forms.Timer(components); timerTypeIP = new System.Windows.Forms.Timer(components);
TimerFlash = new System.Windows.Forms.Timer(components); TimerFlash = new System.Windows.Forms.Timer(components);
BtnFactoryDefault = new Button();
((System.ComponentModel.ISupportInitialize)PicBxMAV).BeginInit(); ((System.ComponentModel.ISupportInitialize)PicBxMAV).BeginInit();
((System.ComponentModel.ISupportInitialize)PicBxAiQ).BeginInit(); ((System.ComponentModel.ISupportInitialize)PicBxAiQ).BeginInit();
((System.ComponentModel.ISupportInitialize)PicBxIRF2).BeginInit(); ((System.ComponentModel.ISupportInitialize)PicBxIRF2).BeginInit();
@@ -273,6 +273,7 @@ namespace AiQ_GUI
CbBxUserName.Items.AddRange(new object[] { "Guest", "Clive", "Conor", "Charlie", "Henry", "Sam C", "Sam L", "Simon", "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;
@@ -1910,6 +1911,24 @@ namespace AiQ_GUI
TabSoak.TabIndex = 2; TabSoak.TabIndex = 2;
TabSoak.Text = "Soak"; TabSoak.Text = "Soak";
// //
// BtnFactoryDefault
//
BtnFactoryDefault.BackColor = Color.FromArgb(70, 65, 80);
BtnFactoryDefault.Enabled = false;
BtnFactoryDefault.FlatAppearance.BorderColor = Color.FromArgb(70, 65, 80);
BtnFactoryDefault.FlatAppearance.BorderSize = 0;
BtnFactoryDefault.FlatStyle = FlatStyle.Flat;
BtnFactoryDefault.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
BtnFactoryDefault.ForeColor = SystemColors.Control;
BtnFactoryDefault.Location = new Point(222, 209);
BtnFactoryDefault.Margin = new Padding(4, 3, 4, 3);
BtnFactoryDefault.Name = "BtnFactoryDefault";
BtnFactoryDefault.Size = new Size(181, 49);
BtnFactoryDefault.TabIndex = 242;
BtnFactoryDefault.Text = "Set Modules to Factory Defaults";
BtnFactoryDefault.UseVisualStyleBackColor = false;
BtnFactoryDefault.Click += BtnFactoryDefault_Click;
//
// SetGodModeAll // SetGodModeAll
// //
SetGodModeAll.BackColor = Color.FromArgb(70, 65, 80); SetGodModeAll.BackColor = Color.FromArgb(70, 65, 80);
@@ -2000,24 +2019,6 @@ namespace AiQ_GUI
timerTypeIP.Interval = 2000; timerTypeIP.Interval = 2000;
timerTypeIP.Tick += timerTypeIP_Tick; timerTypeIP.Tick += timerTypeIP_Tick;
// //
// BtnFactoryDefault
//
BtnFactoryDefault.BackColor = Color.FromArgb(70, 65, 80);
BtnFactoryDefault.Enabled = false;
BtnFactoryDefault.FlatAppearance.BorderColor = Color.FromArgb(70, 65, 80);
BtnFactoryDefault.FlatAppearance.BorderSize = 0;
BtnFactoryDefault.FlatStyle = FlatStyle.Flat;
BtnFactoryDefault.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold);
BtnFactoryDefault.ForeColor = SystemColors.Control;
BtnFactoryDefault.Location = new Point(222, 209);
BtnFactoryDefault.Margin = new Padding(4, 3, 4, 3);
BtnFactoryDefault.Name = "BtnFactoryDefault";
BtnFactoryDefault.Size = new Size(181, 49);
BtnFactoryDefault.TabIndex = 242;
BtnFactoryDefault.Text = "Set Modules to Factory Defaults";
BtnFactoryDefault.UseVisualStyleBackColor = false;
BtnFactoryDefault.Click += BtnFactoryDefault_Click;
//
// MainForm // MainForm
// //
AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleDimensions = new SizeF(7F, 15F);

View File

@@ -143,15 +143,12 @@ 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.
@@ -228,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.
} }
@@ -464,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;
@@ -675,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
@@ -772,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;
@@ -1137,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;
@@ -1823,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);
@@ -1886,6 +1880,7 @@ namespace AiQ_GUI
//BtnPreTest_Click(sender, e); //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);
} }

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();
@@ -288,15 +310,14 @@ namespace AiQ_GUI
return 0; return 0;
} }
// Expands the filesystem to max // Expands the filesystem to max
public async static Task<bool> ExpandFS(string device, string IPAddress) public async static Task<bool> ExpandFS(string device, string IPAddress)
{ {
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

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

@@ -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"
}
}