Skip to main content
适配器是 FSP 服务中贴近具体设备的一层。它接收已经通过动作契约和能力门控的请求,调用驱动,并把设备返回值解释成上层能理解的结果。 本页用同一个加液例子说明三部分怎样协作。页面中的代码都是伪代码,用来表达流程,不限定编程语言。完整的可运行 Python 示例和测试放在 GitCode 源仓库中。

查看 GitCode 可运行示例

查看动作契约、能力门控、适配器和模拟驱动的完整实现。
一句话说:契约定义动作,门控决定是否放行,适配器对接设备;厂商设备接口必须包含操作、对象、系统三个维度的内容。

1. 动作契约:把动作的意思写清楚

动作契约不写串口地址、厂商命令或某台设备的连接配置。它说明同名操作应该遵守的共同规则。 add_liquid 为例: 这些数字只是教学例子,不代表真实设备规格。不同设备可以采用更严格的范围,但不能偷偷改变单位或降低完成要求。

契约检查伪代码

参数检查、设备绑定和结果判断都引用同一份动作契约,不能在每个适配器里另抄一份范围和误差。 本例的来源和目标由对象列表中的 sourcetarget 角色确定,所以参数中不重复填写来源编号。若接口同时提供两处容器编号,必须检查它们一致。

2. 能力门控:不能只看“支持”两个字

“支持加液”至少要分开检查:
  1. 硬件支持:这台设备是否有加液能力?
  2. 代码已实现:有没有这台设备对应的 add_liquid 实现?
  3. 配置完成:必要连接参数、标定和验收是否完成?
  4. 本次允许执行:调用方有权限吗?设备是否空闲?容器和版本是否正确?
前两项通常来自设备定义和程序注册。配置是否完成来自部署检查。设备是否忙、容器剩余多少液体,则要在执行前确认。静态说明或 Function Skill 不能代替这些现场检查。

门控伪代码

权限结果必须来自服务端检查,不能直接相信客户端传来的布尔值。对象状态应来自服务端持有的当前记录,调用方只提供预期版本。正式系统还要检查状态读取时间、设备版本及其他安全限制。 能力门控只判断能不能执行,不发送设备命令。检查失败时,适配器不应被调用。

3. 适配器:只负责这台设备怎么做

同一个加液动作,不同设备可能使用不同单位、命令和返回格式。这些差异放在适配器和驱动中,不要求调用方了解。 驱动负责具体通信。适配器可以调用串口、HTTP 或厂商 SDK 驱动,但不会因为调用方式不同,就改变 add_liquid 的含义。

适配器伪代码

适配器返回的是驱动报告的量,不是请求量。只有 ACK、没有停止确认或实际量时,不能返回成功。真实设备可以继续查询同一任务,但不能因为回执丢失就重新发出加液命令。

4. 三部分怎样接起来

设备绑定使用“设备编号、动作名称、契约版本”作为查找条件。找不到就拒绝,不使用默认适配器。
适配器交回的是供上层使用的结果片段,不是完整 FSP 响应:
  • 操作状态放入 operation.status
  • 实际加液量放入 operation.actual_parameters.measured,并附测量来源、时间和任务等证据信息。
  • 容器状态变化放入 object.changes。实际转移量不能自动当成两个容器的当前液量;仍需按操作要求取得容器状态。
  • 设备状态、资源占用和任务信息放入 system
如果动作后没有重新读取容器液量,就要把对应字段标为未知。再次执行前必须补充新的容器读数和版本。资源占用状态和设备实际运动状态也必须分开表达。

可运行源码与测试

完整示例只使用 Python 标准库,模拟驱动会把 0.5 mL 请求执行为 0.498 mL,并验证实际量仍在本例允许误差内。它还覆盖权限拒绝、能力缺失、设备忙、版本冲突、容量不足、只有 ACK、动作后回执丢失以及结果超出误差等情况。 在源仓库根目录运行:
所有结果都是模拟结果,不能用于确认真实实验完成。

哪些事情还要由外层服务处理

这个示例只解释三部分的分工。它没有实现并发锁、幂等记录、任务持久化、重启恢复、状态有效期检查或完整响应组装,不能直接作为控制真实设备的网关。 正式服务要在取得相关资源后再次检查条件,再调用适配器;受理任务、记录幂等键和资源占用应按任务状态与异常恢复处理。动作结果判断见操作,完整请求和响应见设备接口说明