从 CSV 批量导入资产
本指南展示如何从 CSV 文件在孪生中批量创建 RealityAsset。每一行定义一个资产名称和一个孪生空间中的定向边界框。该工作流程使用 Client Credentials 流程和 write:asset 作用域。
- 一个配置为 Client Credentials 的 OAuth 应用
- 作用域:
read:basic、read:hierarchy、write:asset - 你的
client_id和client_secret - 对目标孪生具有内容访问权限和编辑权限
- 要创建资产的孪生 ID
何时使用此模式
Section titled “何时使用此模式”当你已经在 Prevu3D 之外拥有资产定义时,请使用 CSV 驱动的导入,例如:
- 从 CMMS 或 ERP 系统导出的带 3D 坐标的设备清单
- 来自外部工具的勘测或标记结果
- 从另一个平台迁移,其中资产以孪生坐标定位
每次 API 调用创建一个资产。脚本遍历 CSV 行,并为每个条目调用 POST /v1/twin/{twinId}/assets。
CSV 格式
Section titled “CSV 格式”电子表格必须包含一个标题行。必需列:
| 列 | 映射到 | 说明 |
|---|---|---|
Description | 资产 name | RealityAsset 的显示名称 |
Manual_X | 框中心 x | 孪生空间中框中心的 X 坐标 |
Manual_Y | 框中心 y | 孪生空间中框中心的 Y 坐标 |
Manual_Z | 框中心 z | 孪生空间中框中心的 Z 坐标 |
Manual_Box_X | 框尺寸 x | 边界框的宽度 |
Manual_Box_Y | 框尺寸 y | 边界框的深度 |
Manual_Box_Z | 框尺寸 z | 边界框的高度 |
示例:
Description,Manual_X,Manual_Z,Manual_Y,Manual_Box_X,Manual_Box_Z,Manual_Box_YPump A,6.27,-5.10,187.12,0.35,0.64,0.33Valve B,8.84,-3.14,189.41,2.99,1.11,4.69坐标必须与孪生使用相同的坐标系。如果你在 RealityTwin 中手动定位了资产,请以孪生空间导出或记录值。旋转默认为单位值;如果你需要定向体积,API 会在每个框上接受一个可选的 rotation 四元数。
flowchart LR A["1. Authenticate"] --> B["2. Read CSV rows"] B --> C["3. Build workingStructure"] C --> D["4. POST asset per row"] D --> E["5. Review results"]
| 步骤 | 端点 | 你会得到什么 |
|---|---|---|
| 身份验证 | POST /oauth/token | 访问令牌 |
| 解析 API URL | GET /oauth/api-info | 区域 apiUrl |
| 创建资产 | POST /v1/twin/{twinId}/assets | 每行一个新资产 ID |
资产有效负载结构
Section titled “资产有效负载结构”每一行成为一个带有包含单个定向框的 workingStructure 的资产:
{ "name": "Pump A", "workingStructure": { "boxes": [ { "center": { "x": 6.27, "y": 187.12, "z": -5.10 }, "size": { "x": 0.35, "y": 0.33, "z": 0.64 }, "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 } } ] }}要在创建时分配资产类型,请添加 assetTypeId 以及你组织中配置的某个类型的 UUID。有关如何在 RealityPlatform 中定义类型,请参阅资产类型。
步骤 1 — 身份验证
Section titled “步骤 1 — 身份验证”使用 Client Credentials 获取访问令牌:
POST https://cloud-api.prevu3d.com/oauth/tokenAuthorization: Basic base64(client_id:client_secret)Content-Type: application/x-www-form-urlencoded
grant_type=client_credentialsGET https://cloud-api.prevu3d.com/oauth/api-infoAuthorization: Bearer {access_token}步骤 2 — 从 CSV 创建资产
Section titled “步骤 2 — 从 CSV 创建资产”POST {api_url}/v1/twin/{twinId}/assetsAuthorization: Bearer {access_token}Content-Type: application/json
{ "name": "Pump A", "workingStructure": { "boxes": [ { "center": { "x": 6.27, "y": 187.12, "z": -5.10 }, "size": { "x": 0.35, "y": 0.33, "z": 0.64 }, "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 } } ] }}成功的响应返回创建的资产,包括其 id。为每个 CSV 行重复此操作。
import base64import csvfrom pathlib import Path
import requests
CLIENT_ID = "your-client-id"CLIENT_SECRET = "your-client-secret"CLOUD_API_BASE = "https://cloud-api.prevu3d.com"TWIN_ID = "your-twin-id"CSV_FILE = Path("assets.csv")
credentials = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()token_response = requests.post( f"{CLOUD_API_BASE}/oauth/token", data={"grant_type": "client_credentials"}, headers={"Authorization": f"Basic {credentials}"},)token_response.raise_for_status()access_token = token_response.json()["access_token"]headers = {"Authorization": f"Bearer {access_token}"}
api_info = requests.get(f"{CLOUD_API_BASE}/oauth/api-info", headers=headers).json()api_url = api_info["apiUrl"].rstrip("/")
def api_post(path: str, body: dict) -> dict: response = requests.post(f"{api_url}{path}", json=body, headers=headers) response.raise_for_status() return response.json()
def oriented_box(cx: float, cy: float, cz: float, sx: float, sy: float, sz: float) -> dict: return { "center": {"x": cx, "y": cy, "z": cz}, "size": {"x": sx, "y": sy, "z": sz}, "rotation": {"x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0}, }
with CSV_FILE.open(newline="", encoding="utf-8") as handle: rows = list(csv.DictReader(handle))
created = []errors = []
for row in rows: name = row["Description"].strip() body = { "name": name, "workingStructure": { "boxes": [ oriented_box( cx=float(row["Manual_X"]), cy=float(row["Manual_Y"]), cz=float(row["Manual_Z"]), sx=float(row["Manual_Box_X"]), sy=float(row["Manual_Box_Y"]), sz=float(row["Manual_Box_Z"]), ) ] }, }
try: asset = api_post(f"/v1/twin/{TWIN_ID}/assets", body) print(f"[OK] {name} -> {asset['id']}") created.append(asset) except requests.HTTPError as error: print(f"[ERR] {name} -> {error.response.status_code} {error.response.text}") errors.append(name)
print(f"\nCreated: {len(created)} / Errors: {len(errors)}")查找孪生 ID
Section titled “查找孪生 ID”孪生 ID 是你内容层级中孪生节点的 UUID。你可以:
- 在孪生打开时从 RealityPlatform URL 复制它
- 使用
GET /v1/nodes/{organizationId}/browse浏览层级,并定位一个type: "Twin"的节点
大型导入的技巧
Section titled “大型导入的技巧”- 合理分批。 API 每个请求创建一个资产。对于数百行,如果遇到速率限制,请添加短暂延迟或退避。
- 先验证坐标。 在运行完整文件之前,先导入单个测试行。
- 在 RealityTwin 中使用草稿模式,当你想在其他用户看到之前审查资产时。除非你的集成针对草稿工作流程,否则通过 API 创建的资产会立即出现在孪生中。
- 稍后附加元数据。 创建后,使用
PATCH /v1/twin/{twinId}/assets/{assetId}/metadata添加属性值。请参阅 API 参考中的资产端点。
下一步是什么?
Section titled “下一步是什么?”- 在 Client Credentials 流程指南中设置身份验证。
- 了解资产在孪生工作区中的工作方式:使用 RealityAsset。
- 在 API 参考中浏览资产端点。