mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-05 14:05:12 +00:00
361 lines
11 KiB
Python
361 lines
11 KiB
Python
import time
|
||
import threading
|
||
from datetime import datetime, timedelta
|
||
|
||
class MockPump:
|
||
def __init__(self, port: str = "MOCK"):
|
||
self.port = port
|
||
|
||
# 设备基本状态属性
|
||
self._current_device = "MockPump1" # 设备标识符
|
||
self._status: str = "Idle" # 设备状态:Idle, Running, Error, Stopped
|
||
self._pump_state: str = "Stopped" # 泵运行状态:Running, Stopped, Paused
|
||
|
||
# 流量相关属性
|
||
self._flow_rate: float = 0.0 # 当前流速 (mL/min)
|
||
self._target_flow_rate: float = 0.0 # 目标流速 (mL/min)
|
||
self._max_flow_rate: float = 100.0 # 最大流速 (mL/min)
|
||
self._total_volume: float = 0.0 # 累计流量 (mL)
|
||
|
||
# 压力相关属性
|
||
self._pressure: float = 0.0 # 当前压力 (bar)
|
||
self._max_pressure: float = 10.0 # 最大压力 (bar)
|
||
|
||
# 运行控制线程
|
||
self._pump_thread = None
|
||
self._running = False
|
||
self._thread_lock = threading.Lock()
|
||
|
||
# 新增 PumpTransfer 相关属性
|
||
self._from_vessel: str = ""
|
||
self._to_vessel: str = ""
|
||
self._transfer_volume: float = 0.0
|
||
self._amount: str = ""
|
||
self._transfer_time: float = 0.0
|
||
self._is_viscous: bool = False
|
||
self._rinsing_solvent: str = ""
|
||
self._rinsing_volume: float = 0.0
|
||
self._rinsing_repeats: int = 0
|
||
self._is_solid: bool = False
|
||
|
||
# 时间追踪
|
||
self._start_time: datetime = None
|
||
self._time_spent: timedelta = timedelta()
|
||
self._time_remaining: timedelta = timedelta()
|
||
|
||
# ==================== 状态属性 ====================
|
||
# 这些属性会被Uni-Lab系统自动识别并定时对外广播
|
||
|
||
@property
|
||
def status(self) -> str:
|
||
return self._status
|
||
|
||
@property
|
||
def current_device(self) -> str:
|
||
"""当前设备标识符"""
|
||
return self._current_device
|
||
|
||
@property
|
||
def pump_state(self) -> str:
|
||
return self._pump_state
|
||
|
||
@property
|
||
def flow_rate(self) -> float:
|
||
return self._flow_rate
|
||
|
||
@property
|
||
def target_flow_rate(self) -> float:
|
||
return self._target_flow_rate
|
||
|
||
@property
|
||
def pressure(self) -> float:
|
||
return self._pressure
|
||
|
||
@property
|
||
def total_volume(self) -> float:
|
||
return self._total_volume
|
||
|
||
@property
|
||
def max_flow_rate(self) -> float:
|
||
return self._max_flow_rate
|
||
|
||
@property
|
||
def max_pressure(self) -> float:
|
||
return self._max_pressure
|
||
|
||
# 添加新的属性访问器
|
||
@property
|
||
def from_vessel(self) -> str:
|
||
return self._from_vessel
|
||
|
||
@property
|
||
def to_vessel(self) -> str:
|
||
return self._to_vessel
|
||
|
||
@property
|
||
def transfer_volume(self) -> float:
|
||
return self._transfer_volume
|
||
|
||
@property
|
||
def amount(self) -> str:
|
||
return self._amount
|
||
|
||
@property
|
||
def transfer_time(self) -> float:
|
||
return self._transfer_time
|
||
|
||
@property
|
||
def is_viscous(self) -> bool:
|
||
return self._is_viscous
|
||
|
||
@property
|
||
def rinsing_solvent(self) -> str:
|
||
return self._rinsing_solvent
|
||
|
||
@property
|
||
def rinsing_volume(self) -> float:
|
||
return self._rinsing_volume
|
||
|
||
@property
|
||
def rinsing_repeats(self) -> int:
|
||
return self._rinsing_repeats
|
||
|
||
@property
|
||
def is_solid(self) -> bool:
|
||
return self._is_solid
|
||
|
||
# 修改这两个属性装饰器
|
||
@property
|
||
def time_spent(self) -> float:
|
||
"""已用时间(秒)"""
|
||
if isinstance(self._time_spent, timedelta):
|
||
return self._time_spent.total_seconds()
|
||
return float(self._time_spent)
|
||
|
||
@property
|
||
def time_remaining(self) -> float:
|
||
"""剩余时间(秒)"""
|
||
if isinstance(self._time_remaining, timedelta):
|
||
return self._time_remaining.total_seconds()
|
||
return float(self._time_remaining)
|
||
|
||
# ==================== 设备控制方法 ====================
|
||
# 这些方法需要在注册表中添加,会作为ActionServer接受控制指令
|
||
def pump_transfer(self, from_vessel: str, to_vessel: str, volume: float,
|
||
amount: str = "", time: float = 0.0, viscous: bool = False,
|
||
rinsing_solvent: str = "", rinsing_volume: float = 0.0,
|
||
rinsing_repeats: int = 0, solid: bool = False) -> dict:
|
||
"""Execute pump transfer operation"""
|
||
# Stop any existing operation first
|
||
self._stop_pump_operation()
|
||
|
||
# Set transfer parameters
|
||
self._from_vessel = from_vessel
|
||
self._to_vessel = to_vessel
|
||
self._transfer_volume = float(volume)
|
||
self._amount = amount
|
||
self._transfer_time = float(time)
|
||
self._is_viscous = viscous
|
||
self._rinsing_solvent = rinsing_solvent
|
||
self._rinsing_volume = float(rinsing_volume)
|
||
self._rinsing_repeats = int(rinsing_repeats)
|
||
self._is_solid = solid
|
||
|
||
# Calculate flow rate
|
||
if self._transfer_time > 0 and self._transfer_volume > 0:
|
||
self._target_flow_rate = (self._transfer_volume / self._transfer_time) * 60.0
|
||
else:
|
||
self._target_flow_rate = 10.0 if not self._is_viscous else 5.0
|
||
|
||
# Reset timers and counters
|
||
self._start_time = datetime.now()
|
||
self._time_spent = timedelta()
|
||
self._time_remaining = timedelta(seconds=self._transfer_time)
|
||
self._total_volume = 0.0
|
||
self._flow_rate = 0.0
|
||
|
||
# Start pump operation
|
||
self._pump_state = "Running"
|
||
self._status = "Starting Transfer"
|
||
self._running = True
|
||
|
||
# Start pump operation thread
|
||
self._pump_thread = threading.Thread(target=self._pump_operation_loop)
|
||
self._pump_thread.daemon = True
|
||
self._pump_thread.start()
|
||
|
||
# Wait briefly to ensure thread starts
|
||
time.sleep(0.1)
|
||
|
||
return {
|
||
"success": True,
|
||
"status": self._status,
|
||
"current_device": self._current_device,
|
||
"time_spent": 0.0,
|
||
"time_remaining": float(self._transfer_time)
|
||
}
|
||
|
||
def pause_pump(self) -> str:
|
||
|
||
if self._pump_state != "Running":
|
||
self._status = "Error: Pump not running"
|
||
return "Error"
|
||
|
||
self._pump_state = "Paused"
|
||
self._status = "Pump Paused"
|
||
self._stop_pump_operation()
|
||
|
||
return "Success"
|
||
|
||
def resume_pump(self) -> str:
|
||
|
||
if self._pump_state != "Paused":
|
||
self._status = "Error: Pump not paused"
|
||
return "Error"
|
||
|
||
self._pump_state = "Running"
|
||
self._status = "Resuming Pump"
|
||
self._start_pump_operation()
|
||
|
||
return "Success"
|
||
|
||
def reset_volume_counter(self) -> str:
|
||
self._total_volume = 0.0
|
||
self._status = "Volume counter reset"
|
||
return "Success"
|
||
|
||
def emergency_stop(self) -> str:
|
||
self._status = "Emergency Stop"
|
||
self._pump_state = "Stopped"
|
||
self._stop_pump_operation()
|
||
self._flow_rate = 0.0
|
||
self._pressure = 0.0
|
||
self._target_flow_rate = 0.0
|
||
|
||
return "Success"
|
||
|
||
# ==================== 内部控制方法 ====================
|
||
|
||
def _start_pump_operation(self):
|
||
with self._thread_lock:
|
||
if not self._running:
|
||
self._running = True
|
||
self._pump_thread = threading.Thread(target=self._pump_operation_loop)
|
||
self._pump_thread.daemon = True
|
||
self._pump_thread.start()
|
||
|
||
def _stop_pump_operation(self):
|
||
with self._thread_lock:
|
||
self._running = False
|
||
if self._pump_thread and self._pump_thread.is_alive():
|
||
self._pump_thread.join(timeout=2.0)
|
||
|
||
def _pump_operation_loop(self):
|
||
"""泵运行主循环"""
|
||
print("Pump operation loop started") # Debug print
|
||
|
||
while self._running and self._pump_state == "Running":
|
||
try:
|
||
# Calculate flow rate adjustment
|
||
flow_diff = self._target_flow_rate - self._flow_rate
|
||
|
||
# Adjust flow rate more aggressively (50% of difference)
|
||
adjustment = flow_diff * 0.5
|
||
self._flow_rate += adjustment
|
||
|
||
# Ensure flow rate is within bounds
|
||
self._flow_rate = max(0.1, min(self._max_flow_rate, self._flow_rate))
|
||
|
||
# Update status based on flow rate
|
||
if abs(flow_diff) < 0.1:
|
||
self._status = "Running at Target Flow Rate"
|
||
else:
|
||
self._status = "Adjusting Flow Rate"
|
||
|
||
# Calculate volume increment
|
||
volume_increment = (self._flow_rate / 60.0) # mL/s
|
||
self._total_volume += volume_increment
|
||
|
||
# Update time tracking
|
||
self._time_spent = datetime.now() - self._start_time
|
||
if self._transfer_time > 0:
|
||
remaining = self._transfer_time - self._time_spent.total_seconds()
|
||
self._time_remaining = timedelta(seconds=max(0, remaining))
|
||
|
||
# Check completion
|
||
if self._total_volume >= self._transfer_volume:
|
||
self._status = "Transfer Completed"
|
||
self._pump_state = "Stopped"
|
||
self._running = False
|
||
break
|
||
|
||
# Update pressure
|
||
self._pressure = (self._flow_rate / self._max_flow_rate) * self._max_pressure
|
||
|
||
print(f"Debug - Flow: {self._flow_rate:.1f}, Volume: {self._total_volume:.1f}") # Debug print
|
||
|
||
time.sleep(1.0)
|
||
|
||
except Exception as e:
|
||
print(f"Error in pump operation: {str(e)}")
|
||
self._status = "Error in pump operation"
|
||
self._pump_state = "Stopped"
|
||
self._running = False
|
||
break
|
||
|
||
def get_status_info(self) -> dict:
|
||
"""
|
||
获取完整的设备状态信息
|
||
|
||
Returns:
|
||
dict: 包含所有设备状态的字典
|
||
"""
|
||
return {
|
||
"status": self._status,
|
||
"pump_state": self._pump_state,
|
||
"flow_rate": self._flow_rate,
|
||
"target_flow_rate": self._target_flow_rate,
|
||
"pressure": self._pressure,
|
||
"total_volume": self._total_volume,
|
||
"max_flow_rate": self._max_flow_rate,
|
||
"max_pressure": self._max_pressure,
|
||
"current_device": self._current_device,
|
||
"from_vessel": self._from_vessel,
|
||
"to_vessel": self._to_vessel,
|
||
"transfer_volume": self._transfer_volume,
|
||
"amount": self._amount,
|
||
"transfer_time": self._transfer_time,
|
||
"is_viscous": self._is_viscous,
|
||
"rinsing_solvent": self._rinsing_solvent,
|
||
"rinsing_volume": self._rinsing_volume,
|
||
"rinsing_repeats": self._rinsing_repeats,
|
||
"is_solid": self._is_solid,
|
||
"time_spent": self._time_spent.total_seconds(),
|
||
"time_remaining": self._time_remaining.total_seconds()
|
||
}
|
||
|
||
|
||
# 用于测试的主函数
|
||
if __name__ == "__main__":
|
||
pump = MockPump()
|
||
|
||
# 测试基本功能
|
||
print("启动泵设备测试...")
|
||
print(f"初始状态: {pump.get_status_info()}")
|
||
|
||
# 设置流速并启动
|
||
pump.set_flow_rate(50.0)
|
||
pump.start_pump()
|
||
|
||
# 模拟运行10秒
|
||
for i in range(10):
|
||
time.sleep(1)
|
||
print(f"第{i+1}秒: 流速={pump.flow_rate:.1f}mL/min, 压力={pump.pressure:.2f}bar, 状态={pump.status}")
|
||
|
||
# 测试方向切换
|
||
print("切换泵方向...")
|
||
|
||
|
||
pump.emergency_stop()
|
||
print("测试完成")
|