`Secs4Net` 是一个开源的 .NET 库,用于实现 SEMI 标准(如 SECS-I、HSMS、SECS-II 和 GEM)的通讯协议,广泛应用于半导体设备与主机间的通信
功能支持 SECS-I(串口通信)和 HSMS(TCP/IP 通信)。实现 SECS-II 消息的编码、解码和传输。支持 GEM 标准的事件报告、远程命令、报警处理等。提供Item类用于构造复杂的 SECS-II 消息结构。支持异步消息处理,适合实时通信。常用类:表示 SECS-II 消息,包含 Stream(S)、Function(F)、名称和数据项(Item)。Item:用于构造 SECS-I
Secs4Net 是一个开源的 .NET 库,用于实现 SEMI 标准(如 SECS-I、HSMS、SECS-II 和 GEM)的通讯协议,广泛应用于半导体设备与主机间的通信。以下是基于 Secs4Net 库的使用详解,结合你提供的 EAPHelper 类代码,重点说明如何在 C# 中使用 Secs4Net 实现 SECS/GEM 通讯,以及如何封装为 DLL 供 LabVIEW 调用。内容将以简洁、结构化的中文说明,涵盖关键功能、代码示例和注意事项。
一、Secs4Net 库概述
功能:
- 支持 SECS-I(串口通信)和 HSMS(TCP/IP 通信)。
- 实现 SECS-II 消息的编码、解码和传输。
- 支持 GEM 标准的事件报告、远程命令、报警处理等。
- 提供
Item类用于构造复杂的 SECS-II 消息结构。 - 支持异步消息处理,适合实时通信。
常用类:
Secs4Net.SecsMessage:表示 SECS-II 消息,包含 Stream(S)、Function(F)、名称和数据项(Item)。Item:用于构造 SECS-II 消息的数据结构(如 List、U4、A 等)。IEAP:设备端接口,用于发送和接收消息。PrimaryMessageWrapper:封装接收到的主消息,包含Message(收到的消息)和ReplyAsync(回复方法)。
依赖:
- 通过 NuGet 包管理器安装
Secs4Net。 - 依赖
log4net(日志记录)、Newtonsoft.Json(JSON 序列化)等库。
二、在 C# 中使用 Secs4Net
以下基于你提供的 EAPHelper 类,说明如何使用 Secs4Net 实现 SECS/GEM 通讯,并封装为 DLL。
1. 安装 Secs4Net
- 在 Visual Studio 中打开项目,右键点击“解决方案资源管理器”中的项目,选择“管理 NuGet 包”。
- 搜索并安装
Secs4Net。 - 安装其他依赖:
log4net:用于日志记录(如ILog)。Newtonsoft.Json:用于 JSON 序列化(如JsonNewtonsoft.ToJSON)。
2. 初始化 EAP 连接
EAPHelper 使用 IEAP 接口初始化设备连接。以下是初始化 HSMS 或 SECS-I 连接的示例:
using Secs4Net;
using log4net;
namespace SecGemLibrary
{
public class SecsGemClient
{
private static readonly ILog m_Log = LogManager.GetLogger("ROBOT");
private readonly IEAP _eap;
// 构造函数,初始化 HSMS 或 SECS-I 连接
public SecsGemClient(string ipAddress, int port, bool isHsms = true)
{
try
{
var config = isHsms
? new ConnectionConfig { IPAddress = ipAddress, Port = port } // HSMS
: new ConnectionConfig { DeviceId = 0, PortName = "COM1", BaudRate = 9600 }; // SECS-I
_eap = new EAP(config);
}
catch (Exception ex)
{
m_Log.Error($"初始化失败: {ex.Message}");
throw;
}
}
// 连接设备
public bool Connect()
{
try
{
_eap.Connect();
_eap.PrimaryMessageReceived += ReplyPrimary; // 注册消息处理回调
return true;
}
catch (Exception ex)
{
m_Log.Error($"连接失败: {ex.Message}");
return false;
}
}
// 断开连接
public void Disconnect()
{
try
{
_eap.Disconnect();
}
catch (Exception ex)
{
m_Log.Error($"断开连接失败: {ex.Message}");
}
}
}
}
说明:
ConnectionConfig:配置 HSMS(IP 和端口)或 SECS-I(串口、波特率)。EAP:Secs4Net提供的设备端接口,负责消息收发。PrimaryMessageReceived:事件回调,处理接收到的主消息(如 S1F1、S2F41)。
3. 处理主消息
基于 EAPHelper 的 ReplyPrimary 方法,实现对主消息的处理。以下是简化的示例,处理 S1F1(Are You Online?)和 S2F41(远程命令):
private void ReplyPrimary(object sender, PrimaryMessageWrapper e)
{
string key = $"S{e.Message.S}F{e.Message.F}";
try
{
switch (key)
{
case "S1F1": // Are You Online?
e.ReplyAsync(new SecsMessage(1, 2, "Connected", Item.L(
Item.U4(0),
Item.U4(0))));
m_Log.Info("回复 S1F2: 设备在线");
break;
case "S2F41": // Remote Command
if (e.Message.SecsItem != null)
{
string cmdCode = e.Message.SecsItem.Items[0].GetString();
switch (cmdCode)
{
case "PP-SELECT":
string recipe = e.Message.SecsItem.Items[1].Items[0].Items[1].GetString();
string lot = e.Message.SecsItem.Items[1].Items[1].Items[1].GetString();
string zone = e.Message.SecsItem.Items[1].Items[2].Items[1].GetString();
m_Log.Info($"收到 S2F41 PP-SELECT: ZONE={zone}, RECIPE={recipe}");
e.ReplyAsync(new SecsMessage(2, 42, "PP_SELECT", Item.L(Item.U4(0))));
break;
case "START":
string state = e.Message.SecsItem.Items[1].Items[0].Items[1].GetString();
string message = e.Message.SecsItem.Items[1].Items[1].Items[1].GetString();
string zone2 = e.Message.SecsItem.Items[1].Items[2].Items[1].GetString();
m_Log.Info($"收到 S2F41 START: zone={zone2}, state={state}, message={message}");
e.ReplyAsync(new SecsMessage(2, 42, "EQP_START", Item.L(Item.U4(0), Item.U4(0))));
break;
}
}
break;
default:
e.ReplyAsync(new SecsMessage(e.Message.S, (byte)(e.Message.F + 1), "Default", Item.L(Item.U4(0))));
break;
}
}
catch (Exception ex)
{
m_Log.Error($"处理消息 {key} 失败: {ex.Message}");
}
}
说明:
PrimaryMessageWrapper:包含接收到的主消息(e.Message)和回复方法(e.ReplyAsync)。e.Message.SecsItem:获取消息的数据项(Item类型),如Item.L表示列表,Item.A表示字符串。ReplyAsync:异步回复消息,构造SecsMessage(Stream、Function、名称和数据项)。
4. 发送事件报告
基于 EAPHelper 的 SendEndTestResult 和 GemJobCompleted,实现 S6F11 事件报告:
public void SendJobCompleted(string testSectionId)
{
try
{
Interlocked.Increment(ref DataId);
_eap.SendAsync(new SecsMessage(6, 11, "JobCompleted", Item.L(
Item.U4((uint)DataId),
Item.U4(104),
Item.A(testSectionId)
), true));
m_Log.Info($"发送 S6F11 JobCompleted: testSectionId={testSectionId}");
}
catch (Exception ex)
{
m_Log.Error($"SendJobCompleted 失败: {ex.Message}");
}
}
public void SendEndTestResult(string lotId, string[] arr)
{
try
{
List<Item> items = new List<Item>
{
Item.A(""),
Item.A("306"),
Item.L(
Item.A(lotId),
Item.A(arr[0]), // productID
Item.A(arr[2]), // posID
Item.A(arr[1]), // channelID
Item.A(arr[3]), // fxtureID
Item.A(arr[4]), // startTime
Item.A(arr[5]), // testTime
Item.A(arr[6]), // saveTime
Item.A(arr[7]), // passfail
Item.A(arr[8]), // failBin
Item.A(arr[9]), // lVMax
Item.A(arr[10]), // lICEmax
Item.A(arr[11]), // lICEmin
Item.A(arr[12]), // lEndICE
Item.A(arr[13]), // tCmax
Item.A(arr[14]) // tCmin
)
};
Interlocked.Increment(ref DataId);
_eap.SendAsync(new SecsMessage(6, 11, "ParameterDataReport", Item.L(items), true));
m_Log.Info($"发送 S6F11 ParameterDataReport: lotID={lotId}");
}
catch (Exception ex)
{
m_Log.Error($"SendEndTestResult 失败: {ex.Message}");
}
}
说明:
SendAsync:异步发送SecsMessage,最后一个参数true表示等待回复(S6F12)。Item.L和Item.A:构造 SECS-II 消息的层次结构,符合 GEM 标准。DataId:使用Interlocked.Increment确保线程安全的唯一标识。
5. 编译 DLL
- 在 Visual Studio 中点击“生成 -> 生成解决方案”。
- 在
bin\Debug或bin\Release目录下获取SecGemLibrary.dll。 - 复制依赖 DLL(如
Secs4Net.dll、log4net.dll、Newtonsoft.Json.dll)到目标路径。
三、LabVIEW 调用 Secs4Net DLL
1. 创建 LabVIEW 项目
- 打开 LabVIEW,创建新项目(File -> New Project)。
- 添加一个新 VI(Virtual Instrument)。
2. 配置 .NET 构造器
- 在程序框图中,从函数选板选择“Connectivity -> .NET -> Constructor Node”。
- 放置构造器节点,双击打开配置窗口,浏览并选择
SecGemLibrary.dll。 - 选择
SecGemLibrary.SecsGemClient类,配置构造函数参数:ipAddress:字符串(如 “192.168.1.100”)。port:I32(如 5000)。isHsms:布尔值(True 表示 HSMS)。
3. 调用方法
- 添加“Invoke Node”(Connectivity -> .NET -> Invoke Node),连接到构造器节点的输出。
- 右键单击调用节点,选择“Methods”,可用方法包括:
Connect:连接设备,返回布尔值。Disconnect:断开连接,无返回值。SendJobCompleted:发送 S6F11 事件,输入testSectionId(字符串)。SendEndTestResult:发送测试结果,输入lotId(字符串)和arr(字符串数组)。
- 参数配置:
SendJobCompleted:输入字符串(如 “Section1”)。SendEndTestResult:输入lotId和字符串数组(LabVIEW 数组控件,包含 15 个元素,如["product1", "channel1", "pos1", ...])。
4. 示例程序框图
[构造器节点: SecsGemClient(ipAddress, port, isHsms)] -> [调用节点: Connect] -> [调用节点: SendJobCompleted] -> [调用节点: SendEndTestResult] -> [调用节点: Disconnect]
- 构造器节点:初始化
SecsGemClient。 - Connect:建立连接。
- SendJobCompleted:发送任务完成事件。
- SendEndTestResult:发送测试结果。
- Disconnect:关闭连接。
5. 数据类型映射
- 字符串:C# 的
string映射到 LabVIEW 的字符串(String)。 - 字符串数组:C# 的
string[]映射到 LabVIEW 的字符串数组(Array of String)。 - 布尔值:C# 的
bool映射到 LabVIEW 的布尔值(Boolean)。
6. 错误处理
- 使用 LabVIEW 的错误簇(Error Cluster)捕获 .NET 异常。
- 在每个调用节点后添加错误输出连线,检查异常。
四、SECS/GEM 通讯实现
1. 消息处理
- 接收消息:
ReplyPrimary方法处理 S1F1(在线确认)、S2F41(远程命令)等,自动回复 S1F2、S2F42。 - 发送消息:
SendJobCompleted:发送 S6F11 事件(CEID=104),通知任务完成。SendEndTestResult:发送 S6F11 事件(CEID=306),包含测试数据。
2. 消息格式
- S1F1/S1F2(在线确认):
S1F1 W S1F2 <L[2] <U4 0> <U4 0> > - S2F41/S2F42(远程命令,PP-SELECT):
S2F41 W <L[3] <A "PP-SELECT"> <L[2] <A "Zone1"> <A "RecipeName"> > > S2F42 <L[1] <U4 0> > - S6F11(事件报告,SendEndTestResult):
S6F11 W <L[ <A ""> // DATAID <A "306"> // CEID <L[ <A "lotID"> <A "productID"> <A "posID"> ... ]> ]>
3. 通讯流程
- 初始化并连接:调用
Connect,建立 HSMS 连接。 - 处理消息:
ReplyPrimary自动处理 S1F1、S2F41 等。 - 发送事件:调用
SendJobCompleted或SendEndTestResult,发送 S6F11。 - 断开连接:调用
Disconnect。
五、注意事项
-
依赖管理:
- 确保
Secs4Net.dll、log4net.dll、Newtonsoft.Json.dll复制到 LabVIEW 项目目录或C:\Windows\System32。 - 配置
log4net(如log4net.config文件):<log4net> <appender name="FileAppender" type="log4net.Appender.FileAppender"> <file value="log.txt" /> <appendToFile value="true" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> </layout> </appender> <root> <level value="INFO" /> <appender-ref ref="FileAppender" /> </root> </log4net>
- 确保
-
线程安全:
DataId使用Interlocked.Increment确保线程安全。- LabVIEW 调用节点设为“Run in any thread”以支持异步操作。
-
异常处理:
- 在 C# 中使用 try-catch 捕获异常,记录到日志。
- 在 LabVIEW 中检查错误簇,处理 .NET 异常。
-
调试:
- 查看
log.txt(log4net 日志)排查通讯问题。 - 在 LabVIEW 中启用探针(Probe)监控输入/输出数据。
- 查看
六、总结
使用 Secs4Net 库,你可以通过以下步骤实现 SECS/GEM 通讯:
- C# 开发:
- 初始化
IEAP接口(HSMS 或 SECS-I)。 - 处理主消息(
ReplyPrimary),回复 S1F2、S2F42 等。 - 发送事件报告(S6F11),如
SendJobCompleted和SendEndTestResult。
- 初始化
- 封装 DLL:
- 将功能封装到非静态类
SecsGemClient中,生成SecGemLibrary.dll。
- 将功能封装到非静态类
- LabVIEW 调用:
- 使用 .NET 构造器和调用节点,调用
Connect、SendJobCompleted、SendEndTestResult等方法。 - 配置字符串和数组参数,处理错误。
- 使用 .NET 构造器和调用节点,调用
如果需要更详细的 LabVIEW VI 示例、特定消息格式或调试帮助,请提供设备 IP、端口或消息结构,我可以进一步优化解答!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)