diff --git a/Console/.gitignore b/Console/.gitignore index 06171a2..5c0d7a0 100644 --- a/Console/.gitignore +++ b/Console/.gitignore @@ -2,9 +2,9 @@ [Bb]in/ [Oo]bj/ -# Packaged runnable console (dotnet publish output) + its zip -/TeslaConsole-app/ -/TeslaConsole-app*.zip +# Build & install package (build-package.bat output) + zips +/dist/ +*-pkg.zip # IDE / OS .vs/ diff --git a/Console/TeslaConsole/SiteManagement.cs b/Console/TeslaConsole/SiteManagement.cs index 3033ef0..a9e01eb 100644 --- a/Console/TeslaConsole/SiteManagement.cs +++ b/Console/TeslaConsole/SiteManagement.cs @@ -450,6 +450,12 @@ public class SiteManagement : Form mConfigureButtons.Remove(tuple.A); flpPodsToConfigure.Controls.Add(label); mConfigureLabels.Add(tuple.B.Pod.ID, label); + // Reconfiguring an already-known pod (e.g. after a launcher reinstall): + // pause its ping/connect loop and drop any stale connection to its old IP, + // so the console isn't racing SecureConfig for that address. Resumed when + // configuration completes (see ConfigureWorker_RunWorkerCompleted). + tuple.B.OperationInProgress = true; + tuple.B.Conn?.Disconnect(); ConfigurePod(tuple.A, text.ToUpper(), tuple.B.Pod, tuple.B.Squad); } } @@ -529,6 +535,11 @@ public class SiteManagement : Form Label value = mConfigureLabels[ex.Pod.ID]; flpPodsToConfigure.Controls.Remove(value); mConfigureLabels.Remove(ex.Pod.ID); + // If this was a known pod, resume its ping/connect loop (paused before SecureConfig). + foreach (PodData mPod in mPods) + { + if (mPod.Pod.ID == ex.Pod.ID) { mPod.OperationInProgress = false; break; } + } } else { @@ -545,6 +556,9 @@ public class SiteManagement : Form { if (mPod.Pod.ID == tuple.A.ID) { + // Existing pod reconfigured: resume its ping/connect loop so the console + // reconnects with the new session key (paused before SecureConfig). + mPod.OperationInProgress = false; return; } } @@ -1351,6 +1365,11 @@ public class SiteManagement : Form { dgvPods.Rows.RemoveAt(rowIndex); mPods[rowIndex].StopPing(); + // Close any lingering/half-open connection to the pod's IP. Without this the + // socket + connection state survive until the console process exits — which is + // why deleting a pod previously still required a console restart before it + // could be reconfigured. + mPods[rowIndex].Conn?.Disconnect(); mPods.RemoveAt(rowIndex); } } diff --git a/Console/build-package.bat b/Console/build-package.bat new file mode 100644 index 0000000..c3c7215 --- /dev/null +++ b/Console/build-package.bat @@ -0,0 +1,60 @@ +@echo off +:: ============================================================================= +:: TeslaConsole - Build ^& Package +:: ============================================================================= +:: Publishes the console (net48, framework-dependent) into TeslaConsole\App and +:: assembles the installable package (App\ + install.bat) next to it. net48 is +:: in-box on Windows 10/11, so the target control PC needs no runtime install. +:: +:: Requirements: .NET SDK (6.0+) to drive the build; internet for first restore. +:: +:: Output: +:: TeslaConsole\ +:: install.bat +:: App\ (TeslaConsole.exe + dependencies + RedPlanet\ content) +:: ============================================================================= + +setlocal + +set ROOT=%~dp0 +:: Package under dist\ so it never collides with the TeslaConsole\ SOURCE folder. +set BUILD_DIR=%ROOT%dist\TeslaConsole +set APP_OUT=%BUILD_DIR%\App + +echo. +echo ============================================================ +echo TeslaConsole - Build ^& Package (net48, framework-dependent) +echo Output : %BUILD_DIR% +echo ============================================================ +echo. + +where dotnet >nul 2>&1 +if errorlevel 1 ( + echo ERROR: dotnet not found. Install the .NET SDK from https://dotnet.microsoft.com/download + pause & exit /b 1 +) + +:: Don't publish over a running instance. +taskkill /F /IM TeslaConsole.exe >nul 2>&1 + +echo Publishing TeslaConsole... +if exist "%APP_OUT%" rmdir /s /q "%APP_OUT%" +dotnet publish "%ROOT%TeslaConsole.csproj" -c Release -o "%APP_OUT%" +if errorlevel 1 ( + echo. + echo ERROR: Build failed. + pause & exit /b 1 +) + +if exist "%ROOT%install.bat" copy /y "%ROOT%install.bat" "%BUILD_DIR%\" >nul + +echo. +echo ============================================================ +echo Package built: %BUILD_DIR% +echo ============================================================ +echo. +echo Next steps: +echo 1. Copy the TeslaConsole\ folder to the control PC +echo 2. Run TeslaConsole\install.bat as Administrator +echo. +pause diff --git a/Console/install.bat b/Console/install.bat new file mode 100644 index 0000000..52cc8d4 --- /dev/null +++ b/Console/install.bat @@ -0,0 +1,95 @@ +@echo off +:: ============================================================================= +:: TeslaConsole - Installation Script +:: ============================================================================= +:: Installs the operator console on a control PC. Run as Administrator. +:: Must be run from the package folder produced by build-package.bat: +:: +:: TeslaConsole\ +:: install.bat <- this file +:: App\ +:: TeslaConsole.exe + dependencies + RedPlanet\ (content) +:: +:: The console is .NET Framework 4.8 (framework-dependent) — net48 is in-box on +:: Windows 10/11, so there is no runtime to install. +:: ============================================================================= + +setlocal + +echo ============================================================ +echo TeslaConsole - Installation +echo ============================================================ +echo. + +set ROOT=%~dp0 +set APP_SRC=%ROOT%App +set INSTALL_DIR=C:\Program Files\TeslaConsole +set EXE=%INSTALL_DIR%\TeslaConsole.exe +set DATA_DIR=%ProgramData%\Tesla Console + +:: -- Admin check -------------------------------------------------------------- +net session >nul 2>&1 +if %errorlevel% neq 0 ( + echo ERROR: This script must be run as Administrator. + pause & exit /b 1 +) + +:: -- Verify source ------------------------------------------------------------ +if not exist "%APP_SRC%\TeslaConsole.exe" ( + echo ERROR: TeslaConsole.exe not found in %APP_SRC% + echo Run build-package.bat first, then run install.bat from the package folder. + pause & exit /b 1 +) + +:: -- .NET Framework 4.8 check (informational; 528040 = 4.8) -------------------- +set NETREL=0 +for /f "tokens=3" %%v in ('reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v Release 2^>nul') do set NETREL=%%v +if %NETREL% LSS 528040 ( + echo WARNING: .NET Framework 4.8 was not detected ^(Release=%NETREL%^). + echo It ships in-box with Windows 10/11; install it if the console fails to start. + echo. +) + +:: -- STEP 1: Copy files ------------------------------------------------------- +echo [1/4] Installing to %INSTALL_DIR% ... +taskkill /F /IM TeslaConsole.exe >nul 2>&1 +if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%" +xcopy /E /I /Y /Q "%APP_SRC%\*" "%INSTALL_DIR%\" >nul +if errorlevel 1 ( + echo ERROR: Failed to copy files to %INSTALL_DIR%. + pause & exit /b 1 +) +echo Files copied. + +:: -- STEP 2: Data directory (site config, mission recordings) ----------------- +echo [2/4] Preparing data directory... +if not exist "%DATA_DIR%" mkdir "%DATA_DIR%" +:: Grant the local Users group modify access so a normal operator account can +:: write local.siteconfig / RP Missions when the console is not run elevated. +icacls "%DATA_DIR%" /grant *S-1-5-32-545:(OI)(CI)M /T >nul 2>&1 +echo %DATA_DIR% (Users: modify access) + +:: -- STEP 3: Start Menu shortcut ---------------------------------------------- +echo [3/4] Creating Start Menu shortcut... +powershell -NoProfile -Command "$s=(New-Object -ComObject WScript.Shell).CreateShortcut([Environment]::GetFolderPath('CommonPrograms')+'\TeslaConsole.lnk'); $s.TargetPath='%EXE%'; $s.WorkingDirectory='%INSTALL_DIR%'; $s.IconLocation='%EXE%,0'; $s.Save()" >nul 2>&1 +echo Shortcut created (Start Menu -^> TeslaConsole). + +:: -- STEP 4: Windows Firewall ------------------------------------------------- +:: The console receives UDP RQST discovery beacons from unconfigured pods, so it +:: must be allowed to accept inbound traffic. A per-program rule is enough. +echo [4/4] Allowing TeslaConsole through Windows Firewall... +netsh advfirewall firewall delete rule name="TeslaConsole" >nul 2>&1 +netsh advfirewall firewall add rule name="TeslaConsole" dir=in action=allow program="%EXE%" enable=yes profile=any >nul +echo Firewall rule added. + +:: -- Done --------------------------------------------------------------------- +echo. +echo ============================================================ +echo Installation Complete +echo ============================================================ +echo. +echo Installed to : %INSTALL_DIR% +echo Data dir : %DATA_DIR% +echo Launch from : Start Menu -^> TeslaConsole +echo. +pause