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

View File

@@ -0,0 +1,59 @@
{
"cameraName": "AiQ-ANPR-Camera",
"version": "1.6.4",
"revision": "bf16134",
"serialNumber": "K1005001",
"modelNumber": "AB12CD",
"MAC": "3C:6D:66:0A:BA:18",
"timeStamp": 1754296734,
"licenses": {
"saf1": true,
"saf2": true,
"saf3": false,
"saf4": false,
"audit": false,
"stream": false,
"raptorKeyID": "833051022471605126"
},
"internalTemperature": 50.5,
"cpuUsage": 80.8987815001732,
"trim": [
-57,
48
],
"zoomLock": true,
"IRmodule": {
"zoom": 0,
"focus": 40960,
"expMode": 0,
"shutter": 11,
"iris": 12,
"gain": 3,
"firmwareVer": "1.1"
},
"OVmodule": {
"zoom": 0,
"focus": 16384,
"expMode": 0,
"shutter": 12,
"iris": 12,
"gain": 0,
"firmwareVer": "1.1"
},
"ledChannelVoltages": [
21.5,
22.75,
21.75,
21.5,
21,
21.25
],
"ledChannelCurrents": [
92,
89,
89,
95,
96,
90
]
}

View File

@@ -0,0 +1,59 @@
{
"cameraName": "AiQ-ANPR-Camera",
"version": "1.2",
"revision": "77e042f",
"serialNumber": "K1005001",
"modelNumber": "AB12CD",
"MAC": "3C:6D:66:0A:BA:18",
"timeStamp": 1754296734,
"licenses": {
"saf1": true,
"saf2": true,
"saf3": false,
"saf4": false,
"audit": false,
"stream": false,
"raptorKeyID": "833051022471605126"
},
"internalTemperature": 110.2,
"cpuUsage": 1000,
"trim": [
-57,
12
],
"zoomLock": true,
"IRmodule": {
"zoom": 934500,
"focus": 4,
"expMode": 3000,
"shutter": 110,
"iris": 120,
"gain": 3000,
"firmwareVer": "99"
},
"OVmodule": {
"zoom": 9345000,
"focus": 1,
"expMode": -1,
"shutter": 1200,
"iris": 120,
"gain": 9999,
"firmwareVer": "-1"
},
"ledChannelVoltages": [
250,
2.3,
261,
21,
282,
21.25
],
"ledChannelCurrents": [
12,
100,
132,
51,
34,
61
]
}

View File

@@ -0,0 +1,59 @@
{
"cameraName": "AiQ-ANPR-Camera",
"version": "1.6.4",
"revision": "77e042f",
"serialNumber": "K1005001",
"modelNumber": "AB12CD",
"MAC": "21",
"timeStamp": 1754296734,
"licenses": {
"saf1": no,
"saf2": yes,
"saf3": 0,
"saf4": -1,
"audit": false,
"stream": true,
"raptorKeyID": "000"
},
"internalTemperature": NOPE,
"cpuUsage": "WHAT IS A CPU",
"trim": [
-57,
48
],
"zoomLock": NahNOTTODAY,
"IRmodule": {
"zoom": 934dff,
"focus": 4096d0,
"expMode": 3,
"shutter": 11,
"iris": 12,
"gain": 3,
"firmwareVer": "FIRMWARE"
},
"OVmodule": {
"zoom": 0,
"focus": FOCAL,
"expMode": 02321243,
"shutter": 1232323,
"iris": 12,
"gain": 0,
"firmwareVer": "1.1"
},
"ledChannelVoltages": [
"ddsda",
22.75,
21.75,
"####",
"!!!!!",
"你好"
],
"ledChannelCurrents": [
"你好",
####,
-1,
262000,
TEST,
265
]
}

354
FakeCamera/FakeCamera.cs Normal file
View File

@@ -0,0 +1,354 @@
using Newtonsoft.Json;
using System.Net;
using System.Text;
namespace AiQ_GUI
{
public enum CAMTYPE
{
GOOD,
BAD,
BIZARRE
}
public class FakeCamera
{
public const string JSONLoc = "C:\\Users\\BradleyBorn\\OneDrive - MAV Systems Ltd\\Desktop\\AIQ_GUI_TEST\\FakeCameraGood\\";
public static bool Snapshot = false;
private HttpListener listener;
public FakeCamera(int port = 8080)
{
listener = new HttpListener();
listener.Prefixes.Add($"http://*:{port}/");
listener.Prefixes.Add("http://localhost:8080/");
}
public async Task StartAsync(CAMTYPE camType)
{
try
{
listener.Start();
MainForm.Instance.AddToActionsList("Started server successfully");
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Failed to start server: {ex.Message}");
return;
}
while (true)
{
HttpListenerContext? context = await listener.GetContextAsync();
_ = HandleRequestAsync(context, camType);
}
}
public void Stop()
{
if (listener.IsListening)
{
listener.Stop();
listener.Close();
}
}
public static bool ValidateCredentials(string username, string password, CAMTYPE camType)
{
string filePath = camType switch
{
CAMTYPE.GOOD => $"{JSONLoc}Versions.json",
CAMTYPE.BAD => $"{JSONLoc}Versions_Bad.json",
CAMTYPE.BIZARRE => $"{JSONLoc}Versions_Bizarre.json",
_ => throw new ArgumentOutOfRangeException(nameof(camType), "Invalid camera type")
};
string versJson = File.ReadAllText(filePath);
Versions vers = JsonConvert.DeserializeObject<Versions>(versJson);
TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
int secondsSinceEpoch = (int)t.TotalSeconds;
string PASS = Lics.GeneratePassword(vers.MAC, vers.version, secondsSinceEpoch);
return username == "developer" && password == PASS;
}
private static async Task HTTPReplySetup(HttpListenerContext context, string ResponseText, int StatusCode, string ContentType)
{
try
{
context.Response.StatusCode = StatusCode;
context.Response.ContentType = ContentType;
byte[] responseBytes = Encoding.UTF8.GetBytes(ResponseText);
context.Response.ContentLength64 = responseBytes.Length;
await context.Response.OutputStream.WriteAsync(responseBytes);
}
finally
{
context.Response.OutputStream.Close();
}
}
private static async Task HTTPReplySetup(HttpListenerContext context, byte[] content, int statusCode, string contentType)
{
context.Response.StatusCode = statusCode;
context.Response.ContentType = contentType;
context.Response.ContentLength64 = content.Length;
await context.Response.OutputStream.WriteAsync(content);
await context.Response.OutputStream.FlushAsync();
context.Response.OutputStream.Close();
}
private static async Task HandleRequestAsync(HttpListenerContext context, CAMTYPE camType)
{
string path = context.Request.Url?.AbsolutePath ?? "/";
string Method = context.Request.HttpMethod;
string headers = context.Request.Headers.ToString();
string Content = context.Request.InputStream?.ToString() ?? "";
// Define endpoints that do NOT require authentication
string[] publicEndpoints = ["/api/versions", "/api/diagnostics"];
bool requiresAuth = !publicEndpoints.Contains(path);
if (requiresAuth)
{
string authHeader = context.Request.Headers["Authorization"];
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Basic "))
{
context.Response.AddHeader("WWW-Authenticate", "Basic realm=\"FakeCamera\"");
await HTTPReplySetup(context, "", 401, "text/plain");
return;
}
try
{
string encodedCredentials = authHeader.Substring("Basic ".Length).Trim();
string decodedCredentials = Encoding.UTF8.GetString(Convert.FromBase64String(encodedCredentials));
string[] parts = decodedCredentials.Split(':', 2);
if (parts.Length != 2)
{
throw new Exception("Invalid Basic auth format. Expected username:password.");
}
string username = parts[0];
string password = parts[1];
if (!ValidateCredentials(username, password, camType))
{
throw new Exception("Invalid credentials");
}
}
catch
{
context.Response.AddHeader("WWW-Authenticate", "Basic realm=\"FakeCamera\"");
await HTTPReplySetup(context, "", 401, "text/plain");
return;
}
}
try
{
if (Method == "GET")
{
if (path.Equals("/Infrared/led-controls")) // Works
{
string[] allowedPowers = ["LOW", "MID", "HIGH", "SAFE", "OFF"];
string power = context.Request.QueryString["power"]?.ToUpper();
if (allowedPowers.Contains(power))
await HTTPReplySetup(context, "Power levels set successfully", 200, "text/plain");
else
await HTTPReplySetup(context, "Power level not accepted", 400, "text/plain");
}
else if (path.Equals("/api/versions"))
{
string versionsJson = File.ReadAllText(camType switch
{
CAMTYPE.GOOD => $"{JSONLoc}Versions.json",
CAMTYPE.BAD => $"{JSONLoc}Versions_Bad.json",
CAMTYPE.BIZARRE => $"{JSONLoc}Versions_Bizarre.json",
_ => throw new ArgumentOutOfRangeException()
});
Versions vers = JsonConvert.DeserializeObject<Versions>(versionsJson);
vers.timeStamp = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
versionsJson = JsonConvert.SerializeObject(vers);
await HTTPReplySetup(context, versionsJson, 200, "application/json");
}
else if (path.Equals("/api/diagnostics"))
{
string filePath = camType switch
{
CAMTYPE.GOOD => $"{JSONLoc}Diagnostics.json",
CAMTYPE.BAD => $"{JSONLoc}Diagnostics_Bad.json",
CAMTYPE.BIZARRE => $"{JSONLoc}Diagnostics_Bizarre.json",
_ => throw new ArgumentOutOfRangeException()
};
string diagsJson = File.ReadAllText(filePath);
if (camType == CAMTYPE.GOOD)
{
Diags diags = JsonConvert.DeserializeObject<Diags>(diagsJson);
diags.timeStamp = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
diagsJson = JsonConvert.SerializeObject(diags);
}
await HTTPReplySetup(context, diagsJson, 200, "application/json");
}
else if (path.Equals("/api/zoomLock")) // Fixed
{
string enable = context.Request.QueryString["enable"];
if (!string.IsNullOrEmpty(enable) && enable.Equals("true", StringComparison.OrdinalIgnoreCase)) // FIXED Use http://localhost:8080/api/zoomLock?enable=true
{
await HTTPReplySetup(context, "Zoom lock enabled.", 200, "text/plain");
}
else if (!string.IsNullOrEmpty(enable) && enable.Equals("false", StringComparison.OrdinalIgnoreCase)) // FIXED Use http://localhost:8080/api/zoomLock?enable=false
{
await HTTPReplySetup(context, "Zoom lock disabled.", 200, "text/plain");
}
else
{
await HTTPReplySetup(context, "Missing or invalid 'enable' parameter.", 400, "text/plain");
}
}
else if (path.Equals("/Infrared-camera-factory-reset") || path.Equals("/Colour-camera-factory-reset")) // WORKS
{
await HTTPReplySetup(context, "Factory reset OK.", 200, "text/plain");
}
else if (path.Equals("/Infrared-camera-control") || path.Equals("/Colour-camera-control")) // Fixed
{
string viscaReply = "9041FF9051FF";
if (!RegexCache.VISCARegex().IsMatch(context.Request.QueryString["commandHex"]))
viscaReply = "9060FF";
await HTTPReplySetup(context, viscaReply, 200, "text/plain");
}
else if (path.Equals("/SightingCreator-plate-positions")) //Works
{
string trimJson = File.ReadAllText($"{JSONLoc}Trim.json");
await HTTPReplySetup(context, trimJson, 200, "application/json");
}
else if (path.Equals("/Infrared-snapshot")) // Fixed
{
string jpegPath;
if (!Snapshot)
{
jpegPath = $"{JSONLoc}IR_Open_image.jpg"; // Light Image
Snapshot = true;
}
else
{
jpegPath = $"{JSONLoc}IR_Tight_image.jpg"; // Dark Image
}
byte[] jpegBytes = File.ReadAllBytes(jpegPath);
await HTTPReplySetup(context, jpegBytes, 200, "image/jpeg");
}
else if (path.Equals("/Colour-snapshot")) // Fixed
{
byte[] jpegBytes = File.ReadAllBytes($"{JSONLoc}OV_image.jpg");
await HTTPReplySetup(context, jpegBytes, 200, "image/jpeg");
}
else if (path.Equals("/api/fetch-config"))
{
ConfigObject config = JsonConvert.DeserializeObject<ConfigObject>(Content);
if (config.Id == "GLOBAL--NetworkConfig")
{
// TODO - Return success message?
}
else
{
await HTTPReplySetup(context, "ID not valid.", 200, "text/plain");
}
}
else if (path.Equals("/api/RaptorOCR-auto-license")) // Works
{
string vaxtorJson = "{ \"protectionKeyId\":\"123456789012345678\" }";
await HTTPReplySetup(context, vaxtorJson, 200, "application/json");
}
else
{
await HTTPReplySetup(context, $"GET request for {path} not supported", 400, "text/plain");
}
}
else if (Method == "POST")
{
if (path.Equals("/api/update-config"))
{
ConfigObject fo = JsonConvert.DeserializeObject<ConfigObject>(Content);
if (fo.Id == "GLOBAL--NetworkConfig" || fo.Id == "SightingCreator" || fo.Id == "RaptorOCR")
{
await HTTPReplySetup(context, "Update successful.", 200, "text/plain");
}
else if (fo.Id == "Internal Config")
{
string SerialNumber = "";
string ModelNumber = "";
fo.Fields.ForEach(field =>
{
if (field.Property == "propSerialNumber")
SerialNumber = field.Value;
else if (field.Property == "propMavModelNumber")
ModelNumber = field.Value;
});
// Update JSON with new SerialNumber and ModelNumber beofre sending back to the client
using StreamReader r = new($"{JSONLoc}InternalConfig.json");
string InternalConfig_JSON = r.ReadToEnd();
InternalConfig_JSON = InternalConfig_JSON.Replace("SSSSSS", SerialNumber).Replace("MMMMMM", ModelNumber);
HTTPReplySetup(context, InternalConfig_JSON, 200, "application/json");
}
else
{
await HTTPReplySetup(context, "ID not valid.", 200, "text/plain");
}
}
else
{
await HTTPReplySetup(context, $"POST request for {path} not supported.", 400, "text/plain");
}
}
else
{
await HTTPReplySetup(context, "Bad Request.", 400, "text/plain");
}
}
catch (Exception ex)
{
await HTTPReplySetup(context, $"Server error: {ex.Message}", 500, "text/plain");
MainForm.Instance.AddToActionsList($"Server error handling {Method} {path}: {ex.Message}");
}
}
public class ConfigObject
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("fields")]
public List<Field> Fields { get; set; }
}
public class Field
{
[JsonProperty("property")]
public string Property { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,40 @@
{
"id": "GLOBAL",
"configHash": "1698097425",
"propPipelineFile": {
"value": "DUAL_CAMERA_BASIC_ANPR.json",
"datatype": "java.lang.String"
},
"propPipelineLocked": {
"value": "false",
"datatype": "boolean"
},
"propUpdateDisabled": {
"value": "false",
"datatype": "boolean"
},
"propSerialNumber": {
"value": "SSSSSS",
"datatype": "java.lang.String"
},
"propMavModelNumber": {
"value": "MMMMMM",
"datatype": "java.lang.String"
},
"propHardwareIdentifiers": {
"value": "N/A",
"datatype": "java.lang.String"
},
"propStartupWaitMillis": {
"value": "5000",
"datatype": "long"
},
"propGodMode": {
"value": "true",
"datatype": "boolean"
},
"propYUY2ByteArrayPoolSize": {
"value": "0",
"datatype": "int"
}
}

BIN
FakeCamera/OV_image.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

6
FakeCamera/Trim.json Normal file
View File

@@ -0,0 +1,6 @@
{
"infraredX": 1197,
"infraredY": 792,
"colourX": 1167,
"colourY": 806
}

12
FakeCamera/Versions.json Normal file
View File

@@ -0,0 +1,12 @@
{
"version": "1.6.4",
"revision": "77e042f",
"buildtime": "2025-07-24T10:35:36.445241784Z",
"appname": "FlexiAI",
"MAC": "3C:6D:66:0A:BA:18",
"timeStamp": 1754296711,
"UUID": "b7c1ab51-4543-4b1b-8f05-2697905047ff",
"proquint": "hijag-hosir",
"Serial No.": "K1005001",
"Model No.": "AB12CD"
}

View File

@@ -0,0 +1,12 @@
{
"version": "1.2",
"revision": "77e042f",
"buildtime": "2025-07-24T10:35:36.445241784Z",
"appname": "FlexiAI",
"MAC": "3C:6D:66:0A:BA:18",
"timeStamp": 1754296711,
"UUID": "b7c1ab51-4543-4b1b-8f05-2697905047ff",
"proquint": "hijag-hosir",
"Serial No.": "K1005001",
"Model No.": "AB12CD"
}

View File

@@ -0,0 +1,12 @@
{
"version": "BAAAAAAA",
"revision": "77e042f",
"buildtime": "2025-07-24T10:35:36.445241784Z",
"appname": "",
"MAC": "-1",
"timeStamp": 1754296711,
"UUID": "b7c1ab51-4543-4b1b-8f05-2697905047ff",
"proquint": "hijag-hosir",
"Serial No.": "K1005001",
"Model No.": "31"
}