protocol完整修复版本& bump version to 0.9.10

This commit is contained in:
KCFeng425
2025-07-10 16:48:09 +08:00
parent d82ccd5cf1
commit 7b93332bf5
25 changed files with 3760 additions and 1843 deletions

View File

@@ -67,6 +67,16 @@ class VirtualFilter:
volume: float = 0.0
) -> bool:
"""Execute filter action - 完全按照 Filter.action 参数"""
# 🔧 新增:温度自动调整
original_temp = temp
if temp == 0.0:
temp = 25.0 # 0度自动设置为室温
self.logger.info(f"温度自动调整: {original_temp}°C → {temp}°C (室温)")
elif temp < 4.0:
temp = 4.0 # 小于4度自动设置为4度
self.logger.info(f"温度自动调整: {original_temp}°C → {temp}°C (最低温度)")
self.logger.info(f"Filter: vessel={vessel}, filtrate_vessel={filtrate_vessel}")
self.logger.info(f" stir={stir}, stir_speed={stir_speed}, temp={temp}")
self.logger.info(f" continue_heatchill={continue_heatchill}, volume={volume}")

View File

@@ -3,6 +3,9 @@ import logging
import time as time_module
from typing import Dict, Any, Optional
def debug_print(message):
"""调试输出"""
print(f"[ROTAVAP] {message}", flush=True)
class VirtualRotavap:
"""Virtual rotary evaporator device - 简化版,只保留核心功能"""
@@ -70,12 +73,19 @@ class VirtualRotavap:
vessel: str,
pressure: float = 0.1,
temp: float = 60.0,
time: float = 1800.0, # 30分钟默认
time: float = 1800.0,
stir_speed: float = 100.0,
solvent: str = "", # 🔧 新增参数
**kwargs # 🔧 接受额外参数
solvent: str = "",
**kwargs
) -> bool:
"""Execute evaporate action - 兼容性增强"""
"""Execute evaporate action - 简化"""
# 🔧 简化处理如果vessel就是设备自己直接操作
if vessel == self.device_id:
debug_print(f"在设备 {self.device_id} 上直接执行蒸发操作")
actual_vessel = self.device_id
else:
actual_vessel = vessel
# 参数预处理
if solvent:
@@ -86,8 +96,12 @@ class VirtualRotavap:
temp = max(temp, 80.0)
pressure = max(pressure, 0.2)
self.logger.info("水系溶剂:调整参数")
elif any(s in solvent_lower for s in ['ethanol', 'methanol', 'acetone']):
temp = min(temp, 50.0)
pressure = min(pressure, 0.05)
self.logger.info("易挥发溶剂:调整参数")
self.logger.info(f"Evaporate: vessel={vessel}, pressure={pressure} bar, temp={temp}°C, time={time}s, rotation={stir_speed} RPM, solvent={solvent}")
self.logger.info(f"Evaporate: vessel={actual_vessel}, pressure={pressure} bar, temp={temp}°C, time={time}s, rotation={stir_speed} RPM, solvent={solvent}")
# 验证参数
if temp > self._max_temp or temp < 10.0:
@@ -96,6 +110,9 @@ class VirtualRotavap:
self.data.update({
"status": f"Error: {error_msg}",
"rotavap_state": "Error",
"current_temp": 25.0,
"progress": 0.0,
"evaporated_volume": 0.0,
"message": error_msg
})
return False
@@ -106,6 +123,9 @@ class VirtualRotavap:
self.data.update({
"status": f"Error: {error_msg}",
"rotavap_state": "Error",
"current_temp": 25.0,
"progress": 0.0,
"evaporated_volume": 0.0,
"message": error_msg
})
return False
@@ -116,13 +136,16 @@ class VirtualRotavap:
self.data.update({
"status": f"Error: {error_msg}",
"rotavap_state": "Error",
"current_temp": 25.0,
"progress": 0.0,
"evaporated_volume": 0.0,
"message": error_msg
})
return False
# 开始蒸发
self.data.update({
"status": f"蒸发中: {vessel}",
"status": f"蒸发中: {actual_vessel}",
"rotavap_state": "Evaporating",
"current_temp": temp,
"target_temp": temp,
@@ -131,7 +154,7 @@ class VirtualRotavap:
"remaining_time": time,
"progress": 0.0,
"evaporated_volume": 0.0,
"message": f"Evaporating {vessel} at {temp}°C, {pressure} bar, {stir_speed} RPM"
"message": f"Evaporating {actual_vessel} at {temp}°C, {pressure} bar, {stir_speed} RPM"
})
try:
@@ -148,12 +171,13 @@ class VirtualRotavap:
# 模拟蒸发体积
evaporated_vol = progress * 0.8 # 假设最多蒸发80mL
# 更新状态
# 🔧 更新状态 - 确保包含所有必需字段
self.data.update({
"remaining_time": remaining,
"progress": progress,
"evaporated_volume": evaporated_vol,
"status": f"蒸发中: {vessel} | {temp}°C | {pressure} bar | {progress:.1f}% | 剩余: {remaining:.0f}s",
"progress": progress, # 确保这个字段存在
"evaporated_volume": evaporated_vol, # 确保这个字段存在
"current_temp": temp, # 确保这个字段存在
"status": f"蒸发中: {actual_vessel} | {temp}°C | {pressure} bar | {progress:.1f}% | 剩余: {remaining:.0f}s",
"message": f"Evaporating: {progress:.1f}% complete, {remaining:.0f}s remaining"
})
@@ -167,18 +191,18 @@ class VirtualRotavap:
# 蒸发完成
final_evaporated = 80.0
self.data.update({
"status": f"蒸发完成: {vessel} | 蒸发量: {final_evaporated:.1f}mL",
"status": f"蒸发完成: {actual_vessel} | 蒸发量: {final_evaporated:.1f}mL",
"rotavap_state": "Completed",
"evaporated_volume": final_evaporated,
"progress": 100.0,
"current_temp": temp, # 保持温度信息
"remaining_time": 0.0,
"current_temp": 25.0, # 冷却下来
"rotation_speed": 0.0, # 停止旋转
"vacuum_pressure": 1.0, # 恢复大气压
"message": f"Evaporation completed: {final_evaporated}mL evaporated from {vessel}"
"message": f"Evaporation completed: {final_evaporated}mL evaporated from {actual_vessel}"
})
self.logger.info(f"Evaporation completed: {final_evaporated}mL evaporated from {vessel}")
self.logger.info(f"Evaporation completed: {final_evaporated}mL evaporated from {actual_vessel}")
return True
except Exception as e:
@@ -189,6 +213,8 @@ class VirtualRotavap:
"status": f"蒸发错误: {str(e)}",
"rotavap_state": "Error",
"current_temp": 25.0,
"progress": 0.0,
"evaporated_volume": 0.0,
"rotation_speed": 0.0,
"vacuum_pressure": 1.0,
"message": f"Evaporation failed: {str(e)}"

View File

@@ -43,10 +43,25 @@ class VirtualSolenoidValve:
def is_open(self) -> bool:
return self._is_open
def get_valve_position(self) -> str:
@property
def valve_position(self) -> str:
"""获取阀门位置状态"""
return "OPEN" if self._is_open else "CLOSED"
@property
def state(self) -> dict:
"""获取阀门完整状态"""
return {
"device_id": self.device_id,
"port": self.port,
"voltage": self.voltage,
"response_time": self.response_time,
"is_open": self._is_open,
"valve_state": self._valve_state,
"status": self._status,
"position": self.valve_position
}
async def set_valve_position(self, command: str = None, **kwargs):
"""
设置阀门位置 - ROS动作接口
@@ -91,7 +106,7 @@ class VirtualSolenoidValve:
return {
"success": True,
"message": result_msg,
"valve_position": self.get_valve_position()
"valve_position": self.valve_position
}
async def open(self, **kwargs):
@@ -102,21 +117,25 @@ class VirtualSolenoidValve:
"""关闭电磁阀 - ROS动作接口"""
return await self.set_valve_position(command="CLOSED")
async def set_state(self, command: Union[bool, str], **kwargs):
async def set_status(self, string: str = None, **kwargs):
"""
设置阀门状态 - 兼容 SendCmd 类型
设置阀门状态 - 兼容 StrSingleInput 类型
Args:
command: True/False"open"/"close"
string: "ON"/"OFF""OPEN"/"CLOSED"
"""
if isinstance(command, bool):
cmd_str = "OPEN" if command else "CLOSED"
elif isinstance(command, str):
cmd_str = command
else:
return {"success": False, "message": "Invalid command type"}
if string is None:
return {"success": False, "message": "Missing string parameter"}
return await self.set_valve_position(command=cmd_str)
# 将 string 参数转换为 command 参数
if string.upper() in ["ON", "OPEN"]:
command = "OPEN"
elif string.upper() in ["OFF", "CLOSED"]:
command = "CLOSED"
else:
command = string
return await self.set_valve_position(command=command)
def toggle(self):
"""切换阀门状态"""
@@ -129,19 +148,6 @@ class VirtualSolenoidValve:
"""检查阀门是否关闭"""
return not self._is_open
def get_state(self) -> dict:
"""获取阀门完整状态"""
return {
"device_id": self.device_id,
"port": self.port,
"voltage": self.voltage,
"response_time": self.response_time,
"is_open": self._is_open,
"valve_state": self._valve_state,
"status": self._status,
"position": self.get_valve_position()
}
async def reset(self):
"""重置阀门到关闭状态"""
return await self.close()