From 4a61a9f8c315e06082de52346952e0e4a6a3f170 Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 30 Jun 2026 19:26:28 -0500 Subject: [PATCH] Fix pod reconfigure timeout; add console installer + package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reconfigure timeout (launcher reinstall of an already-configured pod): - The console pings each configured pod and connects on success, on a loop, and never tore that down — so it kept hammering the pod's old IP with a stale connection while SecureConfig tried to bring the pod up on that address, which timed out. Only a console restart (closing all sockets) cleared it. - DeletePod now Disconnect()s the pod's connection (closes the lingering socket) so delete-to-reconfigure works WITHOUT a console restart. - Reconfiguring a known pod in place now pauses that pod's ping/connect loop (OperationInProgress) and drops its stale connection before SecureConfig, and resumes on completion (success or failure) so it reconnects with the new key. (StopPing kills the ping thread irreversibly, so pause via OperationInProgress.) Note: PodInfo's static mPods registry is dead code (nothing registers), so the real fix is the disconnect, not an unregister. Console deployment: - Console/install.bat: installs the console to C:\Program Files\TeslaConsole, preps the %ProgramData%\Tesla Console data dir (Users: modify), creates a Start Menu shortcut, and adds a per-program inbound firewall rule so it can receive pod discovery beacons. net48 is in-box, no runtime install. - Console/build-package.bat: publishes the console (net48 framework-dependent) to dist\TeslaConsole\App and assembles the package with install.bat. 74 tests green; the pod-config fix is UI/network behavior, validate on a pod. Co-Authored-By: Claude Opus 4.8 --- Console/.gitignore | 6 +- Console/TeslaConsole/SiteManagement.cs | 19 ++++++ Console/build-package.bat | 60 ++++++++++++++++ Console/install.bat | 95 ++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 Console/build-package.bat create mode 100644 Console/install.bat 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