本 Skill 只负责协议编解码,不含具体串口/socket 收发实现。
4.2 核心概念速览:陌生协议先建心智模型
接入一个陌生协议,AI(和读代码的人)都需要先有心智模型。用表格把概念固化下来最有效。
Modbus 是请求/响应协议,采用主从模型。四类数据模型:| 数据块 | 访问 | 单位 | 典型功能码 | 地址惯例 ||--------|------|------|-----------|---------|| Coils(线圈) | 读写 | 1 bit | 01 读 / 05,15 写 | 0xxxx || Discrete Inputs | 只读 | 1 bit | 02 读 | 1xxxx || Input Registers | 只读 | 16 bit | 04 读 | 3xxxx || Holding Registers | 读写 | 16 bit | 03 读 / 06,16 写 | 4xxxx |
4.3 调用/协议规范:怎么连、怎么调
写清协议分层、地址、端口、鉴权、请求-响应格式。协议类要精确到字节 / 位 / 字段顺序。
ADU = 地址/头 + PDU + 校验PDU = 功能码(1B) + 数据(NB)
先构造 PDU,再按传输模式包装成 ADU:RTU:| 从站地址 1B | PDU | CRC16 2B(低字节在前)|TCP:| MBAP 头 7B | PDU |,默认端口 502
4.4 参数定义:用表格锁死每个参数
读保持寄存器(功能码 0x03)参数:
| 参数 | 必填 | 类型 | 取值范围 | 说明 ||------|------|------|----------|------|| slave_addr | 是 | int | 1–247 | 从站地址,0 为广播 || start_addr | 是 | int | 0–65535 | 协议地址,从 0 开始 || quantity | 是 | int | 1–125 | 读取寄存器个数 |
4.5 调用示例:给可直接套用的样例
示例是 AI 复用率最高的部分。给请求 + 返回 + 结果解读。
读从站 0x11 的保持寄存器,起始地址 0,读 1 个:请求帧:[11] [03] [0000] [0001] [CRC低] [CRC高]返回帧:[11] [03] [02] [01 F4] [CRC低] [CRC高]解读:字节数=2,值=0x01F4=500,若手册说 ÷10,则温度=50.0°C
4.6 注意事项:把坑写在前面
把你踩过的坑、边界、经验固化下来。这是资深经验的沉淀,价值极高。
地址偏移:手册写 40001 → 协议发 0x0000(减掉基址)字节序:CRC 低字节在前,与寄存器大端相反异常判断:响应功能码最高位 = 1 表示出错,后跟异常码优先用成熟库(pymodbus / libmodbus),别手写协议栈
面向“代码接入特定协议”的实战写法
这是把技能从“AI 能看懂”升级到“AI 能据此写出可用接入代码”的关键一步。
5.1 为什么协议接入类技能必须拆附属文件
协议规范往往很长(功能码几十个、帧格式好几种、异常码一大表)。如果全塞进 SKILL.md:
正确做法:SKILL.md 给全貌 + 索引,细节下沉到 references/,AI 按需读取。
5.2 references/ 怎么写
按主题拆分,一个主题一个文件,职责单一:
references/├── frame-formats.md # 三种传输模式的帧格式、CRC/LRC 算法├── function-codes.md # 每个功能码的 PDU 结构、参数、示例└── troubleshooting.md # 异常码、常见故障与排查
关键要求:内容要“可被 AI 直接翻译成代码”。
精确到字节、位、字段顺序,不留模糊
用表格 / 伪代码固化规则,减少歧义
每个字段标清长度、字节序、取值范围
反面教材:“CRC 放在帧尾”——AI 不知道 2 字节还是 1 字节、什么字节序。
正面写法:
| 字段 | 字节 | 说明 ||------|------|------|| CRC | 2 | 低字节在前,高字节在后(little-endian) |
5.3 scripts/ 怎么写
对于有固定算法的协议(校验、编解码、帧构造),给一份可运行的参考代码作为“算法范本”,让 AI 据其逻辑生成,而不是凭空重写——重写极易出错。
写法要点:
例如 scripts/modbus_codec.py 里的 CRC 实现:
def crc16(data: bytes) -> int:"""计算 Modbus RTU CRC16(多项式 0xA001,初值 0xFFFF)。""" crc = 0xFFFFfor byte in data: crc ^= bytefor _ in range(8):if crc & 0x0001: crc = (crc >> 1) ^ 0xA001else: crc >>= 1return crc & 0xFFFFdef crc16_bytes(data: bytes) -> bytes:"""返回 RTU 帧尾 CRC 的 2 字节,低字节在前。"""return struct.pack("<H", crc16(data))
有了这段脚本,AI 生成接入代码时会直接调用它,CRC 一次就对。
5.4 assets/ 怎么写
放静态、可复制的资源,减少 AI 编造:
5.5 主文件与附属文件的引用/索引方式
在 SKILL.md 里明确列出“何时读哪个文件”,这样 AI 才知道去哪找细节:
## 参考文件(按需深入阅读)- 需要具体功能码的 PDU 结构 → 读 references/function-codes.md- 需要封装成可传输的帧(含 CRC/LRC)→ 读 references/frame-formats.md- 遇到异常响应或通信故障 → 读 references/troubleshooting.md- 需要现成编解码代码 → 用 scripts/modbus_codec.py
5.6 协议接入通用要点清单
写任何协议接入技能,这些点都建议覆盖:
字节序:大端/小端,多字节数值跨字段的顺序
地址偏移:文档地址 vs 协议地址的换算
超时与重试:无响应怎么办
异常响应:如何判断和解析错误码
帧定界 / 粘包:怎么切分一帧
成熟库优先:列出各语言推荐库,避免不必要的手写
完整范例:写一个“协议接入”技能
6.1 目录结构
modbus-protocol/├── SKILL.md├── references/│ ├── frame-formats.md│ ├── function-codes.md│ └── troubleshooting.md└── scripts/└── modbus_codec.py
6.2 SKILL.md(骨架示意)
---name: modbus-protocoldescription: Modbus 工业通信协议实现指南。当用户需要与 PLC、RTU、传感器、 电表、变频器通信,或提到 "Modbus"、"RTU"、"ASCII"、"TCP"、"线圈"、"保持寄存器"、"功能码"、"CRC16"、"读写寄存器" 时使用此 Skill。---# Skill: Modbus 工业通信协议## 能力说明本 Skill 帮助在应用中正确实现 Modbus 通信,覆盖 RTU / ASCII / TCP。只负责协议编解码,不含实际串口/socket 收发。## 何时使用- 与工业设备(PLC、仪表、传感器)通信- 读写线圈、离散输入、保持寄存器、输入寄存器## 核心概念速览(四类数据模型表格、PDU/ADU 分层、字节序说明)## 实现工作流