144 lines
4.5 KiB
Python
144 lines
4.5 KiB
Python
"""Finger-compatible sensor-bundle presets for the 3D dashboard."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
|
|
|
|
|
|
def _repo_root_candidates() -> list[Path]:
|
|
here = Path(__file__).resolve()
|
|
return [
|
|
Path.cwd(),
|
|
here.parents[3], # examples/gui/viewer3d -> repo root
|
|
]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SensorBundlePreset:
|
|
label: str
|
|
bundle_dir: str
|
|
config: str
|
|
export_dir: str
|
|
|
|
|
|
def _packaged_finger_preset() -> SensorBundlePreset | None:
|
|
"""Use logical names that resolve through the installed wheel sensors/ layout."""
|
|
try:
|
|
from orisys.configs import resolve_sensor_bundle
|
|
except ImportError:
|
|
return None
|
|
bundle = resolve_sensor_bundle("finger")
|
|
if bundle is None:
|
|
return None
|
|
return SensorBundlePreset(
|
|
label="ORY-FINGER",
|
|
bundle_dir="sensors/finger",
|
|
config="finger",
|
|
export_dir=DEFAULT_FINGER_EXPORT_DIR,
|
|
)
|
|
|
|
|
|
def _load_manifest(bundle_root: Path) -> dict:
|
|
path = bundle_root / "manifest.json"
|
|
if not path.is_file():
|
|
return {}
|
|
try:
|
|
return json.loads(path.read_text(encoding="utf-8"))
|
|
except Exception:
|
|
return {}
|
|
|
|
|
|
def _bundle_from_root(bundle_root: Path, *, label: str | None = None) -> SensorBundlePreset | None:
|
|
sensor_json = bundle_root / "sensor.json"
|
|
if not sensor_json.is_file():
|
|
return None
|
|
manifest = _load_manifest(bundle_root)
|
|
assets_dir = manifest.get("assets_dir", "assets/30fps-0703")
|
|
if not isinstance(assets_dir, str) or not assets_dir.strip():
|
|
assets_dir = "assets/30fps-0703"
|
|
rel_bundle = bundle_root.as_posix()
|
|
for root in _repo_root_candidates():
|
|
try:
|
|
rel_bundle = bundle_root.relative_to(root).as_posix()
|
|
break
|
|
except ValueError:
|
|
continue
|
|
# Packaged / checkout sensors/finger: keep resolvable product names, not absolute paths.
|
|
if rel_bundle.replace("\\", "/").endswith("sensors/finger") or bundle_root.name == "finger":
|
|
return SensorBundlePreset(
|
|
label=label or "ORY-FINGER",
|
|
bundle_dir="sensors/finger",
|
|
config="finger",
|
|
export_dir=DEFAULT_FINGER_EXPORT_DIR,
|
|
)
|
|
return SensorBundlePreset(
|
|
label=label or "ORY-FINGER",
|
|
bundle_dir=rel_bundle,
|
|
config=f"{rel_bundle}/sensor.json",
|
|
export_dir=f"{rel_bundle}/{assets_dir}".replace("\\", "/"),
|
|
)
|
|
|
|
|
|
def default_finger_bundle() -> SensorBundlePreset:
|
|
packaged = _packaged_finger_preset()
|
|
if packaged is not None:
|
|
return packaged
|
|
for root in _repo_root_candidates():
|
|
preset = _bundle_from_root(root / "sensors" / "finger", label="ORY-FINGER")
|
|
if preset is not None:
|
|
return preset
|
|
return SensorBundlePreset(
|
|
label="ORY-FINGER",
|
|
bundle_dir="sensors/finger",
|
|
config="finger",
|
|
export_dir=DEFAULT_FINGER_EXPORT_DIR,
|
|
)
|
|
|
|
|
|
def discover_sensor_bundle_presets() -> list[SensorBundlePreset]:
|
|
"""Return finger-compatible sensor bundle presets."""
|
|
presets = [default_finger_bundle()]
|
|
known_dirs = {presets[0].bundle_dir.replace("\\", "/")}
|
|
|
|
for root in _repo_root_candidates():
|
|
sensors_root = root / "sensors"
|
|
if not sensors_root.is_dir():
|
|
continue
|
|
for child in sorted(sensors_root.iterdir()):
|
|
if not child.is_dir():
|
|
continue
|
|
if child.name != "finger":
|
|
continue
|
|
preset = _bundle_from_root(child, label="ORY-FINGER")
|
|
if preset is None:
|
|
continue
|
|
key = preset.bundle_dir.replace("\\", "/")
|
|
if key in known_dirs:
|
|
continue
|
|
presets.append(preset)
|
|
known_dirs.add(key)
|
|
break
|
|
|
|
return presets
|
|
|
|
|
|
def sensor_bundle_preset_index(
|
|
config: str,
|
|
export_dir: str,
|
|
presets: list[SensorBundlePreset],
|
|
) -> int:
|
|
config = (config or "").strip().replace("\\", "/")
|
|
export_dir = (export_dir or "").strip().replace("\\", "/")
|
|
for idx, preset in enumerate(presets):
|
|
if config == preset.config and export_dir == preset.export_dir:
|
|
return idx
|
|
if config in ("finger", "dd02", "dd02-ov") and preset.config == "finger":
|
|
return idx
|
|
if config.endswith("/sensor.json") and export_dir.endswith("/" + Path(preset.export_dir).name):
|
|
return idx
|
|
return -1
|