mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-06 06:25:06 +00:00
bump version to 0.9.7 新增一个测试PumpTransferProtocol的teststation,亲测可以运行,将八通阀们和转移泵与pump_protocol适配
This commit is contained in:
@@ -192,6 +192,16 @@ class VirtualMultiwayValve:
|
||||
def __str__(self):
|
||||
return f"VirtualMultiwayValve(Position: {self._current_position}/{self.max_positions}, Port: {self.get_current_port()}, Status: {self._status})"
|
||||
|
||||
def set_valve_position(self, command: Union[int, str]):
|
||||
"""
|
||||
设置阀门位置 - 兼容pump_protocol调用
|
||||
这是set_position的别名方法,用于兼容pump_protocol.py
|
||||
|
||||
Args:
|
||||
command: 目标位置 (0-8) 或位置字符串
|
||||
"""
|
||||
return self.set_position(command)
|
||||
|
||||
|
||||
# 使用示例
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -11,23 +11,39 @@ class VirtualPumpMode(Enum):
|
||||
AccuratePosVel = 2
|
||||
|
||||
|
||||
class VirtualPump:
|
||||
"""虚拟泵类 - 模拟泵的基本功能,无需实际硬件"""
|
||||
class VirtualTransferPump:
|
||||
"""虚拟转移泵类 - 模拟泵的基本功能,无需实际硬件"""
|
||||
|
||||
def __init__(self, device_id: str = None, max_volume: float = 25.0, mode: VirtualPumpMode = VirtualPumpMode.Normal, transfer_rate=0):
|
||||
self.device_id = device_id or "virtual_pump"
|
||||
self.max_volume = max_volume
|
||||
self._transfer_rate = transfer_rate
|
||||
self.mode = mode
|
||||
def __init__(self, device_id: str = None, config: dict = None, **kwargs):
|
||||
"""
|
||||
初始化虚拟转移泵
|
||||
|
||||
# 状态变量
|
||||
Args:
|
||||
device_id: 设备ID
|
||||
config: 配置字典,包含max_volume, port等参数
|
||||
**kwargs: 其他参数,确保兼容性
|
||||
"""
|
||||
self.device_id = device_id or "virtual_transfer_pump"
|
||||
|
||||
# 从config或kwargs中获取参数,确保类型正确
|
||||
if config:
|
||||
self.max_volume = float(config.get('max_volume', 25.0))
|
||||
self.port = config.get('port', 'VIRTUAL')
|
||||
else:
|
||||
self.max_volume = float(kwargs.get('max_volume', 25.0))
|
||||
self.port = kwargs.get('port', 'VIRTUAL')
|
||||
|
||||
self._transfer_rate = float(kwargs.get('transfer_rate', 0))
|
||||
self.mode = kwargs.get('mode', VirtualPumpMode.Normal)
|
||||
|
||||
# 状态变量 - 确保都是正确类型
|
||||
self._status = "Idle"
|
||||
self._position = 0.0 # 当前柱塞位置 (ml)
|
||||
self._max_velocity = 5.0 # 默认最大速度 (ml/s)
|
||||
self._current_volume = 0.0 # 当前注射器中的体积
|
||||
self._position = 0.0 # float
|
||||
self._max_velocity = 5.0 # float
|
||||
self._current_volume = 0.0 # float
|
||||
|
||||
self.logger = logging.getLogger(f"VirtualPump.{self.device_id}")
|
||||
|
||||
self.logger = logging.getLogger(f"VirtualTransferPump.{self.device_id}")
|
||||
|
||||
async def initialize(self) -> bool:
|
||||
"""初始化虚拟泵"""
|
||||
self.logger.info(f"Initializing virtual pump {self.device_id}")
|
||||
@@ -86,30 +102,73 @@ class VirtualPump:
|
||||
velocity = self._max_velocity
|
||||
return abs(volume) / velocity
|
||||
|
||||
# 基本泵操作
|
||||
async def set_position(self, position: float, velocity: float = None):
|
||||
# 新的set_position方法 - 专门用于SetPumpPosition动作
|
||||
async def set_position(self, position: float, max_velocity: float = None):
|
||||
"""
|
||||
移动到绝对位置
|
||||
移动到绝对位置 - 专门用于SetPumpPosition动作
|
||||
|
||||
Args:
|
||||
position (float): 目标位置 (ml)
|
||||
velocity (float): 移动速度 (ml/s)
|
||||
max_velocity (float): 移动速度 (ml/s)
|
||||
|
||||
Returns:
|
||||
dict: 符合SetPumpPosition.action定义的结果
|
||||
"""
|
||||
position = max(0, min(self.max_volume, position)) # 限制在有效范围内
|
||||
try:
|
||||
# 验证并转换参数
|
||||
target_position = float(position)
|
||||
velocity = float(max_velocity) if max_velocity is not None else self._max_velocity
|
||||
|
||||
# 限制位置在有效范围内
|
||||
target_position = max(0.0, min(float(self.max_volume), target_position))
|
||||
|
||||
# 计算移动距离和时间
|
||||
volume_to_move = abs(target_position - self._position)
|
||||
duration = self._calculate_duration(volume_to_move, velocity)
|
||||
|
||||
self.logger.info(f"SET_POSITION: Moving to {target_position} ml (current: {self._position} ml), velocity: {velocity} ml/s")
|
||||
|
||||
# 模拟移动过程
|
||||
start_position = self._position
|
||||
steps = 10 if duration > 0.1 else 1 # 如果移动距离很小,只用1步
|
||||
step_duration = duration / steps if steps > 1 else duration
|
||||
|
||||
for i in range(steps + 1):
|
||||
# 计算当前位置和进度
|
||||
progress = (i / steps) * 100 if steps > 0 else 100
|
||||
current_pos = start_position + (target_position - start_position) * (i / steps) if steps > 0 else target_position
|
||||
|
||||
# 更新状态
|
||||
self._status = "Moving" if i < steps else "Idle"
|
||||
self._position = current_pos
|
||||
self._current_volume = current_pos
|
||||
|
||||
# 等待一小步时间
|
||||
if i < steps and step_duration > 0:
|
||||
await asyncio.sleep(step_duration)
|
||||
|
||||
volume_to_move = abs(position - self._position)
|
||||
duration = self._calculate_duration(volume_to_move, velocity)
|
||||
|
||||
self.logger.info(f"Moving to position {position} ml (current: {self._position} ml)")
|
||||
|
||||
# 模拟移动过程
|
||||
await self._simulate_operation(duration)
|
||||
|
||||
self._position = position
|
||||
self._current_volume = position # 假设位置等于体积
|
||||
|
||||
self.logger.info(f"Reached position {self._position} ml")
|
||||
# 确保最终位置准确
|
||||
self._position = target_position
|
||||
self._current_volume = target_position
|
||||
self._status = "Idle"
|
||||
|
||||
self.logger.info(f"SET_POSITION: Reached position {self._position} ml, current volume: {self._current_volume} ml")
|
||||
|
||||
# 返回符合action定义的结果
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Successfully moved to position {self._position} ml"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Failed to set position: {str(e)}"
|
||||
self.logger.error(error_msg)
|
||||
return {
|
||||
"success": False,
|
||||
"message": error_msg
|
||||
}
|
||||
|
||||
# 其他泵操作方法
|
||||
async def pull_plunger(self, volume: float, velocity: float = None):
|
||||
"""
|
||||
拉取柱塞(吸液)
|
||||
@@ -135,7 +194,7 @@ class VirtualPump:
|
||||
self._current_volume = new_position
|
||||
|
||||
self.logger.info(f"Pulled {actual_volume} ml, current volume: {self._current_volume} ml")
|
||||
|
||||
|
||||
async def push_plunger(self, volume: float, velocity: float = None):
|
||||
"""
|
||||
推出柱塞(排液)
|
||||
@@ -161,37 +220,18 @@ class VirtualPump:
|
||||
self._current_volume = new_position
|
||||
|
||||
self.logger.info(f"Pushed {actual_volume} ml, current volume: {self._current_volume} ml")
|
||||
|
||||
|
||||
# 便捷操作方法
|
||||
async def aspirate(self, volume: float, velocity: float = None):
|
||||
"""
|
||||
吸液操作
|
||||
|
||||
Args:
|
||||
volume (float): 吸液体积 (ml)
|
||||
velocity (float): 吸液速度 (ml/s)
|
||||
"""
|
||||
"""吸液操作"""
|
||||
await self.pull_plunger(volume, velocity)
|
||||
|
||||
async def dispense(self, volume: float, velocity: float = None):
|
||||
"""
|
||||
排液操作
|
||||
|
||||
Args:
|
||||
volume (float): 排液体积 (ml)
|
||||
velocity (float): 排液速度 (ml/s)
|
||||
"""
|
||||
"""排液操作"""
|
||||
await self.push_plunger(volume, velocity)
|
||||
|
||||
async def transfer(self, volume: float, aspirate_velocity: float = None, dispense_velocity: float = None):
|
||||
"""
|
||||
转移操作(先吸后排)
|
||||
|
||||
Args:
|
||||
volume (float): 转移体积 (ml)
|
||||
aspirate_velocity (float): 吸液速度 (ml/s)
|
||||
dispense_velocity (float): 排液速度 (ml/s)
|
||||
"""
|
||||
"""转移操作(先吸后排)"""
|
||||
# 吸液
|
||||
await self.aspirate(volume, aspirate_velocity)
|
||||
|
||||
@@ -252,7 +292,7 @@ class VirtualPump:
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
return f"VirtualPump({self.device_id}: {self._current_volume:.2f}/{self.max_volume} ml, {self._status})"
|
||||
return f"VirtualTransferPump({self.device_id}: {self._current_volume:.2f}/{self.max_volume} ml, {self._status})"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
@@ -261,30 +301,28 @@ class VirtualPump:
|
||||
# 使用示例
|
||||
async def demo():
|
||||
"""虚拟泵使用示例"""
|
||||
pump = VirtualPump("demo_pump", max_volume=50.0)
|
||||
pump = VirtualTransferPump("demo_pump", {"max_volume": 50.0})
|
||||
|
||||
await pump.initialize()
|
||||
|
||||
print(f"Initial state: {pump}")
|
||||
|
||||
# 测试set_position方法
|
||||
result = await pump.set_position(10.0, max_velocity=2.0)
|
||||
print(f"Set position result: {result}")
|
||||
print(f"After setting position to 10ml: {pump}")
|
||||
|
||||
# 吸液测试
|
||||
await pump.aspirate(10.0, velocity=2.0)
|
||||
print(f"After aspirating 10ml: {pump}")
|
||||
|
||||
# 排液测试
|
||||
await pump.dispense(5.0, velocity=3.0)
|
||||
print(f"After dispensing 5ml: {pump}")
|
||||
|
||||
# 转移测试
|
||||
await pump.transfer(3.0)
|
||||
print(f"After transfer 3ml: {pump}")
|
||||
await pump.aspirate(5.0, velocity=2.0)
|
||||
print(f"After aspirating 5ml: {pump}")
|
||||
|
||||
# 清空测试
|
||||
await pump.empty_syringe()
|
||||
result = await pump.set_position(0.0)
|
||||
print(f"Empty result: {result}")
|
||||
print(f"After emptying: {pump}")
|
||||
|
||||
print("\nPump info:", pump.get_pump_info())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(demo())
|
||||
asyncio.run(demo())
|
||||
|
||||
Reference in New Issue
Block a user