Building and deploying¶
Both control tools live in this repository. Their build and deploy paths are different and described separately below.
ADCL WinSoft¶
The Python application is packaged as a single-file Windows .exe via PyInstaller. Build is a Windows operation — the .exe is for Windows, the NI-DAQmx bindings only exist on Windows, and the build tooling has been validated only on the lab PC.
Dev install (after git pull)¶
From a Windows command prompt or PowerShell:
This xcopys the package source into C:\Users\kshit\.venvs\adcl_winsoft\Lib\site-packages\adcl_winsoft\. The reason we do not pip install -e . over the WSL UNC share is that the share is slow and the editable install is unreliable across the boundary. See the PyInstaller quirks note.
Dev run¶
This activates the venv and runs python -m adcl_winsoft. Use this for any change-iterate-test loop; do not rebuild the .exe for every edit.
Building the .exe¶
What this does:
- Stages source from the WSL repo to
C:\Users\kshit\.adcl_winsoft_build\viaxcopy(much faster than reading via the WSL share). - Activates the venv.
- Runs
pyinstaller --noconfirm --clean adcl_winsoft.spec. - Copies the resulting
dist\ADCL WinSoft.exeintocode\adcl_winsoft\release\and toE:\Wind_tunnel\ADCLWinSoft\on the lab PC.
Total build time on the lab PC is about 2 minutes. The resulting binary is ~65 MB, single-file, console=False.
What the spec file does¶
adcl_winsoft.spec is a hand-written PyInstaller spec, not an auto-generated one. The notable parts:
datas=carries the bundled Roboto fonts fromsrc/adcl_winsoft/resources/fonts/.copy_metadata()calls bundle package metadata fornidaqmx,nitypes,hightime,deprecation,pymodbus,argon2_cffi,PySide6,pyqtgraph. Without these, the.execrashes at first import onimportlib.metadata.version(...)calls. See PyInstaller quirks note.hiddenimports=listspymodbussubmodules that PyInstaller's static analyzer does not catch.excludes=removes large modules that are imported transitively but not used (tkinter, scipy submodules, etc.) to keep the binary small.
If you add a new third-party dependency to pyproject.toml, ask yourself:
- Does it call
importlib.metadata.version(...)on itself or anything it imports? If yes, add it tocopy_metadata(). - Does it have submodules that are imported via string lookup or
importlib? If yes, add them tohiddenimports. - Test the bundled
.exe, not just the dev run. The dev run will not catch metadata bugs.
Admin password¶
tools/init_admin.py was the original CLI for setting the admin password. It is now legacy — first-run dialogs in __main__.py handle it interactively. The CLI is kept around because it is useful for unattended bring-up.
WindTunnelControl.ps1¶
The PowerShell tool needs no build step. Deployment is a copy.
Deploy after editing¶
From the WSL side (in the repository working copy):
deploy.ps1 copies WindTunnelControl.ps1 and a .cmd launcher to E:\Wind_tunnel\AeroWare\. From there, the operator runs the launcher.
Why deploy alongside AeroWare¶
E:\Wind_tunnel\AeroWare\ is the directory the existing operators look in. Putting the new tool there avoids a "where is the tunnel software?" moment for anyone returning to the lab after a few months. It is not a technical requirement; the script will run from anywhere.
Versioning¶
Neither tool has a formal version-tagging discipline yet. The source in this repository is the truth; the deployed copies are derivatives. To know what version is on the lab PC, look at the file mtimes and compare to the git log of the source.
If we end up shipping ADCL WinSoft to anyone outside this lab, a semver tag inside pyproject.toml plus a CHANGELOG.md entry per release should be added.
Where the release binary lives¶
code/adcl_winsoft/release/ADCL WinSoft.exe is the most recent built binary, committed to the repository so a fresh clone of the repo on the lab PC can be deployed without rebuilding. The release directory has its own README.md describing what is there.