mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-04 13:25:13 +00:00
Upgrade to py 3.11.14; ROS2 Humble 0.7; unilabos 0.10.16
Workbench example, adjust log level, and ci check (#220) * TestLatency Return Value Example & gitignore update * Adjust log level & Add workbench virtual example & Add not action decorator & Add check_mode & * Add CI Check Fix/workstation yb revision (#217) * Revert log change & update registry * Revert opcua client & move electrolyte node Workstation yb merge dev ready 260113 (#216) * feat(bioyond): 添加计算实验设计功能,支持化合物配比和滴定比例参数 * feat(bioyond): 添加测量小瓶功能,支持基本参数配置 * feat(bioyond): 添加测量小瓶配置,支持新设备参数 * feat(bioyond): 更新仓库布局和尺寸,支持竖向排列的测量小瓶和试剂存放堆栈 * feat(bioyond): 优化任务创建流程,确保无论成功与否都清理任务队列以避免重复累积 * feat(bioyond): 添加设置反应器温度功能,支持温度范围和异常处理 * feat(bioyond): 调整反应器位置配置,统一坐标格式 * feat(bioyond): 添加调度器启动功能,支持任务队列执行并处理异常 * feat(bioyond): 优化调度器启动功能,添加异常处理并更新相关配置 * feat(opcua): 增强节点ID解析兼容性和数据类型处理 改进节点ID解析逻辑以支持多种格式,包括字符串和数字标识符 添加数据类型转换处理,确保写入值时类型匹配 优化错误提示信息,便于调试节点连接问题 * feat(registry): 新增后处理站的设备配置文件 添加后处理站的YAML配置文件,包含动作映射、状态类型和设备描述 * 添加调度器启动功能,合并物料参数配置,优化物料参数处理逻辑 * 添加从 Bioyond 系统自动同步工作流序列的功能,并更新相关配置 * fix:兼容 BioyondReactionStation 中 workflow_sequence 被重写为 property * fix:同步工作流序列 * feat: remove commented workflow synchronization from `reaction_station.py`. * 添加时间约束功能及相关配置 * fix:自动更新物料缓存功能,添加物料时更新缓存并在删除时移除缓存项 * fix:在添加物料时处理字符串和字典返回值,确保正确更新缓存 * fix:更新奔曜错误处理报送为物料变更报送,调整日志记录和响应消息 * feat:添加实验报告简化功能,去除冗余信息并保留关键信息 * feat: 添加任务状态事件发布功能,监控并报告任务运行、超时、完成和错误状态 * fix: 修复添加物料时数据格式错误 * Refactor bioyond_dispensing_station and reaction_station_bioyond YAML configurations - Removed redundant action value mappings from bioyond_dispensing_station. - Updated goal properties in bioyond_dispensing_station to use enums for target_stack and other parameters. - Changed data types for end_point and start_point in reaction_station_bioyond to use string enums (Start, End). - Simplified descriptions and updated measurement units from μL to mL where applicable. - Removed unused commands from reaction_station_bioyond to streamline the configuration. * fix:Change the material unit from μL to mL * fix:refresh_material_cache * feat: 动态获取工作流步骤ID,优化工作流配置 * feat: 添加清空服务端所有非核心工作流功能 * fix:修复Bottle类的序列化和反序列化方法 * feat:增强材料缓存更新逻辑,支持处理返回数据中的详细信息 * Add debug log * feat(workstation): update bioyond config migration and coin cell material search logic - Migrate bioyond_cell config to JSON structure and remove global variable dependencies - Implement material search confirmation dialog auto-handling - Add documentation: 20260113_物料搜寻确认弹窗自动处理功能.md and 20260113_配置迁移修改总结.md * Refactor module paths for Bioyond devices in YAML configuration files - Updated the module path for BioyondDispensingStation in bioyond_dispensing_station.yaml to reflect the new directory structure. - Updated the module path for BioyondReactionStation and BioyondReactor in reaction_station_bioyond.yaml to align with the revised organization of the codebase. * fix: WareHouse 的不可哈希类型错误,优化父节点去重逻辑 * refactor: Move config from module to instance initialization * fix: 修正 reaction_station 目录名拼写错误 * feat: Integrate material search logic and cleanup deprecated files - Update coin_cell_assembly.py with material search dialog handling - Update YB_warehouses.py with latest warehouse configurations - Remove outdated documentation and test data files * Refactor: Use instance attributes for action names and workflow step IDs * refactor: Split tipbox storage into left and right warehouses * refactor: Merge tipbox storage left and right into single warehouse --------- Co-authored-by: ZiWei <131428629+ZiWei09@users.noreply.github.com> Co-authored-by: Andy6M <xieqiming1132@qq.com> fix: WareHouse 的不可哈希类型错误,优化父节点去重逻辑 fix parent_uuid fetch when bind_parent_id == node_name 物料更新也是用父节点进行报送 Add None conversion for tube rack etc. Add set_liquid example. Add create_resource and test_resource example. Add restart. Temp allow action message. Add no_update_feedback option. Create session_id by edge. bump version to 0.10.15 temp cancel update req
This commit is contained in:
@@ -85,7 +85,7 @@ Verification:
|
||||
-------------
|
||||
|
||||
The verify_installation.py script will check:
|
||||
- Python version (3.11.11)
|
||||
- Python version (3.11.14)
|
||||
- ROS2 rclpy installation
|
||||
- UniLabOS installation and dependencies
|
||||
|
||||
@@ -104,7 +104,7 @@ Build Information:
|
||||
|
||||
Branch: {branch}
|
||||
Platform: {platform}
|
||||
Python: 3.11.11
|
||||
Python: 3.11.14
|
||||
Date: {build_date}
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
214
scripts/dev_install.py
Normal file
214
scripts/dev_install.py
Normal file
@@ -0,0 +1,214 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Development installation script for UniLabOS.
|
||||
Auto-detects Chinese locale and uses appropriate mirror.
|
||||
|
||||
Usage:
|
||||
python scripts/dev_install.py
|
||||
python scripts/dev_install.py --no-mirror # Force no mirror
|
||||
python scripts/dev_install.py --china # Force China mirror
|
||||
python scripts/dev_install.py --skip-deps # Skip pip dependencies installation
|
||||
|
||||
Flow:
|
||||
1. pip install -e . (install unilabos in editable mode)
|
||||
2. Detect Chinese locale
|
||||
3. Use uv to install pip dependencies from requirements.txt
|
||||
4. Special packages (like pylabrobot) are handled by environment_check.py at runtime
|
||||
"""
|
||||
|
||||
import locale
|
||||
import subprocess
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
# Tsinghua mirror URL
|
||||
TSINGHUA_MIRROR = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
|
||||
|
||||
|
||||
def is_chinese_locale() -> bool:
|
||||
"""
|
||||
Detect if system is in Chinese locale.
|
||||
Same logic as EnvironmentChecker._is_chinese_locale()
|
||||
"""
|
||||
try:
|
||||
lang = locale.getdefaultlocale()[0]
|
||||
if lang and ("zh" in lang.lower() or "chinese" in lang.lower()):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def run_command(cmd: list, description: str, retry: int = 2) -> bool:
|
||||
"""Run command with retry support."""
|
||||
print(f"[INFO] {description}")
|
||||
print(f"[CMD] {' '.join(cmd)}")
|
||||
|
||||
for attempt in range(retry + 1):
|
||||
try:
|
||||
result = subprocess.run(cmd, check=True, timeout=600)
|
||||
print(f"[OK] {description}")
|
||||
return True
|
||||
except subprocess.CalledProcessError as e:
|
||||
if attempt < retry:
|
||||
print(f"[WARN] Attempt {attempt + 1} failed, retrying...")
|
||||
else:
|
||||
print(f"[ERROR] {description} failed: {e}")
|
||||
return False
|
||||
except subprocess.TimeoutExpired:
|
||||
print(f"[ERROR] {description} timed out")
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def install_editable(project_root: Path, use_mirror: bool) -> bool:
|
||||
"""Install unilabos in editable mode using pip."""
|
||||
cmd = [sys.executable, "-m", "pip", "install", "-e", str(project_root)]
|
||||
if use_mirror:
|
||||
cmd.extend(["-i", TSINGHUA_MIRROR])
|
||||
|
||||
return run_command(cmd, "Installing unilabos in editable mode")
|
||||
|
||||
|
||||
def install_requirements_uv(requirements_file: Path, use_mirror: bool) -> bool:
|
||||
"""Install pip dependencies using uv (installed via conda-forge::uv)."""
|
||||
cmd = ["uv", "pip", "install", "-r", str(requirements_file)]
|
||||
if use_mirror:
|
||||
cmd.extend(["-i", TSINGHUA_MIRROR])
|
||||
|
||||
return run_command(cmd, "Installing pip dependencies with uv", retry=2)
|
||||
|
||||
|
||||
def install_requirements_pip(requirements_file: Path, use_mirror: bool) -> bool:
|
||||
"""Fallback: Install pip dependencies using pip."""
|
||||
cmd = [sys.executable, "-m", "pip", "install", "-r", str(requirements_file)]
|
||||
if use_mirror:
|
||||
cmd.extend(["-i", TSINGHUA_MIRROR])
|
||||
|
||||
return run_command(cmd, "Installing pip dependencies with pip", retry=2)
|
||||
|
||||
|
||||
def check_uv_available() -> bool:
|
||||
"""Check if uv is available (installed via conda-forge::uv)."""
|
||||
try:
|
||||
subprocess.run(["uv", "--version"], capture_output=True, check=True)
|
||||
return True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Development installation script for UniLabOS")
|
||||
parser.add_argument("--china", action="store_true", help="Force use China mirror (Tsinghua)")
|
||||
parser.add_argument("--no-mirror", action="store_true", help="Force use default PyPI (no mirror)")
|
||||
parser.add_argument(
|
||||
"--skip-deps", action="store_true", help="Skip pip dependencies installation (only install unilabos)"
|
||||
)
|
||||
parser.add_argument("--use-pip", action="store_true", help="Use pip instead of uv for dependencies")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Determine project root
|
||||
script_dir = Path(__file__).parent
|
||||
project_root = script_dir.parent
|
||||
requirements_file = project_root / "unilabos" / "utils" / "requirements.txt"
|
||||
|
||||
if not (project_root / "setup.py").exists():
|
||||
print(f"[ERROR] setup.py not found in {project_root}")
|
||||
sys.exit(1)
|
||||
|
||||
print("=" * 60)
|
||||
print("UniLabOS Development Installation")
|
||||
print("=" * 60)
|
||||
print(f"Project root: {project_root}")
|
||||
print()
|
||||
|
||||
# Determine mirror usage based on locale
|
||||
if args.no_mirror:
|
||||
use_mirror = False
|
||||
print("[INFO] Mirror disabled by --no-mirror flag")
|
||||
elif args.china:
|
||||
use_mirror = True
|
||||
print("[INFO] China mirror enabled by --china flag")
|
||||
else:
|
||||
use_mirror = is_chinese_locale()
|
||||
if use_mirror:
|
||||
print("[INFO] Chinese locale detected, using Tsinghua mirror")
|
||||
else:
|
||||
print("[INFO] Non-Chinese locale detected, using default PyPI")
|
||||
|
||||
print()
|
||||
|
||||
# Step 1: Install unilabos in editable mode
|
||||
print("[STEP 1] Installing unilabos in editable mode...")
|
||||
if not install_editable(project_root, use_mirror):
|
||||
print("[ERROR] Failed to install unilabos")
|
||||
print()
|
||||
print("Manual fallback:")
|
||||
if use_mirror:
|
||||
print(f" pip install -e {project_root} -i {TSINGHUA_MIRROR}")
|
||||
else:
|
||||
print(f" pip install -e {project_root}")
|
||||
sys.exit(1)
|
||||
|
||||
print()
|
||||
|
||||
# Step 2: Install pip dependencies
|
||||
if args.skip_deps:
|
||||
print("[INFO] Skipping pip dependencies installation (--skip-deps)")
|
||||
else:
|
||||
print("[STEP 2] Installing pip dependencies...")
|
||||
|
||||
if not requirements_file.exists():
|
||||
print(f"[WARN] Requirements file not found: {requirements_file}")
|
||||
print("[INFO] Skipping dependencies installation")
|
||||
else:
|
||||
# Try uv first (faster), fallback to pip
|
||||
if args.use_pip:
|
||||
print("[INFO] Using pip (--use-pip flag)")
|
||||
success = install_requirements_pip(requirements_file, use_mirror)
|
||||
elif check_uv_available():
|
||||
print("[INFO] Using uv (installed via conda-forge::uv)")
|
||||
success = install_requirements_uv(requirements_file, use_mirror)
|
||||
if not success:
|
||||
print("[WARN] uv failed, falling back to pip...")
|
||||
success = install_requirements_pip(requirements_file, use_mirror)
|
||||
else:
|
||||
print("[WARN] uv not available (should be installed via: mamba install conda-forge::uv)")
|
||||
print("[INFO] Falling back to pip...")
|
||||
success = install_requirements_pip(requirements_file, use_mirror)
|
||||
|
||||
if not success:
|
||||
print()
|
||||
print("[WARN] Failed to install some dependencies automatically.")
|
||||
print("You can manually install them:")
|
||||
if use_mirror:
|
||||
print(f" uv pip install -r {requirements_file} -i {TSINGHUA_MIRROR}")
|
||||
print(" or:")
|
||||
print(f" pip install -r {requirements_file} -i {TSINGHUA_MIRROR}")
|
||||
else:
|
||||
print(f" uv pip install -r {requirements_file}")
|
||||
print(" or:")
|
||||
print(f" pip install -r {requirements_file}")
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print("Installation complete!")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print("Note: Some special packages (like pylabrobot) are installed")
|
||||
print("automatically at runtime by unilabos if needed.")
|
||||
print()
|
||||
print("Verify installation:")
|
||||
print(' python -c "import unilabos; print(unilabos.__version__)"')
|
||||
print()
|
||||
print("If you encounter issues, you can manually install dependencies:")
|
||||
if use_mirror:
|
||||
print(f" uv pip install -r unilabos/utils/requirements.txt -i {TSINGHUA_MIRROR}")
|
||||
else:
|
||||
print(" uv pip install -r unilabos/utils/requirements.txt")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user