好的,我们正式进入:
关键词:项目结构、类图、通信类、事件处理、连接生命周期、异步机制
我们从源码入手,一步步搞懂:
你将不再只是“调 Sample”,而是可以掌控它的主干脉络,甚至模仿它写出你自己的通信程序。
这个项目结构很清晰,大致可以分成三大块:
主要是以下几个类和命名空间:
类名 / 接口 | 功能描述 |
---|---|
SecsGem |
主控类,负责建立连接、发送接收消息,是你最常用的接口 |
SecsMessage |
表示一条 SECS 报文 |
SecsItem |
表示报文内部的数据结构(Item Tree) |
SecsGemBuilder |
构建 SecsGem 的工厂类,负责配置通信参数 |
HSMSConnectMode |
枚举,指明是主机模式还是设备模式 |
这些类都在 Sec4net
命名空间中,是整个通信流程的核心。
这是个完整的 WPF Demo,它通过 UI 来驱动 Host 端的连接、发命令、注册事件等。
你可以从 SampleHost 入手,理解 SECS4NET 是如何实际运作的:
App.xaml.cs
中初始化 HostGemService
类作为核心逻辑封装比如:
MessageLogViewModel.cs
:将 SECS 报文日志格式化输出App.xaml
:注册依赖注入,绑定服务层Config
配置项:定义设备地址、端口、模式等参数这是你最常打交道的类,我们来详细拆解一下它的几个核心接口和机制。
var gem = new SecsGemBuilder()
.UseHsms()
.ConnectMode(HSMSConnectMode.Active) // 主机模式
.DeviceId(0)
.Host("127.0.0.1") // 设备 IP
.Port(5000) // 设备端口
.Build();
解释知识点:
.UseHsms()
表示使用 HSMS 协议(TCP 通信).ConnectMode()
设为 Active 就是主机,Passive 就是设备.DeviceId()
是主机的设备编号.Host()
和 .Port()
指的是连接目标设备的地址和端口.Build()
返回一个 SecsGem
实例await gem.ConnectAsync();
连接过程其实包括 TCP 建立、SECS 建链(S1F13/S1F14)、状态机启动等。
gem.MessageReceived += OnSecsMessageReceived;
你只要写一个回调函数:
private void OnSecsMessageReceived(object sender, SecsMessage e)
{
if (e.Stream == 6 && e.Function == 11)
{
var ceid = e.SecsItem[0].GetValue<ushort>();
Console.WriteLine($"收到事件:CEID = {ceid}");
}
}
报文进来后你可以按 SML 结构解析,把报文打印出来或入库。
发送很简单,你只需要构造一个 SecsMessage
,比如:
var msg = new SecsMessage(2, 41, true,
Item.L(
Item.A("START_PROCESS"),
Item.L(Item.A("Lot123"), Item.A("Recipe1"))
)
);
await gem.SendAsync(msg);
这里 2
是 Stream,41
是 Function,true
表示需要对方回应(W bit)。
整个 SECS4NET 框架基于 async/await
实现异步通信,这样你就不会阻塞主线程。
比如你在 WPF 程序中接收报文、发送命令,UI 不会卡顿。
在 SampleHost 项目中,一般是在 App.xaml.cs
启动时初始化 Gem 服务:
GemService.Instance.Init();
关闭时调用 DisconnectAsync()
,并释放资源。
SecsGem
就是你跟设备之间的“翻译官”,你通过它说话(Send),也通过它接收设备的回应(MessageReceived)。
你只需要:
这个封装非常适合你这种以业务逻辑为主的开发者。
我们先到这里告一段落。总结如下:
你已经掌握了:
SecsGem
建立连接;如果你觉得节奏 OK,就可以告诉我:“继续”,我们就进入《第三讲:如何从零构建一个 Host 主机端程序》
那一讲会更实战,我们会一步步搭一个“小型主机”,来收发真正的事件和指令。
你来决定节奏!