HSMS/SECS-II(Semi)
定义
一、说明
TouchSocket.Semi 是一个半导体协议功能库,实现了基于 HSMS(SEMI E37) 的 TCP 传输层以及 SECS-II(SEMI E5) 数据项解析与序列化,可用于半导体设备与主机系统之间的标准化通信。
1.1 HSMS 协议概述
HSMS(High Speed Message Services,高速报文服务) 是由 SEMI 组织制定的 E37 标准,定义了设备与主机之间通过 TCP/IP 进行通信的传输层协议。HSMS 使用固定 10 字节的消息头(Header),并在消息体中承载 SECS-II 数据。
HSMS 会话建立流程如下:
- 被动端(Passive)启动监听,等待主动端连接。
- 主动端(Active)发起 TCP 连接。
- TCP 连接建立后,主动端发送 Select.req 消息,被动端回复 Select.rsp 完成 HSMS 握手。
- 握手成功后,双方可通过数据消息(SType=0)传递 SECS-II 内容。
1.2 SECS-II 协议概述
SECS-II(SEMI Equipment Communications Standard, Part 2) 是 SEMI E5 标准,定义了设备与主机之间交换数据的消息格式和语义。每条 SECS-II 消息由 Stream(S) 和 Function(F) 编号标识,并携带结构化的数据项(SecsItem)。
SECS-II 数据项(Item)支持以下格式类型:
| 格式 | C# 类型 | 说明 |
|---|---|---|
List | ListSecsItem | 子数据项列表 |
Binary | BinarySecsItem | 二进制字节数组 |
Boolean | BooleanSecsItem | 布尔值(用 byte 存储) |
ASCII | ASCIISecsItem | ASCII 字符串 |
JIS8 | JIS8SecsItem | JIS8 字符串 |
I1 | I1SecsItem | 1 字节有符号整数数组 |
I2 | I2SecsItem | 2 字节有符号整数数组 |
I4 | I4SecsItem | 4 字节有符号整数数组 |
I8 | I8SecsItem | 8 字节有符号整数数组 |
U1 | U1SecsItem | 1 字节无符号整数数组 |
U2 | U2SecsItem | 2 字节无符号整数数组 |
U4 | U4SecsItem | 4 字节无符号整数数组 |
U8 | U8SecsItem | 8 字节无符号整数数组 |
F4 | F4SecsItem | 4 字节浮点数数组 |
F8 | F8SecsItem | 8 字节浮点数数组 |
二、HsmsService(被动端/设备端)
HsmsService 是 HSMS 的被动监听端(Passive),通常用于模拟半导体设备端。它基于 TcpServiceBase<HsmsSessionClient> 实现,每个连入的主动端由一个 HsmsSessionClient 实例管理。
2.1 创建 HsmsService
2.2 处理接收到的消息并发送响应
在服务插件中,可以接收来自主动端的 SECS-II 数据消息并发送回复:
SystemBytes 字段相当于消息的"事务 ID",发送响应时需要回填请求消息中的 SystemBytes,使客户端的等待机制能够正确匹配响应。
三、HsmsClient(主动端/主机端)
HsmsClient 是 HSMS 的主动连接端(Active),通常用于主机系统(Host)。连接成功后会自动完成 HSMS Select 握手。
3.1 创建 HsmsClient
3.2 快捷连接方式
使用扩展方法 ConnectAsync(string ipHost) 可以简化配置步骤:
四、发送消息
4.1 发送数据消息(SType=0)
HsmsMessage 的 S、F 属性分别表示 Stream 和 Function 编号。ReplyExpected 为 true 时,SendHsmsMessageAsync 将阻塞等待对端响应;为 false 时则直接返回 null。
4.2 发送 Linktest
Linktest 用于在空闲期间检测 TCP 链路是否仍然有效。调用 SendLinkTestAsync 扩展方法即可发送 Linktest.req 并等待 Linktest.rsp:
4.3 发送 Separate(主动断开)
向对端发送 Separate.req,通知其断开 HSMS 连接:
await client.SendSeparateAsync();
五、SECS-II 数据项(SecsItem)
5.1 数据项构造
每种 SECS-II 格式对应一个具体的 SecsItem 子类,可直接在构建 HsmsMessage 时将数据项赋予 Body 属性:
5.2 List 嵌套结构
ListSecsItem 可以包含任意数量的子 SecsItem,用于表达 SECS-II 中的 L 格式,从而构造复杂的嵌套结构。
5.3 从消息体解析数据项
当收到一条带 Body 的 HsmsMessage 时,可通过类型检查获取具体数据:
if (e.Message.Body is ASCIISecsItem ascii)
{
Console.WriteLine(ascii.Value);
}
else if (e.Message.Body is ListSecsItem list)
{
foreach (var item in list.Items.Span)
{
// 处理子项
}
}
六、插件
TouchSocket.Semi 支持以下插件接口:
| 插件接口 | 触发时机 |
|---|---|
IHsmsConnectingPlugin | 连接即将建立时(TCP 握手前) |
IHsmsConnectedPlugin | HSMS 会话建立完成(Select 握手后) |
IHsmsClosingPlugin | 连接即将主动关闭时 |
IHsmsClosedPlugin | 连接已关闭时 |
IHsmsReceivedPlugin | 收到 SECS-II 数据消息时 |
6.1 插件使用示例
插件可用于实现连接认证、消息日志记录、心跳检测、访问控制等横切关注点,而无需修改核心业务代码。
七、消息类型说明
HsmsMessageType 枚举定义了 HSMS 所有标准消息类型(SType 字节):
| 枚举值 | SType | 说明 |
|---|---|---|
DataMessage | 0 | SECS-II 数据消息 |
SelectRequest | 1 | Select.req(选择请求) |
SelectResponse | 2 | Select.rsp(选择响应) |
DeselectRequest | 3 | Deselect.req(取消选择请求) |
DeselectResponse | 4 | Deselect.rsp(取消选择响应) |
LinkTestRequest | 5 | Linktest.req(链路测试请求) |
LinkTestResponse | 6 | Linktest.rsp(链路测试响应) |
RejectRequest | 7 | Reject.req(拒绝请求) |
SeparateRequest | 9 | Separate.req(分离请求) |
八、注意事项
HsmsClient.ConnectAsync()内部会在 TCP 连接建立后自动发送 Select.req,并等待 Select.rsp 返回Success状态,若握手失败则抛出HsmsException。- 当收到对端发来的 Separate.req 时,
HsmsClient和HsmsSessionClient都会自动调用CloseAsync断开连接。 HsmsService收到主动端的 Select.req 时,会自动回复 Select.rsp(Success)并完成握手,无需手动处理。SecsItem继承自DisposableObject,在不再使用时应调用Dispose释放资源(或使用using语句)。