5.1 KiB
AGENTS.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Also follow the monorepo-level rules in ../AGENTS.md.
Build & Development
# Install in editable mode (requires mamba env with python 3.11)
pip install -e .
uv pip install -r unilabos/utils/requirements.txt
# Run with a device graph
unilab --graph <graph.json> --config <config.py> --backend ros
unilab --graph <graph.json> --config <config.py> --backend simple # no ROS2 needed
# Common CLI flags
unilab --app_bridges websocket fastapi # communication bridges
unilab --test_mode # simulate hardware, no real execution
unilab --check_mode # CI validation of registry imports
unilab --skip_env_check # skip auto-install of dependencies
unilab --visual rviz|web|disable # visualization mode
unilab --is_slave # run as slave node
# Workflow upload subcommand
unilab workflow_upload -f <workflow.json> -n <name> --tags tag1 tag2
# Tests
pytest tests/ # all tests
pytest tests/resources/test_resourcetreeset.py # single test file
pytest tests/resources/test_resourcetreeset.py::TestClassName::test_method # single test
Architecture
Startup Flow
unilab CLI → unilabos/app/main.py:main() → loads config → builds registry → reads device graph (JSON/GraphML) → starts backend thread (ROS2/simple) → starts FastAPI web server + WebSocket client.
Core Layers
Registry (unilabos/registry/): Singleton Registry class discovers and catalogs all device types, resource types, and communication devices from YAML definitions. Device types live in registry/devices/*.yaml, resources in registry/resources/, comms in registry/device_comms/. The registry resolves class paths to actual Python classes via utils/import_manager.py.
Resource Tracking (unilabos/resources/resource_tracker.py): Pydantic-based ResourceDict → ResourceDictInstance → ResourceTreeSet hierarchy. ResourceTreeSet is the canonical in-memory representation of all devices and resources, used throughout the system. Graph I/O is in resources/graphio.py (reads JSON/GraphML device topology files into nx.Graph + ResourceTreeSet).
Device Drivers (unilabos/devices/): 30+ hardware drivers organized by device type (liquid_handling, hplc, balance, arm, etc.). Each driver is a Python class that gets wrapped by ros/device_node_wrapper.py:ros2_device_node() to become a ROS2 node with publishers, subscribers, and action servers.
ROS2 Layer (unilabos/ros/): device_node_wrapper.py dynamically wraps any device class into ROS2DeviceNode (defined in ros/nodes/base_device_node.py). Preset node types in ros/nodes/presets/ include host_node, controller_node, workstation, serial_node, camera. Messages use custom unilabos_msgs (pre-built, distributed via releases).
Protocol Compilation (unilabos/compile/): 20+ protocol compilers (add, centrifuge, dissolve, filter, heatchill, stir, pump, etc.) that transform YAML protocol definitions into executable sequences.
Communication (unilabos/device_comms/): Hardware communication adapters — OPC-UA client, Modbus PLC, RPC, and a universal driver. app/communication.py provides a factory pattern for WebSocket client connections to the cloud.
Web/API (unilabos/app/web/): FastAPI server with REST API (api.py), Jinja2 template pages (pages.py), and HTTP client for cloud communication (client.py). Runs on port 8002 by default.
Configuration System
- Config classes in
unilabos/config/config.py:BasicConfig,WSConfig,HTTPConfig,ROSConfig— all class-level attributes, loaded from Python config files - Config files are
.pyfiles with matching class names (seeconfig/example_config.py) - Environment variables override with prefix
UNILABOS_(e.g.,UNILABOS_BASICCONFIG_PORT=9000) - Device topology defined in graph files (JSON with node-link format, or GraphML)
Key Data Flow
- Graph file →
graphio.read_node_link_json()→(nx.Graph, ResourceTreeSet, resource_links) ResourceTreeSet+Registry→initialize_device.initialize_device_from_dict()→ROS2DeviceNodeinstances- Device nodes communicate via ROS2 topics/actions or direct Python calls (simple backend)
- Cloud sync via WebSocket (
app/ws_client.py) and HTTP (app/web/client.py)
Test Data
Example device graphs and experiment configs are in unilabos/test/experiments/ (not tests/). Registry test fixtures in unilabos/test/registry/.
Code Conventions
- Code comments and log messages in simplified Chinese
- Python 3.11+, type hints expected
- Pydantic models for data validation (
resource_tracker.py) - Singleton pattern via
@singletondecorator (utils/decorator.py) - Dynamic class loading via
utils/import_manager.py— device classes resolved at runtime from registry YAML paths - CLI argument dashes auto-converted to underscores for consistency
Licensing
- Framework code: GPL-3.0
- Device drivers (
unilabos/devices/): DP Technology Proprietary License — do not redistribute