2025-12-22 14:37:43 +00:00
using AiQ_GUI.AiQ_Tests ;
using Newtonsoft.Json ;
2025-09-02 15:32:24 +01:00
using System.ComponentModel ;
using System.Diagnostics ;
2025-12-22 14:37:43 +00:00
using System.Net.Http.Json ;
2025-09-02 15:32:24 +01:00
using System.Reflection ;
2025-12-22 14:37:43 +00:00
using System.Text.Json ;
using System.Windows.Forms ;
2025-09-02 15:32:24 +01:00
namespace AiQ_GUI
{
2025-11-26 14:39:07 +00:00
public enum Level
{
ERROR ,
WARNING ,
2025-12-02 12:59:40 +00:00
LOG ,
Success
2025-11-26 14:39:07 +00:00
}
2025-09-02 15:32:24 +01:00
public partial class MainForm : Form
{
// Classes
LocalDataStore localDataStore = new ( ) ;
2025-12-22 14:37:43 +00:00
//public Diags DiagsAPI = new();
2025-09-02 15:32:24 +01:00
VaxtorLic VaxtorLicResp = new ( ) ;
2025-12-22 14:37:43 +00:00
public Versions Vers = new ( ) ;
public readonly Camera CamOnTest = new ( ) ;
public SSHData sshData = new ( ) ;
2025-09-02 15:32:24 +01:00
private List < Camera > soakCameraList = [ ] ;
private List < CancellationTokenSource > soakCtsList = [ ] ;
private List < Task > soakTasks = [ ] ;
2025-11-04 14:29:38 +00:00
2025-09-02 15:32:24 +01:00
// Colours
public static readonly Color BtnColour = Color . FromArgb ( 70 , 65 , 80 ) ;
public static readonly Color TxBxColour = Color . FromArgb ( 53 , 51 , 64 ) ;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public static MainForm ? Instance { get ; private set ; }
2025-12-22 14:37:43 +00:00
private TabPage CurrentTab ; // remember what's currently inserted
2025-09-02 15:32:24 +01:00
public MainForm ( )
{
InitializeComponent ( ) ;
Instance = this ;
}
private async void AiQGUI_Load ( object sender , EventArgs e )
{
Task ? closeProcessesTask = Windows . CloseProcesses ( ) ; // Fire and forget closing other apps
2025-10-28 12:35:28 +00:00
Windows . UpdateFirewall ( ) ;
2025-09-02 15:32:24 +01:00
Task UniDataTask = Task . Run ( ( ) = > Access . ReadUniData ( ) ) ; // Get universal data
2025-11-26 14:39:07 +00:00
Task < LocalDataStore > LDSWAIT = Task . Run ( ( ) = > LDS . GetLDS ( ) ) ; // Get and deserialise LDS.json
Task < string > guiVerTask = Task . Run ( ( ) = > GUIUpdate . FindGUIVersion ( ) ) ; // Get GUI Version
2025-09-02 15:32:24 +01:00
2025-12-02 11:02:24 +00:00
Network . Initialize ( "admin" , "admin" ) ; // Initialise HTTP client with basic auth creds.
2025-09-02 15:32:24 +01:00
if ( await Network . PingIP ( "8.8.8.8" ) ) // Ping to check if we're online
{
if ( ! GoogleAPI . Setup ( ) )
2025-11-26 14:39:07 +00:00
AddToActionsList ( "Cannot setup Google API" , Level . WARNING ) ;
2025-09-02 15:32:24 +01:00
}
else
{
Flags . Offline = true ;
BtnStartTest . Text = "Offline Mode" ;
}
2025-12-22 14:37:43 +00:00
// Hide on default so will only show based on the camera type selected later
TabImagesandSettings . TabPages . Remove ( TabSoak ) ;
TabImagesandSettings . TabPages . Remove ( Mobile ) ;
2025-09-02 15:32:24 +01:00
GUIUpdate . GUIVerShort = await guiVerTask ; // Guess the GUI version will be first to finish
this . Name = "AiQ GUI V" + GUIUpdate . GUIVerShort ;
LblGUIVers . Text + = GUIUpdate . GUIVerShort ;
await UniDataTask ; // Have to wait for expected GUI version to compare to.
GUIUpdate . UpdateGUI ( ) ; // Check if a GUI update is available
// Load local data store
localDataStore = await LDSWAIT ;
Logging . LogMessage ( "Opening GUI" ) ; // Done after LDS to make sure directory exists.
2025-11-26 14:39:07 +00:00
2025-09-02 15:32:24 +01:00
if ( localDataStore = = null )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Could not deserialise LDS.json please help!" , Level . WARNING ) ;
2025-09-02 15:32:24 +01:00
return ;
}
Task CheckHWOnline = PingCheck ( ) ; // Async check all hardware is online
PopulateUIWithLDS ( localDataStore ) ; // Update fields that depend on LDS
2025-12-19 16:14:13 +00:00
CbBxCameraModel . Text = localDataStore . LastModel ; // Set last model that was tested into combobox
2025-09-02 15:32:24 +01:00
BtnSave . BackColor = BtnSave . Enabled ? Color . ForestGreen : BtnSave . BackColor ; // Sets the colour of the save button depending on if it is enabled.
BtnRefreshUnix_Click ( sender , e ) ; // Reset timestamp
if ( RegexCache . FlexiVerRegex ( ) . IsMatch ( UniversalData . ExpFlexiVer ) ) // Update Flexi version from universal data
TxBxFlexiVer . Text = UniversalData . ExpFlexiVer ;
await CheckHWOnline ;
Flags . Start = false ;
2025-12-22 14:37:43 +00:00
2025-09-02 15:32:24 +01:00
}
2025-12-22 14:37:43 +00:00
private void InsertCamTab ( string camType )
2025-12-19 16:14:13 +00:00
{
2025-12-22 14:37:43 +00:00
// Remove previously inserted tab if present
if ( CurrentTab ! = null & & TabImagesandSettings . TabPages . Contains ( CurrentTab ) )
TabImagesandSettings . TabPages . Remove ( CurrentTab ) ;
// Choose desired tab
TabPage desired = null ;
if ( camType = = "Mobile" ) desired = Mobile ;
else if ( camType = = "AiQ" ) desired = TabSoak ;
// Insert desired tab if any
if ( desired ! = null & & ! TabImagesandSettings . TabPages . Contains ( desired ) )
{
int idx = Math . Min ( 3 , TabImagesandSettings . TabPages . Count ) ;
TabImagesandSettings . TabPages . Insert ( idx , desired ) ;
CurrentTab = desired ;
}
else
{
CurrentTab = desired ; // may be null
}
}
2025-12-19 16:14:13 +00:00
2025-12-22 14:37:43 +00:00
private async void CbBxCamType_SelectedIndexChanged ( object sender , EventArgs e )
{
CbBxCameraModel . Items . Clear ( ) ;
2025-12-19 16:14:13 +00:00
2025-12-22 14:37:43 +00:00
var camType = CbBxCamType . Text ;
InsertCamTab ( camType ) ;
2025-12-19 16:14:13 +00:00
2025-12-22 14:37:43 +00:00
var models = await Task . Run ( ( ) = > Access . ReadCamTypes ( camType ) ) ;
2025-12-19 16:14:13 +00:00
if ( models ! = null & & models . Length > 0 )
CbBxCameraModel . Items . AddRange ( models ) ;
}
2025-09-02 15:32:24 +01:00
private void PopulateUIWithLDS ( LocalDataStore lds )
{
CbBxUserName . Text = lds . User ;
TxBxPsuIP . Text = PSU . PSUIP = lds . PSUIP ;
TxBxEzIP . Text = Ez . PoEPowerIP = lds . EzIP ;
TxBxZebraIP . Text = Printer . ZebraIP = lds . ZebraIP ;
TxBxTestTubeIP . Text = TestTube . TTPiPicoIP = lds . TestTubeIP ;
CbBxShutter . SelectedIndex = lds . Shutter ;
CbBxIris . SelectedIndex = lds . Iris ;
CbBxGain . SelectedIndex = lds . Gain ;
2025-10-20 10:31:58 +01:00
if ( lds . User = = "Bradley" | | lds . User = = "Sophie" )
2025-09-02 15:32:24 +01:00
BtnTest . Visible = true ;
TxBxCheckValid ( TxBxPsuIP ) ; // Set save button color if valid
}
private async void MainForm_Shown ( object sender , EventArgs e ) // Done on show as all UI elements are loaded in properly for find cams to use
{
BtnFindCams_Click ( sender , e ) ;
CheckPrintCapable ( ) ; // Check if the print buttons can be enabled
TestStartConditions ( ) ;
await Task . Delay ( 1000 ) ; // Delay for UI to catch up
if ( LblPSUPing . ForeColor = = Color . ForestGreen ) // Check state of PSU if it is connected.
Task . Run ( ( ) = > PSU . DisplayState ( PSU . PSUIP ) ) ;
}
// ***** Test buttons *****
private async void BtnStartTest_Click ( object sender , EventArgs e )
{
// Show user test has started
BtnStartTest . BackColor = Color . Orange ;
BtnStartTest . Text = "Test underway" ;
BtnPreTest . Enabled = BtnStartTest . Enabled = false ; // Disable buttons to stop user rnning multiple tests at the same time.
Logging . LogMessage ( "Final Test Started" ) ;
2025-12-23 13:01:15 +00:00
if ( CbBxCamType . Text = = "AiQ" )
2025-09-02 15:32:24 +01:00
{
2025-12-23 13:01:15 +00:00
await AiQTests . AiQFinalTest ( ) ;
2025-09-02 15:32:24 +01:00
}
2025-12-23 13:01:15 +00:00
else if ( CbBxCamType . Text = = "Mobile" )
2025-09-02 15:32:24 +01:00
{
2025-12-22 14:37:43 +00:00
await PreTestPassed ( ) ;
2025-09-02 15:32:24 +01:00
}
}
2025-10-17 12:06:36 +01:00
2025-09-02 15:32:24 +01:00
private async void BtnPreTest_Click ( object sender , EventArgs e )
{
// Show user test has started
BtnPreTest . BackColor = Color . Orange ;
BtnPreTest . Text = "Pre-Test underway" ;
2025-12-22 14:37:43 +00:00
BtnPreTest . Enabled = BtnStartTest . Enabled = false ; // Disable buttons to stop user running multiple tests at the same time.
2025-09-02 15:32:24 +01:00
Logging . LogMessage ( "Pre Test Started" ) ;
2025-12-22 14:37:43 +00:00
if ( CbBxCamType . Text = = "AiQ" )
2025-09-02 15:32:24 +01:00
{
2025-12-23 13:01:15 +00:00
await AiQTests . AiQPreTest ( ) ;
2025-09-02 15:32:24 +01:00
}
2025-12-22 14:37:43 +00:00
else if ( CbBxCamType . Text = = "Mobile" )
2025-10-17 12:06:36 +01:00
{
2025-12-22 14:37:43 +00:00
await PreTestPassed ( ) ;
2025-10-17 12:06:36 +01:00
}
2025-09-02 15:32:24 +01:00
}
// ***** Pass/Fails *****
2025-12-22 14:37:43 +00:00
public async Task TestPassed ( DateTime PCTime )
2025-09-02 15:32:24 +01:00
{
// Updates Vaxtor versions, licenses and unticks WIP
2025-12-22 14:37:43 +00:00
string err = GoogleAPI . UpdateSpreadSheetFinalTest ( CameraAccessInfo . SpreadsheetID , TestingFunctions . DiagsAPI , sshData , CamOnTest . RMANum ) ;
2025-09-02 15:32:24 +01:00
if ( err ! = string . Empty ) // If there is an error message, display it
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Failed to write to spreadsheet " + err , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
// Purge camera of all reads
await FlexiAPI . APIHTTPRequest ( "/api/purge-all" , CamOnTest . IP ) ;
2025-10-17 14:26:33 +01:00
if ( await DisplayQuestion ( "Do you want to set this camera to 211 and God mode off?" ) )
2025-09-02 15:32:24 +01:00
{
// Turn off God mode
string [ , ] GOD_JSON = { { "propGodMode" , "false" } } ;
2025-11-04 13:16:07 +00:00
string IntConf = await FlexiAPI . HTTP_Update ( "GLOBAL--FlexiApplication" , CamOnTest . IP , GOD_JSON ) ;
2025-09-02 15:32:24 +01:00
if ( ! IntConf . Contains ( "\"propGodMode\": {\"value\": \"false\", \"datatype\": \"boolean\"}," ) )
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Could not turn off God mode" , Level . WARNING ) ;
2025-09-02 15:32:24 +01:00
Thread Thr211 = new ( async ( ) = >
{
if ( ! await FlexiAPI . ChangeNetwork211 ( CamOnTest . IP ) ) // Change camera IP to 192.168.1.211. Waits for camera to come back.
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Could not find camera at 192.168.1.211. Please check manually" , Level . WARNING ) ;
2025-09-02 15:32:24 +01:00
} ) ;
Thr211 . IsBackground = true ;
Thr211 . Start ( ) ;
}
this . Refresh ( ) ; // To make sure all labels are up to date before reading them
string fulltestvalues = $"GUI Version = {GUIUpdate.GUIVerShort}\n" +
string . Join ( "\n" , PnlLbls . Controls
. OfType < Label > ( )
. Where ( lbl = > lbl . Visible ) // Only include visible labels
. OrderBy ( lbl = > lbl . Location . Y ) // Sort from top to bottom
. Select ( lbl = > lbl . Text ) ) ; // Get the text of each label
fulltestvalues + = Helper . GetOverriddenActions ( PnlLbls , RhTxBxActions ) ;
// TODO make sure serial number is in CamOnTest before making PDF
// Serial number is either what came out of the camera under RMA or updated above as new serial number from next empty row in spreadsheet
PDF . CreateFinalTestReport ( CamOnTest , CbBxUserName . Text , fulltestvalues , PCTime ) ;
// Indicators to the user the test has passed
BtnStartTest . BackColor = Color . ForestGreen ;
BtnStartTest . Text = "Test Passed" ;
PnlQuestion . Visible = false ; // just in case this came from an override
Logging . LogMessage ( "Final Test Passed" ) ;
2025-11-26 14:39:07 +00:00
2025-10-17 12:06:36 +01:00
if ( CamOnTest . RMANum = = 0 ) // Yap to check if it is not a RMA
2025-10-21 15:46:28 +01:00
Access . Stats ( "Final Tests Passed" , CamOnTest . Model ) ;
2025-10-17 12:06:36 +01:00
else
2025-10-21 15:46:28 +01:00
Access . Stats ( "RMA Final Tests Passed" , CamOnTest . Model ) ;
2025-09-02 15:32:24 +01:00
}
public async Task TestFailed ( Button Btn , string ErrMssg )
{
// Indicators to the user the test has failed
Btn . BackColor = Color . Maroon ;
Btn . Text = "Test Failed" ;
2025-10-17 12:06:36 +01:00
2025-10-20 10:31:58 +01:00
if ( ! ( CamOnTest . RMANum ! = 0 ) ) // Yap to check if it is not a RMA
2025-10-28 16:13:05 +00:00
Access . Stats ( [ "Final Tests Failed" , ErrMssg ] , CamOnTest . Model ) ;
2025-10-20 10:31:58 +01:00
else
2025-10-28 16:13:05 +00:00
Access . Stats ( "RMA Final Tests Failed" , CamOnTest . Model ) ;
2025-11-26 14:39:07 +00:00
2025-12-02 12:59:40 +00:00
AddToActionsList ( ErrMssg , Level . ERROR ) ;
2025-10-28 16:13:05 +00:00
string RedLbls = string . Join ( Environment . NewLine , PnlLbls . Controls
. OfType < Label > ( )
. Where ( lbl = > lbl . ForeColor = = Color . Red ) // Only include red labels
. Select ( lbl = > lbl . Text ) ) ; // Extract text
string FullFailureValues = RhTxBxActions . Text + Environment . NewLine + RedLbls ;
2025-10-17 12:06:36 +01:00
2025-10-28 16:13:05 +00:00
Access . StatsDiags ( RedLbls , RhTxBxActions . Text , CamOnTest . Model ) ; // Log to Access database
2025-10-17 14:26:33 +01:00
2025-09-02 15:32:24 +01:00
if ( await DisplayQuestion ( "Test failed, appeal?" + Environment . NewLine + "See Actions textbox for details." ) )
{
if ( CbBxUserName . Text = = "Bradley" )
{
await TestPassed ( DateTime . Now ) ; // Debugging
return ;
}
BtnYes . Visible = BtnNo . Visible = false ; // Remove buttons
LblQuestion . Text = "Please ask for approval" ;
PnlQuestion . Visible = true ;
this . Refresh ( ) ; // To make sure all labels are up to date before reading them
// Joins the actions box to any red labels to use as a full failed text
Logging . LogErrorMessage ( FullFailureValues ) ;
IList < IList < object > > values = GoogleAPI . service . Spreadsheets . Values . Get ( GoogleAPI . spreadsheetId_ModelInfo , "'Approval'!A1:A" ) . Execute ( ) . Values ;
if ( values ? . Count > 0 )
{
int nextRow = values . Count + 1 ;
List < object > oblistA = [ CbBxUserName . Text ] ;
GoogleAPI . WriteToSS ( oblistA , "'Approval'!A" + nextRow , GoogleAPI . spreadsheetId_ModelInfo ) ;
List < object > oblistCD = [ CamOnTest . Model , FullFailureValues ] ;
GoogleAPI . WriteToSS ( oblistCD , "'Approval'!C" + nextRow + ":D" + nextRow , GoogleAPI . spreadsheetId_ModelInfo ) ;
2025-11-04 13:16:07 +00:00
await Teams . SendMssg ( Convert . ToString ( nextRow ) , CbBxUserName . Text ) ;
2025-09-02 15:32:24 +01:00
string Approved = "" ;
while ( Approved ! = "TRUE" )
{
await Task . Delay ( 1000 ) ;
values = GoogleAPI . service . Spreadsheets . Values . Get ( GoogleAPI . spreadsheetId_ModelInfo , "'Approval'!B" + nextRow ) . Execute ( ) . Values ;
if ( values ? . Count > 0 )
Approved = Convert . ToString ( values [ 0 ] [ 0 ] ) ;
else
{
await Logging . LogErrorMessage ( "No values returned from Approval spreadsheet for row " + nextRow ) ;
Helper . RestartApp ( ) ;
}
}
}
else
Helper . RestartApp ( ) ;
// Sets back to continue test
PnlQuestion . Visible = false ;
BtnYes . Visible = BtnNo . Visible = true ;
Btn . BackColor = Color . Orange ;
Btn . Text = "Test underway" ;
}
else
Helper . RestartApp ( ) ;
}
2025-12-22 14:37:43 +00:00
public async Task PreTestPassed ( )
2025-09-02 15:32:24 +01:00
{
BtnPreTest . BackColor = Color . ForestGreen ; // Indicators to the user the test has passed
BtnPreTest . Text = "Pre Test Passed" ;
PnlQuestion . Visible = true ;
BtnNo . Visible = false ;
Logging . LogMessage ( "Pre Test Passed" ) ;
2025-10-29 16:17:59 +00:00
2025-10-17 12:06:36 +01:00
if ( CamOnTest . RMANum = = 0 ) // Yap to check if it is not a RMA
2025-10-21 15:46:28 +01:00
Access . Stats ( "Pre Tests Passed" , CamOnTest . Model ) ;
2025-10-17 12:06:36 +01:00
else
2025-10-21 15:46:28 +01:00
Access . Stats ( "RMA Pre Tests Passed" , CamOnTest . Model ) ;
2025-09-02 15:32:24 +01:00
if ( await DisplayQuestion ( "Test passed, restart?" ) )
Helper . RestartApp ( ) ;
}
2025-12-22 14:37:43 +00:00
public async Task PreTestFailed ( string ErrMssg )
2025-09-02 15:32:24 +01:00
{
BtnPreTest . BackColor = Color . Maroon ; // Indicators to the user the test has failed
BtnPreTest . Text = "Test Failed" ;
PnlQuestion . Visible = true ;
BtnNo . Visible = false ;
Logging . LogMessage ( "Pre Test Failed" ) ;
2025-10-28 16:13:05 +00:00
if ( CamOnTest . RMANum = = 0 ) // Yap to check if it is not a RMA
Access . Stats ( [ "Pre Tests Failed" , ErrMssg ] , CamOnTest . Model ) ;
else
Access . Stats ( "RMA Pre Tests Failed" , CamOnTest . Model ) ;
2025-10-20 10:31:58 +01:00
string RedLbls = string . Join ( Environment . NewLine , PnlLbls . Controls
. OfType < Label > ( )
. Where ( lbl = > lbl . ForeColor = = Color . Red ) // Only include red labels
. Select ( lbl = > lbl . Text ) ) ; // Extract text
string FullFailureValues = RhTxBxActions . Text + Environment . NewLine + RedLbls ;
2025-10-28 16:13:05 +00:00
Access . StatsDiags ( RedLbls , RhTxBxActions . Text , CamOnTest . Model ) ; // Log to Access database
2025-09-02 15:32:24 +01:00
if ( await DisplayQuestion ( "Test failed, restart?" + Environment . NewLine + "See Actions textbox for details." ) )
Helper . RestartApp ( ) ;
}
2025-12-22 14:37:43 +00:00
public async Task AllocateSerial ( )
2025-09-02 15:32:24 +01:00
{
// Update the serial number register with new cameras details
// Cam description is in model drop down 6 digit model num + 3 for " - "
2025-12-19 16:14:13 +00:00
string NewSerial = GoogleAPI . UpdateSpreadSheetPreTest ( CameraAccessInfo . SpreadsheetID , Vers , CbBxCameraModel . Text . Substring ( 9 ) , CamOnTest . Model ) ;
2025-09-02 15:32:24 +01:00
if ( NewSerial . Contains ( "ERROR" ) )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( NewSerial + Environment . NewLine + "Please remove any information that was put into the serial number mistake, change the camera model/serial to 'N/A' and retry the test." , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
return ;
}
else if ( NewSerial = = "Last serial number not found" )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Last serial number not found in spreadsheet. Please check spreadsheet is in correct format before retrying." , Level . WARNING ) ;
2025-09-02 15:32:24 +01:00
return ;
}
// Set serial and model into camera
string [ , ] TEST_JSON = { { "propSerialNumber" , NewSerial } , { "propMavModelNumber" , CamOnTest . Model } } ;
2025-10-27 11:14:20 +00:00
string JSONResponse = await FlexiAPI . HTTP_Update ( "GLOBAL--FlexiApplication" , CamOnTest . IP , TEST_JSON ) ;
2025-09-02 15:32:24 +01:00
if ( ! JSONResponse . Contains ( NewSerial ) | | ! JSONResponse . Contains ( CamOnTest . Model ) )
{
2025-12-22 14:37:43 +00:00
AddToActionsList ( "Could not set model or serial numbers into camera." , Level . ERROR ) ;
2025-10-17 12:06:36 +01:00
await PreTestFailed ( "Failed To Set Model Or Serial Number" ) ;
2025-09-02 15:32:24 +01:00
}
2025-12-22 14:37:43 +00:00
TestingFunctions . DiagsAPI . modelNumber = CamOnTest . Model ; // Update Diags and labels
TestingFunctions . DiagsAPI . serialNumber = NewSerial ;
lblModel . Text + = TestingFunctions . DiagsAPI . modelNumber ;
2025-09-02 15:32:24 +01:00
lblModel . ForeColor = lblSerial . ForeColor = Color . LightGreen ;
2025-12-22 14:37:43 +00:00
lblSerial . Text + = TestingFunctions . DiagsAPI . serialNumber ;
2025-09-02 15:32:24 +01:00
Printer . ZebraIP = localDataStore . ZebraIP ;
Printer . PrintGBLbl ( ) ; // Print GB label
Printer . PrintSerialLbl ( CamOnTest . Model , NewSerial , CameraAccessInfo . Processor ) ; // Print model/serial label
}
// ***** Top right buttons *****
private void BtnClose_Click ( object sender , EventArgs e )
{
// Save user settings in LDS for next time if values are valid
2025-12-19 16:14:13 +00:00
if ( CbBxUserName . Text . Length > 2 & & CbBxCameraModel . Text . Length > 6 )
2025-09-02 15:32:24 +01:00
{
localDataStore . User = CbBxUserName . Text ;
2025-12-19 16:14:13 +00:00
localDataStore . LastModel = CbBxCameraModel . Text ;
2025-09-02 15:32:24 +01:00
LDS . SetLDS ( localDataStore ) ;
}
Environment . Exit ( 0 ) ; // Close app and dispose of everything, a very abrupt method
}
private void BtnMin_Click ( object sender , EventArgs e )
{
this . WindowState = FormWindowState . Minimized ;
}
private void BtnRestart_Click ( object sender , EventArgs e )
{
2025-12-19 16:14:13 +00:00
Helper . RestartApp ( ) ; // Restart abruptly don't worry about anything else going on
2025-09-02 15:32:24 +01:00
}
// ***** Allows moving GUI by grab and dragging *****
private void Form1_MouseDown ( object sender , MouseEventArgs e )
{
if ( e . Button = = MouseButtons . Left )
{
Helper . ReleaseCapture ( ) ;
Helper . SendMessage ( Handle , 0xA1 , 0x2 , 0 ) ;
}
}
// ***** Button actions *****
// Find cameras, sending broadcast and receiving simultaneously
private async void BtnFindCams_Click ( object sender , EventArgs e )
{
CbBxFoundCams . Text = "Searching" ;
2025-11-11 13:49:42 +00:00
BtnFindCams . Enabled = BtnSetAll211 . Enabled = BtnSoak . Enabled = BtnSet211 . Enabled = BtnSetGodMode . Enabled = BtnUploadBlob . Enabled = SetGodModeAll . Enabled = BtnFactoryDefault . Enabled = BtnUploadWonwooSetIR . Enabled = BtnUploadWonwooSetOV . Enabled = false ;
2025-09-16 10:42:51 +01:00
BtnSetGodMode . BackColor = BtnUploadBlob . BackColor = BtnFactoryDefault . BackColor = BtnSetAll211 . BackColor = BtnColour ;
2025-09-02 15:32:24 +01:00
CbBxFoundCams . Items . Clear ( ) ;
soakCameraList . Clear ( ) ;
// Deletes all the checkboxes in TabSoak
List < CheckBox > checkBoxes = TabSoak . Controls . OfType < CheckBox > ( ) . Except ( [ CkBxTickAll ] ) . ToList ( ) ;
foreach ( CheckBox ? cb in checkBoxes )
{
TabSoak . Controls . Remove ( cb ) ;
cb . Dispose ( ) ;
}
IList < string > FoundCams = await Network . SearchForCams ( ) ;
foreach ( string Cam in FoundCams )
{
CbBxFoundCams . Items . Add ( Cam ) ; // Update combo box list
if ( TabImagesandSettings . SelectedIndex = = 3 )
{
Camera NewCam = await Helper . NewCamera ( Cam ) ;
if ( NewCam ! = null )
soakCameraList . Add ( NewCam ) ;
}
}
// Order soakCameraList by serial
soakCameraList . Sort ( ( a , b ) = > string . Compare ( a . Serial , b . Serial , StringComparison . OrdinalIgnoreCase ) ) ;
int YLoc = 74 ;
foreach ( Camera soakInfo in soakCameraList )
{
2025-11-26 14:39:07 +00:00
CheckBox chkBox = SoakTest . MakeNewCheckbox ( soakInfo , YLoc ) ;
TabSoak . Controls . Add ( chkBox ) ;
soakInfo . CheckBox = chkBox ;
2025-09-02 15:32:24 +01:00
YLoc + = 24 ;
}
int cameraCount = CbBxFoundCams . Items . Count ;
CbBxFoundCams . Text = cameraCount > 0 ? $"{cameraCount} Camera{(cameraCount == 1 ? "" : " s ")} Found" : "No Cameras Found" ;
2025-09-16 10:42:51 +01:00
BtnFindCams . Enabled = BtnSetAll211 . Enabled = SetGodModeAll . Enabled = BtnSoak . Enabled = BtnUploadBlob . Enabled = BtnFactoryDefault . Enabled = true ;
2025-09-02 15:32:24 +01:00
}
private void BtnYes_Click ( object sender , EventArgs e )
{
Flags . Yes = true ; // Set the Yes flag to true
}
private void BtnNo_Click ( object sender , EventArgs e )
{
Flags . No = true ;
}
private void CmBoBoxUserName_TextChanged ( object sender , EventArgs e )
{
TestStartConditions ( ) ;
}
private void CmBoFoundCams_TextChanged ( object sender , EventArgs e )
{
timerTypeIP . Enabled = false ;
timerTypeIP . Enabled = true ;
}
private async void CbBxFoundCams_SelectedIndexChanged ( object sender , EventArgs e ) // Also services the timerTypeIP_Tick
{
timerTypeIP . Enabled = false ; // Stop this triggering again
CamOnTest . DevPass = TxBxOutput . Text = RhTxBxActions . Text = "" ; // Blank password & Clear actions box as it is now a different camera
2025-12-19 16:14:13 +00:00
string selectedText = CbBxFoundCams . Text . Trim ( ) ;
string ipOnly = selectedText . Split ( ' ' , StringSplitOptions . RemoveEmptyEntries ) [ 0 ] ;
2025-12-22 14:37:43 +00:00
bool isOnvif = selectedText . Contains ( "Onvif" , StringComparison . OrdinalIgnoreCase ) ;
2025-12-19 16:14:13 +00:00
if ( RegexCache . RegexIPPattern ( ) . IsMatch ( ipOnly ) ) // Check IP address is valid
2025-09-02 15:32:24 +01:00
{
2025-12-22 14:37:43 +00:00
CamOnTest . IP = ipOnly ; // Always store clean IP
CbBxFoundCams . BackColor = BtnColour ;
// ONVIF cameras: webpage only
if ( isOnvif )
{
BtnOpenWebpage . Enabled = true ;
TestStartConditions ( ) ;
return ;
}
// Non-ONVIF cameras
2025-12-19 16:14:13 +00:00
if ( ! await Network . PingIP ( ipOnly ) )
2025-09-02 15:32:24 +01:00
{
CbBxFoundCams . BackColor = Color . Red ;
return ;
}
BtnSecret . Enabled = true ;
2025-12-19 16:14:13 +00:00
Vers = await FlexiAPI . GetVersions ( ipOnly ) ;
2025-09-02 15:32:24 +01:00
// Wont be filled out before the pre test but needed for final test
2025-12-22 14:37:43 +00:00
if ( RegexCache . SerialRegex ( ) . IsMatch ( CamOnTest . Serial ) & &
RegexCache . ModelRegex ( ) . IsMatch ( CamOnTest . Model ) )
2025-09-02 15:32:24 +01:00
{
2025-12-22 14:37:43 +00:00
CamOnTest . Serial = Vers . Serial ;
CamOnTest . Model = Vers . Model ;
2025-09-02 15:32:24 +01:00
}
2025-12-22 14:37:43 +00:00
if ( Vers = = null ) // Flexi not running or not AiQ
2025-09-02 15:32:24 +01:00
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Failed to get API from camera. Flexi not running yet or not an AiQ" , Level . WARNING ) ;
2025-09-02 15:32:24 +01:00
return ;
}
2025-12-22 14:37:43 +00:00
Lics . DisplayDevPassword ( Vers , CamOnTest ) ;
2025-09-02 15:32:24 +01:00
2025-12-19 16:14:13 +00:00
string networkConfigText = await FlexiAPI . ProcessNetworkConfig ( ipOnly ) ;
2025-09-02 15:32:24 +01:00
BtnSet211 . Text = string . IsNullOrEmpty ( networkConfigText ) ? "Set to 211" : networkConfigText ;
2025-12-22 14:37:43 +00:00
ShowToolTip ( BtnSecret ) ;
2025-09-02 15:32:24 +01:00
}
2025-12-19 16:14:13 +00:00
else if ( selectedText . Contains ( "Found" ) )
2025-09-02 15:32:24 +01:00
{
CbBxFoundCams . BackColor = BtnColour ;
}
else
{
CbBxFoundCams . BackColor = Color . Red ;
2025-12-22 14:37:43 +00:00
BtnSecret . Enabled =
BtnOpenWebpage . Enabled =
BtnSet211 . Enabled =
BtnSetGodMode . Enabled =
BtnUploadWonwooSetIR . Enabled =
BtnUploadWonwooSetOV . Enabled = false ;
2025-09-02 15:32:24 +01:00
}
TestStartConditions ( ) ;
}
2025-12-22 14:37:43 +00:00
2025-09-02 15:32:24 +01:00
private void btnPsuOn_Click ( object sender , EventArgs e )
{
PSU . PSU_ON ( PSU . PSUIP ) ;
}
private void btnPsuOff_Click ( object sender , EventArgs e )
{
PSU . PSU_OFF ( PSU . PSUIP ) ;
}
private void btnPsu48V_Click ( object sender , EventArgs e )
{
PSU . PSU_OFF ( PSU . PSUIP ) ;
PSU . SendDataPsu ( "V1 48" , PSU . PSUIP ) ;
PSU . SendDataPsu ( "I1 1.5" , PSU . PSUIP ) ;
}
private void btnPsu12V_Click ( object sender , EventArgs e )
{
PSU . PSU_OFF ( PSU . PSUIP ) ;
PSU . SendDataPsu ( "V1 12" , PSU . PSUIP ) ;
PSU . SendDataPsu ( "I1 3.5" , PSU . PSUIP ) ;
}
private async void BtnSetGodMode_Click ( object sender , EventArgs e )
{
2025-09-16 10:42:51 +01:00
BtnSetGodMode . BackColor = BtnColour ;
2025-09-02 15:32:24 +01:00
bool isGodModeCurrentlyOn = BtnSetGodMode . Text . Contains ( "On" ) ;
string newGodModeValue = isGodModeCurrentlyOn ? "true" : "false" ;
string [ , ] GOD_JSON = { { "propGodMode" , newGodModeValue } } ;
try
{
2025-11-04 13:16:07 +00:00
await FlexiAPI . HTTP_Update ( "GLOBAL--FlexiApplication" , CamOnTest . IP , GOD_JSON ) ;
2025-09-02 15:32:24 +01:00
BtnSetGodMode . Text = newGodModeValue = = "true" ? "Set God Mode Off" : "Set God Mode On" ;
BtnSetGodMode . BackColor = Color . Green ;
}
catch ( Exception ex )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( $"Failed to set God mode for camera {CamOnTest.IP}. Reason: {ex.Message}" , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
}
}
// ***** Helper functions *****
2025-11-26 14:39:07 +00:00
public void AddToActionsList ( string Mssg , Level Lvl = Level . LOG )
2025-09-02 15:32:24 +01:00
{
2025-11-26 14:39:07 +00:00
if ( Lvl = = Level . ERROR )
{
2025-09-02 15:32:24 +01:00
Logging . LogErrorMessage ( Mssg ) ;
2025-11-26 14:39:07 +00:00
RhTxBxActions . SelectionColor = Color . IndianRed ;
}
else if ( Lvl = = Level . WARNING )
{
Logging . LogWarningMessage ( Mssg ) ;
RhTxBxActions . SelectionColor = Color . Orange ;
}
else if ( Lvl = = Level . LOG )
2025-12-02 12:59:40 +00:00
{
Logging . LogMessage ( Mssg ) ;
RhTxBxActions . SelectionColor = Color . White ;
}
else if ( Lvl = = Level . Success )
2025-11-26 14:39:07 +00:00
{
2025-09-02 15:32:24 +01:00
Logging . LogMessage ( Mssg ) ;
2025-11-26 14:39:07 +00:00
RhTxBxActions . SelectionColor = Color . LightGreen ;
}
2025-09-02 15:32:24 +01:00
2025-12-19 16:14:13 +00:00
RhTxBxActions . AppendText ( Mssg + Environment . NewLine ) ;
2025-09-02 15:32:24 +01:00
RhTxBxActions . SelectionStart = RhTxBxActions . Text . Length ;
2025-11-26 14:39:07 +00:00
RhTxBxActions . SelectionColor = SystemColors . Control ;
2025-09-02 15:32:24 +01:00
RhTxBxActions . ScrollToCaret ( ) ;
}
2025-12-23 13:01:15 +00:00
private void CbBxCamTypSelectedIndexChanged ( object sender , EventArgs e )
{
TestStartConditions ( ) ;
}
2025-09-02 15:32:24 +01:00
private async void TestStartConditions ( )
{
if ( Flags . Start )
return ; // If on GUI load don't evaluate
RhTxBxActions . Text = "" ; // Clear actions box
bool TSC = true ;
if ( Flags . Offline = = true ) // If start found we are offline
{
if ( await Network . PingIP ( "8.8.8.8" ) ) // Ping to find if we are online
{
Flags . Offline = false ; // Ping succeeded
2025-12-19 16:14:13 +00:00
CbBxCameraModel . Enabled = true ;
2025-09-02 15:32:24 +01:00
}
else
TSC = SetInvalid ( "Offline Mode, could not connect to the internet." ) ; // Ping failed
}
// Camera IP selected
if ( CbBxFoundCams . BackColor ! = BtnColour | | CbBxFoundCams . Text . Contains ( "Found" ) )
TSC = SetInvalid ( "Select camera IP address." ) ;
else
2025-11-11 13:49:42 +00:00
BtnOpenWebpage . Enabled = BtnSet211 . Enabled = BtnSetGodMode . Enabled = BtnZoom8000 . Enabled = BtnZoomWide . Enabled = BtnUploadWonwooSetIR . Enabled = BtnUploadWonwooSetOV . Enabled = true ; // Allow user to go to camera webpage & change DHCP/211
2025-09-02 15:32:24 +01:00
// Name chosen
if ( CbBxUserName . Text = = "Select Operator to Begin Test" | | CbBxUserName . Text . Length < 2 )
TSC = SetInvalid ( "Select Username." ) ;
// Model number selected
2025-12-19 16:14:13 +00:00
if ( CbBxCameraModel . SelectedIndex = = - 1 )
2025-09-02 15:32:24 +01:00
TSC = SetInvalid ( "Select Model number." ) ;
// Settings IP addresses filled in
if ( BtnSave . BackColor ! = Color . ForestGreen )
TSC = SetInvalid ( "Fill in hardware accessies IP's & click 'Save & Check'." ) ;
// All hardware accessories are on the network
//if (PanelSettings.Controls.OfType<Label>().Any(label => label.Text.Contains("❌")))
if ( LblZebraPing . Text = = "❌" | | LblEzPing . Text = = "❌" | | LblPSUPing . Text = = "❌" ) // Testtube not connected then will do 2.7m check
TSC = SetInvalid ( "Hardware accessories not found on network, see red X's in settings tab for details. Fill in IP addresses and press Save & Check." ) ;
// Shutter, Iris and Gain selected
if ( CbBxShutter . SelectedIndex = = - 1 | | CbBxIris . SelectedIndex = = - 1 | | CbBxGain . SelectedIndex = = - 1 )
TSC = SetInvalid ( "Shutter, iris and gain drop downs not filled in." ) ;
if ( TSC )
BtnStartTest . Text = "Start Final test" ;
BtnStartTest . Enabled = BtnPreTest . Enabled = BtnLicVaxtor . Enabled = TSC ; // Licensing Vaxtor requires all the info
}
private bool SetInvalid ( string reason )
{
RhTxBxActions . Text + = reason + Environment . NewLine ;
return false ;
}
public async Task < bool > DisplayOK ( string QuestionString )
{
BtnNo . Visible = false ;
BtnYes . Text = "OK" ;
bool YesNo = await DisplayQuestion ( QuestionString ) ;
BtnNo . Visible = true ;
BtnYes . Text = "Yes" ;
return YesNo ;
}
public async Task < bool > DisplayQuestion ( string QuestionString )
{
Flags . Yes = Flags . No = false ; // Clear flags
PnlQuestion . Visible = true ;
LblQuestion . Text = QuestionString ; // Show question box and give them the right to appeal
while ( ! Flags . Yes & & ! Flags . No )
await Task . Delay ( 100 ) ; // Check flags every 100ms
PnlQuestion . Visible = false ;
if ( Flags . Yes )
{
Flags . Yes = false ; // Clear flag
return true ;
}
else
{
Flags . No = false ; // Clear flag
return false ;
}
}
// Display the input panel for either RMA number input (default) or Vaxtor Key ID input
2025-12-22 14:37:43 +00:00
public async Task < string > DisplayInput ( string Request , bool RMAorVaxtor = true )
2025-09-02 15:32:24 +01:00
{
RMANumBox . Visible = BtnRerun . Visible = RMAorVaxtor ;
TxBxProductKey . Visible = ! RMAorVaxtor ;
LblRMA . Text = Request ;
PnlInputValue . Visible = true ;
while ( Flags . Done = = false ) // Waiting for user input in RMA Num panel
await Task . Delay ( 100 ) ; // Check every 100ms
2025-10-21 14:01:27 +01:00
2025-09-02 15:32:24 +01:00
Flags . Done = false ; // Reset flag
PnlInputValue . Visible = false ;
if ( RMAorVaxtor )
return RMANumBox . Value . ToString ( ) ;
else
return TxBxProductKey . Text ;
}
// ***** Settings menu *****
// Save all current user settings to disk then check devices are online
private async void BtnSave_Click ( object sender , EventArgs e )
{
BtnSave . Enabled = false ;
localDataStore . PSUIP = TxBxPsuIP . Text ;
localDataStore . EzIP = TxBxEzIP . Text ;
localDataStore . ZebraIP = TxBxZebraIP . Text ;
localDataStore . TestTubeIP = TxBxTestTubeIP . Text ;
localDataStore . Shutter = CbBxShutter . SelectedIndex ;
localDataStore . Iris = CbBxIris . SelectedIndex ;
localDataStore . Gain = CbBxGain . SelectedIndex ;
LDS . SetLDS ( localDataStore ) ;
BtnSave . BackColor = Color . ForestGreen ;
PSU . PSUIP = localDataStore . PSUIP ;
Printer . ZebraIP = localDataStore . ZebraIP ;
Ez . PoEPowerIP = localDataStore . EzIP ;
TestTube . TTPiPicoIP = localDataStore . TestTubeIP ;
await PingCheck ( ) ;
TestStartConditions ( ) ;
CheckPrintCapable ( ) ;
BtnSave . Enabled = true ;
}
// Revert settings to last saved
private async void BtnCancel_Click ( object sender , EventArgs e )
{
TxBxPsuIP . Text = localDataStore . PSUIP ;
TxBxEzIP . Text = localDataStore . EzIP ;
TxBxZebraIP . Text = localDataStore . ZebraIP ;
TxBxTestTubeIP . Text = localDataStore . TestTubeIP ;
CbBxShutter . SelectedIndex = localDataStore . Shutter ;
CbBxIris . SelectedIndex = localDataStore . Iris ;
CbBxGain . SelectedIndex = localDataStore . Gain ;
await PingCheck ( ) ;
TestStartConditions ( ) ;
}
private void BtnFirewall_Click ( object sender , EventArgs e )
{
Properties . Settings . Default . FirstRun = true ;
Properties . Settings . Default . Save ( ) ;
Windows . UpdateFirewall ( ) ;
}
private void BtnAdminStart_Click ( object sender , EventArgs e )
{
string ExeLoc = Assembly . GetEntryAssembly ( ) . Location . Replace ( "dll" , "exe" ) ; // Sometimes trys to open the dll instead of exe
Windows . StartAsAdmin ( ExeLoc ) ;
}
// Flips between setting camera to 211 and DHCP
private async void BtnSet211_Click ( object sender , EventArgs e )
{
if ( BtnSet211 . Text = = "Set to 211" )
{
bool Online = await FlexiAPI . ChangeNetwork211 ( CamOnTest . IP ) ; // Change camera IP to 192.168.1.211 and hardware reboot. Waits for camera to come back for 50s.
if ( ! Online )
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Could not find camera at 192.168.1.211. Please check manually" , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
else
BtnSet211 . Text = "Set to DHCP" ;
}
else if ( BtnSet211 . Text = = "Set to DHCP" )
{
await FlexiAPI . ChangeNetworkToDHCP ( CamOnTest . IP ) ;
BtnSet211 . Text = "Set to 211" ;
}
}
private async void BtnSetAll211_Click ( object sender , EventArgs e )
{
BtnSetAll211 . BackColor = BtnColour ; // Reset button colour
if ( await DisplayQuestion ( "Are you sure? This will set all checked cameras to 211." ) )
{
string [ , ] Network_JSON = { { "propDHCP" , "false" } , { "propHost" , "192.168.1.211" } , { "propNetmask" , "255.255.255.0" } , { "propGateway" , "192.168.1.1" } } ;
foreach ( Camera SCL in soakCameraList . Where ( c = > c . IsChecked ) ) // only checked cameras
{
try
{
Network . Initialize ( "developer" , SCL . DevPass ) ; // Ensure network is initialized to the right camera
await FlexiAPI . HTTP_Update ( "GLOBAL--NetworkConfig" , SCL . IP , Network_JSON ) ;
2025-11-26 14:39:07 +00:00
Instance . AddToActionsList ( $"Setting 211 for camera {SCL.IP}" , Level . LOG ) ;
2025-09-02 15:32:24 +01:00
}
catch ( Exception ex )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Failed to set all cameras to 211. Reason: " + ex . Message , Level . ERROR ) ; // In case non AiQ's get caught up
2025-09-02 15:32:24 +01:00
}
}
BtnSetAll211 . BackColor = Color . Green ;
}
}
private async void SetGodModeAll_Click ( object sender , EventArgs e )
{
SetGodModeAll . BackColor = BtnColour ; // Reset button colour
bool isGodModeCurrentlyOn = SetGodModeAll . Text . Contains ( "On" ) ;
string newGodModeValue = isGodModeCurrentlyOn ? "true" : "false" ;
string [ , ] GOD_JSON = { { "propGodMode" , newGodModeValue } } ;
if ( await DisplayQuestion ( "Are you sure? This will toggle God mode for all checked cameras." ) )
{
foreach ( Camera SCL in soakCameraList . Where ( c = > c . IsChecked ) ) // only checked cameras
{
try
{
Network . Initialize ( "developer" , SCL . DevPass ) ; // Ensure network is initialized to the right camera
2025-11-04 13:16:07 +00:00
string RESP = await FlexiAPI . HTTP_Update ( "GLOBAL--FlexiApplication" , SCL . IP , GOD_JSON ) ;
2025-11-26 14:39:07 +00:00
Instance . AddToActionsList ( $"Setting God mode for camera {SCL.IP} to {newGodModeValue}" , Level . LOG ) ;
2025-09-02 15:32:24 +01:00
}
catch ( Exception ex )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( $"Failed to set God mode for camera {SCL.IP}. Reason: {ex.Message}" , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
}
}
// Update the button text and flash green only if successful for all
SetGodModeAll . Text = newGodModeValue = = "true" ? "Set God Mode Off" : "Set God Mode On" ;
SetGodModeAll . BackColor = Color . Green ;
}
}
private void TxBxZebraIP_TextChanged ( object sender , EventArgs e )
{
TxBxCheckValid ( TxBxZebraIP ) ;
}
private void TxBxPSUIP_TextChanged ( object sender , EventArgs e )
{
TxBxCheckValid ( TxBxPsuIP ) ;
}
private void TxBxEzIP_TextChanged ( object sender , EventArgs e )
{
TxBxCheckValid ( TxBxEzIP ) ;
}
private void TxBxAccBoardIP_TextChanged ( object sender , EventArgs e )
{
TxBxCheckValid ( TxBxTestTubeIP ) ;
}
// Start a thread that pings each IP in the hardware accessories menu
private async Task PingCheck ( )
{
List < Task > tasks = // Run all ping checks in parallel
[
Network . PingAndUpdateUI ( localDataStore . PSUIP , LblPSUPing , "PSU" , ToolTipAvailable , [ btnPsuOff , btnPsuOn , btnPsu12V , btnPsu48V ] ) ,
Network . PingAndUpdateUI ( localDataStore . EzIP , LblEzPing , "Ez" , ToolTipAvailable , [ BtnEzOff , BtnEzOn ] ) ,
Network . PingAndUpdateUI ( localDataStore . ZebraIP , LblZebraPing , "Zebra" , ToolTipAvailable , [ BtnPrintGB ] ) ,
Network . PingAndUpdateUI ( localDataStore . TestTubeIP , LblTestTubePing , "Test Tube" , ToolTipAvailable )
] ;
await Task . WhenAll ( tasks ) ; // Wait for all tasks to complete
}
private void TxBxCheckValid ( TextBox TxBx )
{
if ( RegexCache . RegexIPPattern ( ) . IsMatch ( TxBx . Text ) ) // Check IP address is valid
{
TxBx . BackColor = TxBxColour ; // Assume all is good
BtnSave . Enabled = ! PanelSettings . Controls . Cast < Control > ( ) . Any ( tb = > tb . BackColor = = Color . Red ) ;
}
else
{
TxBx . BackColor = Color . Red ;
BtnSave . Enabled = false ;
BtnSave . BackColor = BtnColour ;
}
TestStartConditions ( ) ;
}
private void BtnGenerate_Click ( object sender , EventArgs e )
{
// Return code straight into rich textbox
string LicCode = Lics . GenerateLicCode ( TxBxChallenge . Text , CbBxType . Text ) ;
RhTxBxCode . AppendText ( LicCode + Environment . NewLine ) ;
RhTxBxCode . SelectionStart = RhTxBxCode . Text . Length ;
RhTxBxCode . ScrollToCaret ( ) ;
Clipboard . SetText ( LicCode ) ; // Copy license code to clipboard
Button button = ( Button ) sender ;
int yOffset = button . Height + 5 ; // Offset 5 pixels below the button
ToolTipClipboard . Show ( "Copied to clipboard!" , button , 0 , yOffset , 2000 ) ; // Tool tip visible to show copied
}
private void TxBxChallenge_TextChanged ( object sender , EventArgs e ) // Also services CboBxType_SelectedIndexChanged
{
CheckCodeFormat ( TxBxChallenge . Text ) ;
}
private void CheckCodeFormat ( string ChlgCode )
{
if ( RegexCache . LicCodeRegex ( ) . IsMatch ( ChlgCode ) )
{
if ( ChlgCode . Length = = 7 ) // If length is 7 then it has the license type distingusher on front
{
string type = ChlgCode . Substring ( 0 , 1 ) ;
TxBxChallenge . Text = ChlgCode . Substring ( 1 , 6 ) ; // Cut down text to only the challenge code.
if ( type = = "F" ) // SAF
CbBxType . SelectedIndex = 0 ;
else if ( type = = "S" ) // Streaming
CbBxType . SelectedIndex = 1 ;
else if ( type = = "A" ) // Audit
CbBxType . SelectedIndex = 2 ;
BtnGenerate . Enabled = true ;
}
else if ( ChlgCode . Length = = 6 & & CbBxType . SelectedIndex ! = - 1 ) // Code without distinguser and type chosen
{
TxBxChallenge . Text = ChlgCode ;
BtnGenerate . Enabled = true ;
}
}
else
{
BtnGenerate . Enabled = false ;
}
}
// License Vaxtor button
private async void BtnLicVaxtor_Click ( object sender , EventArgs e )
{
if ( CameraAccessInfo . VaxtorLic ) // If camera should have a Vaxtor license then license it now
{
if ( await DisplayQuestion ( "Are you sure you want to license Vaxtor to this camera?" ) )
{
// Update server endpoint, username and password before licensing
string [ , ] Endpoint_JSON = { { "propLicenceKeyEndpointURL" , UniversalData . LicencingServerURL } } ;
await FlexiAPI . HTTP_Update ( "RaptorOCR" , CamOnTest . IP , Endpoint_JSON ) ;
string ALresponse ;
try
{
ALresponse = await FlexiAPI . APIHTTPRequest ( "/api/RaptorOCR-auto-license" , CamOnTest . IP , 10 ) ; // License Vaxtor
}
catch
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Failed to communicate with camera, please check network and try again." , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
return ;
}
try // Deserialise the JSON
{
VaxtorLicResp = JsonConvert . DeserializeObject < VaxtorLic > ( ALresponse ) ;
2025-11-26 14:39:07 +00:00
if ( VaxtorLicResp . error ! = string . Empty )
{
AddToActionsList ( VaxtorLicResp . error , Level . ERROR ) ;
}
else if ( VaxtorLicResp . protectionKeyId ! = string . Empty )
2025-09-02 15:32:24 +01:00
{
string err = GoogleAPI . UpdateSpreadSheetVaxtor ( VaxtorLicResp , Vers . Serial , CamOnTest . Model ) ;
if ( err ! = string . Empty ) // If there is an error message, display it
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Failed to update Vaxtor spreadsheet: " + err , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
RhTxBxCode . AppendText ( "Licencing Success, Key ID: " + VaxtorLicResp . protectionKeyId + Environment . NewLine + "Waiting for files to save" ) ;
if ( await DisplayQuestion ( "Do you want to sync to disk? (If unsure what this means press yes)" ) )
SSH . Sync ( CamOnTest . IP ) ; // Sync everything in RAM to the disk
await DisplayOK ( "Please wait at least a minute before turning off the unit." ) ;
}
else
{
2025-11-26 14:39:07 +00:00
AddToActionsList ( $"Error reading JSON - {ALresponse}" , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
}
}
catch
{
2025-11-26 14:39:07 +00:00
AddToActionsList ( $"Error reading JSON - {ALresponse}" , Level . ERROR ) ;
2025-09-02 15:32:24 +01:00
return ;
}
}
}
else
{
RhTxBxCode . AppendText ( "This model shouldn't have a Vaxtor license. NOT LICENSED" ) ;
}
}
// Refresh the unix time that is displayed and used to generate developer password
private void BtnRefreshUnix_Click ( object sender , EventArgs e )
{
TimeSpan t = DateTime . UtcNow - new DateTime ( 1970 , 1 , 1 ) ;
int secondsSinceEpoch = ( int ) t . TotalSeconds ;
TxBxUnixTime . Text = Convert . ToString ( secondsSinceEpoch ) ;
}
// Check if MAC address textbox contains a valid MAC
private void TxBxMAC_TextChanged ( object sender , EventArgs e )
{
if ( RegexCache . MACRegex ( ) . IsMatch ( TxBxMAC . Text ) )
{
TxBxMAC . BackColor = TxBxColour ;
BtnSecretMan . Enabled = true ;
}
else
{
TxBxMAC . BackColor = Color . Red ;
BtnSecretMan . Enabled = false ;
}
}
// Check if unix textbox contains a valid Unix time
private void TxBxUnixTime_TextChanged ( object sender , EventArgs e )
{
if ( long . TryParse ( TxBxUnixTime . Text , out long unixTime ) & & unixTime > = 0 & & unixTime < = 2147483647 )
{
TxBxUnixTime . BackColor = TxBxColour ;
BtnSecretMan . Enabled = true ;
}
else
{
TxBxUnixTime . BackColor = Color . Red ;
BtnSecretMan . Enabled = false ;
}
}
// Check if Flexi version textbox contains a valid version
private void TxBxFlexiVer_TextChanged ( object sender , EventArgs e )
{
if ( RegexCache . FlexiVerRegex ( ) . IsMatch ( TxBxFlexiVer . Text ) ) // Regex on Flexi version that should be three values dot seperated up to three digits each
{
TxBxFlexiVer . BackColor = TxBxColour ;
BtnSecretMan . Enabled = true ;
}
else
{
TxBxFlexiVer . BackColor = Color . Red ;
BtnSecretMan . Enabled = false ;
}
}
// Use the version API with connected camera to generate developer password
private async void BtnSecret_Click ( object sender , EventArgs e )
{
Vers = await FlexiAPI . GetVersions ( CamOnTest . IP ) ;
Lics . DisplayDevPassword ( Vers , CamOnTest ) ;
ShowToolTip ( BtnSecret ) ;
}
// Generate password using manual inputs
private void BtnSecretMan_Click ( object sender , EventArgs e )
{
CamOnTest . DevPass = Lics . GeneratePassword ( TxBxMAC . Text , TxBxFlexiVer . Text , Convert . ToInt32 ( TxBxUnixTime . Text ) ) ;
ShowToolTip ( sender ) ;
}
private void ShowToolTip ( object sender ) // Shows 'Copied to clipboard!' tooltip below sender button
{
try // Catches sender when it comes from combo box
{
Button button = ( Button ) sender ;
int yOffset = button . Height + 5 ; // Offset 5 pixels below the button
ToolTipClipboard . Show ( "Copied to clipboard!" , button , 0 , yOffset , 2000 ) ; // Show tool tip
Clipboard . SetText ( CamOnTest . DevPass ) ; // Copy password to clipboard
}
catch { }
TxBxOutput . Text = CamOnTest . DevPass ; // Done last to maintain focus on box
}
private void TxBxOutput_Click ( object sender , EventArgs e )
{
TxBxOutput . SelectAll ( ) ; // Select the password in the box
TxBxOutput . Focus ( ) ; // Make it the users focus so it is in focus after generate
}
private async void BtnEzOn_Click ( object sender , EventArgs e )
{
BtnEzOff . BackColor = BtnColour ;
if ( await Ez . EzOutletControl ( "ON" ) )
BtnEzOn . BackColor = Color . ForestGreen ;
else
BtnEzOn . BackColor = Color . Maroon ;
}
private async void BtnEzOff_Click ( object sender , EventArgs e )
{
BtnEzOn . BackColor = BtnColour ;
if ( await Ez . EzOutletControl ( "OFF" ) )
BtnEzOff . BackColor = Color . ForestGreen ;
else
BtnEzOff . BackColor = Color . Maroon ;
}
private async void BtnZoomWide_Click ( object sender , EventArgs e )
{
2025-12-02 11:02:24 +00:00
if ( await CameraModules . ZoomModules ( "0000" , CamOnTest . IP ) )
2025-09-02 15:32:24 +01:00
BtnZoomWide . BackColor = Color . Green ;
else
BtnZoomWide . BackColor = Color . Red ;
BtnZoom8000 . BackColor = BtnColour ;
}
private async void BtnZoom8000_Click ( object sender , EventArgs e )
{
2025-12-02 11:02:24 +00:00
if ( await CameraModules . ZoomModules ( "1F40" , CamOnTest . IP ) )
2025-09-02 15:32:24 +01:00
BtnZoom8000 . BackColor = Color . Green ;
else
BtnZoom8000 . BackColor = Color . Red ;
BtnZoomWide . BackColor = BtnColour ;
}
private void BtnOpenWebpage_Click ( object sender , EventArgs e )
{
2025-12-19 16:14:13 +00:00
// Cut off anything after the first space (e.g. " - Onvif")
string ip = CamOnTest . IP . Split ( ' ' ) [ 0 ] ;
2025-09-02 15:32:24 +01:00
ProcessStartInfo psi = new ( )
{
2025-12-19 16:14:13 +00:00
FileName = $"http://{ip}" ,
UseShellExecute = true
2025-09-02 15:32:24 +01:00
} ;
Process . Start ( psi ) ;
}
2025-12-19 16:14:13 +00:00
2025-11-04 14:29:38 +00:00
private async void UploadWonwooSetOV_Click ( object sender , EventArgs e )
{
await FlexiAPI . UploadWonwooSet ( CbBxFoundCams . Text , false ) ; // false = Colour
}
private async void UploadWonwooSetIR_Click ( object sender , EventArgs e )
{
await FlexiAPI . UploadWonwooSet ( CbBxFoundCams . Text , true ) ; // true = Infrared
}
2025-09-02 15:32:24 +01:00
private void TxBxSerialPrint_Click ( object sender , EventArgs e )
{
if ( TxBxSerialPrint . Text = = "K – – – – – – – " ) // If at default then remove the dashes ready for user to put in number
{
TxBxSerialPrint . Text = "K" ;
TxBxSerialPrint . SelectionStart = 1 ;
}
}
private void BtnPrintAiQ_Click ( object sender , EventArgs e )
{
Printer . PrintSerialLbl ( CamOnTest . Model , TxBxSerialPrint . Text , CameraAccessInfo . Processor ) ; // Print model/serial label
}
private void BtnPrintGB_Click ( object sender , EventArgs e )
{
Printer . PrintGBLbl ( ) ; // Print GB label
}
private void TxBxSerialPrint_TextChanged ( object sender , EventArgs e )
{
CheckPrintCapable ( ) ; // Check if the print buttons can be enabled
}
private void CheckPrintCapable ( )
{
if ( LblZebraPing . Text = = "✔" ) // Check the IP address is ok
{
BtnPrintGB . Enabled = true ;
2025-12-19 16:14:13 +00:00
if ( CbBxCameraModel . SelectedIndex ! = - 1 & & RegexCache . SerialRegex ( ) . IsMatch ( TxBxSerialPrint . Text ) ) // Check model and serial are known
2025-09-02 15:32:24 +01:00
{
Printer . ZebraIP = localDataStore . ZebraIP ;
BtnPrintAiQ . Enabled = true ;
}
}
}
// ***** RMA Panel *****
private void BtnDone_Click ( object sender , EventArgs e )
{
CamOnTest . RMANum = Convert . ToInt16 ( RMANumBox . Value ) ;
Flags . Done = true ;
}
private void BtnDont_Click ( object sender , EventArgs e )
{
CamOnTest . RMANum = - 1 ;
Flags . Done = true ;
}
private void BtnRerun_Click ( object sender , EventArgs e )
{
CamOnTest . RMANum = 0 ;
Flags . Done = true ;
}
// ***** Soak *****
// Sets the soak test running for all cameras that are ticked.
private async void BtnSoak_Click ( object sender , EventArgs e )
{
if ( BtnSoak . Text = = "Start Soak" )
{
BtnSoak . BackColor = Color . Orange ;
BtnSoak . Text = "Stop Soak" ;
soakCtsList . Clear ( ) ;
soakTasks . Clear ( ) ;
foreach ( Camera SCL in soakCameraList )
{
if ( ! SCL . IsChecked )
continue ;
CancellationTokenSource cts = new ( ) ;
soakCtsList . Add ( cts ) ;
2025-12-02 11:02:24 +00:00
soakTasks . Add ( SoakTest . StartSoak ( SCL , cts ) ) ;
2025-11-11 13:18:02 +00:00
await Task . Delay ( 10000 ) ;
2025-09-02 15:32:24 +01:00
}
}
else
{
BtnSoak . BackColor = BtnColour ; // Reset button colour
BtnSoak . Text = "Start Soak" ;
foreach ( CancellationTokenSource cts in soakCtsList )
cts . Cancel ( ) ;
soakCtsList . Clear ( ) ;
soakTasks . Clear ( ) ;
2025-11-11 13:49:42 +00:00
int i = soakCameraList . Count + 1 ; // Add 1 for 211 itself staying in the list
2025-09-02 15:32:24 +01:00
2025-11-11 13:18:02 +00:00
string [ , ] Network_JSON = { { "propDHCP" , "false" } , { "propHost" , "192.168.1.211" } , { "propNetmask" , "255.255.255.0" } , { "propGateway" , "192.168.1.1" } } ;
string [ , ] GOD_JSON = { { "propGodMode" , "false" } } ;
foreach ( Camera SCL in soakCameraList . Where ( c = > c . IsChecked ) ) // only checked cameras
2025-09-02 15:32:24 +01:00
{
if ( ! SCL . IsChecked )
continue ;
2025-11-04 13:16:07 +00:00
try
{
2025-11-26 14:39:07 +00:00
AddToActionsList ( $"Setting 211 & God Mode off for camera {SCL.IP}" , Level . LOG ) ;
2025-11-11 14:17:31 +00:00
Network . Initialize ( "developer" , SCL . DevPass ) ; // Ensure network is initialized to the right camera
await CameraModules . FactoryResetModules ( SCL . IP ) ; // Reset camera modules
2025-09-02 15:32:24 +01:00
2025-11-11 14:17:31 +00:00
string GOD = await FlexiAPI . HTTP_Update ( "GLOBAL--FlexiApplication" , SCL . IP , GOD_JSON ) ;
2025-11-04 13:16:07 +00:00
if ( GOD . Contains ( "Error" ) )
throw new Exception ( "Could not set God mode off" ) ;
2025-11-11 13:49:42 +00:00
// Update GLOBAL--NetworkConfig with fixed IP and turn off DHCP
2025-11-11 14:17:31 +00:00
await FlexiAPI . HTTP_Update ( "GLOBAL--NetworkConfig" , SCL . IP , Network_JSON ) ;
2025-11-11 13:49:42 +00:00
i - - ; // Decriment count becuase they will stack into 211
2025-11-04 13:16:07 +00:00
}
catch ( Exception ex )
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "Failed to set all cameras to 211 and god mode off. Reason: " + ex . Message , Level . ERROR ) ; // In case non AiQ's get caught up
2025-11-04 13:16:07 +00:00
}
2025-11-26 14:39:07 +00:00
if ( SCL . CheckBox . ForeColor = = Color . Red )
{
DialogResult DR = MessageBox . Show ( $"CAMERA {SCL.Serial} {SCL.Model} DID NOT PASS SOAK TEST. Check soak test report to see error. Do you want to open the test report" , "SOAK TEST FAILED" , MessageBoxButtons . YesNo , MessageBoxIcon . Warning ) ;
if ( DR = = DialogResult . Yes )
File . Open ( SCL . TestReportLoc , FileMode . Open ) ;
}
2025-09-02 15:32:24 +01:00
}
2025-11-11 13:49:42 +00:00
await Task . Delay ( 5000 ) ; // Wait for 5 seconds to allow the camera to restart
IList < string > FoundCams = await Network . SearchForCams ( ) ; // Have to check via broadcast becuase Ping sometimes fails across subnets
2025-11-11 14:17:31 +00:00
if ( ( FoundCams . Count = = i & & FoundCams . Contains ( "192.168.1.211" ) ) | | FoundCams . Count = = 1 )
2025-11-11 13:49:42 +00:00
{
2025-12-02 12:59:40 +00:00
AddToActionsList ( "All cameras successfully changed to 211." , Level . Success ) ;
2025-11-11 13:49:42 +00:00
}
else
{
2025-11-26 14:39:07 +00:00
AddToActionsList ( $"Some cameras failed: Found {FoundCams.Count}, expected {i}." , Level . ERROR ) ;
2025-11-11 13:49:42 +00:00
}
2025-09-02 15:32:24 +01:00
}
2025-11-04 14:29:38 +00:00
}
2025-09-02 15:32:24 +01:00
private void CkBxTickAll_CheckedChanged ( object sender , EventArgs e )
{
List < CheckBox > checkBoxes = TabSoak . Controls . OfType < CheckBox > ( ) . Except ( [ CkBxTickAll ] ) . ToList ( ) ;
bool ToTick = CkBxTickAll . Text = = "Tick all" ; // True if we are ticking all checkboxes, false if we are unticking them
CkBxTickAll . Text = ToTick ? "Unick all" : "Tick all" ; // Toggle the text of the checkbox
foreach ( CheckBox ? cb in checkBoxes )
cb . Checked = ToTick ;
}
private async void timerTypeIP_Tick ( object sender , EventArgs e )
{
timerTypeIP . Enabled = false ;
if ( ! RegexCache . RegexIPPattern ( ) . IsMatch ( CbBxFoundCams . Text ) & & ! await Network . PingIP ( CbBxFoundCams . Text ) ) // Check IP address is valid
return ;
if ( TabImagesandSettings . SelectedIndex = = 3 )
{
soakCameraList . Clear ( ) ;
// Deletes all the checkboxes in TabSoak
List < CheckBox > checkBoxes = TabSoak . Controls . OfType < CheckBox > ( ) . Except ( [ CkBxTickAll ] ) . ToList ( ) ;
foreach ( CheckBox ? cb in checkBoxes )
{
TabSoak . Controls . Remove ( cb ) ;
cb . Dispose ( ) ;
}
Camera NewCam = await Helper . NewCamera ( CbBxFoundCams . Text ) ;
if ( NewCam ! = null )
{
soakCameraList . Add ( NewCam ) ;
TabSoak . Controls . Add ( SoakTest . MakeNewCheckbox ( NewCam , 74 ) ) ;
}
}
CbBxFoundCams_SelectedIndexChanged ( sender , e ) ;
}
private async void BtnUploadBlob_Click ( object sender , EventArgs e )
{
2025-09-16 10:42:51 +01:00
BtnUploadBlob . BackColor = BtnColour ;
2025-11-26 14:39:07 +00:00
FlexiAPI . UploadBlob ( soakCameraList ) ;
2025-09-16 10:42:51 +01:00
BtnUploadBlob . BackColor = Color . Green ;
2025-09-02 15:32:24 +01:00
}
private async void BtnFactoryDefault_Click ( object sender , EventArgs e )
{
2025-09-16 10:42:51 +01:00
BtnFactoryDefault . BackColor = BtnColour ;
2025-09-02 15:32:24 +01:00
foreach ( Camera SCL in soakCameraList ) // Reset all cameras that were being soaked to default module settings
{
if ( ! SCL . IsChecked )
continue ;
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 ) ;
}
2025-09-16 10:42:51 +01:00
BtnFactoryDefault . BackColor = Color . Green ;
2025-09-02 15:32:24 +01:00
}
// ***** Test & Debug *****
2025-12-22 14:37:43 +00:00
private async void BtnTest_Click ( object sender , EventArgs e )
2025-09-02 15:32:24 +01:00
{
Stopwatch stopWatchTest = Stopwatch . StartNew ( ) ;
2025-10-17 12:06:36 +01:00
2025-10-27 11:14:20 +00:00
2025-12-23 13:01:15 +00:00
//await MobilePreTest.CheckFirmwareAsync();
//AddLabelToPanel("Test Complete", false);
FakeCamera fakeCamera = new FakeCamera ( 80 ) ; // Create an instance of FakeCamera
2025-11-04 13:16:07 +00:00
2025-12-23 13:01:15 +00:00
//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}" ) ;
}
} ) ;
await Task . Delay ( 3000 ) ; // Wait for server to start
CbBxFoundCams . Text = "localhost" ; // Should force update in creds an network reinit
CmBoFoundCams_TextChanged ( sender , e ) ;
CbBxCameraModel . SelectedIndex = CbBxCameraModel . Items . Count - 1 ; // Selects AB12CD as model number
await Task . Delay ( 3000 ) ; // Wait for server to start
BtnStartTest_Click ( sender , e ) ;
2025-12-02 12:59:40 +00:00
2025-11-26 14:39:07 +00:00
AddToActionsList ( "RunTime " + stopWatchTest . Elapsed . ToString ( @"hh\:mm\:ss\.ff" ) , Level . LOG ) ;
2025-11-04 12:56:16 +00:00
}
2025-12-23 13:01:15 +00:00
public static Label MakeNewLabel ( string text , bool isRed , int yLoc )
{
return new Label
{
Location = new Point ( 5 , yLoc ) ,
Height = 20 ,
Width = 220 ,
ForeColor = isRed ? Color . Red : Color . LightGreen ,
Text = text ,
Name = "Lbl_" + Guid . NewGuid ( ) ,
AutoSize = false
} ;
}
public void AddLabelToPanel ( string text , bool isRed )
{
int yLoc = PnlLbls . Controls
. OfType < Label > ( )
. Count ( ) * 22 ; // 20 height + 2px spacing
Label lbl = MakeNewLabel ( text , isRed , yLoc ) ;
PnlLbls . Controls . Add ( lbl ) ;
}
2025-12-22 14:37:43 +00:00
2025-09-02 15:32:24 +01:00
}
}