# 添加设备：注册表配置完整指南

本文档说明如何为设备创建和配置注册表，包括基本结构、特殊类型识别、动作配置等内容。

## 概述

注册表（Registry）是 Uni-Lab 的设备配置系统，采用 YAML 格式定义设备的：

- 可用动作（Actions）
- 状态类型（Status Types）
- 初始化参数（Init Parameters）
- 连接点（Handles）

好消息是系统会自动生成大部分配置内容，你只需要提供核心信息，让系统帮你完成剩余工作。

## 快速开始：使用注册表编辑器

推荐使用 UniLabOS 自带的可视化编辑器，它能帮你自动生成大部分配置，省去手写的麻烦。

### 使用步骤

1. 启动 UniLabOS
2. 在浏览器中打开"注册表编辑器"页面
3. 上传你的 Python 设备驱动文件
4. 点击"分析文件"，让系统读取类信息
5. 填写基本信息（设备描述、图标等）
6. 点击"生成注册表"，复制生成的内容
7. 保存到 `unilabos/registry/devices/your_device.yaml`

**提示**：我们提供了测试驱动用于在界面上尝试注册表生成，参见：`test/registry/example_devices.py`

## 注册表的基本结构

### 核心字段说明

| 字段名            | 类型   | 需要手写 | 说明                              |
| ----------------- | ------ | -------- | --------------------------------- |
| 设备标识符        | string | 是       | 设备的唯一名字，如 `mock_chiller` |
| class             | object | 部分     | 设备的核心信息，必须配置          |
| description       | string | 否       | 设备描述，系统默认给空字符串      |
| handles           | array  | 否       | 连接关系，默认为空                |
| icon              | string | 否       | 图标路径，默认为空                |
| init_param_schema | object | 否       | 初始化参数，系统自动分析生成      |
| version           | string | 否       | 版本号，默认 "1.0.0"              |
| category          | array  | 否       | 设备分类，默认使用文件名          |
| config_info       | array  | 否       | 嵌套配置，默认为空                |
| file_path         | string | 否       | 文件路径，系统自动设置            |
| registry_type     | string | 否       | 注册表类型，自动设为 "device"     |

### class 字段详解

class 是核心部分，包含这些内容：

| 字段名                | 类型   | 需要手写 | 说明                               |
| --------------------- | ------ | -------- | ---------------------------------- |
| module                | string | 是       | Python 类的路径，必须写            |
| type                  | string | 是       | 驱动类型，一般写 "python"          |
| status_types          | object | 否       | 状态类型，系统自动分析生成         |
| action_value_mappings | object | 部分     | 动作配置，系统会自动生成一些基础的 |

### 基本结构示例

```yaml
my_device:
  class:
    module: unilabos.devices.my_module.my_device:MyDevice
    type: python
    status_types:
      status: str
      temperature: float
    action_value_mappings:
      # 动作配置（详见后文）
      action_name:
        type: UniLabJsonCommand
        goal: { ... }
        result: { ... }

  description: '设备描述'
  version: '1.0.0'
  category:
    - device_category
  handles: []
  icon: ''
  init_param_schema:
    config:
      properties:
        port:
          default: DEFAULT_PORT
          type: string
      required: []
      type: object
    data:
      properties:
        status:
          type: string
        temperature:
          type: number
      required:
        - status
      type: object
```

## 创建注册表的方式

### 方式 1: 使用注册表编辑器（推荐）

适合大多数场景，快速高效。

**步骤**：

1. 启动 Uni-Lab
2. 访问 Web 界面的"注册表编辑器"
3. 上传您的 Python 设备驱动文件
4. 点击"分析文件"
5. 填写描述和图标
6. 点击"生成注册表"
7. 复制生成的 YAML 内容
8. 保存到 `unilabos/registry/devices/your_device.yaml`

### 方式 2: 使用--complete_registry 参数（开发调试）

适合开发阶段，自动补全配置。

```bash
# 启动时自动补全注册表
unilab -g dev.json --complete_registry --registry_path ./my_registry
```

系统会：

1. 扫描 Python 类
2. 分析方法签名和类型
3. 自动生成缺失的字段
4. 保存到注册表文件

**或者在代码中**：

```python
# 启动系统时使用参数
启动系统时用 complete_registry=True 参数，让系统自动补全
```

### 方式 3: 手动编写（高级）

适合需要精细控制或特殊需求的场景。

**最小化配置示例**：

```yaml
# devices/my_device.yaml
my_device:
  class:
    module: unilabos.devices.my_module.my_device:MyDevice
    type: python
```

然后启动时使用 `--complete_registry` 让系统自动补全其余内容。

## action_value_mappings 详解

这个部分定义设备能做哪些动作。系统会自动生成大部分动作，你通常只需要添加特殊的自定义动作。

### 系统自动生成的动作

1. **以 `auto-` 开头的动作**：从 Python 类的方法自动生成
2. **通用的驱动动作**：
   - `_execute_driver_command`：同步执行驱动命令（仅本地可用）
   - `_execute_driver_command_async`：异步执行驱动命令（仅本地可用）

### 动作配置字段

| 字段名           | 需要手写 | 说明                             |
| ---------------- | -------- | -------------------------------- |
| type             | 是       | 动作类型，必须指定               |
| goal             | 是       | 输入参数映射                     |
| feedback         | 否       | 实时反馈，通常为空               |
| result           | 是       | 结果返回映射                     |
| goal_default     | 部分     | 参数默认值，ROS 动作会自动生成   |
| schema           | 部分     | 前端表单配置，ROS 动作会自动生成 |
| handles          | 否       | 连接关系，默认为空               |
| placeholder_keys | 否       | 特殊输入字段配置                 |

### 动作类型

| 类型                   | 使用场景             | 系统自动生成内容       |
| ---------------------- | -------------------- | ---------------------- |
| UniLabJsonCommand      | 自定义同步 JSON 命令 | 无                     |
| UniLabJsonCommandAsync | 自定义异步 JSON 命令 | 无                     |
| ROS 动作类型           | 标准 ROS 动作        | goal_default 和 schema |

**常用的 ROS 动作类型**：

- `SendCmd`：发送简单命令
- `NavigateThroughPoses`：导航动作
- `SingleJointPosition`：单关节位置控制
- `Stir`：搅拌动作
- `HeatChill`、`HeatChillStart`：加热冷却动作

### 动作命名建议

根据设备用途来起名字：

- **启动停止类**：`start`、`stop`、`pause`、`resume`
- **设置参数类**：`set_speed`、`set_temperature`、`set_timer`
- **移动控制类**：`move_to_position`、`move_through_points`
- **功能操作类**：`stir`、`heat_chill_start`、`heat_chill_stop`
- **开关控制类**：`valve_open_cmd`、`valve_close_cmd`、`push_to`
- **命令执行类**：`send_nav_task`、`execute_command_from_outer`

### 动作配置示例

```yaml
heat_chill_start:
  type: HeatChillStart
  goal:
    purpose: purpose
    temp: temp
  goal_default:
    purpose: ''
    temp: 0.0
  handles:
    output:
      - handler_key: labware
        label: Labware
        data_type: resource
        data_source: handle
        data_key: liquid
  placeholder_keys:
    purpose: unilabos_resources
  result:
    status: status
    success: success
  schema:
    description: '启动加热冷却功能'
    properties:
      goal:
        properties:
          purpose:
            type: string
            description: '用途说明'
          temp:
            type: number
            description: '目标温度'
        required:
          - purpose
          - temp
        title: HeatChillStart_Goal
        type: object
    required:
      - goal
    title: HeatChillStart
    type: object
  feedback: {}
```

## 特殊类型的自动识别

### ResourceSlot 和 DeviceSlot 识别

当您在驱动代码中使用这些特殊类型时，系统会自动识别并生成相应的前端选择器。

**Python 驱动代码示例**：

```python
from unilabos.registry.placeholder_type import ResourceSlot, DeviceSlot
from typing import List

class MyDevice:
    def test_resource(
        self,
        resource: ResourceSlot,           # 单个资源
        resources: List[ResourceSlot],    # 多个资源
        device: DeviceSlot,               # 单个设备
        devices: List[DeviceSlot]         # 多个设备
    ):
        pass
```

**自动生成的注册表**（使用--complete_registry）：

```yaml
my_device:
  class:
    action_value_mappings:
      test_resource:
        type: UniLabJsonCommand
        goal:
          resource: resource
          resources: resources
          device: device
          devices: devices
        placeholder_keys:
          resource: unilabos_resources # 自动添加！
          resources: unilabos_resources # 自动添加！
          device: unilabos_devices # 自动添加！
          devices: unilabos_devices # 自动添加！
        result:
          success: success
```

### 识别规则

| Python 类型          | placeholder_keys 值  | 前端效果       |
| -------------------- | -------------------- | -------------- |
| `ResourceSlot`       | `unilabos_resources` | 单选资源下拉框 |
| `List[ResourceSlot]` | `unilabos_resources` | 多选资源下拉框 |
| `DeviceSlot`         | `unilabos_devices`   | 单选设备下拉框 |
| `List[DeviceSlot]`   | `unilabos_devices`   | 多选设备下拉框 |

### 前端 UI 效果

#### 单选资源

```yaml
placeholder_keys:
  source: unilabos_resources
```

**前端渲染**:

```
Source: [下拉选择框 ▼]
        ├── plate_1 (96孔板)
        ├── tiprack_1 (枪头架)
        ├── reservoir_1 (试剂槽)
        └── ...
```

#### 多选资源

```yaml
placeholder_keys:
  targets: unilabos_resources
```

**前端渲染**:

```
Targets: [多选下拉框 ▼]
         ☑ plate_1 (96孔板)
         ☐ plate_2 (384孔板)
         ☑ plate_3 (96孔板)
         └── ...
```

#### 单选设备

```yaml
placeholder_keys:
  pump: unilabos_devices
```

**前端渲染**:

```
Pump: [下拉选择框 ▼]
      ├── pump_1 (注射泵A)
      ├── pump_2 (注射泵B)
      └── ...
```

#### 多选设备

```yaml
placeholder_keys:
  sync_devices: unilabos_devices
```

**前端渲染**:

```
Sync Devices: [多选下拉框 ▼]
              ☑ heater_1 (加热器A)
              ☑ stirrer_1 (搅拌器)
              ☐ pump_1 (注射泵)
```

### 手动配置 placeholder_keys

如果需要手动添加或覆盖自动生成的 placeholder_keys：

#### 场景 1: 非标准参数名

```yaml
action_value_mappings:
  custom_action:
    goal:
      my_custom_resource_param: resource_param
      my_device_param: device_param
    placeholder_keys:
      my_custom_resource_param: unilabos_resources
      my_device_param: unilabos_devices
```

#### 场景 2: 混合类型

```python
def mixed_params(
    self,
    resource: ResourceSlot,
    normal_param: str,
    device: DeviceSlot
):
    pass
```

```yaml
placeholder_keys:
  resource: unilabos_resources # 资源选择
  device: unilabos_devices # 设备选择
  # normal_param不需要placeholder_keys
```

#### 场景 3: 自定义选择器

```yaml
placeholder_keys:
  special_param: custom_selector # 使用自定义选择器
```

## 系统自动生成的字段

### status_types

系统会扫描你的 Python 类，从带有 `@topic_config` 装饰器的 `@property` 或方法自动生成这部分：

```yaml
status_types:
  current_temperature: float # 从 @topic_config 装饰的 @property 或方法
  is_heating: bool
  status: str
```

**注意事项**：

- 仅有带 `@topic_config` 装饰器的 `@property` 或方法才会被识别为状态属性
- 没有 `@topic_config` 的 `@property` 不会生成 status_types，也不会广播
- `get_` 前缀的方法名会自动去除前缀（如 `get_temperature` → `temperature`）
- 类型会自动转成相应的类型（如 `str`、`float`、`bool`）
- 如果类型是 `Any`、`None` 或未知的，默认使用 `String`

### init_param_schema

完全由系统自动生成，无需手动编写：

```yaml
init_param_schema:
  config: # 从 __init__ 方法分析得出
    properties:
      port:
        type: string
        default: '/dev/ttyUSB0'
      baudrate:
        type: integer
        default: 9600
    required: []
    type: object

  data: # 根据 status_types 生成的前端类型定义
    properties:
      current_temperature:
        type: number
      is_heating:
        type: boolean
      status:
        type: string
    required:
      - status
    type: object
```

**生成规则**：

- `config` 部分：分析 `__init__` 方法的参数、类型和默认值
- `data` 部分：根据 `status_types` 生成前端显示用的类型定义

### 其他自动填充的字段

```yaml
version: '1.0.0' # 默认版本
category: ['文件名'] # 使用 yaml 文件名作为类别
description: '' # 默认为空
icon: '' # 默认为空
handles: [] # 默认空数组
config_info: [] # 默认空数组
file_path: '/path/to/file' # 系统自动填写
registry_type: 'device' # 自动设为设备类型
```

### handles 字段

定义设备连接关系：

```yaml
handles: # 大多数情况为空，除非设备需要特定连接
  - handler_key: device_output
    label: Device Output
    data_type: resource
    data_source: value
    data_key: default_value
```

### 可选配置字段

```yaml
description: '设备的详细描述'

icon: 'device_icon.webp' # 设备图标文件名（会上传到OSS）

version: '0.0.1' # 版本号

category: # 设备分类，前端用于分组显示
  - 'heating'
  - 'cooling'
  - 'temperature_control'

config_info: # 嵌套配置，用于包含子设备
  - children:
      - opentrons_24_tuberack_nest_1point5ml_snapcap_A1
      - other_nested_component
```

## 完整示例

### Python 驱动代码

```python
# unilabos/devices/my_lab/liquid_handler.py

from unilabos.registry.placeholder_type import ResourceSlot, DeviceSlot
from typing import List, Dict, Any, Optional

class AdvancedLiquidHandler:
    """高级液体处理工作站"""

    def __init__(self, config: Dict[str, Any]):
        self.simulation = config.get('simulation', False)
        self._status = "idle"
        self._temperature = 25.0

    @property
    @topic_config()
    def status(self) -> str:
        """设备状态"""
        return self._status

    @property
    @topic_config()
    def temperature(self) -> float:
        """当前温度"""
        return self._temperature

    def transfer(
        self,
        source: ResourceSlot,
        target: ResourceSlot,
        volume: float,
        tip: Optional[ResourceSlot] = None
    ) -> Dict[str, Any]:
        """转移液体"""
        return {"success": True}

    def multi_transfer(
        self,
        source: ResourceSlot,
        targets: List[ResourceSlot],
        volumes: List[float]
    ) -> Dict[str, Any]:
        """多目标转移"""
        return {"success": True}

    def coordinate_with_heater(
        self,
        plate: ResourceSlot,
        heater: DeviceSlot,
        temperature: float
    ) -> Dict[str, Any]:
        """与加热器协同"""
        return {"success": True}
```

### 生成的完整注册表

```yaml
# unilabos/registry/devices/advanced_liquid_handler.yaml

advanced_liquid_handler:
  class:
    module: unilabos.devices.my_lab.liquid_handler:AdvancedLiquidHandler
    type: python

    # 自动提取的状态类型
    status_types:
      status: str
      temperature: float

    # 自动生成的初始化参数
    init_param_schema:
      config:
        properties:
          simulation:
            type: boolean
            default: false
        type: object
      data:
        properties:
          status:
            type: string
          temperature:
            type: number
        required:
          - status
        type: object

    # 动作映射
    action_value_mappings:
      transfer:
        type: UniLabJsonCommand
        goal:
          source: source
          target: target
          volume: volume
          tip: tip
        goal_default:
          source: {}
          target: {}
          volume: 0.0
          tip: null
        placeholder_keys:
          source: unilabos_resources # 自动添加
          target: unilabos_resources # 自动添加
          tip: unilabos_resources # 自动添加
        result:
          success: success
        schema:
          description: '转移液体'
          properties:
            goal:
              properties:
                source:
                  type: object
                  description: '源容器'
                target:
                  type: object
                  description: '目标容器'
                volume:
                  type: number
                  description: '体积(μL)'
                tip:
                  type: object
                  description: '枪头(可选)'
              required:
                - source
                - target
                - volume
              type: object
          required:
            - goal
          type: object

      multi_transfer:
        type: UniLabJsonCommand
        goal:
          source: source
          targets: targets
          volumes: volumes
        placeholder_keys:
          source: unilabos_resources # 单选
          targets: unilabos_resources # 多选
        result:
          success: success

      coordinate_with_heater:
        type: UniLabJsonCommand
        goal:
          plate: plate
          heater: heater
          temperature: temperature
        placeholder_keys:
          plate: unilabos_resources # 资源选择
          heater: unilabos_devices # 设备选择
        result:
          success: success

  description: '高级液体处理工作站，支持多目标转移和设备协同'
  version: '1.0.0'
  category:
    - liquid_handling
  handles: []
  icon: ''
```

### 另一个完整示例：温度控制器

```yaml
my_temperature_controller:
  class:
    action_value_mappings:
      heat_start:
        type: HeatChillStart
        goal:
          target_temp: temp
          vessel: vessel
        goal_default:
          target_temp: 25.0
          vessel: ''
        handles:
          output:
            - handler_key: heated_sample
              label: Heated Sample
              data_type: resource
              data_source: handle
              data_key: sample
        placeholder_keys:
          vessel: unilabos_resources
        result:
          status: status
          success: success
        schema:
          description: '启动加热功能'
          properties:
            goal:
              properties:
                target_temp:
                  type: number
                  description: '目标温度'
                vessel:
                  type: string
                  description: '容器标识'
              required:
                - target_temp
                - vessel
              title: HeatStart_Goal
              type: object
          required:
            - goal
          title: HeatStart
          type: object
        feedback: {}

      stop:
        type: UniLabJsonCommand
        goal: {}
        goal_default: {}
        handles: {}
        result:
          status: status
        schema:
          description: '停止设备'
          properties:
            goal:
              type: object
              title: Stop_Goal
          title: Stop
          type: object
        feedback: {}

    module: unilabos.devices.temperature.my_controller:MyTemperatureController
    status_types:
      current_temperature: float
      target_temperature: float
      is_heating: bool
      is_cooling: bool
      status: str
      vessel: str
    type: python

  description: '我的温度控制器设备'
  handles: []
  icon: 'temperature_controller.webp'
  init_param_schema:
    config:
      properties:
        port:
          default: '/dev/ttyUSB0'
          type: string
        baudrate:
          default: 9600
          type: number
      required: []
      type: object
    data:
      properties:
        current_temperature:
          type: number
        target_temperature:
          type: number
        is_heating:
          type: boolean
        is_cooling:
          type: boolean
        status:
          type: string
        vessel:
          type: string
      required:
        - current_temperature
        - target_temperature
        - status
      type: object

  version: '1.0.0'
  category:
    - 'temperature_control'
    - 'heating'
  config_info: []
```

## 部署和使用

### Python 驱动类要求

你的设备类需要符合以下要求：

```python
from unilabos.registry.decorators import device, topic_config

@device(id="my_device", category=["temperature"], description="My Device")
class MyDevice:
    def __init__(self, config):
        """初始化，参数会自动分析到 init_param_schema.config"""
        self.port = config.get('port', '/dev/ttyUSB0')

    # 状态方法（必须添加 @topic_config 才会生成到 status_types 并广播）
    @property
    @topic_config()
    def status(self):
        """返回设备状态"""
        return "idle"

    @property
    @topic_config()
    def temperature(self):
        """返回当前温度"""
        return 25.0

    # 动作方法（会自动生成 auto- 开头的动作）
    async def start_heating(self, temperature: float):
        """开始加热到指定温度"""
        pass

    def stop(self):
        """停止操作"""
        pass
```

### 方法一：使用编辑器（推荐）

1. 先编写 Python 驱动类
2. 使用注册表编辑器自动生成 yaml 配置
3. 保存生成的文件到 `devices/` 目录
4. 重启 UniLabOS 即可使用

### 方法二：手动编写（简化版）

1. 创建最小配置：

```yaml
# devices/my_device.yaml
my_device:
  class:
    module: unilabos.devices.my_module.my_device:MyDevice
    type: python
```

2. 启动系统时使用 `--complete_registry` 参数，让系统自动补全

3. 检查生成的配置是否符合预期

### 系统集成

1. 将 yaml 文件放到 `unilabos/registry/devices/` 目录
2. 系统启动时会自动扫描并加载设备
3. 系统会自动补全所有缺失的字段
4. 设备即可在前端界面中使用

### 高级配置

如果需要特殊设置，可以手动添加：

```yaml
my_device:
  class:
    module: unilabos.devices.my_module.my_device:MyDevice
    type: python
    action_value_mappings:
      # 自定义动作
      special_command:
        type: UniLabJsonCommand
        goal: {}
        result: {}

  # 可选的自定义配置
  description: '我的特殊设备'
  icon: 'my_device.webp'
  category: ['temperature', 'heating']
```

## 调试和验证

### 1. 检查生成的注册表

```bash
# 使用complete_registry生成
unilab -g dev.json --complete_registry

# 查看生成的文件
cat unilabos/registry/devices/my_device.yaml
```

### 2. 验证 placeholder_keys

确认：

- ResourceSlot 参数有 `unilabos_resources`
- DeviceSlot 参数有 `unilabos_devices`
- List 类型被正确识别

### 3. 测试前端效果

1. 启动 Uni-Lab
2. 访问 Web 界面
3. 选择设备
4. 调用动作
5. 检查是否显示正确的选择器

### 4. 检查文件路径和导入

```bash
# 确认模块路径正确
python -c "from unilabos.devices.my_module.my_device import MyDevice"
```

## 常见问题

### Q1: placeholder_keys 没有自动生成

**检查**:

1. 是否使用了`--complete_registry`参数？
2. 类型注解是否正确？

   ```python
   # ✓ 正确
   def method(self, resource: ResourceSlot):

   # ✗ 错误（缺少类型注解）
   def method(self, resource):
   ```

3. 是否正确导入？
   ```python
   from unilabos.registry.placeholder_type import ResourceSlot, DeviceSlot
   ```

### Q2: 前端显示普通输入框而不是选择器

**原因**: placeholder_keys 未正确配置

**解决**:

```yaml
# 检查YAML中是否有
placeholder_keys:
  resource: unilabos_resources
```

### Q3: 多选不工作

**检查类型注解**:

```python
# ✓ 正确 - 会生成多选
def method(self, resources: List[ResourceSlot]):

# ✗ 错误 - 会生成单选
def method(self, resources: ResourceSlot):
```

### Q4: 运行时收到错误的类型

**说明**: 运行时会自动转换

前端传递：

```json
{
  "resource": "plate_1" // 字符串ID
}
```

运行时收到：

```python
resource.id        # "plate_1"
resource.name      # "96孔板"
resource.type      # "resource"
# 完整的Resource对象
```

### Q5: 设备加载不了

**检查**:

1. 确认 `class.module` 路径是否正确
2. 确认 Python 驱动类能否正常导入
3. 使用 yaml 验证器检查文件格式
4. 查看 UniLabOS 启动日志中的错误信息

### Q6: 自动生成失败

**检查**:

1. 确认类继承了正确的基类
2. 确保状态方法的返回类型注解清晰
3. 检查类能否被动态导入
4. 确认启用了 `complete_registry=True`

### Q7: 前端显示问题

**解决步骤**:

1. 删除旧的 yaml 文件，用编辑器重新生成
2. 清除浏览器缓存，重新加载页面
3. 确认必需字段（如 `schema`）都存在
4. 检查 `goal_default` 和 `schema` 的数据类型是否一致

### Q8: 动作执行出错

**检查**:

1. 确认动作方法名符合规范（如 `execute_<action_name>`）
2. 检查 `goal` 字段的参数映射是否正确
3. 确认方法返回值格式符合 `result` 映射
4. 在驱动类中添加异常处理

## 最佳实践

### 开发流程

1. **优先使用编辑器**：除非有特殊需求，否则优先使用注册表编辑器
2. **最小化配置**：手动配置时只定义必要字段，让系统自动生成其他内容
3. **增量开发**：先创建基本配置，后续根据需要添加特殊动作
4. **及时测试**：每次修改后及时在开发环境测试

### 代码规范

1. **使用 `@device` 装饰器标识设备类**

```python
from unilabos.registry.decorators import device

@device(id="my_device", category=["heating"], description="My Device")
class MyDevice:
    ...
```

2. **使用 `@topic_config` 声明广播属性**

```python
from unilabos.registry.decorators import topic_config

# ✓ 需要广播的状态属性
@property
@topic_config(period=2.0)
def temperature(self) -> float:
    return self._temp

# ✗ 仅有 @property 不会广播
@property
def internal_counter(self) -> int:
    return self._counter
```

3. **始终使用类型注解**

```python
# ✓ 好
def method(self, resource: ResourceSlot, device: DeviceSlot):
    pass

# ✗ 差
def method(self, resource, device):
    pass
```

4. **提供有意义的参数名**

```python
# ✓ 好 - 清晰的参数名
def transfer(self, source: ResourceSlot, target: ResourceSlot):
    pass

# ✗ 差 - 模糊的参数名
def transfer(self, r1: ResourceSlot, r2: ResourceSlot):
    pass
```

5. **使用 Optional 表示可选参数**

```python
from typing import Optional

def method(
    self,
    required_resource: ResourceSlot,
    optional_resource: Optional[ResourceSlot] = None
):
    pass
```

6. **添加详细的文档字符串**

```python
def method(
    self,
    source: ResourceSlot,        # 源容器
    targets: List[ResourceSlot]  # 目标容器列表
) -> Dict[str, Any]:
    """方法说明

    Args:
        source: 源容器，必须包含足够的液体
        targets: 目标容器列表，每个容器应该为空

    Returns:
        包含操作结果的字典
    """
    pass
```

7. **方法命名规范**

   - 状态方法使用 `@property` + `@topic_config` 装饰器，或普通方法 + `@topic_config`
   - 动作方法使用动词开头
   - 保持命名清晰、一致

8. **完善的错误处理**
   - 实现完善的错误处理
   - 添加日志记录
   - 提供有意义的错误信息

### 配置管理

1. **版本控制**：所有 yaml 文件纳入版本控制
2. **命名一致性**：设备 ID、文件名、类名保持一致的命名风格
3. **定期更新**：定期运行完整注册以更新自动生成的字段
4. **备份配置**：在修改前备份重要的手动配置
5. **文档同步**：保持配置文件和文档的同步更新

### 测试验证

1. **本地测试**：在本地环境充分测试后再部署
2. **渐进部署**：先部署到测试环境，验证无误后再上生产环境
3. **监控日志**：密切监控设备加载和运行日志
4. **回滚准备**：准备快速回滚机制，以应对紧急情况
5. **自动化测试**：编写单元测试和集成测试

### 性能优化

1. **按需加载**：只加载实际使用的设备类型
2. **缓存利用**：充分利用系统的注册表缓存机制
3. **资源管理**：合理管理设备连接和资源占用
4. **监控指标**：设置关键性能指标的监控和告警

## 参考资料

- {doc}`add_device` - 设备驱动编写指南
- {doc}`04_add_device_testing` - 设备测试指南
- Python [typing 模块](https://docs.python.org/3/library/typing.html)
- [YAML 语法](https://yaml.org/)
- [JSON Schema](https://json-schema.org/)
