Cascadia PLM integration for FreeCAD 1.x (verified on 1.1.3 / Python 3.11 / PySide6). One "Cascadia PLM" workbench: a toolbar + menu of commands and Qt dialogs for everything richer
| Box | Commands |
|---|---|
| Connection | Connect |
| Create & Link | New Part · Link |
| File Ops | Check Out · Check In · Cancel Check Out · Get Latest |
| Sync | Sync Properties · Push (assembly + BOM — Phase 2) |
| Browse | Search · Status |
| Settings | Settings |
Context is per document, not global. Search and Link carry a multi-select
design filter, New Part picks its design plus where the work goes (main /
an ECO / a workspace, with "New ECO…" inline). Each document remembers its own
design and branch in its CascadiaPLM_* document Meta entries
(File ▸ Project information shows them), and the active document's context is
rendered as a permanent label in the FreeCAD status bar:
Cascadia: TDJ-25 · ECO-000521 · TDJ-25-P-10003-TUBE (in work) · Draft · checked out by me
- Link: each
.FCStdcarriesCascadiaPLM_*keys indoc.Meta(MasterId is the stable anchor; ItemId tracks the working-copy row while on a branch). Operational state (fileIds, hashes, lock flags) lives inDocuments\Cascadia\.cascadia-freecad-cache.json(the workspace root is shared with the SolidWorks add-in; the cache file is separate). - ECO-as-Branch: editing a Released item routes through the guided ECO
flow (
POST /change-orders/{id}/checkout— one call = scope + branch + working copy + reservation). Revisions are assigned by Cascadia at ECO release; the workbench shows "(in work on ECO-000123)" until then. - Check In runs an ordered protocol: file version (new fileId every time) → optional STEP upload + convert job (GLB/thumbnail for the web viewer) → optional thumbnail → metadata commit (always, on branches — it's what earns the revision bump) → reservation release. Item reservations and vault file locks are independent and both handled.
- Interchange geometry: an item that only holds STEP/GLB/STL opens via
import; FreeCAD saves it as
.FCStdnext to it and a later Check In promotes the FreeCAD file to the item's primary CAD model. - Auth: sign in once; the workbench mints a personal API key and stores it
in Windows Credential Manager (file fallback with 0600 on other OSes).
All calls are
Authorization: Bearer csc_…. - Property sync: FreeCAD document fields (Label, Comment, Company, … and
any Meta key; Mass from volume × material density, Material from
ShapeMaterial) ↔ Cascadia fields via an editable mapping. Revision/State only ever flow PLM → FreeCAD.
powershell -File install.ps1 # junction %APPDATA%\FreeCAD\v1-1\Mod\Cascadia -> .\Cascadia (edits are live)
powershell -File install.ps1 -Production # copy instead of junction
powershell -File uninstall.ps1Then start FreeCAD, pick the Cascadia PLM workbench, and click Connect. Use Tools ▸ Customize ▸ Toolbars if you want the Cascadia toolbars visible in other workbenches too.
Cascadia/ the FreeCAD Mod folder (junction target)
├─ InitGui.py / Init.py / package.xml
├─ resources/icons/*.svg generated by tools/make_icons.py
└─ cascadia_plm/
├─ config.py ids, paths, toolbar layout
├─ plm/ PURE (stdlib only, no FreeCAD) — unit-tested
│ ├─ client.py CascadiaApiClient (urllib; Bearer; cookie-jar bootstrap)
│ ├─ models.py DTOs (camelCase JSON ↔ dataclasses, `extra` kept)
│ ├─ pdm_workflows.py protocol brain: resolve / peek / check-out / check-in / cancel / get-latest
│ ├─ context_catalog.py designs + branch choices (main / ECOs / workspaces)
│ ├─ property_sync.py mapping, diff rows, push payload
│ ├─ config_manager.py %AppData%\Cascadia\FreeCAD\config.json
│ ├─ credential_store.py Credential Manager (ctypes) / file fallback
│ ├─ file_manager.py workspace + SHA-256 cache
│ ├─ document_link.py CascadiaPLM_* ↔ DocumentLink
│ └─ multipart.py, logger.py, cancellation.py
├─ freecad_bridge/ FreeCAD-aware, no GUI: doc.Meta link, metadata/mass/material, STEP/PNG export, open/save/reload/import
├─ gui/ PySide dialogs (Connect, Settings, Search, Link, New Part, ECO guide, Check In, Sync Properties, Status, …)
├─ controller.py PlmController: every command (port of PlmController.cs)
├─ commands.py Gui.Command wrappers + enable rules
└─ workbench.py workbench, document observer, status-bar label
tests/ pytest: pure layer (http.server stub, fake API) + bridge script driven inside FreeCADCmd
tools/api_harness.py headless exerciser: auth | smoke | roundtrip | ecoflow
server-patches/ .fcstd upload allowlist patch for cascadia-private
python -m pytest tests -q # pure layer + FreeCADCmd bridge test (auto-skips without FreeCAD)
python tools/api_harness.py smoke http://localhost:3001 <csc_key>
python tools/api_harness.py auth http://localhost:3001 <email> <password>The 3D-viewer conversion (STEP → GLB/thumbnail) needs the server's job queue
and CAD workers (RabbitMQ via Docker); without them the server rejects
/convert and the workbench simply skips it (item, file and link are still
created; the message box says so). Untick "Export STEP for the web 3D viewer"
in Settings if you don't run the workers.
Dev server: API direct on :3001 (npm run dev in cascadia-private); the
TDJ-25 demo dataset (npm run demo:fetch && npm run db:seed:demo) is the
intended smoke-test set — its STEP files open in FreeCAD via Search ▸ Download
& Open.
- Phase 0 + Phase 1 feature-complete at parity with the SolidWorks add-in (connect, link, new part, search, status, check out/in/cancel, get latest, property sync, STEP pipeline, guided ECO flow); Push (assembly + BOM) is the Phase 2 placeholder, exactly as in the SolidWorks add-in.
- Pure layer + FreeCAD bridge covered by automated tests; in-app smoke via
tools/gui_smoke.py(see CLAUDE.md). End-to-end against a live Cascadia server is done withtools/api_harness.py.
GNU Affero General Public License v3.0 or later — see LICENSE, matching the Cascadia PLM core.