mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 13:01:12 +00:00
Merge branch 'main' into dev
# Conflicts: # .conda/recipe.yaml # .github/workflows/conda-pack-build.yml # recipes/msgs/recipe.yaml # recipes/unilabos/recipe.yaml # scripts/verify_installation.py # setup.py # unilabos/app/main.py # unilabos/app/mq.py # unilabos/app/register.py # unilabos/compile/heatchill_protocol.py # unilabos/compile/separate_protocol.py # unilabos/config/config.py # unilabos/devices/pump_and_valve/runze_backbone.py # unilabos/devices/pump_and_valve/runze_multiple_backbone.py # unilabos/registry/devices/characterization_chromatic.yaml # unilabos/registry/devices/liquid_handler.yaml # unilabos/registry/devices/pump_and_valve.yaml # unilabos/registry/devices/robot_arm.yaml # unilabos/registry/devices/robot_linear_motion.yaml # unilabos/registry/devices/work_station.yaml # unilabos/registry/registry.py # unilabos/registry/resources/organic/workstation.yaml # unilabos/resources/plr_additional_res_reg.py # unilabos/ros/nodes/base_device_node.py # unilabos/ros/nodes/presets/host_node.py # unilabos/ros/nodes/presets/workstation.py # unilabos/ros/nodes/resource_tracker.py # unilabos/utils/environment_check.py # unilabos_msgs/package.xml
This commit is contained in:
98
.github/workflows/deploy-docs.yml
vendored
Normal file
98
.github/workflows/deploy-docs.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
name: Deploy Docs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
branch:
|
||||||
|
description: '要部署文档的分支'
|
||||||
|
required: false
|
||||||
|
default: 'main'
|
||||||
|
type: string
|
||||||
|
deploy_to_pages:
|
||||||
|
description: '是否部署到 GitHub Pages'
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
# 设置 GITHUB_TOKEN 权限以部署到 GitHub Pages
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# 只允许一个并发部署,跳过正在进行和最新排队之间的运行
|
||||||
|
# 但是不取消正在进行的运行,因为我们希望允许这些生产部署完成
|
||||||
|
concurrency:
|
||||||
|
group: 'pages'
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Build documentation
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.inputs.branch || github.ref }}
|
||||||
|
|
||||||
|
- name: Setup Python environment
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y pandoc
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
# Install package in development mode to get version info
|
||||||
|
pip install -e .
|
||||||
|
# Install documentation dependencies
|
||||||
|
pip install -r docs/requirements.txt
|
||||||
|
|
||||||
|
- name: Setup Pages
|
||||||
|
id: pages
|
||||||
|
uses: actions/configure-pages@v4
|
||||||
|
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
|
||||||
|
|
||||||
|
- name: Build Sphinx documentation
|
||||||
|
run: |
|
||||||
|
cd docs
|
||||||
|
# Clean previous builds
|
||||||
|
rm -rf _build
|
||||||
|
# Build HTML documentation
|
||||||
|
python -m sphinx -b html . _build/html -v
|
||||||
|
|
||||||
|
- name: Check build results
|
||||||
|
run: |
|
||||||
|
echo "Documentation build completed, checking output directory:"
|
||||||
|
ls -la docs/_build/html/
|
||||||
|
echo "Checking for index.html:"
|
||||||
|
test -f docs/_build/html/index.html && echo "✓ index.html exists" || echo "✗ index.html missing"
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
|
||||||
|
with:
|
||||||
|
path: docs/_build/html
|
||||||
|
|
||||||
|
# Deploy to GitHub Pages
|
||||||
|
deploy:
|
||||||
|
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
@@ -31,7 +31,7 @@ Join the [Intelligent Organic Chemistry Synthesis Competition](https://bohrium.d
|
|||||||
|
|
||||||
Detailed documentation can be found at:
|
Detailed documentation can be found at:
|
||||||
|
|
||||||
- [Online Documentation](https://readthedocs.dp.tech/Uni-Lab/v0.8.0/)
|
- [Online Documentation](https://dptech-corp.github.io/Uni-Lab-OS/)
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ pip install .
|
|||||||
|
|
||||||
3. Start Uni-Lab System:
|
3. Start Uni-Lab System:
|
||||||
|
|
||||||
Please refer to [Documentation - Boot Examples](https://readthedocs.dp.tech/Uni-Lab/v0.8.0/boot_examples/index.html)
|
Please refer to [Documentation - Boot Examples](https://dptech-corp.github.io/Uni-Lab-OS/boot_examples/index.html)
|
||||||
|
|
||||||
## Message Format
|
## Message Format
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Uni-Lab-OS 是一个用于实验室自动化的综合平台,旨在连接和控
|
|||||||
|
|
||||||
详细文档可在以下位置找到:
|
详细文档可在以下位置找到:
|
||||||
|
|
||||||
- [在线文档](https://readthedocs.dp.tech/Uni-Lab/v0.8.0/)
|
- [在线文档](https://dptech-corp.github.io/Uni-Lab-OS/)
|
||||||
|
|
||||||
## 快速开始
|
## 快速开始
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ pip install .
|
|||||||
|
|
||||||
3. 启动 Uni-Lab 系统:
|
3. 启动 Uni-Lab 系统:
|
||||||
|
|
||||||
请见[文档-启动样例](https://readthedocs.dp.tech/Uni-Lab/v0.8.0/boot_examples/index.html)
|
请见[文档-启动样例](https://dptech-corp.github.io/Uni-Lab-OS/boot_examples/index.html)
|
||||||
|
|
||||||
## 消息格式
|
## 消息格式
|
||||||
|
|
||||||
|
|||||||
13
docs/requirements.txt
Normal file
13
docs/requirements.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Sphinx文档构建依赖
|
||||||
|
sphinx>=7.0.0
|
||||||
|
sphinx-rtd-theme>=2.0.0
|
||||||
|
myst-parser>=2.0.0
|
||||||
|
|
||||||
|
# 用于支持Jupyter notebook文档
|
||||||
|
myst-nb>=1.0.0
|
||||||
|
|
||||||
|
# 用于代码复制按钮
|
||||||
|
sphinx-copybutton>=0.5.0
|
||||||
|
|
||||||
|
# 用于自动摘要生成
|
||||||
|
sphinx-autobuild>=2024.2.4
|
||||||
@@ -4741,7 +4741,6 @@ virtual_stirrer:
|
|||||||
status_types:
|
status_types:
|
||||||
current_speed: float
|
current_speed: float
|
||||||
current_vessel: str
|
current_vessel: str
|
||||||
device_info: dict
|
|
||||||
is_stirring: bool
|
is_stirring: bool
|
||||||
max_speed: float
|
max_speed: float
|
||||||
min_speed: float
|
min_speed: float
|
||||||
@@ -4776,8 +4775,6 @@ virtual_stirrer:
|
|||||||
type: number
|
type: number
|
||||||
current_vessel:
|
current_vessel:
|
||||||
type: string
|
type: string
|
||||||
device_info:
|
|
||||||
type: object
|
|
||||||
is_stirring:
|
is_stirring:
|
||||||
type: boolean
|
type: boolean
|
||||||
max_speed:
|
max_speed:
|
||||||
@@ -4799,7 +4796,6 @@ virtual_stirrer:
|
|||||||
- remaining_time
|
- remaining_time
|
||||||
- max_speed
|
- max_speed
|
||||||
- min_speed
|
- min_speed
|
||||||
- device_info
|
|
||||||
type: object
|
type: object
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
virtual_transfer_pump:
|
virtual_transfer_pump:
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
<<<<<<<< HEAD:unilabos/ros/nodes/presets/workstation.py
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from typing import List, Dict, Any, Optional, TYPE_CHECKING
|
from typing import List, Dict, Any, Optional, TYPE_CHECKING
|
||||||
|
========
|
||||||
|
from pprint import pprint, saferepr, pformat
|
||||||
|
from typing import Union
|
||||||
|
>>>>>>>> main:unilabos/ros/nodes/presets/protocol_node.py
|
||||||
|
|
||||||
import rclpy
|
import rclpy
|
||||||
from rosidl_runtime_py import message_to_ordereddict
|
from rosidl_runtime_py import message_to_ordereddict
|
||||||
@@ -193,8 +198,13 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
|||||||
execute_callback=self._create_protocol_execute_callback(action_name, protocol_steps_generator),
|
execute_callback=self._create_protocol_execute_callback(action_name, protocol_steps_generator),
|
||||||
callback_group=ReentrantCallbackGroup(),
|
callback_group=ReentrantCallbackGroup(),
|
||||||
)
|
)
|
||||||
|
<<<<<<<< HEAD:unilabos/ros/nodes/presets/workstation.py
|
||||||
self.lab_logger().trace(f"发布动作: {action_name}, 类型: {str_action_type}")
|
self.lab_logger().trace(f"发布动作: {action_name}, 类型: {str_action_type}")
|
||||||
return
|
return
|
||||||
|
========
|
||||||
|
|
||||||
|
self.lab_logger().trace(f"发布动作: {action_name}, 类型: {str_action_type}")
|
||||||
|
>>>>>>>> main:unilabos/ros/nodes/presets/protocol_node.py
|
||||||
|
|
||||||
def _create_protocol_execute_callback(self, protocol_name, protocol_steps_generator):
|
def _create_protocol_execute_callback(self, protocol_name, protocol_steps_generator):
|
||||||
async def execute_protocol(goal_handle: ServerGoalHandle):
|
async def execute_protocol(goal_handle: ServerGoalHandle):
|
||||||
@@ -245,10 +255,15 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
|||||||
logs.append(step)
|
logs.append(step)
|
||||||
elif isinstance(step, list):
|
elif isinstance(step, list):
|
||||||
logs.append(step)
|
logs.append(step)
|
||||||
|
<<<<<<<< HEAD:unilabos/ros/nodes/presets/workstation.py
|
||||||
self.lab_logger().info(
|
self.lab_logger().info(
|
||||||
f"Goal received: {protocol_kwargs}, running steps: "
|
f"Goal received: {protocol_kwargs}, running steps: "
|
||||||
f"{json.dumps(logs, indent=4, ensure_ascii=False)}"
|
f"{json.dumps(logs, indent=4, ensure_ascii=False)}"
|
||||||
)
|
)
|
||||||
|
========
|
||||||
|
self.lab_logger().info(f"Goal received: {protocol_kwargs}, running steps: "
|
||||||
|
f"{json.dumps(logs, indent=4, ensure_ascii=False)}")
|
||||||
|
>>>>>>>> main:unilabos/ros/nodes/presets/protocol_node.py
|
||||||
|
|
||||||
time_start = time.time()
|
time_start = time.time()
|
||||||
time_overall = 100
|
time_overall = 100
|
||||||
@@ -263,6 +278,7 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
|||||||
time.sleep(action["action_kwargs"]["time"])
|
time.sleep(action["action_kwargs"]["time"])
|
||||||
step_results.append({"step": i + 1, "action": "wait", "result": "completed"})
|
step_results.append({"step": i + 1, "action": "wait", "result": "completed"})
|
||||||
else:
|
else:
|
||||||
|
<<<<<<<< HEAD:unilabos/ros/nodes/presets/workstation.py
|
||||||
try:
|
try:
|
||||||
result = await self.execute_single_action(**action)
|
result = await self.execute_single_action(**action)
|
||||||
step_results.append({"step": i + 1, "action": action["action_name"], "result": result})
|
step_results.append({"step": i + 1, "action": action["action_name"], "result": result})
|
||||||
@@ -273,6 +289,13 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
|||||||
step_results.append(
|
step_results.append(
|
||||||
{"step": i + 1, "action": action["action_name"], "result": ex.args[0]}
|
{"step": i + 1, "action": action["action_name"], "result": ex.args[0]}
|
||||||
)
|
)
|
||||||
|
========
|
||||||
|
result = await self.execute_single_action(**action)
|
||||||
|
step_results.append({"step": i + 1, "action": action["action_name"], "result": result})
|
||||||
|
ret_info = json.loads(getattr(result, "return_info", "{}"))
|
||||||
|
if not ret_info.get("suc", False):
|
||||||
|
raise RuntimeError(f"Step {i + 1} failed.")
|
||||||
|
>>>>>>>> main:unilabos/ros/nodes/presets/protocol_node.py
|
||||||
elif isinstance(action, list):
|
elif isinstance(action, list):
|
||||||
# 如果是并行动作,同时执行
|
# 如果是并行动作,同时执行
|
||||||
actions = action
|
actions = action
|
||||||
@@ -310,6 +333,7 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 捕获并记录错误信息
|
# 捕获并记录错误信息
|
||||||
|
<<<<<<<< HEAD:unilabos/ros/nodes/presets/workstation.py
|
||||||
str_step_results = [
|
str_step_results = [
|
||||||
{
|
{
|
||||||
k: dict(message_to_ordereddict(v)) if k == "result" and hasattr(v, "SLOT_TYPES") else v
|
k: dict(message_to_ordereddict(v)) if k == "result" and hasattr(v, "SLOT_TYPES") else v
|
||||||
@@ -317,6 +341,9 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
|||||||
}
|
}
|
||||||
for i in step_results
|
for i in step_results
|
||||||
]
|
]
|
||||||
|
========
|
||||||
|
str_step_results = [{k: dict(message_to_ordereddict(v)) if k == "result" and hasattr(v, "SLOT_TYPES") else v for k, v in i.items()} for i in step_results]
|
||||||
|
>>>>>>>> main:unilabos/ros/nodes/presets/protocol_node.py
|
||||||
execution_error = f"{traceback.format_exc()}\n\nStep Result: {pformat(str_step_results)}"
|
execution_error = f"{traceback.format_exc()}\n\nStep Result: {pformat(str_step_results)}"
|
||||||
execution_success = False
|
execution_success = False
|
||||||
self.lab_logger().error(f"协议 {protocol_name} 执行出错: {str(e)} \n{traceback.format_exc()}")
|
self.lab_logger().error(f"协议 {protocol_name} 执行出错: {str(e)} \n{traceback.format_exc()}")
|
||||||
|
|||||||
Reference in New Issue
Block a user