Correct drift that predated IOModbus and persisted after the merge: - RUNNING.md: retitled to the suite; run commands for all 3 modules; per-module data locations; generalized architecture map and simulator note. - SUITE-ARCHITECTURE.md: 'one real module' -> three; sequencing steps 4/5 done. - DESIGN-SYSTEM.md: theme path corrected to cim_suite/core/ui/theme (it moved in the monorepo reshape); import examples fully qualified. - REBUILD-STATUS.md: hover help now spans all modules (IOModbus included). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.5 KiB
Running & Building the CIMTechniques Service Suite
Modern rebuild in Python 3 + PySide6 of the legacy VB6 service tools, unified into one
app. Three modules are built: DA-12 (da12), DA-07 (da07), and IOModbus
(iomodbus).
Prerequisites
- Windows 10/11
- Python 3.11+ (developed on 3.13)
- For building the installer: Inno Setup 6
Developer setup
# from the repo root
py -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]"
Run it
# Against a simulator (no hardware needed) — best for a first look. Swap the module
# id for da07 or iomodbus to launch the other tools:
.venv\Scripts\python -m cim_suite.shell.app --module da12 --simulate
.venv\Scripts\python -m cim_suite.shell.app --module da07 --simulate
.venv\Scripts\python -m cim_suite.shell.app --module iomodbus --simulate
# Against real hardware on a serial port:
.venv\Scripts\python -m cim_suite.shell.app --module da12 --port COM3
# With no arguments it opens the suite launcher landing page (a card per module):
.venv\Scripts\python -m cim_suite.shell.app
Inside the app you can also pick the port via Connect… in the toolbar; the choice is remembered in a small JSON config under your user app-data folder.
Tests & linting
.venv\Scripts\python -m pytest -q
.venv\Scripts\python -m ruff check cim_suite tests
The whole suite runs without hardware (each module ships an in-memory simulator that
speaks its real wire protocol — DA-12/DA-07 stations and a Modbus slave bank for
IOModbus). UI tests run headless via pytest-qt.
Build the standalone app
.venv\Scripts\pyinstaller --noconfirm --distpath packaging\dist --workpath packaging\build packaging\suite.spec
Produces packaging\dist\CIM-Service-Suite\CIM-Service-Suite.exe — a self-contained folder
with no Python/VB6 runtime or OCX dependencies. The bundle's entry point is
packaging\suite_launcher.py (it imports the package absolutely so app.py's
relative imports resolve — running app.py directly as the entry causes
"attempted relative import with no known parent package").
Verify it — don't just eyeball that a window appears. A bundled windowed app shows a modal error dialog and stays alive on an unhandled exception, so "the process is still running" does NOT mean it booted. Use the self-test hook, which boots then auto-exits, and check the exit code:
$env:SUITE_SELFTEST="1"
.\packaging\dist\CIM-Service-Suite\CIM-Service-Suite.exe --module da12 --simulate
echo "exit=$LASTEXITCODE" # 0 = booted cleanly; non-zero = failed to start
Remove-Item Env:\SUITE_SELFTEST
# Then a normal interactive run to click around:
.\packaging\dist\CIM-Service-Suite\CIM-Service-Suite.exe --module da12 --simulate
tests/test_packaging_entry.py runs this same boot check against the launcher in CI.
Build the installer
After the PyInstaller build, compile the Inno Setup script:
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" packaging\installer.iss
Produces packaging\Output\DA12-Service-Setup.exe. For the cleanest customer
experience (and to avoid SmartScreen/AV warnings), sign both CIM-Service-Suite.exe
and the installer with an Authenticode certificate — see the commented SignTool
line in installer.iss.
Where data lives
Each module scopes its own files under the user app-data folder (never next to the
exe), via cim_suite/modules/<id>/config.py:
- Config (last COM port, logging toggle):
<module>_config.json - Calibration history:
DACal.csv - Measurement logs:
DA-Logs\(DA-12/DA-07) orIO-Logs\(IOModbus) - IOModbus additionally reads its device catalog from the bundled
resources/IOModbus.txt, overridable by dropping anIOModbus.txtin the data folder.
Architecture (quick map)
Five layers per module under cim_suite/modules/<id>/ (where <id> is da12,
da07, or iomodbus), on a shared cim_suite/core + cim_suite/shell:
| Layer | Package | Responsibility |
|---|---|---|
| Protocol (pure) | modules/<id>/protocol |
framing/codecs/decode/encode — no I/O, fully tested |
| Transport | modules/<id>/transport |
in-memory simulator (real serial is shared in core) |
| Domain | modules/<id>/domain |
models, calibration, logging, the controller hub |
| UI | modules/<id>/ui |
PySide6 window, tabs/grids, dialogs |
See CLAUDE.md for the per-module protocol differences, and
docs/superpowers/specs/ and docs/superpowers/plans/ for the designs and plans.