| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- """故障 → 3D 部件对照表(data/fault_part_map.csv 的读写)。
- 列:model, alarm_type, device_point, device_part, part, camera_x/y/z, target_x/y/z
- - device_point / device_part 支持多值,用 ``|`` 分隔(未来一个故障多个点)。
- - part 为前端部件标签(createUniqueName 约定:如 ``三维立体_1687``);一个部件一行。
- - camera_/target_ 为该故障的“场景位置”(参考系坐标,空=未记录)。
- """
- import csv
- import os
- from typing import Any
- from config import DATA_DIR, FAULT_MAP_CSV
- FIELDS = [
- "model", "alarm_type", "device_point", "device_part", "part",
- "camera_x", "camera_y", "camera_z", "target_x", "target_y", "target_z",
- ]
- # 初始种子(一个部件一行,场景位置留空)。
- SEED: list[list[str]] = [
- ["压缩机2326-3000-one.glb", "润滑油压力故障", "YSJ_5", "润滑油压力", "三维立体_1687"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_11", "链轮端振动", "三维立体_3815"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_11", "链轮端振动", "三维立体_3814"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_101"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_97"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_98"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_130"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_135"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_134"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_138"],
- ["压缩机2326-3000-one.glb", "振动故障", "YSJ_10", "联轴器端振动", "三维立体_3813"],
- ]
- def _ensure_file() -> None:
- if FAULT_MAP_CSV.exists():
- return
- DATA_DIR.mkdir(parents=True, exist_ok=True)
- with FAULT_MAP_CSV.open("w", encoding="utf-8", newline="") as handle:
- writer = csv.writer(handle)
- writer.writerow(FIELDS)
- for row in SEED:
- writer.writerow(row + [""] * 6)
- def _read() -> list[dict[str, str]]:
- _ensure_file()
- with FAULT_MAP_CSV.open("r", encoding="utf-8", newline="") as handle:
- return [
- {key: (row.get(key) or "").strip() for key in FIELDS}
- for row in csv.DictReader(handle)
- ]
- def _write(rows: list[dict[str, str]]) -> None:
- DATA_DIR.mkdir(parents=True, exist_ok=True)
- tmp = FAULT_MAP_CSV.parent / (FAULT_MAP_CSV.name + ".tmp")
- with tmp.open("w", encoding="utf-8", newline="") as handle:
- writer = csv.writer(handle)
- writer.writerow(FIELDS)
- for row in rows:
- writer.writerow([row.get(key, "") for key in FIELDS])
- os.replace(tmp, FAULT_MAP_CSV)
- def _split(value: str) -> list[str]:
- return [item.strip() for item in str(value or "").split("|") if item.strip()]
- def _vector(row: dict[str, str], x: str, y: str, z: str) -> list[float] | None:
- try:
- return [float(row[x]), float(row[y]), float(row[z])]
- except (ValueError, KeyError):
- return None
- def _to_api(row: dict[str, str]) -> dict[str, Any]:
- return {
- "model": row["model"],
- "alarm_type": row["alarm_type"],
- "device_point": row["device_point"],
- "device_part": row["device_part"],
- "part": row["part"],
- "camera": _vector(row, "camera_x", "camera_y", "camera_z"),
- "target": _vector(row, "target_x", "target_y", "target_z"),
- }
- def list_rows() -> list[dict[str, Any]]:
- return [_to_api(row) for row in _read() if row.get("part")]
- def remap_parts(model: str, mapping: dict[str, str]) -> int:
- """按 旧label→新label 映射更新指定模型的 part 列,返回改动行数。"""
- if not mapping:
- return 0
- rows = _read()
- changed = 0
- for row in rows:
- if row["model"] != model:
- continue
- part = row.get("part", "")
- if part in mapping:
- row["part"] = mapping[part]
- changed += 1
- if changed:
- _write(rows)
- return changed
- def set_scene_position(
- model: str,
- alarm_type: str,
- device_point: str,
- camera: list[float],
- target: list[float],
- ) -> int:
- rows = _read()
- wanted = set(_split(device_point))
- changed = 0
- for row in rows:
- if row["model"] != model or row["alarm_type"] != alarm_type:
- continue
- row_points = set(_split(row["device_point"]))
- if wanted and not (wanted & row_points):
- continue
- row["camera_x"], row["camera_y"], row["camera_z"] = (
- str(camera[0]), str(camera[1]), str(camera[2]),
- )
- row["target_x"], row["target_y"], row["target_z"] = (
- str(target[0]), str(target[1]), str(target[2]),
- )
- changed += 1
- if changed:
- _write(rows)
- return changed
|