diff --git a/AiQ_GUI.Designer.cs b/AiQ_GUI.Designer.cs index 1b71868..9d140da 100644 --- a/AiQ_GUI.Designer.cs +++ b/AiQ_GUI.Designer.cs @@ -144,6 +144,8 @@ namespace AiQ_GUI BtnZoom8000 = new Button(); BtnZoomWide = new Button(); TabSettings = new TabPage(); + UploadWonwooSetIR = new Button(); + UploadWonwooSetOV = new Button(); BtnAdminStart = new Button(); BtnFirewall = new Button(); TabImages = new TabPage(); @@ -587,6 +589,7 @@ namespace AiQ_GUI BtnTest.TabIndex = 189; BtnTest.Text = "Test"; BtnTest.UseVisualStyleBackColor = false; + BtnTest.Visible = false; BtnTest.Click += BtnTest_Click; // // PicBxIRF2 @@ -1835,6 +1838,8 @@ namespace AiQ_GUI // TabSettings // TabSettings.BackColor = Color.FromArgb(39, 37, 55); + TabSettings.Controls.Add(UploadWonwooSetIR); + TabSettings.Controls.Add(UploadWonwooSetOV); TabSettings.Controls.Add(BtnAdminStart); TabSettings.Controls.Add(BtnFirewall); TabSettings.Controls.Add(PanelSettings); @@ -1845,6 +1850,40 @@ namespace AiQ_GUI TabSettings.TabIndex = 3; TabSettings.Text = "Settings"; // + // UploadWonwooSetIR + // + UploadWonwooSetIR.BackColor = Color.FromArgb(70, 65, 80); + UploadWonwooSetIR.FlatAppearance.BorderColor = Color.FromArgb(70, 65, 80); + UploadWonwooSetIR.FlatAppearance.BorderSize = 0; + UploadWonwooSetIR.FlatStyle = FlatStyle.Flat; + UploadWonwooSetIR.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold); + UploadWonwooSetIR.ForeColor = SystemColors.Control; + UploadWonwooSetIR.Location = new Point(210, 304); + UploadWonwooSetIR.Margin = new Padding(4, 3, 4, 3); + UploadWonwooSetIR.Name = "UploadWonwooSetIR"; + UploadWonwooSetIR.Size = new Size(180, 49); + UploadWonwooSetIR.TabIndex = 244; + UploadWonwooSetIR.Text = "Upload Wonwoo Settings IR"; + UploadWonwooSetIR.UseVisualStyleBackColor = false; + UploadWonwooSetIR.Click += UploadWonwooSetIR_Click; + // + // UploadWonwooSetOV + // + UploadWonwooSetOV.BackColor = Color.FromArgb(70, 65, 80); + UploadWonwooSetOV.FlatAppearance.BorderColor = Color.FromArgb(70, 65, 80); + UploadWonwooSetOV.FlatAppearance.BorderSize = 0; + UploadWonwooSetOV.FlatStyle = FlatStyle.Flat; + UploadWonwooSetOV.Font = new Font("Segoe UI Semibold", 10F, FontStyle.Bold); + UploadWonwooSetOV.ForeColor = SystemColors.Control; + UploadWonwooSetOV.Location = new Point(19, 304); + UploadWonwooSetOV.Margin = new Padding(4, 3, 4, 3); + UploadWonwooSetOV.Name = "UploadWonwooSetOV"; + UploadWonwooSetOV.Size = new Size(181, 49); + UploadWonwooSetOV.TabIndex = 243; + UploadWonwooSetOV.Text = "Upload Wonwoo Settings OV"; + UploadWonwooSetOV.UseVisualStyleBackColor = false; + UploadWonwooSetOV.Click += UploadWonwooSetOV_Click; + // // BtnAdminStart // BtnAdminStart.BackColor = Color.FromArgb(70, 65, 80); @@ -2210,5 +2249,7 @@ namespace AiQ_GUI private Button BtnAdminStart; private Button SetGodModeAll; private Button BtnFactoryDefault; + private Button UploadWonwooSetOV; + private Button UploadWonwooSetIR; } } diff --git a/AiQ_GUI.cs b/AiQ_GUI.cs index ce5b312..a026bef 100644 --- a/AiQ_GUI.cs +++ b/AiQ_GUI.cs @@ -18,6 +18,8 @@ namespace AiQ_GUI private List soakCameraList = []; private List soakCtsList = []; private List soakTasks = []; + + const string GoogleDrivePath = @"G:\Shared drives\MAV Production GUI's\AiQ\GUI's\"; // Colours public static readonly Color BtnColour = Color.FromArgb(70, 65, 80); @@ -304,7 +306,7 @@ namespace AiQ_GUI { // Turn off God mode string[,] GOD_JSON = { { "propGodMode", "false" } }; - string IntConf = await FlexiAPI.HTTP_Update("Internal Config", CamOnTest.IP, GOD_JSON); + string IntConf = await FlexiAPI.HTTP_Update("GLOBAL--FlexiApplication", CamOnTest.IP, GOD_JSON); if (!IntConf.Contains("\"propGodMode\": {\"value\": \"false\", \"datatype\": \"boolean\"},")) AddToActionsList("Could not turn off God mode"); @@ -925,7 +927,7 @@ namespace AiQ_GUI try { - await FlexiAPI.HTTP_Update("Internal Config", CamOnTest.IP, GOD_JSON); + await FlexiAPI.HTTP_Update("GLOBAL--FlexiApplication", CamOnTest.IP, GOD_JSON); BtnSetGodMode.Text = newGodModeValue == "true" ? "Set God Mode Off" : "Set God Mode On"; BtnSetGodMode.BackColor = Color.Green; } @@ -1171,7 +1173,7 @@ namespace AiQ_GUI try { Network.Initialize("developer", SCL.DevPass); // Ensure network is initialized to the right camera - string RESP = await FlexiAPI.HTTP_Update("Internal Config", SCL.IP, GOD_JSON); + string RESP = await FlexiAPI.HTTP_Update("GLOBAL--FlexiApplication", SCL.IP, GOD_JSON); Instance.AddToActionsList($"Setting God mode for camera {SCL.IP} to {newGodModeValue}", false); } catch (Exception ex) @@ -1580,12 +1582,27 @@ namespace AiQ_GUI { if (!SCL.IsChecked) continue; + try + { + 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); // Reset camera modules - 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); + string[,] godJson = { { "propGodMode", "false" } }; // Set God mode explicitly off + string GOD = await FlexiAPI.HTTP_Update("GLOBAL--FlexiApplication", SCL.IP, godJson); + if (GOD.Contains("Error")) + throw new Exception("Could not set God mode off"); + + bool Pass = await FlexiAPI.ChangeNetwork211(SCL.IP); // set camera to 211 + if (!Pass) + throw new Exception("Could not set camera to 211"); + } + catch (Exception ex) + { + AddToActionsList("Failed to set God mode, reset camera modules or 211 for camera " + SCL.IP + ". Reason: " + ex.Message); + } } } - } + } private void CkBxTickAll_CheckedChanged(object sender, EventArgs e) { @@ -1668,7 +1685,7 @@ namespace AiQ_GUI { string apiUrl = $"http://{cam.IP}/upload/software-update/2"; Network.Initialize("developer", cam.DevPass); - + await Task.Delay(1000); // Gives extra time to allow for Network to initialize AddToActionsList($"Uploading to {cam.IP}...", false); string result = await FlexiAPI.SendBlobFileUpload(apiUrl, fileToUpload, fileName); @@ -1706,11 +1723,122 @@ namespace AiQ_GUI { Stopwatch stopWatchTest = Stopwatch.StartNew(); - StatsExcel excelExporter = new(); - excelExporter.ExportDatabaseToExcel(); + //StatsExcel excelExporter = new(); + //excelExporter.ExportDatabaseToExcel(); + + FakeCamera fakeCamera = new FakeCamera(80); // Create an instance of FakeCamera + //CamOnTest.IP = CbBxFoundCams.Text; + _ = fakeCamera.StartAsync(CAMTYPE.GOOD).ContinueWith(task => + { + //Network.Initialize("developer", "Pass123"); + if (task.IsFaulted) + { + AddToActionsList("Error starting FakeCamera: " + task.Exception?.Message); + } + else + { + AddToActionsList($"FakeCamera started successfully. IP: {fakeCamera}", false); + } + }); + await Task.Delay(3000); // Wait for server to start + CbBxFoundCams.Text = "localhost"; // Should force update in creds an network reinit + CmBoFoundCams_TextChanged(sender, e); + CbBxCameraType.SelectedIndex = CbBxCameraType.Items.Count - 1; // Selects AB12CD as model number + await Task.Delay(3000); // Wait for server to start + BtnStartTest_Click(sender, e); stopWatchTest.Stop(); AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff")); + + } + + private async Task UploadWonwooSet(string ipAddress, bool isIR) + { + string fileToUpload = null; + + using OpenFileDialog openFileDialog1 = new() + { + InitialDirectory = GoogleDrivePath, + Filter = "CSV files (*.csv)|*.csv", + FilterIndex = 0 + }; + + if (openFileDialog1.ShowDialog() == DialogResult.OK) + fileToUpload = openFileDialog1.FileName; + else + { + AddToActionsList("File selection cancelled.", false); + return; + } + + //Filename validation + string filename = Path.GetFileName(fileToUpload).ToUpper(); + + if (isIR) + { + if (!filename.Contains("IR") || filename.Contains("OV")) + { + AddToActionsList("Incorrect file selected. Expected IR file.", false); + return; + } + } + else // OV + { + if (!filename.Contains("OV") || filename.Contains("IR")) + { + AddToActionsList("Incorrect file selected. Expected OV file.", false); + return; + } + } + + var lines = File.ReadAllLines(fileToUpload); + + for (int i = 1; i < lines.Length; i++) + { + var parts = lines[i].Split(',') + .Select(p => p.Trim()) + .ToArray(); + + if (parts.Length < 3) + { + AddToActionsList($"Invalid row format at line {i + 1}", false); + continue; + } + + string name = parts[0]; + string command = parts[1]; + string expectedResponse = parts[2]; + + // VISCA format check + if (!RegexCache.VISCAAPIRegex().IsMatch(command)) + { + AddToActionsList($"{name}: Invalid VISCA command ({command})", false); + continue; // do not send it if bad + } + + string result = await FlexiAPI.APIHTTPVISCA(ipAddress, command, isIR); + + if (result.Contains(expectedResponse)) + AddToActionsList($"{name}: Success ({(isIR ? "IR" : "Colour")})", true); + else + AddToActionsList($"{name}: Unexpected response ({result})", false); + + await Task.Delay(150); + } + + + AddToActionsList($"Upload complete ({(isIR ? "IR" : "Colour")}).", true); + } + + + private async void UploadWonwooSetOV_Click(object sender, EventArgs e) + { + await UploadWonwooSet(CbBxFoundCams.Text, false); // false = Colour + } + + private async void UploadWonwooSetIR_Click(object sender, EventArgs e) + { + await UploadWonwooSet(CbBxFoundCams.Text, true); // true = Infrared } } } diff --git a/Camera/FlexiAPI.cs b/Camera/FlexiAPI.cs index 8bb572e..c50aab9 100644 --- a/Camera/FlexiAPI.cs +++ b/Camera/FlexiAPI.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System.Net.Http.Headers; +using System.Net.NetworkInformation; namespace AiQ_GUI { @@ -36,9 +37,9 @@ namespace AiQ_GUI { 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"; return await Network.SendHttpRequest(url, HttpMethod.Post, 2, JSONdata); + } catch (Exception ex) { @@ -354,12 +355,24 @@ namespace AiQ_GUI } // Change network settings to DHCP and restart camera for it to take effect - public async static Task ChangeNetworkToDHCP(string IPAddress) + public async static Task ChangeNetworkToDHCP(string IPAddress) { - string[,] TEST_JSON = { { "propDHCP", "true" } }; // Update GLOBAL--NetworkConfig with fixed IP and turn off DHCP - await HTTP_Update("GLOBAL--NetworkConfig", IPAddress, TEST_JSON); - // TODO - Check if this worked, if not return false + string[,] TEST_JSON = { { "propDHCP", "true" } }; + string result = await HTTP_Update("GLOBAL--NetworkConfig", IPAddress, TEST_JSON); + + await Task.Delay(5000); // Wait for 5 seconds to allow the camera to restart + IList FoundCams = await Network.SearchForCams(); + + if (FoundCams.Contains("192.168.1.211")) + { + MainForm.Instance.AddToActionsList("Could not set camera to DHCP please check camera."); + return false; + } + + MainForm.Instance.AddToActionsList("Camera successfully set to DHCP."); + return true; } + } //Items recieved in Versions API diff --git a/FakeCamera/Diagnostics.json b/FakeCamera/Diagnostics.json index 0cc34cb..28bbc14 100644 --- a/FakeCamera/Diagnostics.json +++ b/FakeCamera/Diagnostics.json @@ -1,7 +1,7 @@ { "cameraName": "AiQ-ANPR-Camera", - "version": "1.6.4", - "revision": "bf16134", + "version": "1.7.1", + "revision": "4b63df5", "serialNumber": "K1005001", "modelNumber": "AB12CD", "MAC": "3C:6D:66:0A:BA:18", diff --git a/FakeCamera/FakeCamera.cs b/FakeCamera/FakeCamera.cs index e14ef55..1a91f16 100644 --- a/FakeCamera/FakeCamera.cs +++ b/FakeCamera/FakeCamera.cs @@ -293,7 +293,7 @@ namespace AiQ_GUI { await HTTPReplySetup(context, "Update successful.", 200, "text/plain"); } - else if (fo.Id == "Internal Config") + else if (fo.Id == "GLOBAL--FlexiApplication") { string SerialNumber = ""; string ModelNumber = ""; diff --git a/Network.cs b/Network.cs index e581920..175e8ce 100644 --- a/Network.cs +++ b/Network.cs @@ -10,7 +10,7 @@ namespace AiQ_GUI public static HttpClient? SingleHTTPClient; public static HttpClient Client => SingleHTTPClient ?? throw new InvalidOperationException("Client not initialized."); - public static void Initialize(string username, string password) + public async static void Initialize(string username, string password) { HttpClientHandler handler = new() { @@ -23,6 +23,21 @@ namespace AiQ_GUI { Timeout = TimeSpan.FromSeconds(20) }; + + bool UP = false; + int i = 0; + + while (!UP) + { + UP = await PingIP("10.10.10.137"); + await Task.Delay(500); + if (i >= 5) + { + //MainForm.Instance.AddToActionsList($"Could not initialise new network with USER: {username} & PSWD: {password}"); + return; // Try 5 times max + } + i++; + } } // Handles get and post to the camera API