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
  1. 在 Visual Studio 中打开项目,右键点击“解决方案资源管理器”中的项目,选择“管理 NuGet 包”。
  2. 搜索并安装 Secs4Net
  3. 安装其他依赖:
    • 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(串口、波特率)。
  • EAPSecs4Net 提供的设备端接口,负责消息收发。
  • PrimaryMessageReceived:事件回调,处理接收到的主消息(如 S1F1、S2F41)。
3. 处理主消息

基于 EAPHelperReplyPrimary 方法,实现对主消息的处理。以下是简化的示例,处理 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. 发送事件报告

基于 EAPHelperSendEndTestResultGemJobCompleted,实现 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.LItem.A:构造 SECS-II 消息的层次结构,符合 GEM 标准。
  • DataId:使用 Interlocked.Increment 确保线程安全的唯一标识。
5. 编译 DLL
  1. 在 Visual Studio 中点击“生成 -> 生成解决方案”。
  2. bin\Debugbin\Release 目录下获取 SecGemLibrary.dll
  3. 复制依赖 DLL(如 Secs4Net.dlllog4net.dllNewtonsoft.Json.dll)到目标路径。

三、LabVIEW 调用 Secs4Net DLL

1. 创建 LabVIEW 项目
  1. 打开 LabVIEW,创建新项目(File -> New Project)。
  2. 添加一个新 VI(Virtual Instrument)。
2. 配置 .NET 构造器
  1. 在程序框图中,从函数选板选择“Connectivity -> .NET -> Constructor Node”。
  2. 放置构造器节点,双击打开配置窗口,浏览并选择 SecGemLibrary.dll
  3. 选择 SecGemLibrary.SecsGemClient 类,配置构造函数参数:
    • ipAddress:字符串(如 “192.168.1.100”)。
    • port:I32(如 5000)。
    • isHsms:布尔值(True 表示 HSMS)。
3. 调用方法
  1. 添加“Invoke Node”(Connectivity -> .NET -> Invoke Node),连接到构造器节点的输出。
  2. 右键单击调用节点,选择“Methods”,可用方法包括:
    • Connect:连接设备,返回布尔值。
    • Disconnect:断开连接,无返回值。
    • SendJobCompleted:发送 S6F11 事件,输入 testSectionId(字符串)。
    • SendEndTestResult:发送测试结果,输入 lotId(字符串)和 arr(字符串数组)。
  3. 参数配置:
    • 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. 通讯流程
  1. 初始化并连接:调用 Connect,建立 HSMS 连接。
  2. 处理消息:ReplyPrimary 自动处理 S1F1、S2F41 等。
  3. 发送事件:调用 SendJobCompletedSendEndTestResult,发送 S6F11。
  4. 断开连接:调用 Disconnect

五、注意事项

  1. 依赖管理

    • 确保 Secs4Net.dlllog4net.dllNewtonsoft.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>
      
  2. 线程安全

    • DataId 使用 Interlocked.Increment 确保线程安全。
    • LabVIEW 调用节点设为“Run in any thread”以支持异步操作。
  3. 异常处理

    • 在 C# 中使用 try-catch 捕获异常,记录到日志。
    • 在 LabVIEW 中检查错误簇,处理 .NET 异常。
  4. 调试

    • 查看 log.txt(log4net 日志)排查通讯问题。
    • 在 LabVIEW 中启用探针(Probe)监控输入/输出数据。

六、总结

使用 Secs4Net 库,你可以通过以下步骤实现 SECS/GEM 通讯:

  1. C# 开发
    • 初始化 IEAP 接口(HSMS 或 SECS-I)。
    • 处理主消息(ReplyPrimary),回复 S1F2、S2F42 等。
    • 发送事件报告(S6F11),如 SendJobCompletedSendEndTestResult
  2. 封装 DLL
    • 将功能封装到非静态类 SecsGemClient 中,生成 SecGemLibrary.dll
  3. LabVIEW 调用
    • 使用 .NET 构造器和调用节点,调用 ConnectSendJobCompletedSendEndTestResult 等方法。
    • 配置字符串和数组参数,处理错误。

如果需要更详细的 LabVIEW VI 示例、特定消息格式或调试帮助,请提供设备 IP、端口或消息结构,我可以进一步优化解答!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐