-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture and Packages
PyCommander is a small monorepo of cooperating packages plus a thin runtime that locates and runs the bundled Simplicity Commander executable. This page explains how the pieces fit together — useful if you are contributing, debugging an installation, or just curious about what happens under the hood.
silabs-pycommander (meta-package: clean install UX)
├── silabs-pycommander-cli (CLI flavor; bundles commander-cli executable)
│ └── silabs-pycommander-core
└── silabs-pycommander-gui (GUI flavor; bundles commander executable) [extra: gui]
└── silabs-pycommander-core
silabs-pycommander-core (the actual Python framework — no executable)
-
pycommander-corecontains all the real logic: theCommanderBaseclass, the command modules, the high-levelAdapter/Target/AemStreamBaseclasses, the subprocessRunner, the typed dataclasses, and the error types. It contains no Commander executable and is not usable on its own. -
pycommander-cliandpycommander-guiare flavor packages. Each one:- bundles a platform-specific Simplicity Commander archive under an
_archive/resource directory, - exposes flavor-specific
Commander,Adapter,TargetandAemStreamclasses that subclass the*Baseclasses from core and hard-wirecli=True/cli=False, - provides a console entry point (
pycommander-cli/pycommander-gui).
- bundles a platform-specific Simplicity Commander archive under an
-
pycommanderis a meta-package: it depends onpycommander-cli(and onpycommander-guivia theguiextra) and provides the user-facingpycommandercommand andimport pycommander.
When you import pycommander or run pycommander, the GUI flavor is preferred when present:
try:
from pycommander_gui import Commander # GUI if installed
CLI = False
except ImportError:
from pycommander_cli import Commander # otherwise CLI
CLI = TrueIf neither flavor is installed, importing fails with a helpful message telling you to pip install silabs-pycommander-cli or silabs-pycommander-gui.
Pure-Python though it is, each flavor wheel carries a platform-specific Commander archive. On first use, pycommander_core._ensure_commander.ensure_commander() makes sure the executable exists:
- It locates the bundled archive (
*.zipon macOS/Windows,*.tar.bzon Linux) inside the flavor package's_archive/resources. - It computes a short SHA-256 hash of that archive.
- It extracts the archive (once) into a per-user cache directory:
user_cache_dir("pycommander", "silabs") / <archive-hash>. The hash in the path means a new Commander version lands in a fresh directory and is re-extracted automatically. - It returns the path to the platform-specific executable inside that cache.
Extraction is platform-aware: ditto on macOS, tar on Linux, and PowerShell Expand-Archive on Windows. The executable's expected relative path per platform lives in pycommander_core.paths:
| Platform | CLI executable | GUI executable |
|---|---|---|
| Windows | Simplicity Commander CLI/commander-cli.exe |
Simplicity Commander/commander.exe |
| macOS | Commander-cli.app/Contents/MacOS/commander-cli |
Commander.app/Contents/MacOS/commander |
| Linux | commander-cli/commander-cli |
commander/commander |
You can bypass all of this by passing an explicit executable_path= to Commander (or PyCommanderCLI), which is handy for testing against a specific Commander build.
All hardware/CLI interaction funnels through pycommander_core.runner.Runner:
-
run(*args, json_format=True)runs Commander synchronously viasubprocess.run(...). Whenjson_formatis true (the default),--jsonis appended so output can be parsed as JSON. The call uses a timeout (default 300 seconds,CommanderBase.default_timeout_s).- A
TimeoutExpiredbecomes a PythonTimeoutError. - A non-zero exit becomes a typed exception: return code
-1/255→PyCommanderInputError,-2/254→PyCommanderRuntimeError, anything else →PyCommanderError. See Error-Handling.
- A
-
open(*args)starts Commander asynchronously (asubprocess.Popen) for streaming use cases such asAemStream. The runner can thensendCtrlC,terminate,kill,wait, and gracefullyclosethe process. -
Logging. If a
log_file_pathwas supplied, every invocation is appended to the log with a timestamp. See Logging. -
Windows niceties. On Windows the runner sets
CREATE_NO_WINDOW, suppresses the GPF crash dialog, and usesCREATE_NEW_PROCESS_GROUPfor async processes (so Ctrl-Break can be delivered).
CommanderBase.__init__ instantiates one command object per CLI suite and attaches it as an attribute, deriving the attribute name from the class name:
AdapterCommand -> commander.adapter
FlashCommand -> commander.flash
DeviceCommand -> commander.device
...
Each command class subclasses BaseCommand, which provides helpers for assembling CLI arguments — connection options (--serialno/--ip/--identifybyserialport), debug options (--speed/--tif/--irpre/--drpre), the --device option, and value formatters for ranges, patches, regions, tokens and ELF sections. Each public method builds an argument list and calls self._run(...), which returns the parsed-JSON dict.
The full surface is documented in the Command-Reference.
On top of the command layer sit the task-oriented classes, which parse Commander's JSON into the typed dataclasses in Data-Types:
-
AdapterBase→ flavorAdapter— adapter info, reset, firmware upgrade, supply voltage, VCOM, energy analysis. -
Target— target info, flashing, erasing, CTUNE, protection, security, keys, region config, SE firmware. -
AemStreamBase→ flavorAemStream— an iterable, unbounded AEM measurement stream.
pycommander/
├── README.md
├── CODE_OF_CONDUCT.md
├── archives/ # platform Commander archives used at release time
├── scripts/
│ └── run_tests.py # discovers & runs all package test suites
├── .github/workflows/
│ ├── unittest-and-coverage.yml
│ └── build-wheels-and-publish.yml
└── packages/
├── pycommander/ # meta-package
├── pycommander-cli/ # CLI flavor (bundles commander-cli)
├── pycommander-gui/ # GUI flavor (bundles commander)
└── pycommander-core/ # the framework
└── src/pycommander_core/
├── commander_base.py # CommanderBase
├── adapter_base.py # AdapterBase
├── target.py # Target
├── aemstream_base.py # AemStreamBase
├── runner.py # subprocess Runner
├── types.py # dataclasses / enums
├── errors.py # exception hierarchy
├── paths.py # per-platform executable paths
├── _ensure_commander.py# extract bundled executable
└── commands/ # one module per CLI suite
See Contributing-and-Development for how these are tested.
PyCommander · GitHub · Simplicity Commander docs · Licensed under the Silicon Labs MSLA
Getting started
Using PyCommander
Topics
Command reference
- Overview
- adapter · aem · vcom · ctune
- device · flash · verify · readmem · extflash
- security
- tokens · nvm3 · littlefs
- convert · ebl · gbl3 · gbl4 · ota · rps · postbuild
- util · serial · mfg917
Contributing