schwitters/openswx

GitHub: schwitters/openswx

跨平台 C++20 工具包,读取 SolidWorks 文件并构建 BOM,提供本地解析库与 Web 查询服务。

Stars: 0 | Forks: 0

# openswx 一个跨平台的工具包,用于读取 SolidWorks® 文件(`.SLDPRT`、`.SLDASM`、`.SLDDRW`),无需安装 SolidWorks、COM 或任何仅 Windows 的依赖。 ## 概述 该仓库包含三个独立的组件: ``` openswx/ ├── libopenswx/ Pure C++20 library — parses SolidWorks files ├── libopenbom/ Pure C++20 library — builds hierarchical BOMs (built on libopenswx) └── asmbox/ HTTP server + CLI tool — built on top of both libraries ``` ### libopenswx 一个零依赖的 C++20 静态库,可读取两种 SolidWorks 文件格式: | 格式 | 版本 | 检测 | |--------|----------|-----------| | 现代分块格式 | SW 2015 及更新版本 | 字节扫描标记 `14 00 06 00 08 00` | | OLE2 复合文档 | SW 2014 及更早版本 | 魔术数 `D0 CF 11 E0 A1 B1 1A E1` | 每个文档提取的数据: - **文档类型**(零件 / 装配体 / 工程图) - **模型版本** 编号 - **全局自定义属性**(`docProps/custom.xml`) - **文档预览** PNG 缩略图 - 每个 **配置**:名称、自定义属性、质量属性(重心、体积、表面积、质量、惯性张量)、预览 PNG、切割清单项(焊件)、装配体组件引用 - 每个 **图纸页**:名称、预览 PNG、视图引用 ### libopenbom 一个 C++20 静态库,用于从 SolidWorks 文件构建层次化、递归的物料清单(BOM)。它将 Windows 组件路径解析为主机文件系统路径,聚合相同实例,并将结果序列化为 JSON。 关键类型: | 类型 | 描述 | |------|-------------| | `BomTransformer` | 入口点 — 调用 `Build(path)` 生成 `Bom` | | `BomTransformerConfig` | 控制配置选择、过滤、递归深度、路径解析 | | `PathResolverConfig` | 通过前缀替换和目录搜索将 Windows 路径映射到主机路径 | | `BomItem` | BOM 树中的一行(名称、数量、属性、子项) | | `Bom` | 根 `BomItem` 加上累积的警告 | | `JsonWriter` | 将 `Bom` 序列化为 JSON 字符串或文件 | ### asmbox 一个 Linux HTTP 服务器,允许你上传 SolidWorks 文件的 ZIP 归档并在 Web UI 中浏览提取的元数据、BOM 树和自定义属性。 它还附带 `swx_dump`,一个命令行工具,用于打印任意单个 SolidWorks 文件的 JSON 表示。 ## 先决条件 | 软件包 | 最低版本 | 用途 | |---------|----------------|---------| | CMake | 3.20 | 构建系统 | | GCC 或 Clang | C++20 兼容(GCC 12+) | 编译器 | | zlib (`libz-dev`) | 任意 | libopenswx 中的原始 Deflate 解压缩 | | pugixml (`libpugixml-dev`) | 1.11+ | libopenswx 中的 XML 解析 | | nlohmann/json (`nlohmann-json3-dev`) | 3.x | asmbox 中的 JSON 序列化 | | SQLite3 (`libsqlite3-dev`) | 3.x | asmbox 中的结果缓存和 BOM 持久化 | | libzip (`libzip-dev`) | 1.x | asmbox 中的 ZIP 上传处理 | 以下内容由 CMake 的 `FetchContent` 在配置时自动获取: - **Crow** v1.2.0 — HTTP 服务器框架 - **plog** v1.1.10 — 日志记录 - **googletest** v1.15.2 — 单元测试 在 Debian/Ubuntu 上,使用以下命令安装系统软件包: ``` sudo apt install cmake build-essential \ libz-dev libpugixml-dev nlohmann-json3-dev \ libsqlite3-dev libzip-dev ``` ## 构建 ``` cd openswx # 配置(自动下载 Crow、plog、googletest) cmake -S . -B build -DCMAKE_BUILD_TYPE=Release # 构建所有内容 cmake --build build -j$(nproc) ``` 这将在 `build/asmbox/` 中生成三个二进制文件: | 二进制文件 | 描述 | |--------|-------------| | `asmbox` | HTTP 服务器(默认端口 8087) | | `swx_dump` | CLI 工具 — 打印 JSON 到标准输出 | | `asmbox_tests` | 单元测试套件 | 运行测试: ``` ./build/asmbox/asmbox_tests ``` ## 教程 ### 1. 使用 `swx_dump` 检查单个文件 ``` ./build/asmbox/swx_dump /path/to/part.SLDPRT | python3 -m json.tool ``` 示例输出(截断): ``` { "doc_type": 1, "version": 17000, "global_properties": { "Desc1": "Winkelstecker", "Material": "Messing" }, "configurations": [ { "name": "Standard", "properties": { "Configuration": "Standard" }, "mass_properties": { "mass": 0.0251, "volume": 2.5e-06, "surface_area": 0.00654, "center_of_gravity": { "x": -0.003, "y": 0.0, "z": 0.013 } } } ] } ``` `doc_type` 值:`1` = 零件,`2` = 装配体,`3` = 工程图。 所有质量/几何值均采用 SI 单位(kg、m、m²、m³)。 ### 2. 运行 asmbox Web 服务器 ``` ./build/asmbox/asmbox ``` 服务器在 `http://0.0.0.0:8087` 启动。 在浏览器中打开 `http://localhost:8087` 访问上传界面。 **上传 ZIP 归档**:包含一个或多个 SolidWorks 文件。服务器将: 1. 解压归档到 `ASMBOX_DATA_DIR//` 2. 扫描 `.SLDPRT`、`.SLDASM` 和 `.SLDDRW` 文件 3. 立即分析每个文件并将结果缓存在 SQLite 中 4. 返回找到的文件列表(JSON 格式) **浏览工作区**:在侧边栏中浏览工作区,点击任意文件查看其解析的文档数据和属性。 **查看 BOM**:在装配体和工程图文件的“物料清单”标签页中查看。 BOM 会通过解析工作区目录中的组件路径递归构建。 **配置属性**:按工作区配置可见属性,并分配语义角色(`part_number`、`description`、`material`、`revision`)。被指定为 `part_number` 的属性在持久化 BOM 时使用。 **配置文件**:允许你定义与工作区无关的可重用映射和转换规则(它们在删除工作区或重启服务器后仍然保留): - **映射**:将 SolidWorks 自定义属性名称映射到输出中的结构化字段(Part、BomItem 或 Bom Thrift 实体)。 - **规则**:实时转换 BOM 树: - `kaufgruppe` — 保留匹配项但移除其子项。 - `non_bom` — 完全排除匹配项。 - `phantom` — 排除匹配项并将其子项提升一级。 通过在 URL 后添加 `?profile=` 来应用配置文件到 BOM 请求。 **可调整面板**:在“详细信息”视图、“物料清单”视图和侧边栏中拖动分隔条来调整面板大小。宽度会保存在 `localStorage` 中。 ### 3. 通过环境变量配置 所有设置均使用 `ASMBOX_` 前缀,并具有合理的默认值: | 变量 | 默认值 | 描述 | |----------|---------|-------------| | `ASMBOX_BIND_ADDR` | `0.0.0.0` | 绑定的 IP 地址 | | `ASMBOX_PORT` | `8087` | TCP 端口 | | `ASMBOX_DATA_DIR` | `$TMPDIR/sw_portal` | 工作区和 SQLite 数据库的根目录 | | `ASMBOX_TEMPLATE_DIR` | `templates` | 包含 Crow HTML 模板的目录 | SQLite 数据库(`global.sqlite`)存储在 `ASMBOX_DATA_DIR` 中,并在服务器重启后保持持久化。 架构使用 `CREATE TABLE IF NOT EXISTS` 创建,因此重启服务器不会清除缓存的数据或配置文件。 示例 — 在非默认端口上运行,仅绑定到本地主机,并使用持久化数据目录: ``` ASMBOX_PORT=9090 \ ASMBOX_BIND_ADDR=127.0.0.1 \ ASMBOX_DATA_DIR=/var/lib/asmbox \ ASMBOX_TEMPLATE_DIR=/usr/share/asmbox/templates \ ./build/asmbox/asmbox ``` ### 4. 在你自己的项目中使用 libopenswx 将 libopenswx 添加到子目录并链接: ``` add_subdirectory(path/to/openswx/libopenswx) target_link_libraries(my_target PRIVATE openswx) ``` 最小用法: ``` #include "openswx/document.h" auto result = openswx::SwxDocument::Open("part.SLDPRT"); if (!result.ok()) { std::cerr << result.error() << "\n"; return 1; } const openswx::Document& doc = result.value().doc(); for (const auto& cfg : doc.configurations) { std::cout << "Config: " << cfg.name << "\n"; if (cfg.mass_properties) { std::cout << " Mass: " << cfg.mass_properties->mass << " kg\n"; } for (const auto& [key, val] : cfg.properties) { std::cout << " " << key << " = " << val << "\n"; } } ``` ### 5. 在你自己的项目中使用 libopenbom 同时添加两个库并链接: ``` add_subdirectory(path/to/openswx/libopenswx) add_subdirectory(path/to/openswx/libopenbom) target_link_libraries(my_target PRIVATE openbom openswx) ``` 最小用法: ``` #include "openbom/transformer.h" #include "openbom/json_writer.h" openbom::BomTransformerConfig cfg; // Map Windows component paths to the host filesystem. cfg.path_resolver.substitutions.push_back( {"C:\\Engineering\\Parts\\", "/mnt/nas/parts/"}); // Or simply search a local directory by filename. cfg.path_resolver.search_dirs.push_back("/data/parts"); cfg.path_resolver.recursive_search = true; cfg.path_resolver.case_insensitive = true; openbom::BomTransformer transformer(cfg); auto result = transformer.Build("/data/top_asm.SLDASM"); if (!result.ok()) { std::cerr << result.error() << "\n"; return 1; } const openbom::Bom& bom = result.value(); for (const auto& w : bom.warnings) std::cerr << "Warning: " << w << "\n"; openbom::JsonWriter writer; writer.WriteToFile(bom, "bom.json"); ``` `BomTransformerConfig` 选项: | 字段 | 默认值 | 描述 | |-------|---------|-------------| | `configuration_name` | `"" | SolidWorks 配置名称;空值表示使用第一个 | | `include_suppressed` | `false` | 包含被抑制的装配体组件 | | `include_hidden` | `false` | 包含隐藏的装配体组件 | | `include_exclude_from_bom` | `false` | 包含标记为“排除 BOM”的组件 | | `expand_cut_lists` | `true` | 将焊件切割清单项作为子项添加 | | `max_depth` | `0` | 最大递归深度(0 = 无限制) | | `path_resolver` | — | 用于 Windows 到主机路径映射的 `PathResolverConfig` | | `item_callback` | `nullptr` | 每个 `BomItem` 的可选后处理回调 | ## REST API 参考 | 方法 | 路径 | 描述 | |--------|------|-------------| | `GET` | `/` | Web UI(`index.html`) | | `GET` | `/api/workspaces` | 以 JSON 列出所有工作区 | | `DELETE` | `/api/workspaces/` | 删除工作区及其文件 | | `POST` | `/upload` | 上传包含 `file` 字段(ZIP)的 `multipart/form-data` 请求 | | `GET` | `/api/doc//` | 单个文件的解析文档 JSON(缓存在 SQLite 中) | | `GET` | `/api/workspaces//props` | 属性名称及工作区配置 | | `POST` | `/api/workspaces//props` | 保存属性配置(可见性、角色) | | `GET` | `/api/profiles` | 列出所有配置文件 | | `POST` | `/api/profiles` | 创建配置文件 `{name, description}` | | `GET` | `/api/profiles/` | 完整配置文件(名称、描述、映射、规则) | | `PUT` | `/api/profiles/` | 保存完整配置文件(更新映射和规则) | | `DELETE` | `/api/profiles/` | 删除配置文件 | | `GET` | `/api/bom//` | 构建 BOM;可选通过 `?profile=` 应用配置文件 | `` 是工作区内相对文件路径的 Base64url 编码。 ## 架构说明 ``` SolidWorks file │ ▼ libopenswx::ParseFile() ├─ IsOle2() → ParseOle2Format() (OLE2 FAT/directory/sector chain) └─ ParseModernFormat() (marker scan + ROL-decoded names + raw deflate) │ ▼ StreamMap (flat map: stream-path → decompressed bytes) │ ├─ ParsePropertyXml() docProps/custom.xml, Config-N-Properties.xml ├─ ParseMassProperties() docProps/ISolidWorksInformation.xml ├─ ParseCutlistXml() docProps/Config-N-Cutlist-Properties.xml ├─ ParseComponents() swXmlContents/COMPINSTANCETREE ├─ ParseSheetNames() SheetPreviews/SheetNames └─ ExtractPng() PreviewPNG / Config-N-PreviewPNG libopenbom::BomTransformer::Build() │ ├─ Detect file type (part / assembly / drawing) ├─ Select active configuration ├─ Recursively expand assembly components │ ├─ PathResolver: Windows path → host path │ │ ├─ Prefix substitution rules │ │ └─ Directory search (shallow + optional recursive) │ └─ Aggregate identical instances (quantity > 1) └─ Return Bom { root: BomItem, warnings: [...] } asmbox (server.cc) │ ├─ POST /upload → unzip, scan, eager-analyze all SWX files ├─ GET /api/doc → load or analyze + cache in SQLite ├─ GET /api/bom → BomTransformer::Build() + ApplyBomRules(profile) │ + SaveBom() to SQLite (surrogate-key schema) ├─ GET|POST /api/workspaces//props → property config CRUD └─ /api/profiles[/] → profile CRUD (workspace-independent) SQLite schema (global.sqlite, persistent) ├─ workspaces, files, documents, properties ├─ boms, bom_items (surrogate-key BOM persistence) ├─ property_configs (per-workspace property visibility + roles) └─ profiles, profile_mappings, profile_rules (workspace-independent) ``` 两种文件格式均会自动检测。库在读取文件时不会写入磁盘,也不会执行任何系统调用。
标签:Bill of Materials, BOM, C++, C++20, HTTP服务器, JSON序列化, SolidWorks, Web服务, 云资产清单, 切割清单, 开源, 技术文档, 数据提取, 数据擦除, 文件解析, 网络测绘, 自定义属性, 装配引用, 质量属性, 路径映射, 逆向工程, 递归构建, 配置文件驱动, 零依赖, 静态库, 预览缩略图