mirror of
https://github.com/deepmodeling/Uni-Lab-OS
synced 2026-04-24 00:19:57 +00:00
use gitee to install pylabrobot
fix virtual import
This commit is contained in:
@@ -12,6 +12,15 @@ from typing import Dict, Any, List
|
|||||||
import networkx as nx
|
import networkx as nx
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
# Windows 中文系统 stdout 默认 GBK,无法编码 banner / emoji 日志中的 Unicode 字符
|
||||||
|
# 强制 stdout/stderr 用 UTF-8,避免 print 触发 UnicodeEncodeError 导致进程崩溃
|
||||||
|
if sys.platform == "win32":
|
||||||
|
for _stream in (sys.stdout, sys.stderr):
|
||||||
|
try:
|
||||||
|
_stream.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
|
||||||
|
except (AttributeError, OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
# 首先添加项目根目录到路径
|
# 首先添加项目根目录到路径
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
unilabos_dir = os.path.dirname(os.path.dirname(current_dir))
|
unilabos_dir = os.path.dirname(os.path.dirname(current_dir))
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
from typing import Union, Dict, Optional
|
from typing import Union, Dict, Optional
|
||||||
|
|
||||||
|
from unilabos.registry.decorators import topic_config
|
||||||
|
|
||||||
|
|
||||||
class VirtualMultiwayValve:
|
class VirtualMultiwayValve:
|
||||||
"""
|
"""
|
||||||
@@ -41,13 +43,11 @@ class VirtualMultiwayValve:
|
|||||||
def target_position(self) -> int:
|
def target_position(self) -> int:
|
||||||
return self._target_position
|
return self._target_position
|
||||||
|
|
||||||
def get_current_position(self) -> int:
|
@property
|
||||||
"""获取当前阀门位置 📍"""
|
@topic_config()
|
||||||
return self._current_position
|
def current_port(self) -> str:
|
||||||
|
"""当前连接的端口名称 🔌"""
|
||||||
def get_current_port(self) -> str:
|
return self.port
|
||||||
"""获取当前连接的端口名称 🔌"""
|
|
||||||
return self._current_position
|
|
||||||
|
|
||||||
def set_position(self, command: Union[int, str]):
|
def set_position(self, command: Union[int, str]):
|
||||||
"""
|
"""
|
||||||
@@ -169,12 +169,14 @@ class VirtualMultiwayValve:
|
|||||||
self._status = "Idle"
|
self._status = "Idle"
|
||||||
self._valve_state = "Closed"
|
self._valve_state = "Closed"
|
||||||
|
|
||||||
close_msg = f"🔒 阀门已关闭,保持在位置 {self._current_position} ({self.get_current_port()})"
|
close_msg = f"🔒 阀门已关闭,保持在位置 {self._current_position} ({self.port})"
|
||||||
self.logger.info(close_msg)
|
self.logger.info(close_msg)
|
||||||
return close_msg
|
return close_msg
|
||||||
|
|
||||||
def get_valve_position(self) -> int:
|
@property
|
||||||
"""获取阀门位置 - 兼容性方法 📍"""
|
@topic_config()
|
||||||
|
def valve_position(self) -> int:
|
||||||
|
"""阀门位置 📍"""
|
||||||
return self._current_position
|
return self._current_position
|
||||||
|
|
||||||
def set_valve_position(self, command: Union[int, str]):
|
def set_valve_position(self, command: Union[int, str]):
|
||||||
@@ -229,19 +231,16 @@ class VirtualMultiwayValve:
|
|||||||
self.logger.info(f"🔄 从端口 {self._current_position} 切换到泵位置...")
|
self.logger.info(f"🔄 从端口 {self._current_position} 切换到泵位置...")
|
||||||
return self.set_to_pump_position()
|
return self.set_to_pump_position()
|
||||||
|
|
||||||
def get_flow_path(self) -> str:
|
@property
|
||||||
"""获取当前流路路径描述 🌊"""
|
@topic_config()
|
||||||
current_port = self.get_current_port()
|
def flow_path(self) -> str:
|
||||||
|
"""当前流路路径描述 🌊"""
|
||||||
if self._current_position == 0:
|
if self._current_position == 0:
|
||||||
flow_path = f"🚰 转移泵已连接 (位置 {self._current_position})"
|
return f"🚰 转移泵已连接 (位置 {self._current_position})"
|
||||||
else:
|
return f"🔌 端口 {self._current_position} 已连接 ({self.current_port})"
|
||||||
flow_path = f"🔌 端口 {self._current_position} 已连接 ({current_port})"
|
|
||||||
|
|
||||||
# 删除debug日志:self.logger.debug(f"🌊 当前流路: {flow_path}")
|
|
||||||
return flow_path
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
current_port = self.get_current_port()
|
current_port = self.current_port
|
||||||
status_emoji = "✅" if self._status == "Idle" else "🔄" if self._status == "Busy" else "❌"
|
status_emoji = "✅" if self._status == "Idle" else "🔄" if self._status == "Busy" else "❌"
|
||||||
|
|
||||||
return f"🔄 VirtualMultiwayValve({status_emoji} 位置: {self._current_position}/{self.max_positions}, 端口: {current_port}, 状态: {self._status})"
|
return f"🔄 VirtualMultiwayValve({status_emoji} 位置: {self._current_position}/{self.max_positions}, 端口: {current_port}, 状态: {self._status})"
|
||||||
@@ -253,7 +252,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
print("🔄 === 虚拟九通阀门测试 === ✨")
|
print("🔄 === 虚拟九通阀门测试 === ✨")
|
||||||
print(f"🏠 初始状态: {valve}")
|
print(f"🏠 初始状态: {valve}")
|
||||||
print(f"🌊 当前流路: {valve.get_flow_path()}")
|
print(f"🌊 当前流路: {valve.flow_path}")
|
||||||
|
|
||||||
# 切换到试剂瓶1(1号位)
|
# 切换到试剂瓶1(1号位)
|
||||||
print(f"\n🔌 切换到1号位: {valve.set_position(1)}")
|
print(f"\n🔌 切换到1号位: {valve.set_position(1)}")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import logging
|
|||||||
import time as time_module
|
import time as time_module
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
from unilabos.registry.decorators import topic_config
|
||||||
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
|
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
|
||||||
|
|
||||||
class VirtualStirrer:
|
class VirtualStirrer:
|
||||||
@@ -314,9 +315,11 @@ class VirtualStirrer:
|
|||||||
def min_speed(self) -> float:
|
def min_speed(self) -> float:
|
||||||
return self._min_speed
|
return self._min_speed
|
||||||
|
|
||||||
def get_device_info(self) -> Dict[str, Any]:
|
@property
|
||||||
"""获取设备状态信息 📊"""
|
@topic_config()
|
||||||
info = {
|
def device_info(self) -> Dict[str, Any]:
|
||||||
|
"""设备状态快照信息 📊"""
|
||||||
|
return {
|
||||||
"device_id": self.device_id,
|
"device_id": self.device_id,
|
||||||
"status": self.status,
|
"status": self.status,
|
||||||
"operation_mode": self.operation_mode,
|
"operation_mode": self.operation_mode,
|
||||||
@@ -325,12 +328,9 @@ class VirtualStirrer:
|
|||||||
"is_stirring": self.is_stirring,
|
"is_stirring": self.is_stirring,
|
||||||
"remaining_time": self.remaining_time,
|
"remaining_time": self.remaining_time,
|
||||||
"max_speed": self._max_speed,
|
"max_speed": self._max_speed,
|
||||||
"min_speed": self._min_speed
|
"min_speed": self._min_speed,
|
||||||
}
|
}
|
||||||
|
|
||||||
# self.logger.debug(f"📊 设备信息: 模式={self.operation_mode}, 速度={self.current_speed} RPM, 搅拌={self.is_stirring}")
|
|
||||||
return info
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
status_emoji = "✅" if self.operation_mode == "Idle" else "🌪️" if self.operation_mode == "Stirring" else "🛑" if self.operation_mode == "Settling" else "❌"
|
status_emoji = "✅" if self.operation_mode == "Idle" else "🌪️" if self.operation_mode == "Stirring" else "🛑" if self.operation_mode == "Settling" else "❌"
|
||||||
return f"🌪️ VirtualStirrer({status_emoji} {self.device_id}: {self.operation_mode}, {self.current_speed} RPM)"
|
return f"🌪️ VirtualStirrer({status_emoji} {self.device_id}: {self.operation_mode}, {self.current_speed} RPM)"
|
||||||
@@ -4,6 +4,7 @@ from enum import Enum
|
|||||||
from typing import Union, Optional
|
from typing import Union, Optional
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from unilabos.registry.decorators import topic_config
|
||||||
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
|
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
|
||||||
|
|
||||||
|
|
||||||
@@ -385,8 +386,10 @@ class VirtualTransferPump:
|
|||||||
"""获取当前体积"""
|
"""获取当前体积"""
|
||||||
return self._current_volume
|
return self._current_volume
|
||||||
|
|
||||||
def get_remaining_capacity(self) -> float:
|
@property
|
||||||
"""获取剩余容量"""
|
@topic_config()
|
||||||
|
def remaining_capacity(self) -> float:
|
||||||
|
"""剩余容量 (ml)"""
|
||||||
return self.max_volume - self._current_volume
|
return self.max_volume - self._current_volume
|
||||||
|
|
||||||
def is_empty(self) -> bool:
|
def is_empty(self) -> bool:
|
||||||
|
|||||||
@@ -3960,6 +3960,14 @@ virtual_separator:
|
|||||||
io_type: source
|
io_type: source
|
||||||
label: bottom_phase_out
|
label: bottom_phase_out
|
||||||
side: SOUTH
|
side: SOUTH
|
||||||
|
- data_key: top_outlet
|
||||||
|
data_source: executor
|
||||||
|
data_type: fluid
|
||||||
|
description: 上相(轻相)液体输出口
|
||||||
|
handler_key: topphaseout
|
||||||
|
io_type: source
|
||||||
|
label: top_phase_out
|
||||||
|
side: NORTH
|
||||||
- data_key: mechanical_port
|
- data_key: mechanical_port
|
||||||
data_source: handle
|
data_source: handle
|
||||||
data_type: mechanical
|
data_type: mechanical
|
||||||
|
|||||||
@@ -188,7 +188,13 @@ class EnvironmentChecker:
|
|||||||
"crcmod": "crcmod-plus",
|
"crcmod": "crcmod-plus",
|
||||||
}
|
}
|
||||||
|
|
||||||
self.special_packages = {"pylabrobot": "git+https://github.com/Xuwznln/pylabrobot.git"}
|
# 中文 locale 下走 Gitee 镜像,规避 GitHub 拉取失败
|
||||||
|
pylabrobot_url = (
|
||||||
|
"git+https://gitee.com/xuwznln/pylabrobot.git"
|
||||||
|
if _is_chinese_locale()
|
||||||
|
else "git+https://github.com/Xuwznln/pylabrobot.git"
|
||||||
|
)
|
||||||
|
self.special_packages = {"pylabrobot": pylabrobot_url}
|
||||||
|
|
||||||
self.version_requirements = {
|
self.version_requirements = {
|
||||||
"msgcenterpy": "0.1.8",
|
"msgcenterpy": "0.1.8",
|
||||||
|
|||||||
Reference in New Issue
Block a user