From 2132895ba29da6cd9af6c59f3544671c565a5b9a Mon Sep 17 00:00:00 2001 From: WenzheG Date: Mon, 29 Sep 2025 11:14:04 +0800 Subject: [PATCH] nmr --- .../devices/Qone_nmr/QOne_NMR_User_Guide.md | 200 +++++++++ unilabos/devices/Qone_nmr/Qone_nmr.py | 382 ++++++++++++++++++ unilabos/devices/Qone_nmr/device.json | 25 ++ unilabos/devices/Qone_nmr/samples.csv | 4 + unilabos/registry/devices/Qone_nmr.yaml | 156 +++++++ 5 files changed, 767 insertions(+) create mode 100644 unilabos/devices/Qone_nmr/QOne_NMR_User_Guide.md create mode 100644 unilabos/devices/Qone_nmr/Qone_nmr.py create mode 100644 unilabos/devices/Qone_nmr/device.json create mode 100644 unilabos/devices/Qone_nmr/samples.csv create mode 100644 unilabos/registry/devices/Qone_nmr.yaml diff --git a/unilabos/devices/Qone_nmr/QOne_NMR_User_Guide.md b/unilabos/devices/Qone_nmr/QOne_NMR_User_Guide.md new file mode 100644 index 00000000..c09785c9 --- /dev/null +++ b/unilabos/devices/Qone_nmr/QOne_NMR_User_Guide.md @@ -0,0 +1,200 @@ +# QOne NMR 用户指南 + +## 概述 + +Qone NMR 设备支持多字符串数据处理功能。该设备可以接收包含多个字符串的输入数据,并将每个字符串转换为独立的 TXT 文件,支持灵活的数据格式化和输出。 + +## 核心功能 + +- **多字符串处理**: 支持逗号分隔或换行分隔的多个字符串输入 +- **自动文件生成**: 每个输入字符串生成一个对应的 TXT 文件 +- **文件夹监督**: 自动监督指定目录,检测新内容生成 +- **错误处理**: 完善的输入验证和错误处理机制 + +## 参数说明 + +### 输入参数 + +- **string** (str): 包含多个字符串的输入数据,支持格式: + - **逗号分隔**: `"字符串1, 字符串2, 字符串3"` + +### 输出参数 + +- **return_info** (str): 处理结果信息,包含监督功能的执行结果 +- **success** (bool): 处理是否成功 +- **files_generated** (int): 生成的 TXT 文件数量 + +## 输入数据格式 + +### 支持的输入格式 + +1. **逗号分隔格式**: + ``` + "A 1 B 1 C 1 D 1 E 1 F 1 G 1 H 1 END, A 2 B 2 C 2 D 2 E 2 F 2 G 2 H 2 END" + ``` + + ``` + +### 数据项格式 + +每个字符串内的数据项应该用空格分隔,例如: +- `A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 END` +- `Sample 001 Method A Volume 10.5 Temp 25.0` + +## 输出文件说明 + +### 文件命名 + +生成的 TXT 文件将按照row_字符串顺序命名,例如: +- `row_1.txt` +- `row_2.txt` + +### 文件格式 + +每个 TXT 文件包含对应字符串的格式化数据,格式为: +``` +A 1 +B 2 +C 3 +D 4 +E 5 +F 6 +G 7 +H 8 +END +``` + +### 输出目录 + +默认输出目录为 `D:/setup/txt`,可以在 `device.json` 中配置 `output_dir` 参数。 + +## 文件夹监督功能 + +### 监督机制 + +设备在完成字符串到TXT文件的转换后,会自动启动文件夹监督功能: + +- **监督目录**: 默认监督 `D:/Data/MyPC/Automation` 目录 +- **检查间隔**: 每60秒检查一次新生成的.nmr文件 +- **检测内容**: 新文件生成或现有文件大小变化 +- **停止条件**: 连续三次文件大小没有变化,则检测完成 + +## 文件夹监督功能详细说明 + +Oxford NMR设备驱动集成了智能文件夹监督功能,用于监测.nmr结果文件的生成完成状态。该功能通过监测文件大小变化来判断文件是否已完成写入。 + +### 工作机制 + +1. **文件大小监测**: 监督功能专门监测指定目录中新生成的.nmr文件的大小变化 +2. **稳定性检测**: 当文件大小在连续多次检查中保持不变时,认为文件已完成写入 +3. **批量处理支持**: 根据输入的.txt文件数量,自动确定需要监测的.nmr文件数量 +4. **实时反馈**: 提供详细的监测进度和文件状态信息 +5. **自动停止**: 当所有期望的.nmr文件都达到稳定状态时,监督功能自动停止,start函数执行完毕 + +### 配置参数 + +可以通过`device.json`配置文件调整监督功能的行为: + +```json +{ + "config": { + "output_dir": "D:/setup/txt", + "monitor_dir": "D:\\Data\\MyPC\\Automation", + "stability_checks": 3, + "check_interval": 60 + } +} +``` + +- `monitor_dir`: 监督的目录路径,默认为`D:\Data\MyPC\Automation` +- `stability_checks`: 文件大小稳定性检查次数,默认为3次(连续2次检查大小不变则认为文件完成) +- `check_interval`: 检查间隔时间(秒),默认为60秒 + +### 监测逻辑 + +1. **初始状态记录**: 记录监督开始时目录中已存在的.nmr文件及其大小 +2. **新文件检测**: 持续检测新生成的.nmr文件 +3. **大小变化跟踪**: 为每个新文件维护大小变化历史记录 +4. **稳定性判断**: 当文件大小在连续`stability_checks`次检查中保持不变且大小大于0时,认为文件完成 +5. **完成条件**: 当达到期望数量的.nmr文件都完成时,监督功能结束 + +### 配置监督目录 + +可以在 `device.json` 中配置 `monitor_dir` 参数来指定监督目录: + +```json +{ + "config": { + "output_dir": "D:/setup/txt", + "monitor_dir": "D:/Data/MyPC/Automation" + } +} +``` + +## 使用示例 + +### 示例 1: 基本多字符串处理 + +```python +from unilabos.devices.Qone_nmr.Qone_nmr import Qone_nmr + +# 创建设备实例 +device = Qone_nmr(output_directory="D:/setup/txt") + +# 输入多个字符串(逗号分隔) +input_data = "A 1 B 1 C 1 D 1 E 1 F 1 G 1 H 1 END, A 2 B 2 C 2 D 2 E 2 F 2 G 2 H 2 END" + +# 处理数据 +result = device.start(string=input_data) + +print(f"处理结果: {result}") +# 输出: {'return_info': 'Oxford NMR处理完成: 已生成 3 个 txt 文件,保存在: ./output | 监督完成: 成功检测到 3 个.nmr文件已完成生成', 'success': True, 'files_generated': 3} + +### 输出示例 + +当设备成功处理输入并完成文件监督后,会返回如下格式的结果: + +```json +{ + "return_info": "Oxford NMR处理完成: 已生成 3 个 txt 文件,保存在: D:/setup/txt | 监督完成: 成功检测到 3 个.nmr文件已完成生成,start函数执行完毕", + "success": true, + "files_generated": 3 +} +``` + +监督过程中的日志输出示例: +``` +[INFO] 开始监督目录: D:/Data/MyPC/Automation,检查间隔: 30秒,期望.nmr文件数量: 3,稳定性检查: 2次 +[INFO] 初始状态: 0 个.nmr文件 +[INFO] 检测到 3 个新.nmr文件,还需要 0 个... +[DEBUG] 文件大小监测中: D:/Data/MyPC/Automation/sample1.nmr (当前: 1024 字节, 检查次数: 1/3) +[DEBUG] 文件大小监测中: D:/Data/MyPC/Automation/sample2.nmr (当前: 2048 字节, 检查次数: 1/3) +[DEBUG] 文件大小监测中: D:/Data/MyPC/Automation/sample3.nmr (当前: 1536 字节, 检查次数: 1/3) +[INFO] 文件大小已稳定: D:/Data/MyPC/Automation/sample1.nmr (大小: 1024 字节) +[INFO] 文件大小已稳定: D:/Data/MyPC/Automation/sample2.nmr (大小: 2048 字节) +[INFO] 文件大小已稳定: D:/Data/MyPC/Automation/sample3.nmr (大小: 1536 字节) +[INFO] 所有期望的.nmr文件都已完成生成! 完成文件数: 3/3 +[INFO] 完成的.nmr文件: D:/Data/MyPC/Automation/sample1.nmr (最终大小: 1024 字节) +[INFO] 完成的.nmr文件: D:/Data/MyPC/Automation/sample2.nmr (最终大小: 2048 字节) +[INFO] 完成的.nmr文件: D:/Data/MyPC/Automation/sample3.nmr (最终大小: 1536 字节) +[INFO] 停止文件夹监测,所有文件已完成 +``` +``` + +## 错误处理 + +设备具有完善的错误处理机制: + +- **空输入**: 如果输入为空或 None,返回错误信息 +- **无效格式**: 如果输入格式不正确,返回相应错误 +- **文件系统错误**: 如果输出目录不存在或无权限,返回错误信息 + +## 注意事项 + +1. **目录权限**: 确保监督目录具有读取权限,以便设备能够检测文件变化 +2. **文件大小监测**: 监督功能现在基于文件大小变化来判断.nmr文件是否完成,而不是简单的文件存在性检查 +3. **稳定性检查**: 文件大小需要在连续多次检查中保持不变才被认为完成,默认为3次检查 +4. **自动停止**: 监督功能会在检测到期望数量的.nmr文件都达到稳定状态后自动停止,避免无限循环 +5. **配置灵活性**: 可以通过`device.json`调整稳定性检查次数和检查间隔,以适应不同的使用场景 +6. **文件类型**: 监督功能专门针对.nmr文件,忽略其他类型的文件变化 +7. **批量处理**: 支持同时监测多个.nmr文件的完成状态,适合批量处理场景 \ No newline at end of file diff --git a/unilabos/devices/Qone_nmr/Qone_nmr.py b/unilabos/devices/Qone_nmr/Qone_nmr.py new file mode 100644 index 00000000..1633a8d6 --- /dev/null +++ b/unilabos/devices/Qone_nmr/Qone_nmr.py @@ -0,0 +1,382 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Oxford NMR Device Driver for Uni-Lab OS + +支持Oxford NMR设备的CSV字符串到TXT文件转换功能。 +通过ROS2动作接口接收CSV字符串,批量生成TXT文件到指定目录。 +""" + +import csv +import io +import logging +import os +import re +import time +from pathlib import Path +from typing import Dict, Any + +class UniversalDriver: + """Fallback UniversalDriver for standalone testing""" + def __init__(self): + self.success = False + +class Qone_nmr(UniversalDriver): + """Oxford NMR Device Driver + + 支持CSV字符串到TXT文件的批量转换功能。 + """ + + def __init__(self, **kwargs): + """Initialize the Oxford NMR driver + + Args: + **kwargs: Device-specific configuration parameters + - config: Configuration dictionary containing output_dir + """ + super().__init__() + + # Device configuration + self.config = kwargs + config_dict = kwargs.get('config', {}) + + # 设置输出目录,优先使用配置中的output_dir,否则使用默认值 + self.output_directory = "D:\\setup\\txt" # 默认输出目录 + if config_dict and 'output_dir' in config_dict: + self.output_directory = config_dict['output_dir'] + + # 设置监督目录,优先使用配置中的monitor_dir,否则使用默认值 + self.monitor_directory = "D:/Data/MyPC/Automation" # 默认监督目录 + if config_dict and 'monitor_dir' in config_dict: + self.monitor_directory = config_dict['monitor_dir'] + + # 设置文件大小稳定性检查参数 + self.stability_checks = 3 # 默认稳定性检查次数 + if config_dict and 'stability_checks' in config_dict: + self.stability_checks = config_dict['stability_checks'] + + # 设置检查间隔时间 + self.check_interval = 60 # 默认检查间隔(秒) + if config_dict and 'check_interval' in config_dict: + self.check_interval = config_dict['check_interval'] + + # 确保输出目录存在 + os.makedirs(self.output_directory, exist_ok=True) + + # ROS节点引用,由框架设置 + self._ros_node = None + + # ROS2 action result properties + self.success = False + self.return_info = "" + + # Setup logging + self.logger = logging.getLogger(f"Qone_nmr-{kwargs.get('id', 'unknown')}") + self.logger.info(f"Oxford NMR driver initialized with output directory: {self.output_directory}") + self.logger.info(f"Monitor directory set to: {self.monitor_directory}") + self.logger.info(f"Stability checks: {self.stability_checks}, Check interval: {self.check_interval}s") + + def post_init(self, ros_node): + """ROS节点初始化后的回调方法 + + Args: + ros_node: ROS节点实例 + """ + self._ros_node = ros_node + ros_node.lab_logger().info(f"Oxford NMR设备初始化完成,输出目录: {self.output_directory}") + + def get_status(self) -> str: + """获取设备状态 + + Returns: + str: 设备状态 (Idle|Offline|Error|Busy|Unknown) + """ + return "Idle" # NMR设备始终处于空闲状态,等待处理请求 + + def strings_to_txt(self, string_list, output_dir=None, txt_encoding="utf-8"): + """ + 将字符串列表写入多个 txt 文件 + string_list: ["A 1 B 1 C 1 D 1 E 1 F 1 G 1 H 1 END", ...] + + Args: + string_list: 字符串列表 + output_dir: 输出目录(如果未指定,使用self.output_directory) + txt_encoding: 文件编码 + + Returns: + int: 生成的文件数量 + """ + # 使用指定的输出目录或默认目录 + target_dir = output_dir if output_dir else self.output_directory + + # 确保输出目录存在 + os.makedirs(target_dir, exist_ok=True) + + self.logger.info(f"开始生成文件到目录: {target_dir}") + + for i, s in enumerate(string_list, start=1): + try: + # 去掉开头结尾的引号(如果有) + s = s.strip('"').strip("'") + + # 拆分字符串 + parts = s.split() + + # 按两两一组重新排版为多行 + txt_lines = [] + for j in range(0, len(parts) - 1, 2): + txt_lines.append("{} {}".format(parts[j], parts[j+1])) + txt_lines.append("END") + + txt_content = "\n".join(txt_lines) + + # 生成文件名(row_1.txt, row_2.txt, ...) + file_name = "row_{}.txt".format(i) + out_path = os.path.join(target_dir, file_name) + + with open(out_path, "w", encoding=txt_encoding) as f: + f.write(txt_content) + + self.logger.info(f"成功生成文件: {file_name}") + + except Exception as e: + self.logger.error(f"处理第{i}个字符串时出错: {str(e)}") + raise + + return len(string_list) # 返回生成文件数量 + + def monitor_folder_for_new_content(self, monitor_dir=None, check_interval=60, expected_count=1, stability_checks=3): + """监督指定文件夹中.nmr文件的大小变化,当文件大小稳定时认为文件完成 + + Args: + monitor_dir (str): 要监督的目录路径,如果未指定则使用self.monitor_directory + check_interval (int): 检查间隔时间(秒),默认60秒 + expected_count (int): 期望生成的.nmr文件数量,默认1个 + stability_checks (int): 文件大小稳定性检查次数,默认3次 + + Returns: + bool: 如果检测到期望数量的.nmr文件且大小稳定返回True,否则返回False + """ + target_dir = monitor_dir if monitor_dir else self.monitor_directory + + # 确保监督目录存在 + if not os.path.exists(target_dir): + self.logger.warning(f"监督目录不存在: {target_dir}") + return False + + self.logger.info(f"开始监督目录: {target_dir},检查间隔: {check_interval}秒,期望.nmr文件数量: {expected_count},稳定性检查: {stability_checks}次") + + # 记录初始的.nmr文件及其大小 + initial_nmr_files = {} + + try: + for root, dirs, files in os.walk(target_dir): + for file in files: + if file.lower().endswith('.nmr'): + file_path = os.path.join(root, file) + try: + file_size = os.path.getsize(file_path) + initial_nmr_files[file_path] = file_size + except OSError: + pass # 忽略无法访问的文件 + except Exception as e: + self.logger.error(f"读取初始目录状态失败: {str(e)}") + return False + + self.logger.info(f"初始状态: {len(initial_nmr_files)} 个.nmr文件") + + # 跟踪新文件的大小变化历史 + new_files_size_history = {} + completed_files = set() + + # 开始监督循环 + while True: + time.sleep(check_interval) + + current_nmr_files = {} + + try: + for root, dirs, files in os.walk(target_dir): + for file in files: + if file.lower().endswith('.nmr'): + file_path = os.path.join(root, file) + try: + file_size = os.path.getsize(file_path) + current_nmr_files[file_path] = file_size + except OSError: + pass + + # 找出新生成的.nmr文件 + new_nmr_files = set(current_nmr_files.keys()) - set(initial_nmr_files.keys()) + + if len(new_nmr_files) < expected_count: + self.logger.info(f"检测到 {len(new_nmr_files)} 个新.nmr文件,还需要 {expected_count - len(new_nmr_files)} 个...") + continue + + # 检查新文件的大小稳定性 + for file_path in new_nmr_files: + if file_path in completed_files: + continue + + current_size = current_nmr_files.get(file_path, 0) + + # 初始化文件大小历史记录 + if file_path not in new_files_size_history: + new_files_size_history[file_path] = [] + + # 记录当前大小 + new_files_size_history[file_path].append(current_size) + + # 保持历史记录长度不超过稳定性检查次数 + if len(new_files_size_history[file_path]) > stability_checks: + new_files_size_history[file_path] = new_files_size_history[file_path][-stability_checks:] + + # 检查大小是否稳定 + size_history = new_files_size_history[file_path] + if len(size_history) >= stability_checks: + # 检查最近几次的大小是否相同且不为0 + if len(set(size_history[-stability_checks:])) == 1 and size_history[-1] > 0: + self.logger.info(f"文件大小已稳定: {file_path} (大小: {current_size} 字节)") + completed_files.add(file_path) + else: + self.logger.debug(f"文件大小仍在变化: {file_path} (当前: {current_size} 字节, 历史: {size_history[-3:]})") + else: + self.logger.debug(f"文件大小监测中: {file_path} (当前: {current_size} 字节, 检查次数: {len(size_history)}/{stability_checks})") + + # 检查是否所有期望的文件都已完成 + if len(completed_files) >= expected_count: + self.logger.info(f"所有期望的.nmr文件都已完成生成! 完成文件数: {len(completed_files)}/{expected_count}") + for completed_file in list(completed_files)[:expected_count]: + final_size = current_nmr_files.get(completed_file, 0) + self.logger.info(f"完成的.nmr文件: {completed_file} (最终大小: {final_size} 字节)") + self.logger.info("停止文件夹监测,所有文件已完成") + return True + else: + self.logger.info(f"已完成 {len(completed_files)} 个文件,还需要 {expected_count - len(completed_files)} 个文件完成...") + + except Exception as e: + self.logger.error(f"监督过程中出错: {str(e)}") + return False + + def start(self, string: str = None) -> dict: + """使用字符串列表启动TXT文件生成(支持ROS2动作调用) + + Args: + string (str): 包含多个字符串的输入数据,支持两种格式: + 1. 逗号分隔:如 "A 1 B 2 C 3, X 10 Y 20 Z 30" + 2. 换行分隔:如 "A 1 B 2 C 3\nX 10 Y 20 Z 30" + + Returns: + dict: ROS2动作结果格式 {"return_info": str, "success": bool, "files_generated": int} + """ + try: + if string is None or string.strip() == "": + error_msg = "未提供字符串参数或参数为空" + self.logger.error(error_msg) + return {"return_info": error_msg, "success": False, "files_generated": 0} + + self.logger.info(f"开始处理字符串数据,长度: {len(string)} 字符") + + # 支持两种分隔方式:逗号分隔或换行分隔 + string_list = [] + + # 首先尝试逗号分隔 + if ',' in string: + string_list = [item.strip() for item in string.split(',') if item.strip()] + else: + # 如果没有逗号,则按换行分隔 + string_list = [line.strip() for line in string.strip().split('\n') if line.strip()] + + if not string_list: + error_msg = "输入字符串解析后为空" + self.logger.error(error_msg) + return {"return_info": error_msg, "success": False, "files_generated": 0} + + # 确保输出目录存在 + os.makedirs(self.output_directory, exist_ok=True) + + # 使用strings_to_txt函数生成TXT文件 + file_count = self.strings_to_txt( + string_list=string_list, + output_dir=self.output_directory, + txt_encoding='utf-8' + ) + + success_msg = f"Oxford NMR处理完成: 已生成 {file_count} 个 txt 文件,保存在: {self.output_directory}" + self.logger.info(success_msg) + + # 在string转txt完成后,启动文件夹监督功能 + self.logger.info(f"开始启动文件夹监督功能,期望生成 {file_count} 个.nmr文件...") + monitor_result = self.monitor_folder_for_new_content( + expected_count=file_count, + check_interval=self.check_interval, + stability_checks=self.stability_checks + ) + + if monitor_result: + success_msg += f" | 监督完成: 成功检测到 {file_count} 个.nmr文件已完成生成,start函数执行完毕" + else: + success_msg += f" | 监督结束: 监督过程中断或失败,start函数执行完毕" + + return {"return_info": success_msg, "success": True, "files_generated": file_count} + + except Exception as e: + error_msg = f"字符串处理失败: {str(e)}" + self.logger.error(error_msg) + return {"return_info": error_msg, "success": False, "files_generated": 0} + + + +def test_qone_nmr(): + """测试Qone_nmr设备的字符串处理功能""" + try: + # 配置日志输出 + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' + ) + logger = logging.getLogger("Qone_nmr_test") + + logger.info("开始测试Qone_nmr设备...") + + # 创建设备实例,使用正确的配置格式 + device = Qone_nmr(config={'output_dir': "D:\\setup\\txt"}) + logger.info(f"设备初始化完成,输出目录: {device.output_directory}") + + # 测试数据:多个字符串,逗号分隔 + test_strings = "A 1 B 1 C 1 D 1 E 1 F 1 G 1 H 1 END, A 2 B 2 C 2 D 2 E 2 F 2 G 2 H 2 END" + logger.info(f"测试输入: {test_strings}") + + # 确保输出目录存在 + if not os.path.exists(device.output_directory): + os.makedirs(device.output_directory, exist_ok=True) + logger.info(f"创建输出目录: {device.output_directory}") + + # 调用start方法 + result = device.start(string=test_strings) + logger.info(f"处理结果: {result}") + + # 显示生成的文件内容 + if result.get('success', False): + output_dir = device.output_directory + if os.path.exists(output_dir): + txt_files = [f for f in os.listdir(output_dir) if f.endswith('.txt')] + logger.info(f"生成的文件数量: {len(txt_files)}") + for i, filename in enumerate(txt_files[:2]): # 只显示前2个文件 + filepath = os.path.join(output_dir, filename) + logger.info(f"文件 {i+1}: {filename}") + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + logger.info(f"内容:\n{content}") + + logger.info("测试完成!") + return result + except Exception as e: + logger.error(f"测试过程中出现错误: {str(e)}") + import traceback + traceback.print_exc() + return {"return_info": f"测试失败: {str(e)}", "success": False, "files_generated": 0} + + +if __name__ == "__main__": + test_qone_nmr() \ No newline at end of file diff --git a/unilabos/devices/Qone_nmr/device.json b/unilabos/devices/Qone_nmr/device.json new file mode 100644 index 00000000..7160f3a4 --- /dev/null +++ b/unilabos/devices/Qone_nmr/device.json @@ -0,0 +1,25 @@ +{ + "nodes": [ + { + "id": "Qone_nmr_device", + "name": "Qone_NMR_Device", + "parent": null, + "type": "device", + "class": "Qone_nmr", + "position": { + "x": 620.6111111111111, + "y": 171, + "z": 0 + }, + "config": { + "output_dir": "D:\\setup\\txt", + "monitor_dir": "D:\\Data\\MyPC\\Automation", + "stability_checks": 3, + "check_interval": 60 + }, + "data": {}, + "children": [] + } + ], + "links": [] +} \ No newline at end of file diff --git a/unilabos/devices/Qone_nmr/samples.csv b/unilabos/devices/Qone_nmr/samples.csv new file mode 100644 index 00000000..672343ac --- /dev/null +++ b/unilabos/devices/Qone_nmr/samples.csv @@ -0,0 +1,4 @@ +USERNAME,SLOT,EXPNAME,FILE,SOLVENT,TEMPLATE,TITLE +User,SLOT,Name,No.,SOLVENT,Experiment,TITLE +用户名,进样器孔位,实验任务的名字,保存文件的名字,溶剂(按照实验的要求),模板(按照实验的要求,指定测试的元素),标题 +admin,18,11LiDFOB,LiDFOB-11B,DMSO,B11,11LiDFOB_400MHz diff --git a/unilabos/registry/devices/Qone_nmr.yaml b/unilabos/registry/devices/Qone_nmr.yaml new file mode 100644 index 00000000..c20363ce --- /dev/null +++ b/unilabos/registry/devices/Qone_nmr.yaml @@ -0,0 +1,156 @@ +Qone_nmr: + category: + - Qone_nmr + class: + action_value_mappings: + abort: + feedback: {} + goal: {} + goal_default: {} + handles: {} + result: {} + schema: + description: '' + properties: + feedback: + properties: {} + required: [] + title: EmptyIn_Feedback + type: object + goal: + properties: {} + required: [] + title: EmptyIn_Goal + type: object + result: + properties: + return_info: + type: string + required: + - return_info + title: EmptyIn_Result + type: object + required: + - goal + title: EmptyIn + type: object + type: EmptyIn + get_status: + feedback: {} + goal: {} + goal_default: {} + handles: {} + result: {} + schema: + description: '' + properties: + feedback: + properties: {} + required: [] + title: EmptyIn_Feedback + type: object + goal: + properties: {} + required: [] + title: EmptyIn_Goal + type: object + result: + properties: + return_info: + type: string + required: + - return_info + title: EmptyIn_Result + type: object + required: + - goal + title: EmptyIn + type: object + type: EmptyIn + start: + feedback: {} + goal: + string: string + goal_default: + string: '' + handles: {} + result: {} + schema: + description: '' + properties: + feedback: + properties: {} + required: [] + title: StrSingleInput_Feedback + type: object + goal: + properties: + string: + type: string + required: + - string + title: StrSingleInput_Goal + type: object + result: + properties: + return_info: + type: string + success: + type: boolean + required: + - return_info + - success + title: StrSingleInput_Result + type: object + required: + - goal + title: StrSingleInput + type: object + type: StrSingleInput + module: unilabos.devices.Qone_nmr.Qone_nmr:Qone_nmr + status_types: + files_generated: int + return_info: str + success: bool + type: python + config_info: [] + description: Oxford NMR设备驱动,支持CSV字符串到TXT文件的批量转换功能,并监测对应.nmr文件的大小变化以确认结果生成完成 + handles: [] + icon: '' + init_param_schema: + config: + properties: + check_interval: + default: 60 + description: 文件监测检查间隔时间(秒) + maximum: 300 + minimum: 10 + type: integer + monitor_dir: + default: D:/Data/MyPC/Automation + type: string + output_dir: + default: D:/setup/txt + type: string + stability_checks: + default: 3 + description: 文件大小稳定性检查次数,文件大小连续N次不变时认为文件完成 + maximum: 10 + minimum: 1 + type: integer + required: [] + type: object + data: + properties: + files_generated: + type: integer + return_info: + type: string + success: + type: boolean + required: + - return_info + - success + - files_generated + type: object + version: 1.0.0