V3.14
This commit is contained in:
240
AiQ_GUI.cs
240
AiQ_GUI.cs
@@ -183,7 +183,7 @@ namespace AiQ_GUI
|
||||
}
|
||||
|
||||
await Wait; // Finished to 5s wait
|
||||
await SetTrim(); // 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
|
||||
await TestFailed(BtnStartTest, "Could not zoom modules to full wide");
|
||||
@@ -686,81 +686,6 @@ namespace AiQ_GUI
|
||||
Printer.PrintSerialLbl(CamOnTest.Model, NewSerial, CameraAccessInfo.Processor); // Print model/serial label
|
||||
}
|
||||
|
||||
private async Task SetTrim(int RetryCount = 0) // Sets trim by getting plate postion as metric
|
||||
{
|
||||
Trim trim;
|
||||
string trimData = await FlexiAPI.APIHTTPRequest("/SightingCreator-plate-positions", CamOnTest.IP, 5); // Get plate positions
|
||||
|
||||
try // Deserialise the JSON
|
||||
{
|
||||
Logging.LogMessage("Trim Data: " + trimData);
|
||||
trim = JsonConvert.DeserializeObject<Trim>(trimData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await TestFailed(BtnStartTest, "Error reading JSON - " + trimData);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check no value is -1 (no plate found) or if the positions are identical (one plate found). If it is then try again 3 times
|
||||
if (new[] { trim.infraredX, trim.infraredY, trim.colourX, trim.colourY }.Any(value => value == -1)
|
||||
|| (trim.infraredX == trim.colourX && trim.infraredY == trim.colourY))
|
||||
{
|
||||
if (RetryCount >= 3)
|
||||
{
|
||||
await DisplayOK("Please align trim in webpage then click OK."); // Awaited till OK has been clicked
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(5000); // Give 5 second delay for it to see a plate
|
||||
await SetTrim(RetryCount++);
|
||||
}
|
||||
|
||||
int offset = 105;
|
||||
|
||||
if (LblTestTubePing.Text == "❌") // Test tube not connected so do the 2.7m check.
|
||||
offset = 98;
|
||||
|
||||
// Horizontal distance offset for 2.7m compared to 30m is 98 pixels. This was empirically found from testing in the car park
|
||||
// Colour camera is to the right of the infrared so it gets the offset.
|
||||
// Using similar triangles going from 2.7m -> 0.65m which is the length of the test tube (Also exactly 1/4 length).
|
||||
// 98 * (29.35/27.3) = 105.35 pixels
|
||||
int OverviewX = trim.colourX + offset;
|
||||
|
||||
if (OverviewX > 1920) // If adding on the offset has pushed it out of limits then remove 0.1
|
||||
{
|
||||
if (OverviewX < 2120 && trim.infraredX > 400) // Within enough of a limit to automatically do it
|
||||
{
|
||||
OverviewX -= 200;
|
||||
trim.infraredX -= 200;
|
||||
}
|
||||
else // Ask user to centre the plate in the field of view
|
||||
{
|
||||
await DisplayOK("Please centralise plate in view THEN press OK"); // Awaited till OK has been clicked
|
||||
|
||||
if (RetryCount >= 3)
|
||||
{
|
||||
await DisplayOK("Please align trim in webpage then click OK."); // Awaited till OK has been clicked
|
||||
return;
|
||||
}
|
||||
await Task.Delay(5000); // Give 5 second delay for it to see a plate
|
||||
await SetTrim(RetryCount++);
|
||||
}
|
||||
}
|
||||
|
||||
// Compensated trim values, therefore should be close to 0,0 with limits of ±5% of 1920 and 1080 respectivly being ±96 and ±54
|
||||
int TrimX = trim.infraredX - OverviewX;
|
||||
int TrimY = trim.infraredY - trim.colourY;
|
||||
|
||||
// Update trim values
|
||||
string[,] Trim_JSON = { { "propInterCameraOffsetX", Convert.ToString(TrimX) }, { "propInterCameraOffsetY", Convert.ToString(TrimY) } };
|
||||
string TrimResp = await FlexiAPI.HTTP_Update("SightingCreator", CamOnTest.IP, Trim_JSON);
|
||||
AddToActionsList(TrimResp, false);
|
||||
|
||||
if (!TrimResp.Contains($"\"propInterCameraOffsetX\": {{\"value\": \"{Convert.ToString(TrimX)}\", \"datatype\": \"int\"}}, \"propInterCameraOffsetY\": {{\"value\": \"{Convert.ToString(TrimY)}\", \"datatype\": \"int\"}},"))
|
||||
AddToActionsList("Could not set camera trim");
|
||||
}
|
||||
|
||||
// ***** Top right buttons *****
|
||||
private void BtnClose_Click(object sender, EventArgs e)
|
||||
{
|
||||
@@ -800,7 +725,8 @@ namespace AiQ_GUI
|
||||
private async void BtnFindCams_Click(object sender, EventArgs e)
|
||||
{
|
||||
CbBxFoundCams.Text = "Searching";
|
||||
BtnFindCams.Enabled = BtnSetAll211.Enabled = BtnSoak.Enabled = BtnSet211.Enabled = BtnSetGodMode.Enabled = BtnUploadBlob.Enabled = SetGodModeAll.Enabled = false;
|
||||
BtnFindCams.Enabled = BtnSetAll211.Enabled = BtnSoak.Enabled = BtnSet211.Enabled = BtnSetGodMode.Enabled = BtnUploadBlob.Enabled = SetGodModeAll.Enabled = BtnFactoryDefault.Enabled = false;
|
||||
BtnSetGodMode.BackColor = BtnUploadBlob.BackColor = BtnFactoryDefault.BackColor = BtnSetAll211.BackColor = BtnColour;
|
||||
CbBxFoundCams.Items.Clear();
|
||||
soakCameraList.Clear();
|
||||
|
||||
@@ -838,7 +764,7 @@ namespace AiQ_GUI
|
||||
|
||||
int cameraCount = CbBxFoundCams.Items.Count;
|
||||
CbBxFoundCams.Text = cameraCount > 0 ? $"{cameraCount} Camera{(cameraCount == 1 ? "" : "s")} Found" : "No Cameras Found";
|
||||
BtnFindCams.Enabled = BtnSetAll211.Enabled = SetGodModeAll.Enabled = BtnSoak.Enabled = BtnUploadBlob.Enabled = true;
|
||||
BtnFindCams.Enabled = BtnSetAll211.Enabled = SetGodModeAll.Enabled = BtnSoak.Enabled = BtnUploadBlob.Enabled = BtnFactoryDefault.Enabled = true;
|
||||
}
|
||||
|
||||
private void BtnYes_Click(object sender, EventArgs e)
|
||||
@@ -947,6 +873,7 @@ namespace AiQ_GUI
|
||||
|
||||
private async void BtnSetGodMode_Click(object sender, EventArgs e)
|
||||
{
|
||||
BtnSetGodMode.BackColor = BtnColour;
|
||||
bool isGodModeCurrentlyOn = BtnSetGodMode.Text.Contains("On");
|
||||
string newGodModeValue = isGodModeCurrentlyOn ? "true" : "false";
|
||||
string[,] GOD_JSON = { { "propGodMode", newGodModeValue } };
|
||||
@@ -954,13 +881,8 @@ namespace AiQ_GUI
|
||||
try
|
||||
{
|
||||
await FlexiAPI.HTTP_Update("Internal Config", CamOnTest.IP, GOD_JSON);
|
||||
|
||||
BtnSetGodMode.Text = newGodModeValue == "true" ? "Set God Mode Off" : "Set God Mode On";
|
||||
|
||||
Color originalColor = BtnSetGodMode.BackColor;
|
||||
BtnSetGodMode.BackColor = Color.Green;
|
||||
await Task.Delay(500);
|
||||
BtnSetGodMode.BackColor = originalColor;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -1663,6 +1585,7 @@ namespace AiQ_GUI
|
||||
|
||||
private async void BtnUploadBlob_Click(object sender, EventArgs e)
|
||||
{
|
||||
BtnUploadBlob.BackColor = BtnColour;
|
||||
const string networkFolderPath = @"G:\Shared drives\MAV Production\MAV_146_AiQ_Mk2\Flexi";
|
||||
string fileToUpload = null;
|
||||
|
||||
@@ -1716,10 +1639,13 @@ namespace AiQ_GUI
|
||||
AddToActionsList($"Upload result for {cam.IP}: {result}", false);
|
||||
await Task.Delay(500);
|
||||
}
|
||||
BtnUploadBlob.BackColor = Color.Green;
|
||||
}
|
||||
|
||||
private async void BtnFactoryDefault_Click(object sender, EventArgs e)
|
||||
{
|
||||
BtnFactoryDefault.BackColor = BtnColour;
|
||||
|
||||
foreach (Camera SCL in soakCameraList) // Reset all cameras that were being soaked to default module settings
|
||||
{
|
||||
if (!SCL.IsChecked)
|
||||
@@ -1728,116 +1654,70 @@ namespace AiQ_GUI
|
||||
Network.Initialize("developer", SCL.DevPass); // Ensure network is initialized to the right camera, cannot be done in soak test finally becuase of this.
|
||||
await CameraModules.FactoryResetModules(SCL.IP);
|
||||
}
|
||||
BtnFactoryDefault.BackColor = Color.Green;
|
||||
}
|
||||
|
||||
private async void SwitchTest(string TestingType)
|
||||
// Constants
|
||||
const double RealPlateWidthMeters = 0.52; // UK standard plate width
|
||||
const double FocalLengthPixels = (50 * 1280) / 14.111224; // focal mm * pixel width / sensor width for IQ
|
||||
// const double FocalLengthPixels = (50 * 1920) / 6.95; // focal mm * pixel width / sensor width for AiQ
|
||||
const double FrameRate = 25.0; // Frames per second
|
||||
|
||||
public class FrameData
|
||||
{
|
||||
object sender = new();
|
||||
EventArgs e = new();
|
||||
|
||||
Properties.Settings.Default.UnitTesting = TestingType;
|
||||
Properties.Settings.Default.Save();
|
||||
|
||||
CAMTYPE CAMTYPE = TestingType.Substring(0, TestingType.IndexOf('_')) switch
|
||||
{
|
||||
"GOOD" => CAMTYPE.GOOD,
|
||||
"BAD" => CAMTYPE.BAD,
|
||||
"BIZARRE" => CAMTYPE.BIZARRE,
|
||||
_ => CAMTYPE.GOOD,
|
||||
};
|
||||
|
||||
FakeCamera fakeCamera = new(80); // Create an instance of FakeCamera
|
||||
|
||||
_ = fakeCamera.StartAsync(CAMTYPE).ContinueWith(task =>
|
||||
{
|
||||
if (task.IsFaulted)
|
||||
AddToActionsList("Error starting FakeCamera: " + task.Exception?.Message);
|
||||
else
|
||||
AddToActionsList($"FakeCamera started successfully. IP: {fakeCamera}", false);
|
||||
});
|
||||
|
||||
await Task.Delay(5000); // Wait for server to start
|
||||
CbBxFoundCams.Text = "localhost"; // Should force update in creds an network reinit
|
||||
CbBxFoundCams_SelectedIndexChanged(sender, e);
|
||||
CbBxCameraType.SelectedIndex = CbBxCameraType.Items.Count - 1; // Selects AB12CD as model number
|
||||
|
||||
while(TxBxOutput.Text.Length < 2) // Wait for developer password to be generated
|
||||
await Task.Delay(1000);
|
||||
|
||||
if (TestingType.Contains("FINAL"))
|
||||
BtnStartTest_Click(sender, e); // Run final test
|
||||
else if (TestingType.Contains("PRE"))
|
||||
BtnPreTest_Click(sender, e); // Run pre-test
|
||||
|
||||
fakeCamera.Stop(); // Stop the server
|
||||
public long FrameID;
|
||||
public int PlatePosX;
|
||||
public int PlatePosY;
|
||||
public int PlateWidthPixels;
|
||||
}
|
||||
|
||||
public double EstimateSpeed(List<FrameData> frames)
|
||||
{
|
||||
double TimeElapsed = 0;
|
||||
int frameCount = frames.Count;
|
||||
|
||||
for (int i = 1; i < frameCount; i++)
|
||||
{
|
||||
double time = (frames[i].FrameID - frames[i - 1].FrameID) / FrameRate;
|
||||
TimeElapsed += time;
|
||||
}
|
||||
|
||||
double FarDist = (FocalLengthPixels * RealPlateWidthMeters) / frames[0].PlateWidthPixels;
|
||||
double CloseDist = (FocalLengthPixels * RealPlateWidthMeters) / frames[frameCount - 1].PlateWidthPixels;
|
||||
|
||||
double speedMph = (Math.Abs(FarDist - CloseDist) / TimeElapsed) * 2.237;
|
||||
return speedMph;
|
||||
}
|
||||
|
||||
|
||||
// ***** Test & Debug *****
|
||||
private void BtnTest_Click(object sender, EventArgs e)
|
||||
{
|
||||
Stopwatch stopWatchTest = Stopwatch.StartNew();
|
||||
|
||||
// *** To be put in startup code!!!! ***
|
||||
if (Properties.Settings.Default.UnitTesting != "NOT_STARTED")
|
||||
BtnTest_Click(sender, e);
|
||||
|
||||
// *** TO be put in test button ***
|
||||
if (Properties.Settings.Default.UnitTesting == "NOT_STARTED")
|
||||
List<FrameData> frames = new List<FrameData>
|
||||
{
|
||||
SwitchTest("GOOD_PRE");
|
||||
new FrameData { FrameID = 60192555, PlatePosX = 1172, PlatePosY = 393, PlateWidthPixels = 108 },
|
||||
new FrameData { FrameID = 60192556, PlatePosX = 1103, PlatePosY = 361, PlateWidthPixels = 105 },
|
||||
new FrameData { FrameID = 60192558, PlatePosX = 983, PlatePosY = 331, PlateWidthPixels = 99 },
|
||||
new FrameData { FrameID = 60192559, PlatePosX = 930, PlatePosY = 301, PlateWidthPixels = 95 },
|
||||
new FrameData { FrameID = 60192560, PlatePosX = 880, PlatePosY = 304, PlateWidthPixels = 93 },
|
||||
new FrameData { FrameID = 60192561, PlatePosX = 834, PlatePosY = 278, PlateWidthPixels = 89 },
|
||||
new FrameData { FrameID = 60192562, PlatePosX = 792, PlatePosY = 229, PlateWidthPixels = 87 },
|
||||
new FrameData { FrameID = 60192563, PlatePosX = 752, PlatePosY = 208, PlateWidthPixels = 85 },
|
||||
new FrameData { FrameID = 60192565, PlatePosX = 680, PlatePosY = 187, PlateWidthPixels = 81 },
|
||||
new FrameData { FrameID = 60192566, PlatePosX = 648, PlatePosY = 167, PlateWidthPixels = 78 },
|
||||
new FrameData { FrameID = 60192567, PlatePosX = 617, PlatePosY = 149, PlateWidthPixels = 76 },
|
||||
new FrameData { FrameID = 60192568, PlatePosX = 588, PlatePosY = 132, PlateWidthPixels = 75 },
|
||||
new FrameData { FrameID = 60192569, PlatePosX = 561, PlatePosY = 100, PlateWidthPixels = 70 },
|
||||
new FrameData { FrameID = 60192570, PlatePosX = 535, PlatePosY = 85, PlateWidthPixels = 72 },
|
||||
new FrameData { FrameID = 60192572, PlatePosX = 488, PlatePosY = 70, PlateWidthPixels = 69 },
|
||||
new FrameData { FrameID = 60192573, PlatePosX = 466, PlatePosY = 55, PlateWidthPixels = 67 }
|
||||
};
|
||||
|
||||
// Run Good pre test
|
||||
// Check it was the correct outcome
|
||||
// Restart GUI
|
||||
}
|
||||
else if (Properties.Settings.Default.UnitTesting == "GOOD_PRE")
|
||||
{
|
||||
SwitchTest("GOOD_FINAL");
|
||||
|
||||
// Run Good final test
|
||||
// Check it was the correct outcome
|
||||
// Restart GUI
|
||||
}
|
||||
else if (Properties.Settings.Default.UnitTesting == "GOOD_FINAL")
|
||||
{
|
||||
SwitchTest("BAD_PRE");
|
||||
|
||||
// Run Bad pre test
|
||||
// Check it was the correct outcome
|
||||
// Restart GUI
|
||||
}
|
||||
// etc...
|
||||
|
||||
//// SSH testing
|
||||
//sshData = SSH.CollectSSHData("localhost");
|
||||
//AddToActionsList(sshData.packages);
|
||||
//AddToActionsList(sshData.FilesystemSize);
|
||||
//AddToActionsList($"{sshData.tailscale}");
|
||||
|
||||
//// Functionality testing
|
||||
//// TODO - SSH server needs to be running at this point for this to work
|
||||
//var server = new FakeCamera(80); // Start the HTTP server in a background task
|
||||
//_ = server.StartAsync(CAMTYPE.GOOD); // Start the server running with correct responses
|
||||
//Task.Delay(1000).Wait(); // Wait for server to start
|
||||
|
||||
//CbBxCameraType.SelectedIndex = CbBxCameraType.Items.Count - 1; // Selects AB12CD as model number
|
||||
//CbBxFoundCams.Text = "localhost"; // Should force update in creds an network reinit
|
||||
|
||||
//BtnPreTest_Click(sender, e); // Run pre-test
|
||||
//BtnStartTest_Click(sender, e); // Run full test
|
||||
//server.Stop(); // Stop the server
|
||||
|
||||
//_ = server.StartAsync(CAMTYPE.BAD); // Start the server running with bad responses
|
||||
//Task.Delay(1000).Wait(); // Wait for server to start
|
||||
//BtnPreTest_Click(sender, e); // Run pre-test
|
||||
//BtnStartTest_Click(sender, e); // Run full test
|
||||
//server.Stop(); // Stop the server
|
||||
|
||||
//_ = server.StartAsync(CAMTYPE.BIZARRE); // Start the server running with incorrect types and odd responses
|
||||
//Task.Delay(1000).Wait(); // Wait for server to start
|
||||
//BtnPreTest_Click(sender, e); // Run pre-test
|
||||
//BtnStartTest_Click(sender, e); // Run full test
|
||||
//server.Stop(); // Stop the server
|
||||
double Spd = EstimateSpeed(frames);
|
||||
AddToActionsList("Estimated Speed: " + Spd.ToString("F2") + " MPH");
|
||||
|
||||
stopWatchTest.Stop();
|
||||
AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff"));
|
||||
|
@@ -16,7 +16,7 @@
|
||||
<Product>AiQ GUI</Product>
|
||||
<Authors>MAV Systems Ltd</Authors>
|
||||
<PackageId>AiQ GUI</PackageId>
|
||||
<Version>3.12.0</Version>
|
||||
<Version>3.14.0</Version>
|
||||
<Description>A GUI to control and test the AiQ</Description>
|
||||
<Copyright>MAV Systems Ltd 2025</Copyright>
|
||||
<PackageIcon>MAV - Plain - Blue.png</PackageIcon>
|
||||
@@ -25,6 +25,7 @@
|
||||
<RootNamespace>AiQ_GUI</RootNamespace>
|
||||
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<SignAssembly>False</SignAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
@@ -41,18 +42,18 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ClosedXML" Version="0.105.0" />
|
||||
<PackageReference Include="Emgu.CV" Version="4.12.0.5763" />
|
||||
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.12.0.5763" />
|
||||
<PackageReference Include="Google.Apis.Auth" Version="1.70.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.71.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="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="PDFsharp-MigraDoc-gdi" Version="6.2.1" />
|
||||
<PackageReference Include="Selenium.Support" Version="4.35.0" />
|
||||
<PackageReference Include="Selenium.WebDriver" Version="4.35.0" />
|
||||
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="139.0.7258.15400" />
|
||||
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="140.0.7339.8200" />
|
||||
<PackageReference Include="SSH.NET" Version="2025.0.0" />
|
||||
<PackageReference Include="System.Data.OleDb" Version="9.0.8" />
|
||||
<PackageReference Include="System.Data.OleDb" Version="9.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
127
AvailableCondigID.json
Normal file
127
AvailableCondigID.json
Normal file
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"ids": [
|
||||
"Dispatcher3-meta",
|
||||
"RaptorOCRColour",
|
||||
"MMCQueueInfrared",
|
||||
"Wizards",
|
||||
"TargetDetection--sequence-target-finder",
|
||||
"Colour--LiveVideoInput",
|
||||
"SightingCreator--CropPreview",
|
||||
"Dispatcher2-json",
|
||||
"SightingAmmend0-lane-ids",
|
||||
"SightingAmmend1-custom-fields",
|
||||
"colourHistory",
|
||||
"Dispatcher0-json",
|
||||
"SightingAmmend1-lane-ids",
|
||||
"TargetDetectionColour-zone-10",
|
||||
"Audit--Infrared",
|
||||
"Dispatcher1-utmc-constants",
|
||||
"-dev-ttyACM1",
|
||||
"SightingAmmend2-zone-names",
|
||||
"TargetDetection-zone--2",
|
||||
"TargetDetection-zone--1",
|
||||
"Dispatcher3-json",
|
||||
"-dev-ttyACM0",
|
||||
"Dispatcher2-utmc-constants",
|
||||
"SightingAmmend0-overlay",
|
||||
"SightingAmmend0-zone-name-overrides",
|
||||
"TargetDetection-zone-4",
|
||||
"TargetDetection-zone-5",
|
||||
"GLOBAL--GPS",
|
||||
"Dispatcher2-bof2-constants",
|
||||
"TargetDetection-zone-1",
|
||||
"TargetDetection-zone-2",
|
||||
"SightingCreator-timing-line-config",
|
||||
"TargetDetection-zone-3",
|
||||
"Infrared",
|
||||
"Dispatcher1-bof2",
|
||||
"UpdateSentinel",
|
||||
"Infrared--RTSP",
|
||||
"Colour",
|
||||
"TargetDetectionColour--TrakVideoWidget",
|
||||
"Infrared--VMS",
|
||||
"Dispatcher0-bof2",
|
||||
"SightingCreator",
|
||||
"TargetDetection",
|
||||
"SightingAmmend3-overlay",
|
||||
"Telemetry",
|
||||
"Colour--camera-control-widget-config",
|
||||
"GLOBAL--NetworkConfig",
|
||||
"Audit",
|
||||
"Dispatcher2-meta",
|
||||
"TargetDetection--VideoPreview",
|
||||
"TargetDetectionColour--sequence-target-finder",
|
||||
"MMCQueueColour",
|
||||
"mergedHistory",
|
||||
"TargetDetection--TrakVideoWidget",
|
||||
"SightingCreator--SightingHeatMap",
|
||||
"GLOBAL--Passwords",
|
||||
"TargetDetectionColour--VideoPreview",
|
||||
"LogView",
|
||||
"Colour--RTSP",
|
||||
"Dispatcher2-utmc",
|
||||
"Dispatcher3-utmc-constants",
|
||||
"SightingAmmend3-zone-name-overrides",
|
||||
"SightingAmmend0-zone-names",
|
||||
"SightingAmmend2",
|
||||
"SightingAmmend1",
|
||||
"SightingAmmend0",
|
||||
"SightingCreator-camera-offset",
|
||||
"SightingAmmend3",
|
||||
"TargetDetectionColour--TargetDetectionFilter",
|
||||
"SightingAmmend3-lane-ids",
|
||||
"Dispatcher3-bof2",
|
||||
"Dispatcher1-utmc",
|
||||
"Dispatcher0-utmc-constants",
|
||||
"Audit--Recorder",
|
||||
"Dispatcher0-bof2-constants",
|
||||
"SightingAmmend2-overlay",
|
||||
"Store2",
|
||||
"Store1",
|
||||
"Store3",
|
||||
"TargetDetectionColour-zone--2",
|
||||
"TargetDetectionColour",
|
||||
"TargetDetectionColour-zone--1",
|
||||
"SightingAmmend0-custom-fields",
|
||||
"Dispatcher1-bof2-constants",
|
||||
"RaptorOCR",
|
||||
"Dispatcher0-utmc",
|
||||
"Store0",
|
||||
"Dispatcher1",
|
||||
"Dispatcher2",
|
||||
"TargetIdentifiedProcessingQueue",
|
||||
"Dispatcher0",
|
||||
"GLOBAL--Device",
|
||||
"Dispatcher3-utmc",
|
||||
"SightingAmmend3-zone-names",
|
||||
"Dispatcher3",
|
||||
"Dispatcher0-meta",
|
||||
"SightingCreator--TimingLineVideoWidgetInfrared",
|
||||
"SightingCreator--TimingLineVideoWidgetColour",
|
||||
"SightingAmmend2-lane-ids",
|
||||
"Dispatcher3-bof2-constants",
|
||||
"WidgetViewer",
|
||||
"TargetDetectionColour-zone-8",
|
||||
"TargetDetectionColour-zone-9",
|
||||
"TargetDetectionColour-zone-6",
|
||||
"TargetDetectionColour-zone-7",
|
||||
"Dispatcher1-meta",
|
||||
"SightingAmmend1-zone-names",
|
||||
"Audit--Colour",
|
||||
"SightingAmmend1-zone-name-overrides",
|
||||
"TargetDetectionProcessingQueue",
|
||||
"SightingAmmend2-zone-name-overrides",
|
||||
"Infrared--camera-control-widget-config",
|
||||
"SightingAmmend3-custom-fields",
|
||||
"Infrared--LiveVideoInput",
|
||||
"TargetDetectionProcessingQueueColour",
|
||||
"VideoFramePairCreator",
|
||||
"Colour--VMS",
|
||||
"Dispatcher2-bof2",
|
||||
"infraredHistory",
|
||||
"Dispatcher1-json",
|
||||
"SightingAmmend1-overlay",
|
||||
"SightingAmmend2-custom-fields",
|
||||
"TargetDetection--TargetDetectionFilter"
|
||||
]
|
||||
}
|
@@ -71,10 +71,8 @@ namespace AiQ_GUI
|
||||
string OneshotReply = await FlexiAPI.APIHTTPVISCA(IPAddress, "8101041801FF", true); // Oneshot auto focus
|
||||
|
||||
if (!ShutterReply.Contains("41") || !IrisReply.Contains("41") || !GainReply.Contains("41") || !OneshotReply.Contains("41"))
|
||||
{
|
||||
MainForm.Instance.AddToActionsList("Could not set Shutter, Iris, Gain correctly" + Environment.NewLine + "Shutter: " + ShutterReply + Environment.NewLine + "Iris: " + IrisReply + Environment.NewLine + "Gain: " + GainReply + Environment.NewLine + "Oneshot: " + OneshotReply);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets back to the latest factory defaults CSV that is in Flexi.
|
||||
public static async Task FactoryResetModules(string IPAddress)
|
||||
|
@@ -49,9 +49,8 @@ namespace AiQ_GUI
|
||||
{
|
||||
try
|
||||
{
|
||||
string JSONdata = "{ \"id\":\"" + ID + "\" }";
|
||||
string url = $"http://{IPAddress}/api/fetch-config";
|
||||
return await Network.SendHttpRequest(url, HttpMethod.Get, Timeout, JSONdata);
|
||||
string url = $"http://{IPAddress}/api/fetch-config?id={ID}";
|
||||
return await Network.SendHttpRequest(url, HttpMethod.Get, Timeout);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -87,14 +86,13 @@ namespace AiQ_GUI
|
||||
try
|
||||
{
|
||||
Network.Client.DefaultRequestHeaders.ExpectContinue = false;
|
||||
MultipartFormDataContent content;
|
||||
|
||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
|
||||
MemoryStream ms = new(fileBytes);
|
||||
StreamContent streamContent = new(ms);
|
||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
|
||||
content = new MultipartFormDataContent { { streamContent, "upload", fileName } };
|
||||
MultipartFormDataContent content = new() { { streamContent, "upload", fileName } };
|
||||
|
||||
using HttpResponseMessage response = await Network.Client.PostAsync(url, content);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
@@ -189,6 +187,80 @@ namespace AiQ_GUI
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task SetTrim(string IPAddress, string LblTxt, int RetryCount = 0) // Sets trim by getting plate postion as metric
|
||||
{
|
||||
Trim trim;
|
||||
string trimData = await APIHTTPRequest("/SightingCreator-plate-positions", IPAddress, 5); // Get plate positions
|
||||
|
||||
try // Deserialise the JSON
|
||||
{
|
||||
Logging.LogMessage("Trim Data: " + trimData);
|
||||
trim = JsonConvert.DeserializeObject<Trim>(trimData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
MainForm.Instance.AddToActionsList("Error reading trim JSON - " + trimData);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check no value is -1 (no plate found) or if the positions are identical (one plate found). If it is then try again 3 times
|
||||
if (new[] { trim.infraredX, trim.infraredY, trim.colourX, trim.colourY }.Any(value => value == -1)
|
||||
|| (trim.infraredX == trim.colourX && trim.infraredY == trim.colourY))
|
||||
{
|
||||
if (RetryCount >= 3)
|
||||
{
|
||||
await MainForm.Instance.DisplayOK("Please align trim in webpage then click OK."); // Awaited till OK has been clicked
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(5000); // Give 5 second delay for it to see a plate
|
||||
await SetTrim(IPAddress, LblTxt, RetryCount++);
|
||||
}
|
||||
|
||||
int offset = 105;
|
||||
|
||||
if (LblTxt == "❌") // Test tube not connected so do the 2.7m check.
|
||||
offset = 98;
|
||||
|
||||
// Horizontal distance offset for 2.7m compared to 30m is 98 pixels. This was empirically found from testing in the car park
|
||||
// Colour camera is to the right of the infrared so it gets the offset.
|
||||
// Using similar triangles going from 2.7m -> 0.65m which is the length of the test tube (Also exactly 1/4 length).
|
||||
// 98 * (29.35/27.3) = 105.35 pixels
|
||||
int OverviewX = trim.colourX + offset;
|
||||
|
||||
if (OverviewX > 1920) // If adding on the offset has pushed it out of limits then remove 0.1
|
||||
{
|
||||
if (OverviewX < 2120 && trim.infraredX > 400) // Within enough of a limit to automatically do it
|
||||
{
|
||||
OverviewX -= 200;
|
||||
trim.infraredX -= 200;
|
||||
}
|
||||
else // Ask user to centre the plate in the field of view
|
||||
{
|
||||
await MainForm.Instance.DisplayOK("Please centralise plate in view THEN press OK"); // Awaited till OK has been clicked
|
||||
|
||||
if (RetryCount >= 3)
|
||||
{
|
||||
await MainForm.Instance.DisplayOK("Please align trim in webpage then click OK."); // Awaited till OK has been clicked
|
||||
return;
|
||||
}
|
||||
await Task.Delay(5000); // Give 5 second delay for it to see a plate
|
||||
await SetTrim(IPAddress, LblTxt, RetryCount++);
|
||||
}
|
||||
}
|
||||
|
||||
// Compensated trim values, therefore should be close to 0,0 with limits of ±5% of 1920 and 1080 respectivly being ±96 and ±54
|
||||
int TrimX = trim.infraredX - OverviewX;
|
||||
int TrimY = trim.infraredY - trim.colourY;
|
||||
|
||||
// Update trim values
|
||||
string[,] Trim_JSON = { { "propInterCameraOffsetX", Convert.ToString(TrimX) }, { "propInterCameraOffsetY", Convert.ToString(TrimY) } };
|
||||
string TrimResp = await HTTP_Update("SightingCreator", IPAddress, Trim_JSON);
|
||||
|
||||
if (!TrimResp.Contains($"\"propInterCameraOffsetX\": {{\"value\": \"{Convert.ToString(TrimX)}\", \"datatype\": \"int\"}}, \"propInterCameraOffsetY\": {{\"value\": \"{Convert.ToString(TrimY)}\", \"datatype\": \"int\"}},"))
|
||||
MainForm.Instance.AddToActionsList("Could not set camera trim");
|
||||
}
|
||||
|
||||
// Processes the network config from the camera and returns a string indicating the status
|
||||
public static async Task<string> ProcessNetworkConfig(string IPAddress)
|
||||
{
|
||||
@@ -210,7 +282,7 @@ namespace AiQ_GUI
|
||||
}
|
||||
|
||||
// Knowing the format this builds the message to send to AiQ
|
||||
private static string BuildJsonUpdate(string[,] jsonData, string id)
|
||||
public static string BuildJsonUpdate(string[,] jsonData, string id)
|
||||
{
|
||||
if (jsonData == null || jsonData.GetLength(1) != 2)
|
||||
throw new ArgumentException("Input data must be a non-null 2D array with two columns.");
|
||||
|
@@ -14,7 +14,7 @@ namespace AiQ_GUI
|
||||
|
||||
try
|
||||
{
|
||||
using SshClient client = new SshClient(IPAddress, SSHUsername, SSHPassword);
|
||||
using SshClient client = new(IPAddress, SSHUsername, SSHPassword);
|
||||
client.Connect();
|
||||
|
||||
try
|
||||
|
@@ -12,7 +12,7 @@ namespace AiQ_GUI
|
||||
|
||||
public static void Initialize(string username, string password)
|
||||
{
|
||||
HttpClientHandler handler = new HttpClientHandler
|
||||
HttpClientHandler handler = new()
|
||||
{
|
||||
MaxConnectionsPerServer = 25,
|
||||
Credentials = new NetworkCredential(username, password)
|
||||
@@ -30,7 +30,7 @@ namespace AiQ_GUI
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpRequestMessage request = new HttpRequestMessage(method, url);
|
||||
HttpRequestMessage request = new(method, url);
|
||||
|
||||
if (jsonData != null) // Fills in the body of the request if jsonData is provided
|
||||
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
|
||||
@@ -48,8 +48,8 @@ namespace AiQ_GUI
|
||||
}
|
||||
}
|
||||
|
||||
int timeoutMs = (Timeout ?? 10) * 1000; // Convert from seconds to ms
|
||||
using CancellationTokenSource cts = new CancellationTokenSource(timeoutMs);
|
||||
int timeoutMs = (Timeout ?? 10) * 1000; // Convert from seconds to ms, default to 10s if null
|
||||
using CancellationTokenSource cts = new(timeoutMs);
|
||||
|
||||
using HttpResponseMessage response = await Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cts.Token);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
73
Test.json
Normal file
73
Test.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user