Add project files.

This commit is contained in:
2025-09-02 15:32:24 +01:00
parent 6a633eed7a
commit 50bb9c9781
53 changed files with 9925 additions and 0 deletions

229
Helper.cs Normal file
View File

@@ -0,0 +1,229 @@
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace AiQ_GUI
{
internal class Helper
{
// ***** Allows moving GUI by grab and dragging *****
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ReleaseCapture();
public static void RestartApp()
{
Application.Restart();
Process.GetCurrentProcess().Kill(); // To make sure no execution on other threads occurs eg. making a test record.
}
public static int[] Shuffle() // Generates random order for visual test
{
Random random = new();
int[] result = new int[4];
for (int i = 0; i < 4; i++)
{
int j = random.Next(0, i + 1);
if (i != j)
result[i] = result[j];
result[j] = i;
}
return result;
}
// Generates a string that is a combination fo labels thats are red and Only RHS of the =. As well as the text in the Actions rich text box.
public static string GetOverriddenActions(Panel pnlLbls, RichTextBox rhTxBxActions)
{
List<string?> redValues = pnlLbls.Controls
.OfType<Label>() // Only labels
.Where(lbl => lbl.BackColor == Color.Red) // Only red labels
.Where(lbl => lbl.Visible == true) // Only visible labels
.Select(lbl =>
{ // Only the RHS of labels
string[] parts = lbl.Text.Split('=');
return parts.Length > 1 ? parts[1].Trim() : null;
})
.Where(value => value != null) // Make sure RHS is not null
.ToList();
string? ActionsText = rhTxBxActions.Text?.Trim();
bool hasRedValues = redValues.Count != 0;
bool hasActionText = !string.IsNullOrWhiteSpace(ActionsText);
if (!hasRedValues && !hasActionText)
return ""; // Nothing to report
string result = "\n\nOverridden actions = ";
if (hasActionText) // If Actions has text then append it.
result += ActionsText;
if (hasRedValues) // If there are red values then append it.
{
if (hasActionText)
result += "\n";
result += string.Join(", ", redValues);
}
return result;
}
// Have to wait asynchronously to make UI responsive while waiting for answer
public static async Task VisualCheck(Button Btn) // To make people read the prompts change the order that they appear on random shuffle
{
foreach (int ShuffleOrder in Shuffle())
{
switch (ShuffleOrder)
{
case 0:
if (!await MainForm.Instance.DisplayQuestion("Is the sleeve aligned correctly?"))
await MainForm.Instance.TestFailed(Btn, "Visual Test Fail - Sleeve not aligned");
break;
case 1:
if (!await MainForm.Instance.DisplayQuestion("Are all the screws fitted in the front?"))
await MainForm.Instance.TestFailed(Btn, "Visual Test Fail - Not all front screws fitted");
break;
case 2:
if (!await MainForm.Instance.DisplayQuestion("Are all the screws fitted in the rear?"))
await MainForm.Instance.TestFailed(Btn, "Visual Test Fail - Not all rear screws fitted");
break;
case 3:
if (await MainForm.Instance.DisplayQuestion("Shake unit, does it rattle?"))
await MainForm.Instance.TestFailed(Btn, "Visual Test Fail - Unit rattles");
break;
default:
MainForm.Instance.AddToActionsList("Numbering problem in visual test");
break;
}
}
}
public static async Task<Camera> NewCamera(string IPAddress)
{
Versions Vers = await FlexiAPI.GetVersions(IPAddress);
try
{
if (Vers.Model == "???")
return null;
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Error fetching versions for {IPAddress}: {ex.Message}");
return null;
}
Camera soakInfo = new()
{
IP = IPAddress,
Model = Vers.Model,
Serial = Vers.Serial,
DevPass = Lics.FetchDevPassword(Vers),
RMANum = GoogleAPI.CheckRMANum(Vers.Serial, Vers.Model),
FlexiVersion = Vers.version,
IsChecked = true
};
return soakInfo;
}
public static void DCPowerCheck(Label Lbl)
{
if (CameraAccessInfo.PowerType.Contains('V')) // AiQ Powered from DC
{
try
{
Lbl.Visible = true; // Show the DC label
string PSUVoltage = PSU.SendDataPsu("V1O?", PSU.PSUIP);
string PSUCurrent = PSU.SendDataPsu("I1O?", PSU.PSUIP);
PSUVoltage = PSUVoltage.Remove(PSUVoltage.IndexOf('V'));
PSUCurrent = PSUCurrent.Remove(PSUCurrent.IndexOf('A'));
Lbl.Text += $" {PSUVoltage}V, {PSUCurrent}A"; // Show the PSU voltage and current on the label
double PSU_V = Convert.ToDouble(PSUVoltage);
double PSU_I = Convert.ToDouble(PSUCurrent);
double Exp_PSU_V = Convert.ToDouble(CameraAccessInfo.PowerType.Remove(CameraAccessInfo.PowerType.IndexOf('V')));
double Exp_PSU_I = Math.Round(UniversalData.PowerConsumption / Exp_PSU_V, 2); // 32W device if AiQ Mk2 on medium LED power
if (PSU_V > Exp_PSU_V + 1 || PSU_V < Exp_PSU_V - 1)
{
MainForm.Instance.AddToActionsList($"PSU Voltage out of range: {PSUVoltage}V. Expected {Exp_PSU_V}V ± 1V.");
}
if (PSU_I < Exp_PSU_I * 0.8 || PSU_I > Exp_PSU_I * 1.2)
{
MainForm.Instance.AddToActionsList($"PSU Current out of range: {PSUCurrent}A. Expected {Exp_PSU_I}A ± 20%.");
}
}
catch
{
MainForm.Instance.AddToActionsList("PSU did not reply as expected.");
}
}
}
}
// TODO - use Processor & ModuleManufacturer
public class Camera
{
public string Model { get; set; } = string.Empty; // Gets last model from LDS on boot
public string Serial { get; set; } = string.Empty;
public string DevPass { get; set; } = string.Empty; // Gets from API
public string IP { get; set; } = string.Empty;
public int RMANum { get; set; } = 0;
public string FlexiVersion { get; set; } = string.Empty; // Flexi version
public string Processor { get; set; } = string.Empty; // Nano, Xavier, Orin or Pi?
public string ModuleManufacturer { get; set; } = string.Empty; // KT&C or Wonwoo
public bool IsChecked { get; set; } // Is it checked for soak test?
}
// Static class for global flags
internal static class Flags
{
public static bool Yes { get; set; }
public static bool No { get; set; }
public static bool Done { get; set; }
public static bool Offline { get; set; }
public static bool Start { get; set; } = true;
}
// Store all precompiled regexes
public static partial class RegexCache
{
[GeneratedRegex(@"^((localhost)|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:?(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[0-9]{1,4}))?$", RegexOptions.Compiled)]
internal static partial Regex RegexIPPattern();
[GeneratedRegex(@"^K\d{7}$", RegexOptions.Compiled)]
internal static partial Regex SerialRegex();
[GeneratedRegex(@"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$", RegexOptions.Compiled)]
internal static partial Regex MACRegex();
[GeneratedRegex(@"^(00:04:4B|3C:6D:66|48:B0:2D):([0-9A-Fa-f]{2}:){2}[0-9A-Fa-f]{2}$", RegexOptions.Compiled)]
internal static partial Regex MACRegexNVIDIA();
[GeneratedRegex(@"^\d{1,3}\.\d{1,3}\.\d{1,3}$", RegexOptions.Compiled)]
internal static partial Regex FlexiVerRegex();
[GeneratedRegex(@"^[A-Z]{2}\d{2}[A-Z]{2}$", RegexOptions.Compiled)]
internal static partial Regex ModelRegex();
[GeneratedRegex(@"^(?:[FSA])?\d{6}$", RegexOptions.Compiled)]
internal static partial Regex LicCodeRegex();
[GeneratedRegex(@"^(?<value>[\d\.]+)(?<unit>[KMGTP]?)(?<suffix>B?)$", RegexOptions.Compiled | RegexOptions.IgnoreCase)]
internal static partial Regex FileSizeRegex();
[GeneratedRegex(@"^81(( [0-9A-Fa-f]{2})+)? FF$", RegexOptions.Compiled | RegexOptions.IgnoreCase)]
internal static partial Regex VISCARegex();
[GeneratedRegex(@"^\d{15,19}$", RegexOptions.Compiled | RegexOptions.IgnoreCase)]
internal static partial Regex VaxtorRegex();
}
}