mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-14 13:14:39 +00:00
* Cleanup registry to be easy-understanding (#76) * delete deprecated mock devices * rename categories * combine chromatographic devices * rename rviz simulation nodes * organic virtual devices * parse vessel_id * run registry completion before merge --------- Co-authored-by: Xuwznln <18435084+Xuwznln@users.noreply.github.com> * fix: workstation handlers and vessel_id parsing * fix: working dir error when input config path feat: report publish topic when error * modify default discovery_interval to 15s * feat: add trace log level * feat: 添加ChinWe设备控制类,支持串口通信和电机控制功能 (#79) * fix: drop_tips not using auto resource select * fix: discard_tips error * fix: discard_tips * fix: prcxi_res * add: prcxi res fix: startup slow * feat: workstation example * fix pumps and liquid_handler handle * feat: 优化protocol node节点运行日志 * fix all protocol_compilers and remove deprecated devices * feat: 新增use_remote_resource参数 * fix and remove redundant info * bugfixes on organic protocols * fix filter protocol * fix protocol node * 临时兼容错误的driver写法 * fix: prcxi import error * use call_async in all service to avoid deadlock * fix: figure_resource * Update recipe.yaml * add workstation template and battery example * feat: add sk & ak * update workstation base * Create workstation_architecture.md * refactor: workstation_base 重构为仅含业务逻辑,通信和子设备管理交给 ProtocolNode * refactor: ProtocolNode→WorkstationNode * Add:msgs.action (#83) * update: Workstation dev 将版本号从 0.10.3 更新为 0.10.4 (#84) * Add:msgs.action * update: 将版本号从 0.10.3 更新为 0.10.4 * simplify resource system * uncompleted refactor * example for use WorkstationBase * feat: websocket * feat: websocket test * feat: workstation example * feat: action status * fix: station自己的方法注册错误 * fix: 还原protocol node处理方法 * fix: build * fix: missing job_id key * ws test version 1 * ws test version 2 * ws protocol * 增加物料关系上传日志 * 增加物料关系上传日志 * 修正物料关系上传 * 修复工站的tracker实例追踪失效问题 * 增加handle检测,增加material edge关系上传 * 修复event loop错误 * 修复edge上报错误 * 修复async错误 * 更新schema的title字段 * 主机节点信息等支持自动刷新 * 注册表编辑器 * 修复status密集发送时,消息出错 * 增加addr参数 * fix: addr param * fix: addr param * 取消labid 和 强制config输入 * Add action definitions for LiquidHandlerSetGroup and LiquidHandlerTransferGroup - Created LiquidHandlerSetGroup.action with fields for group name, wells, and volumes. - Created LiquidHandlerTransferGroup.action with fields for source and target group names and unit volume. - Both actions include response fields for return information and success status. * Add LiquidHandlerSetGroup and LiquidHandlerTransferGroup actions to CMakeLists * Add set_group and transfer_group methods to PRCXI9300Handler and update liquid_handler.yaml * result_info改为字典类型 * 新增uat的地址替换 * runze multiple pump support (cherry picked from commit49354fcf39) * remove runze multiple software obtainer (cherry picked from commit8bcc92a394) * support multiple backbone (cherry picked from commit4771ff2347) * Update runze pump format * Correct runze multiple backbone * Update runze_multiple_backbone * Correct runze pump multiple receive method. * Correct runze pump multiple receive method. * 对于PRCXI9320的transfer_group,一对多和多对多 * 移除MQTT,更新launch文档,提供注册表示例文件,更新到0.10.5 * fix import error * fix dupe upload registry * refactor ws client * add server timeout * Fix: run-column with correct vessel id (#86) * fix run_column * Update run_column_protocol.py (cherry picked from commite5aa4d940a) * resource_update use resource_add * 新增版位推荐功能 * 重新规定了版位推荐的入参 * update registry with nested obj * fix protocol node log_message, added create_resource return value * fix protocol node log_message, added create_resource return value * try fix add protocol * fix resource_add * 修复移液站错误的aspirate注册表 * Feature/xprbalance-zhida (#80) * feat(devices): add Zhida GC/MS pretreatment automation workstation * feat(devices): add mettler_toledo xpr balance * balance * 重新补全zhida注册表 * PRCXI9320 json * PRCXI9320 json * PRCXI9320 json * fix resource download * remove class for resource * bump version to 0.10.6 * 更新所有注册表 * 修复protocolnode的兼容性 * 修复protocolnode的兼容性 * Update install md * Add Defaultlayout * 更新物料接口 * fix dict to tree/nested-dict converter * coin_cell_station draft * refactor: rename "station_resource" to "deck" * add standardized BIOYOND resources: bottle_carrier, bottle * refactor and add BIOYOND resources tests * add BIOYOND deck assignment and pass all tests * fix: update resource with correct structure; remove deprecated liquid_handler set_group action * feat: 将新威电池测试系统驱动与配置文件并入 workstation_dev_YB2 (#92) * feat: 新威电池测试系统驱动与注册文件 * feat: bring neware driver & battery.json into workstation_dev_YB2 * add bioyond studio draft * bioyond station with communication init and resource sync * fix bioyond station and registry * fix: update resource with correct structure; remove deprecated liquid_handler set_group action * frontend_docs * create/update resources with POST/PUT for big amount/ small amount data * create/update resources with POST/PUT for big amount/ small amount data * refactor: add itemized_carrier instead of carrier consists of ResourceHolder * create warehouse by factory func * update bioyond launch json * add child_size for itemized_carrier * fix bioyond resource io * Workstation templates: Resources and its CRUD, and workstation tasks (#95) * coin_cell_station draft * refactor: rename "station_resource" to "deck" * add standardized BIOYOND resources: bottle_carrier, bottle * refactor and add BIOYOND resources tests * add BIOYOND deck assignment and pass all tests * fix: update resource with correct structure; remove deprecated liquid_handler set_group action * feat: 将新威电池测试系统驱动与配置文件并入 workstation_dev_YB2 (#92) * feat: 新威电池测试系统驱动与注册文件 * feat: bring neware driver & battery.json into workstation_dev_YB2 * add bioyond studio draft * bioyond station with communication init and resource sync * fix bioyond station and registry * create/update resources with POST/PUT for big amount/ small amount data * refactor: add itemized_carrier instead of carrier consists of ResourceHolder * create warehouse by factory func * update bioyond launch json * add child_size for itemized_carrier * fix bioyond resource io --------- Co-authored-by: h840473807 <47357934+h840473807@users.noreply.github.com> Co-authored-by: Xie Qiming <97236197+Andy6M@users.noreply.github.com> * 更新物料接口 * Workstation dev yb2 (#100) * Refactor and extend reaction station action messages * Refactor dispensing station tasks to enhance parameter clarity and add batch processing capabilities - Updated `create_90_10_vial_feeding_task` to include detailed parameters for 90%/10% vial feeding, improving clarity and usability. - Introduced `create_batch_90_10_vial_feeding_task` for batch processing of 90%/10% vial feeding tasks with JSON formatted input. - Added `create_batch_diamine_solution_task` for batch preparation of diamine solution, also utilizing JSON formatted input. - Refined `create_diamine_solution_task` to include additional parameters for better task configuration. - Enhanced schema descriptions and default values for improved user guidance. * 修复to_plr_resources * add update remove * 支持选择器注册表自动生成 支持转运物料 * 修复资源添加 * 修复transfer_resource_to_another生成 * 更新transfer_resource_to_another参数,支持spot入参 * 新增test_resource动作 * fix host_node error * fix host_node test_resource error * fix host_node test_resource error * 过滤本地动作 * 移动内部action以兼容host node * 修复同步任务报错不显示的bug * feat: 允许返回非本节点物料,后面可以通过decoration进行区分,就不进行warning了 * update todo * modify bioyond/plr converter, bioyond resource registry, and tests * pass the tests * update todo * add conda-pack-build.yml * add auto install script for conda-pack-build.yml (cherry picked from commit172599adcf) * update conda-pack-build.yml * update conda-pack-build.yml * update conda-pack-build.yml * update conda-pack-build.yml * update conda-pack-build.yml * Add version in __init__.py Update conda-pack-build.yml Add create_zip_archive.py * Update conda-pack-build.yml * Update conda-pack-build.yml (with mamba) * Update conda-pack-build.yml * Fix FileNotFoundError * Try fix 'charmap' codec can't encode characters in position 16-23: character maps to <undefined> * Fix unilabos msgs search error * Fix environment_check.py * Update recipe.yaml * Update registry. Update uuid loop figure method. Update install docs. * Fix nested conda pack * Fix one-key installation path error * Bump version to 0.10.7 * Workshop bj (#99) * Add LaiYu Liquid device integration and tests Introduce LaiYu Liquid device implementation, including backend, controllers, drivers, configuration, and resource files. Add hardware connection, tip pickup, and simplified test scripts, as well as experiment and registry configuration for LaiYu Liquid. Documentation and .gitignore for the device are also included. * feat(LaiYu_Liquid): 重构设备模块结构并添加硬件文档 refactor: 重新组织LaiYu_Liquid模块目录结构 docs: 添加SOPA移液器和步进电机控制指令文档 fix: 修正设备配置中的最大体积默认值 test: 新增工作台配置测试用例 chore: 删除过时的测试脚本和配置文件 * add * 重构: 将 LaiYu_Liquid.py 重命名为 laiyu_liquid_main.py 并更新所有导入引用 - 使用 git mv 将 LaiYu_Liquid.py 重命名为 laiyu_liquid_main.py - 更新所有相关文件中的导入引用 - 保持代码功能不变,仅改善命名一致性 - 测试确认所有导入正常工作 * 修复: 在 core/__init__.py 中添加 LaiYuLiquidBackend 导出 - 添加 LaiYuLiquidBackend 到导入列表 - 添加 LaiYuLiquidBackend 到 __all__ 导出列表 - 确保所有主要类都可以正确导入 * 修复大小写文件夹名字 * 电池装配工站二次开发教程(带目录)上传至dev (#94) * 电池装配工站二次开发教程 * Update intro.md * 物料教程 * 更新物料教程,json格式注释 * Update prcxi driver & fix transfer_liquid mix_times (#90) * Update prcxi driver & fix transfer_liquid mix_times * fix: correct mix_times type * Update liquid_handler registry * test: prcxi.py * Update registry from pr * fix ony-key script not exist * clean files --------- Co-authored-by: Junhan Chang <changjh@dp.tech> Co-authored-by: ZiWei <131428629+ZiWei09@users.noreply.github.com> Co-authored-by: Guangxin Zhang <guangxin.zhang.bio@gmail.com> Co-authored-by: Xie Qiming <97236197+Andy6M@users.noreply.github.com> Co-authored-by: h840473807 <47357934+h840473807@users.noreply.github.com> Co-authored-by: LccLink <1951855008@qq.com> Co-authored-by: lixinyu1011 <61094742+lixinyu1011@users.noreply.github.com> Co-authored-by: shiyubo0410 <shiyubo@dp.tech>
589 lines
17 KiB
Python
589 lines
17 KiB
Python
"""
|
|
示例设备类文件,用于测试注册表编辑器
|
|
"""
|
|
|
|
import asyncio
|
|
from typing import Dict, Any, Optional, List
|
|
|
|
|
|
class SmartPumpController:
|
|
"""
|
|
智能泵控制器
|
|
|
|
支持多种泵送模式,具有高精度流量控制和自动校准功能。
|
|
适用于实验室自动化系统中的液体处理任务。
|
|
"""
|
|
|
|
def __init__(self, device_id: str = "smart_pump_01", port: str = "/dev/ttyUSB0"):
|
|
"""
|
|
初始化智能泵控制器
|
|
|
|
Args:
|
|
device_id: 设备唯一标识符
|
|
port: 通信端口
|
|
"""
|
|
self.device_id = device_id
|
|
self.port = port
|
|
self.is_connected = False
|
|
self.current_flow_rate = 0.0
|
|
self.total_volume_pumped = 0.0
|
|
self.calibration_factor = 1.0
|
|
self.pump_mode = "continuous" # continuous, volume, rate
|
|
|
|
def connect_device(self, timeout: int = 10) -> bool:
|
|
"""
|
|
连接到泵设备
|
|
|
|
Args:
|
|
timeout: 连接超时时间(秒)
|
|
|
|
Returns:
|
|
bool: 连接是否成功
|
|
"""
|
|
# 模拟连接过程
|
|
self.is_connected = True
|
|
return True
|
|
|
|
def disconnect_device(self) -> bool:
|
|
"""
|
|
断开设备连接
|
|
|
|
Returns:
|
|
bool: 断开连接是否成功
|
|
"""
|
|
self.is_connected = False
|
|
self.current_flow_rate = 0.0
|
|
return True
|
|
|
|
def set_flow_rate(self, flow_rate: float, units: str = "ml/min") -> bool:
|
|
"""
|
|
设置泵流速
|
|
|
|
Args:
|
|
flow_rate: 流速值
|
|
units: 流速单位
|
|
|
|
Returns:
|
|
bool: 设置是否成功
|
|
"""
|
|
if not self.is_connected:
|
|
return False
|
|
|
|
self.current_flow_rate = flow_rate
|
|
return True
|
|
|
|
async def pump_volume_async(self, volume: float, flow_rate: float) -> Dict[str, Any]:
|
|
"""
|
|
异步泵送指定体积的液体
|
|
|
|
Args:
|
|
volume: 目标体积 (mL)
|
|
flow_rate: 泵送流速 (mL/min)
|
|
|
|
Returns:
|
|
Dict: 包含操作结果的字典
|
|
"""
|
|
if not self.is_connected:
|
|
return {"success": False, "error": "设备未连接"}
|
|
|
|
# 计算泵送时间
|
|
pump_time = (volume / flow_rate) * 60 # 转换为秒
|
|
|
|
self.current_flow_rate = flow_rate
|
|
await asyncio.sleep(min(pump_time, 3.0)) # 模拟泵送过程
|
|
|
|
self.total_volume_pumped += volume
|
|
self.current_flow_rate = 0.0
|
|
|
|
return {
|
|
"success": True,
|
|
"pumped_volume": volume,
|
|
"actual_time": min(pump_time, 3.0),
|
|
"total_volume": self.total_volume_pumped,
|
|
}
|
|
|
|
def emergency_stop(self) -> bool:
|
|
"""
|
|
紧急停止泵
|
|
|
|
Returns:
|
|
bool: 停止是否成功
|
|
"""
|
|
self.current_flow_rate = 0.0
|
|
return True
|
|
|
|
def perform_calibration(self, reference_volume: float, measured_volume: float) -> bool:
|
|
"""
|
|
执行泵校准
|
|
|
|
Args:
|
|
reference_volume: 参考体积
|
|
measured_volume: 实际测量体积
|
|
|
|
Returns:
|
|
bool: 校准是否成功
|
|
"""
|
|
if measured_volume > 0:
|
|
self.calibration_factor = reference_volume / measured_volume
|
|
return True
|
|
return False
|
|
|
|
# 状态查询方法
|
|
def get_connection_status(self) -> str:
|
|
"""获取连接状态"""
|
|
return "connected" if self.is_connected else "disconnected"
|
|
|
|
def get_current_flow_rate(self) -> float:
|
|
"""获取当前流速 (mL/min)"""
|
|
return self.current_flow_rate
|
|
|
|
def get_total_volume(self) -> float:
|
|
"""获取累计泵送体积 (mL)"""
|
|
return self.total_volume_pumped
|
|
|
|
def get_calibration_factor(self) -> float:
|
|
"""获取校准因子"""
|
|
return self.calibration_factor
|
|
|
|
def get_pump_mode(self) -> str:
|
|
"""获取泵送模式"""
|
|
return self.pump_mode
|
|
|
|
def get_device_status(self) -> Dict[str, Any]:
|
|
"""获取设备完整状态信息"""
|
|
return {
|
|
"device_id": self.device_id,
|
|
"connected": self.is_connected,
|
|
"flow_rate": self.current_flow_rate,
|
|
"total_volume": self.total_volume_pumped,
|
|
"calibration_factor": self.calibration_factor,
|
|
"mode": self.pump_mode,
|
|
"running": self.current_flow_rate > 0,
|
|
}
|
|
|
|
|
|
class AdvancedTemperatureController:
|
|
"""
|
|
高级温度控制器
|
|
|
|
支持PID控制、多点温度监控和程序化温度曲线。
|
|
适用于需要精确温度控制的化学反应和材料处理过程。
|
|
"""
|
|
|
|
def __init__(self, controller_id: str = "temp_controller_01"):
|
|
"""
|
|
初始化温度控制器
|
|
|
|
Args:
|
|
controller_id: 控制器ID
|
|
"""
|
|
self.controller_id = controller_id
|
|
self.current_temperature = 25.0
|
|
self.target_temperature = 25.0
|
|
self.is_heating = False
|
|
self.is_cooling = False
|
|
self.pid_enabled = True
|
|
self.temperature_history: List[Dict] = []
|
|
|
|
def set_target_temperature(self, temperature: float, rate: float = 10.0) -> bool:
|
|
"""
|
|
设置目标温度
|
|
|
|
Args:
|
|
temperature: 目标温度 (°C)
|
|
rate: 升温/降温速率 (°C/min)
|
|
|
|
Returns:
|
|
bool: 设置是否成功
|
|
"""
|
|
self.target_temperature = temperature
|
|
return True
|
|
|
|
async def heat_to_temperature_async(
|
|
self, temperature: float, tolerance: float = 0.5, timeout: int = 600
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
异步加热到指定温度
|
|
|
|
Args:
|
|
temperature: 目标温度 (°C)
|
|
tolerance: 温度容差 (°C)
|
|
timeout: 最大等待时间 (秒)
|
|
|
|
Returns:
|
|
Dict: 操作结果
|
|
"""
|
|
self.target_temperature = temperature
|
|
start_temp = self.current_temperature
|
|
|
|
if temperature > start_temp:
|
|
self.is_heating = True
|
|
elif temperature < start_temp:
|
|
self.is_cooling = True
|
|
|
|
# 模拟温度变化过程
|
|
steps = min(abs(temperature - start_temp) * 2, 20) # 计算步数
|
|
step_time = min(timeout / steps if steps > 0 else 1, 2.0) # 每步最多2秒
|
|
|
|
for step in range(int(steps)):
|
|
progress = (step + 1) / steps
|
|
self.current_temperature = start_temp + (temperature - start_temp) * progress
|
|
|
|
# 记录温度历史
|
|
self.temperature_history.append(
|
|
{
|
|
"timestamp": asyncio.get_event_loop().time(),
|
|
"temperature": self.current_temperature,
|
|
"target": self.target_temperature,
|
|
}
|
|
)
|
|
|
|
await asyncio.sleep(step_time)
|
|
|
|
# 保持历史记录不超过100条
|
|
if len(self.temperature_history) > 100:
|
|
self.temperature_history.pop(0)
|
|
|
|
# 最终设置为目标温度
|
|
self.current_temperature = temperature
|
|
self.is_heating = False
|
|
self.is_cooling = False
|
|
|
|
return {
|
|
"success": True,
|
|
"final_temperature": self.current_temperature,
|
|
"start_temperature": start_temp,
|
|
"time_taken": steps * step_time,
|
|
}
|
|
|
|
def enable_pid_control(self, kp: float = 1.0, ki: float = 0.1, kd: float = 0.05) -> bool:
|
|
"""
|
|
启用PID控制
|
|
|
|
Args:
|
|
kp: 比例增益
|
|
ki: 积分增益
|
|
kd: 微分增益
|
|
|
|
Returns:
|
|
bool: 启用是否成功
|
|
"""
|
|
self.pid_enabled = True
|
|
return True
|
|
|
|
def run_temperature_program(self, program: List[Dict]) -> bool:
|
|
"""
|
|
运行温度程序
|
|
|
|
Args:
|
|
program: 温度程序列表,每个元素包含温度和持续时间
|
|
|
|
Returns:
|
|
bool: 程序启动是否成功
|
|
"""
|
|
# 模拟程序启动
|
|
return True
|
|
|
|
# 状态查询方法
|
|
def get_current_temperature(self) -> float:
|
|
"""获取当前温度 (°C)"""
|
|
return round(self.current_temperature, 2)
|
|
|
|
def get_target_temperature(self) -> float:
|
|
"""获取目标温度 (°C)"""
|
|
return self.target_temperature
|
|
|
|
def get_heating_status(self) -> bool:
|
|
"""获取加热状态"""
|
|
return self.is_heating
|
|
|
|
def get_cooling_status(self) -> bool:
|
|
"""获取制冷状态"""
|
|
return self.is_cooling
|
|
|
|
def get_pid_status(self) -> bool:
|
|
"""获取PID控制状态"""
|
|
return self.pid_enabled
|
|
|
|
def get_temperature_history(self) -> List[Dict]:
|
|
"""获取温度历史记录"""
|
|
return self.temperature_history[-10:] # 返回最近10条记录
|
|
|
|
def get_controller_status(self) -> Dict[str, Any]:
|
|
"""获取控制器完整状态"""
|
|
return {
|
|
"controller_id": self.controller_id,
|
|
"current_temp": self.current_temperature,
|
|
"target_temp": self.target_temperature,
|
|
"is_heating": self.is_heating,
|
|
"is_cooling": self.is_cooling,
|
|
"pid_enabled": self.pid_enabled,
|
|
"history_count": len(self.temperature_history),
|
|
}
|
|
|
|
|
|
class MultiChannelAnalyzer:
|
|
"""
|
|
多通道分析仪
|
|
|
|
支持同时监测多个通道的信号,提供实时数据采集和分析功能。
|
|
常用于光谱分析、电化学测量等应用场景。
|
|
"""
|
|
|
|
def __init__(self, analyzer_id: str = "analyzer_01", channels: int = 8):
|
|
"""
|
|
初始化多通道分析仪
|
|
|
|
Args:
|
|
analyzer_id: 分析仪ID
|
|
channels: 通道数量
|
|
"""
|
|
self.analyzer_id = analyzer_id
|
|
self.channel_count = channels
|
|
self.channel_data = {i: {"value": 0.0, "unit": "V", "enabled": True} for i in range(channels)}
|
|
self.is_measuring = False
|
|
self.sample_rate = 1000 # Hz
|
|
|
|
def configure_channel(self, channel: int, enabled: bool = True, unit: str = "V") -> bool:
|
|
"""
|
|
配置通道
|
|
|
|
Args:
|
|
channel: 通道编号
|
|
enabled: 是否启用
|
|
unit: 测量单位
|
|
|
|
Returns:
|
|
bool: 配置是否成功
|
|
"""
|
|
if 0 <= channel < self.channel_count:
|
|
self.channel_data[channel]["enabled"] = enabled
|
|
self.channel_data[channel]["unit"] = unit
|
|
return True
|
|
return False
|
|
|
|
async def start_measurement_async(self, duration: int = 10) -> Dict[str, Any]:
|
|
"""
|
|
开始异步测量
|
|
|
|
Args:
|
|
duration: 测量持续时间(秒)
|
|
|
|
Returns:
|
|
Dict: 测量结果
|
|
"""
|
|
self.is_measuring = True
|
|
|
|
# 模拟数据采集
|
|
measurements = []
|
|
for second in range(duration):
|
|
timestamp = asyncio.get_event_loop().time()
|
|
frame_data = {}
|
|
|
|
for channel in range(self.channel_count):
|
|
if self.channel_data[channel]["enabled"]:
|
|
# 模拟传感器数据
|
|
import random
|
|
|
|
value = random.uniform(-5.0, 5.0)
|
|
frame_data[f"channel_{channel}"] = value
|
|
self.channel_data[channel]["value"] = value
|
|
|
|
measurements.append({"timestamp": timestamp, "data": frame_data})
|
|
|
|
await asyncio.sleep(1.0) # 每秒采集一次
|
|
|
|
self.is_measuring = False
|
|
|
|
return {
|
|
"success": True,
|
|
"duration": duration,
|
|
"samples_count": len(measurements),
|
|
"measurements": measurements[-5:], # 只返回最后5个样本
|
|
"channels_active": len([ch for ch in self.channel_data.values() if ch["enabled"]]),
|
|
}
|
|
|
|
def stop_measurement(self) -> bool:
|
|
"""
|
|
停止测量
|
|
|
|
Returns:
|
|
bool: 停止是否成功
|
|
"""
|
|
self.is_measuring = False
|
|
return True
|
|
|
|
def reset_channels(self) -> bool:
|
|
"""
|
|
重置所有通道
|
|
|
|
Returns:
|
|
bool: 重置是否成功
|
|
"""
|
|
for channel in self.channel_data:
|
|
self.channel_data[channel]["value"] = 0.0
|
|
return True
|
|
|
|
# 状态查询方法
|
|
def get_measurement_status(self) -> bool:
|
|
"""获取测量状态"""
|
|
return self.is_measuring
|
|
|
|
def get_channel_count(self) -> int:
|
|
"""获取通道数量"""
|
|
return self.channel_count
|
|
|
|
def get_sample_rate(self) -> float:
|
|
"""获取采样率 (Hz)"""
|
|
return self.sample_rate
|
|
|
|
def get_channel_values(self) -> Dict[int, float]:
|
|
"""获取所有通道的当前值"""
|
|
return {ch: data["value"] for ch, data in self.channel_data.items() if data["enabled"]}
|
|
|
|
def get_enabled_channels(self) -> List[int]:
|
|
"""获取已启用的通道列表"""
|
|
return [ch for ch, data in self.channel_data.items() if data["enabled"]]
|
|
|
|
def get_analyzer_status(self) -> Dict[str, Any]:
|
|
"""获取分析仪完整状态"""
|
|
return {
|
|
"analyzer_id": self.analyzer_id,
|
|
"channel_count": self.channel_count,
|
|
"is_measuring": self.is_measuring,
|
|
"sample_rate": self.sample_rate,
|
|
"active_channels": len(self.get_enabled_channels()),
|
|
"channel_data": self.channel_data,
|
|
}
|
|
|
|
|
|
class AutomatedDispenser:
|
|
"""
|
|
自动分配器
|
|
|
|
精确控制固体和液体材料的分配,支持多种分配模式和容器管理。
|
|
集成称重功能,确保分配精度和重现性。
|
|
"""
|
|
|
|
def __init__(self, dispenser_id: str = "dispenser_01"):
|
|
"""
|
|
初始化自动分配器
|
|
|
|
Args:
|
|
dispenser_id: 分配器ID
|
|
"""
|
|
self.dispenser_id = dispenser_id
|
|
self.is_ready = True
|
|
self.current_position = {"x": 0.0, "y": 0.0, "z": 0.0}
|
|
self.dispensed_total = 0.0
|
|
self.container_capacity = 1000.0 # mL
|
|
self.precision_mode = True
|
|
|
|
def move_to_position(self, x: float, y: float, z: float) -> bool:
|
|
"""
|
|
移动到指定位置
|
|
|
|
Args:
|
|
x: X坐标 (mm)
|
|
y: Y坐标 (mm)
|
|
z: Z坐标 (mm)
|
|
|
|
Returns:
|
|
bool: 移动是否成功
|
|
"""
|
|
self.current_position = {"x": x, "y": y, "z": z}
|
|
return True
|
|
|
|
async def dispense_liquid_async(self, volume: float, container_id: str, viscosity: str = "low") -> Dict[str, Any]:
|
|
"""
|
|
异步分配液体
|
|
|
|
Args:
|
|
volume: 分配体积 (mL)
|
|
container_id: 容器ID
|
|
viscosity: 液体粘度等级
|
|
|
|
Returns:
|
|
Dict: 分配结果
|
|
"""
|
|
if not self.is_ready:
|
|
return {"success": False, "error": "设备未就绪"}
|
|
|
|
if volume <= 0:
|
|
return {"success": False, "error": "体积必须大于0"}
|
|
|
|
# 模拟分配过程
|
|
dispense_time = volume * 0.1 # 每mL需要0.1秒
|
|
if viscosity == "high":
|
|
dispense_time *= 2 # 高粘度液体需要更长时间
|
|
|
|
await asyncio.sleep(min(dispense_time, 5.0)) # 最多等待5秒
|
|
|
|
self.dispensed_total += volume
|
|
|
|
return {
|
|
"success": True,
|
|
"dispensed_volume": volume,
|
|
"container_id": container_id,
|
|
"actual_time": min(dispense_time, 5.0),
|
|
"total_dispensed": self.dispensed_total,
|
|
}
|
|
|
|
def clean_dispenser(self, wash_volume: float = 5.0) -> bool:
|
|
"""
|
|
清洗分配器
|
|
|
|
Args:
|
|
wash_volume: 清洗液体积 (mL)
|
|
|
|
Returns:
|
|
bool: 清洗是否成功
|
|
"""
|
|
# 模拟清洗过程
|
|
return True
|
|
|
|
def calibrate_volume(self, target_volume: float) -> bool:
|
|
"""
|
|
校准分配体积
|
|
|
|
Args:
|
|
target_volume: 校准目标体积 (mL)
|
|
|
|
Returns:
|
|
bool: 校准是否成功
|
|
"""
|
|
# 模拟校准过程
|
|
return True
|
|
|
|
# 状态查询方法
|
|
def get_ready_status(self) -> bool:
|
|
"""获取就绪状态"""
|
|
return self.is_ready
|
|
|
|
def get_current_position(self) -> Dict[str, float]:
|
|
"""获取当前位置坐标"""
|
|
return self.current_position.copy()
|
|
|
|
def get_dispensed_total(self) -> float:
|
|
"""获取累计分配体积 (mL)"""
|
|
return self.dispensed_total
|
|
|
|
def get_container_capacity(self) -> float:
|
|
"""获取容器容量 (mL)"""
|
|
return self.container_capacity
|
|
|
|
def get_precision_mode(self) -> bool:
|
|
"""获取精密模式状态"""
|
|
return self.precision_mode
|
|
|
|
def get_dispenser_status(self) -> Dict[str, Any]:
|
|
"""获取分配器完整状态"""
|
|
return {
|
|
"dispenser_id": self.dispenser_id,
|
|
"ready": self.is_ready,
|
|
"position": self.current_position,
|
|
"dispensed_total": self.dispensed_total,
|
|
"capacity": self.container_capacity,
|
|
"precision_mode": self.precision_mode,
|
|
}
|