> ## Documentation Index
> Fetch the complete documentation index at: https://all.mimedal.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 设备仪器接口要求与映射示例

> 说明设备仪器接口必须包含的三个维度，以及转发器如何完成映射。

FSP 要求厂商提供的设备接口必须包含 **操作、对象、系统** 三个维度的内容。操作说明调用什么能力以及实际结果，对象说明涉及哪些容器或样品及其状态变化，系统说明设备、安全、任务和资源状态。三者是同一套厂商接口必须覆盖的三方面内容，不是三套独立服务。

厂商可以继续使用原有的 HTTP API、CLI、MCP 工具、SDK、RPC 或驱动，也可以把三方面信息分布在操作调用、状态查询、结果回调或事件中。FSP 服务中的转发器按预先写好的规则完成字段、单位和结果映射；如果厂商接口没有提供某项实际信息，转发器只能把它标为未知，不能临时猜测或用请求值代替。

处理逻辑见[转发器](/docs/specification/fsp/adapter)：用同一个加液例子说明动作怎么定义、执行前怎么检查、设备命令怎么转换。完整实现见 [GitCode 示例源码](https://gitcode.com/mimedal/all/blob/main/examples/fsp_three_parts.py)。

## 各部分负责什么

| 层次    | 必须承担                       | 不得代替        |
| ----- | -------------------------- | ----------- |
| 契约与注册 | 操作含义、参数、结果、版本，以及对应的设备实现    | 设备现在能否执行的检查 |
| 运行时   | 权限、版本号、幂等、任务持久化、资源互斥、取消与恢复 | 厂商协议细节      |
| 转发器   | 单位与坐标转换、命令顺序、结果解释、证据关联     | 未知设备的默认实现   |
| 驱动    | 厂商通信、超时、原始回执、设备观测          | 样品效果的无依据推断  |
| 执行器   | 按计划调用、核对结果、维护步骤依赖与实验状态     | 设备本地硬件保护    |

这些职责可以放在同一个程序里，也可以分成多个服务，不要求使用特定语言或类名。但要能查清每项检查由谁完成、结果从哪里取得。

每项操作必须对应到指定设备的实现代码。找不到时就报错，不能拿另一台设备的同名动作替代。初始化时必须检查必填参数、返回格式和配置；这些检查通过，不代表设备已经在线或真实动作已经验收。

接入设备前，必须整理协议来源和版本、命令与返回值的对应关系、单位、限制、超时、完成条件，以及哪些功能还不支持。这些材料必须经过人工或既定流程审核。不能把模板或模型生成的配置直接用于控制真实设备。

简单的一请求一响应命令可以采用声明式映射；涉及会话、校验和、二进制帧、分段读写、轮询、取消或多阶段动作时，必须明确实现相应行为。配置中写了命令不等于协议已经被实现。

## 规范请求示例

以下加液场景假设设备定义版本为 `12`，操作契约版本为 `1`，体积单位为 mL。来源和目标都参与资源及版本号检查。字符串条件仅为阅读说明；实现必须把它们关联到稳定规则和可执行检查，不能靠语言模型临场判断。

```json theme={null}
{
  "device_id": "device-01",
  "object": {
    "containers": [
      {
        "container_id": "source-01",
        "role": "source",
        "object_type_id": "container.reservoir",
        "expected_revision": "source-8",
        "before_state": {"sample_status": "液体", "sample_volume_mL": 10}
      },
      {
        "container_id": "container-01",
        "role": "target",
        "object_type_id": "container.centrifuge_tube.50ml",
        "expected_revision": "object-21",
        "before_state": {"container_status": "无盖", "sample_status": "空", "sample_volume_mL": 0},
        "capacity": {"remaining_volume_mL": 45}
      }
    ]
  },
  "operation": {
    "operation_id": "add_liquid",
    "contract_version": "1",
    "parameters": {"source_container_id": "source-01", "volume_mL": 0.5}
  },
  "system": {
    "expected_definition_revision": "12",
    "expected_system_revision": "system-21",
    "expected_device_state": "idle",
    "execution_mode": "async",
    "idempotency_key": "add-liquid-001"
  }
}
```

`before_state` 是调用方预期，不是服务端可无条件采信的现场证据。目标容器由唯一 `target` 角色确定；来源参数必须与 `source` 角色一致。各操作必须明确角色数量、可重复性以及参数引用规则。

## 受理响应示例

```json theme={null}
{
  "object": {
    "changes": []
  },
  "operation": {
    "operation_id": "add_liquid",
    "status": "accepted",
    "actual_parameters": {},
    "completion_evidence": [],
    "diagnostics": []
  },
  "system": {
    "device_state": "idle",
    "system_revision": "system-22",
    "observed_at": "2026-09-21T02:00:00Z",
    "safety_checks": [
      {"rule": "source_volume_sufficient", "passed": true},
      {"rule": "target_capacity_sufficient", "passed": true}
    ],
    "task": {"task_id": "task-001", "status": "queued", "phase": "preconditions", "cancellable": true},
    "notices": ["来源和目标容器已预留，任务解除占用前不得移动"]
  }
}
```

这里设备尚未运动，因此物理状态仍为 `idle`；资源已预留，因此系统版本号发生变化。其他冲突任务仍不可进入。`changes: []` 仅表示受理时没有新增对象变化；`actual_parameters: {}` 表示尚无实际参数证据，不能把请求量抄入该字段。

任务开始后，必须通过查询或订阅取得实际结果。最终状态仍要覆盖操作、对象、系统三个维度；成功证据见[怎样判断操作成功](/docs/specification/device-integration/operations)，未知及取消处理见[任务生命周期](/docs/specification/fsp/lifecycle)。已确认的部分对象变化必须返回，不必等待任务成功。

## 不同接口怎么使用同一份数据

| 接口类型      | 请求和结果放在哪里                   | 注意事项                        |
| --------- | --------------------------- | --------------------------- |
| MCP       | 规范请求放入工具参数，三个维度的结果放入结构化工具结果 | 工具名称不能代替操作定义；调用成功不等于物理成功    |
| HTTP      | 请求体和响应体使用规范字段，设备也可由路径确定     | 202 仅表示受理；连接超时不能触发无幂等的新执行   |
| CLI       | 输入文件或标准输入提供请求，结果文件或标准输出返回结果 | 进程退出码不能替代任务最终状态；异步任务必须能再次查询 |
| RPC / SDK | 参数和返回对象映射规范字段               | 调用异常与任务失败必须分开表达             |

每种接口都必须说明怎样选择设备、调用操作、查询结果、取消任务、提交观察记录，以及怎样返回错误。FSP 不指定 URL、工具名、命令名或函数名。没有实现的可选功能要明确说明，不能返回成功。

接口请求 ID 用于识别一次通信，`system.idempotency_key` 用于关联一次会改变设备或样品状态的操作。HTTP 实现若使用 `Idempotency-Key` 头，必须定义到该规范字段的对应关系；头与请求体同时出现且不一致时拒绝。路径、工具参数、连接上下文等多处设备标识也必须一致。

旧实现的顶层 `operation_id` 或扁平对象参数只有经过明确版本化映射，才是本规范输入。不能仅因能返回 JSON 就声称已经覆盖操作、对象、系统三个维度。

## 接入验证与交付

交付设备实现时，应附上操作版本、设备定义、已支持的功能、必填配置、经过审核的命令对应表、失败情况、结果证据样例和测试记录。测试要分开记录：

1. 静态定义与绑定检查；
2. 桩驱动的参数、状态、锁与故障注入测试；
3. 真实通信及回执解析验证；
4. 真实设备动作、停止和恢复验证；
5. 目标样品效果验证（仅当契约承诺该范围时）。

每层记录版本、设备或桩身份、环境、时间、案例和结果。代码和配置检查、模拟结果、过去的测试报告，不能代替后面的实际测试；未执行项必须标为未验证。验收场景见[符合性](/docs/specification/conformance)。
