Flux SECS 完整技術文件

版本:V1.0 | 日期:2025-12-13

前往下載中心 支援 .NET 6, 7, 8, 10 / .NET Framework 4.7.2+

1. 概觀與配置

FluxSECS 是一套專為 .NET 環境設計的高效能 HSMS / SECS-II / GEM 通訊元件。它聚焦於 SEMI E37 (HSMS)、E5 (SECS-II) 與 E30 (GEM) 的實務整合。

1.1 產品簡介與架構

核心架構

+-----------------------------------------------------------------------+ | User Application | +-----------------------------------------------------------------------+ | FluxSECS API | | (InitializeConfig, SendPrimary, OnDataMessage, SnFx) | +-----------------------------------+-----------------------------------+ | GEM Logic Layer | Message Handling | | (VID / EC / Alarm / Report / CE) | (SecsMessage / SecsItem) | +-----------------------------------+-----------------------------------+ | HSMS Transport Driver | SECS-II Message Engine | | (TCP/IP, T3-T8 Timers) | (Serial, T1-T4 Timers) | +-----------------------------------+-----------------------------------+

1.2 快速開始

快速上手流程

這裡用「最快可跑」為目標:讓你能在幾分鐘內完成連線、看到 Monitor/Trace、並跑通一組 S1F13 ↔ S1F14(再加上 S1F17 ↔ S1F18)。 若你需要更深入的訊息建構、GEM 資料/控制狀態、SnFx 詳解,請往後續章節延伸。

步驟 1:把必要檔案放到執行目錄

  • FluxSECS.dll
  • Connection.xml(通訊協定 / 角色 / 連線參數)
  • Standard.xml(Message定義;開發商自行定義)
  • GemConfig.xml(VID/EC/Report/CEID/Alarm 與 GemSetting)
  • License.license授權檔

InitializeConfig(...) 的四個 Path 參數若傳 null,會自動讀取以上預設檔名(位於執行目錄)。

步驟 2:建立 Connection.xml

目前網站與文件僅聚焦 HSMS 通訊。以下配置以實際已驗證的 HSMS / SECS-II 使用方式為主, 我把範例拆成兩份:你用哪一種,就保留那一份,另一份可以直接刪除。

2-1. HSMS 範例

								<ConnectInfo>
  <DeviceRole>Host</DeviceRole>     <!-- Host 或 Equipment -->
  <Protocol>HSMS</Protocol>       <!-- 目前聚焦 HSMS -->

  <HSMS>
    <HSMSMode>Active</HSMSMode>  <!-- Active 或 Passive -->
    <LocalIP>127.0.0.1</LocalIP>
    <LocalPort>5000</LocalPort>
    <RemoteIP>127.0.0.1</RemoteIP>
    <RemotePort>5000</RemotePort>

    <DeviceID>0</DeviceID>
    <LinkTestInterval>60</LinkTestInterval>

    <T3Time>45</T3Time>
    <T5Time>10</T5Time>
    <T6Time>5</T6Time>
    <T7Time>10</T7Time>
    <T8Time>5</T8Time>
  </HSMS>
</ConnectInfo>
							

步驟 3:建立 GemConfig.xml

FluxSECS 啟動時會讀取 GemConfig.xml。最小可用版本只需要 <GemSetting>; 其他 VIDs/ECs/Reports/CEIDs/Alarms 可以等你整合到對應功能時再慢慢補。

								<?xml version="1.0" encoding="utf-8"?>
<request>
  <GemSetting>
    <DefaultOnlineState>0</DefaultOnlineState>
    <TimeFormat>2</TimeFormat>

    <AutoS9F1>True</AutoS9F1>
    <AutoS9F3>True</AutoS9F3>
    <AutoS9F5>True</AutoS9F5>
    <AutoS9F7>True</AutoS9F7>
    <AutoS9F9>True</AutoS9F9>
  </GemSetting>

  <!-- (可選)先放 1 個示範 VID,日後再逐步補齊 VIDs / ECs / Reports / CEIDs / Alarms -->
  <VIDs>
    <VID ID="1001" Name="ControlState" Format="U4" Type="SVID" Value="0" Units="" />
  </VIDs>
</request>
							

步驟 4:Console 快速驗證

Host 端的重點是:等 ConnectState 進入 Selected 後送訊,並在 OnDataMessage 中處理回來的 Secondary(例如 S1F14 / S1F18)。

using System;
using System.Threading;
using FluxSECS;

class Program
{
    static void Main()
    {
        var secs = new SECS();

        // 1) 一次性初始化:若參數為 null,會讀取「執行目錄」下的預設檔
        //    Connection.xml / GemConfig.xml / Standard.xml / License.license
        secs.InitializeConfig(
            ConnectionPath: null,
            GemDataPath: null,
            StandardDataPath: null,
            LicensePath: null,
            debugmode: true,
            monitor: (m) => Console.WriteLine($"[MON] {m}"),
            trace:   (t) => Console.WriteLine($"[TRC] {t}")
        );

        if (!secs.LicenseValid)
        {
            Console.WriteLine("授權無效,無法啟動通訊。");
            return;
        }

        // 2) 監聽連線狀態:HSMS 建議等待 Selected 後再送 Data Message
        var selected = new ManualResetEventSlim(false);
        secs.ConnectStateChanged += (s) =>
        {
            Console.WriteLine($"[STATE] {s}");
            if (s == ConnectState.Selected) selected.Set();
        };

        // 3) 收到訊息(Primary/Secondary)
        secs.OnDataMessage += (type, msg) =>
        {
            Console.WriteLine($"[RX] {type} S{msg.Stream}F{msg.Function} W={msg.Reply} TID={msg.TID}");
            // Host 端通常處理 SecondaryIn(例如 S1F14 / S1F18)
        };

        // 4) 啟動連線
        secs.Start();

        // 5) 等待 Selected(HSMS 建議在 Selected 後再開始正式收送訊息)
        if (!selected.Wait(TimeSpan.FromSeconds(30)))
        {
            Console.WriteLine("等待 Selected 超時:請檢查 HSMSMode/Port/防火牆/對端是否已啟動。");
            secs.Close();
            return;
        }

        // 6) 最小驗證:送 S1F13 (Establish Comm) -> 等 S1F14
        secs.Standard_S1F13(modelName: "MY_MODEL", softRev: "1.0");

        // 7) 常見下一步:送 S1F17 (Online Request) -> 等 S1F18
        secs.Standard_S1F17();

        Console.WriteLine("Press ENTER to exit...");
        Console.ReadLine();
        secs.Close();
        secs.Dispose();
    }
}

步驟 5:Console 快速驗證

Equipment 端的重點是:在 OnDataMessage 收到 PrimaryIn 後,依需求回 SendSecondary。 下例示範用內建 Standard_S1F14 / Standard_S1F18 回覆。

using System;
using FluxSECS;

class Program
{
    static void Main()
    {
        var secs = new SECS();

        secs.InitializeConfig(
            ConnectionPath: null,
            GemDataPath: null,
            StandardDataPath: null,
            LicensePath: null,
            debugmode: true,
            monitor: (m) => Console.WriteLine($"[MON] {m}"),
            trace:   (t) => Console.WriteLine($"[TRC] {t}")
        );

        if (!secs.LicenseValid)
        {
            Console.WriteLine("授權無效,無法啟動通訊。");
            return;
        }

        secs.ConnectStateChanged += (s) => Console.WriteLine($"[STATE] {s}");

        // Equipment 端:收到 Primary 就回 Secondary(示範 S1F13 / S1F17)
        secs.OnDataMessage += (type, msg) =>
        {
            if (type != TransactionType.PrimaryIn) return;

            Console.WriteLine($"[RX] PrimaryIn S{msg.Stream}F{msg.Function} W={msg.Reply} TID={msg.TID}");

            if (msg.Stream == 1 && msg.Function == 13)
            {
                // 回覆 S1F14
                secs.Standard_S1F14(msg, commAck: 0, mdln: "MY_EQP", softrev: "1.0.0");
            }
            else if (msg.Stream == 1 && msg.Function == 17)
            {
                // 回覆 S1F18
                secs.Standard_S1F18(msg, onlAck: 0);
            }
        };

        secs.Start();

        Console.WriteLine("Equipment ready. Press ENTER to exit...");
        Console.ReadLine();
        secs.Close();
        secs.Dispose();
    }
}

常見問題與排除

  • 一直停在 Connected / NotSelected:請檢查 HSMSMode(Active/Passive)、Port 是否被防火牆擋住、對端是否已啟動監聽或連線。
  • 要送訊但沒有成功:HSMS 建議在 ConnectState == Selected 後才送 Data Message;若已斷線(Disconnected)送訊會被忽略並寫入 Trace。
  • UI 程式卡住/跨執行緒例外OnDataMessage 可能在背景執行緒觸發;WinForms/WPF 請用 Invoke/Dispatcher 回到 UI thread。
  • 看不到 Trace:Trace 受 DebugMode 控制;請在 InitializeConfig(debugmode: true) 或設定 secs.DebugMode = true
  • 要快速定位封包問題:先看 Monitor(封包層 TX/RX),再開 Trace 看聚合後的內容與計時器/狀態細節。

✅ 下一步建議:若你要自訂訊息內容,請到「2.3 訊息建構基礎」與「2.4 基礎訊息收發」;若要直接用標準 API,請到「3. GEM 標準指令庫 (SnFx)」。

1.3 Connection.xml 參數說明

本節說明 Connection.xml 各欄位的用途與常見設定。 若你只想先完成「快速可跑」驗證,請直接使用 ➜ 1.2 快速開始 的「步驟 2」範例(HSMS)。

欄位 範例 說明
DeviceRole Host 角色:HostEquipment。影響你在整合時「誰先送訊 / 誰回覆」的預期流程。
Protocol HSMS 通訊協定。現階段文件與網站僅列出實際驗證中的 HSMS 配置,元件會讀取對應的 <HSMS> 區段。
HSMSMode Active Active 主動連線(對外連出);Passive 被動監聽(等待對方連入)。
LocalIP / LocalPort 127.0.0.1 / 5000 本機 IP/Port。Passive 模式主要依賴 LocalPort 作為監聽埠。
RemoteIP / RemotePort 127.0.0.1 / 5000 遠端 IP/Port。Active 模式會連往此位址。
DeviceID 0 SECS Device ID。雙方需一致(不一致時常見會引發 S9 類錯誤)。
LinkTestInterval 60 LinkTest 週期(秒)。設 0 表示不主動送(仍可回覆對方的 LinkTest)。
T3Time 45 資料訊息交易逾時(等待 Secondary)。常見 45 秒。
T5Time 10 重新連線等待/回復用計時(常見 10 秒)。
T6Time 5 控制訊息回覆等待(如 LinkTest)。常見 5 秒。
T7Time 10 Passive 等待 Select 的逾時計時(常見 10 秒)。
T8Time 5 網路封包層級等待(常見 5 秒)。

小提醒:若你在 HSMS 下要送資料訊息,建議等 ConnectState == Selected 後再送,最容易一次成功。

1.4 標準定義

Standard.xml 用於定義每個 SECS-II 訊息(SxFy)的結構規格,提供執行期的格式驗證(特別是 AutoS9F7 啟用時的 Illegal Data 判斷),以及離線/工具(例如依定義產生範例 raw)所需的樣板。

重點
  • 同一個 SxFy 允許多組定義Name 不同即可)。驗證時會逐一比對,任一組完全符合即視為合法並停止往下比對。
  • List 子項目數量只由 Variables 決定:true 不檢查數量(較多/較少/一致皆合法);false 必須與定義完全一致(較多或較少都不合法)。
  • Scalar(非 List)長度CheckLength="True" 時,使用 Min/Max 進行元素個數上下界檢查(Min=下限、Max=上限)。
  • Value/Values 僅作為讀入/範例值使用,不做固定值比對(不會因為值不同觸發 S9F7)。

1.4.1 驗證流程

  1. 收到 Primary Message 後,以其 Stream/Function(SxFy)Standard.xml 尋找所有同 SxFy 的 <SecsMessage ...> 定義(即使 Name 不同也都納入)。
  2. 對每一組定義進行「結構比對」:由最外層 SecsItem 開始遞迴驗證(格式、List 規則、Scalar 長度規則)。
  3. 若任一組定義「完全符合」則視為合法;若全部不符合且 AutoS9F7 啟用,則回覆 S9F7 (Illegal Data)

1.4.2 欄位與數值意義

欄位 說明
SecsMessage/Name 同一個 SxFy 的「定義名稱」。用於區分多組定義(例如:S1F1 AS1F1 B)。驗證時會逐一定義比對,任一組完全符合即通過。
SecsMessage/Stream, Function 對應 SxFy(例如 Stream=1, Function=1 代表 S1F1)。作為定位候選定義的主要鍵值。
SecsMessage/Reply 描述此 Primary 是否預期有 Secondary(屬於訊息特性描述;不作為 S9F7 的固定值判斷)。
SecsItem/SecsFormat 指定此節點的 SECS-II 型別(例如 List, ASCII, U1, I4 等)。
SecsItem/SecsFormat_Def 允許多個型別(以空白分隔),例如 "U4 ASCII" 代表此節點可接受 U4 或 ASCII。屬於「格式集合」驗證。
SecsItem/Variables 只對 List 有意義
  • Variables="True":可變動結構,不檢查 List 子項目數量(較多/較少/一致皆合法)。
  • Variables="False":固定結構,List 子項目數量必須完全一致
補充:所謂「定義的子項目數量」不是 XML 的獨立屬性,而是該 List 節點底下 <SecsItem .../> 子節點的數量。
SecsItem/CheckLength 元素個數比對開關(預設為 True)。
本專案規則:僅針對 Scalar(非 List)生效,並以 Min/Max 作為元素個數上下界。List 的數量規則不由 CheckLength 控制,請改用 Variables
SecsItem/Min, Max 僅在 Scalar 且 CheckLength="True" 時使用
  • Min:元素個數下限(Lower bound)。
  • Max:元素個數上限(Upper bound)。
  • 數值 0 代表「不設定該邊界」(例如 Min=0 表示不檢查下限;Max=0 表示不檢查上限)。
  • Min > Max(上下界顛倒),視為「不做長度卡控」(不會因長度觸發 S9F7)。
例:ASCII Min="0" Max="3" 表示 ASCII 字串長度可為 0~3;U1 Min="1" Max="2" 表示 U1 元素個數必須在 1~2 之間。
SecsItem/Value, Values 範例值/預設值。用於讀入產生範例訊息(例如依 Standard.xml 產生 raw 作為測試)。
不做固定值比對:實際收到的值與此處不同,不會因此觸發 S9F7。
SecsItem/Remark 備註/說明文字,常用於註記欄位語意(例如參數名稱)。不影響驗證結果。

1.4.3 範例

以下展示常見用法:Scalar 長度限制、List 的 Variables 規則、以及同一個 SxFy 多組定義。

(1)Scalar:用 Min/Max 描述元素個數上下界

								<SecsItem SecsFormat="ASCII" CheckLength="True" Min="1" Max="64" Remark="MODEL_NAME" />
<SecsItem SecsFormat="U1"    CheckLength="True" Min="0" Max="2"  Remark="FLAGS" />
							

(2)List:用 Variables 決定是否檢查子項目數量

								<!-- 固定結構:必須與定義完全一致 -->
<SecsItem SecsFormat="List" Variables="False">
  <SecsItem SecsFormat="U1" />
  <SecsItem SecsFormat="U1" />
</SecsItem>

<!-- 可變動結構:不檢查子項目數量(較多/較少/一致皆合法) -->
<SecsItem SecsFormat="List" Variables="True">
  <SecsItem SecsFormat="ASCII" Remark="CPNAME" />
  <SecsItem SecsFormat="ASCII" Remark="CPVAL" />
</SecsItem>
							

(3)同一個 SxFy 多組定義:逐一比對,任一完全符合即通過

								<SecsFormat>
  <!-- S1F1 定義 A -->
  <SecsMessage Name="S1F1_A" Stream="1" Function="1" Reply="True">
    <SecsItem SecsFormat="List" Variables="False">
      <SecsItem SecsFormat="ASCII" CheckLength="True" Min="0" Max="16" Remark="A_FIELD" />
    </SecsItem>
  </SecsMessage>

  <!-- S1F1 定義 B -->
  <SecsMessage Name="S1F1_B" Stream="1" Function="1" Reply="True">
    <SecsItem SecsFormat="List" Variables="False">
      <SecsItem SecsFormat="U1" CheckLength="True" Min="1" Max="2" Remark="B_FIELD" />
    </SecsItem>
  </SecsMessage>
</SecsFormat>
							

1.5 GemConfig.xml 參數說明

GemConfig.xml 用來定義 GEM 的資料模型(VID/EC/Report/CEID/Alarm)與自動化開關(GemSetting)。 若你只想先完成「最快可跑」驗證,請直接使用 ➜ 1.2 快速開始 的「步驟 3:最小 GemConfig.xml」。

GemSetting(自動化開關 / 行為設定)

欄位 範例 說明
DefaultOnlineState 0 預設 Online 狀態(依你的整合策略設定;不確定就先用 0)。
TimeFormat 2 時間格式設定(不確定就先用 2)。
AutoS9F1 True 收到不合法 Device ID 時,是否自動回 S9F1。
AutoS9F3 True 收到不合法 Stream/Function 時,是否自動回 S9F3。
AutoS9F5 True 收到不合法 Function Type/控制訊息狀態時,是否自動回 S9F5。
AutoS9F7 True 收到資料格式不符 Standard.xml 定義時,是否自動回 S9F7。
AutoS9F9 True 其他錯誤情境(例如資料長度/編碼問題)是否自動回 S9F9(依你的版本實作)。

VIDs(變數定義)

<VIDs> 內包含多筆 <VID ... />。每一筆代表一個可讀/可回報的變數(SVID / DVID)。

屬性 範例 說明
ID 1001 VID 編碼(字串或數值皆可;建議用純數字字串)。
Name ControlState 顯示名稱(給人看的)。
Format U4 SECS-II 格式(例如 U4 / I4 / ASCII / Boolean...)。
Type SVID 類型:常見 SVID / DVID
Value 0 (可選)預設值;若你的整合是由程式動態更新,可先不填或填 0。
Units "" (可選)單位描述。

其他節點(ECs / Reports / CEIDs / Alarms)

這些節點用於完整 GEM 整合:事件回報、報表綁定、異常/警報 等。 若你目前只需要先把通訊跑通,可以先不建立;等整合到對應功能時再逐步補齊。

1.6 API 參考:初始化與載入

方法 path 參數 行為說明
InitializeConfig(...) 多個路徑 整合初始化,依序呼叫下列 Load 方法。
LoadConnectionInfo
ReLoadConnectionInfo
null 讀取 Connection.xml
LoadStandardData
ReLoadStandardData
null 讀取 Standard.xml
LoadGemData
ReLoadGemData
null 讀取 GemConfig.xml
LoadLicense null 讀取 License.license

2. 核心開發指南

2.1 元件生命週期

本節說明如何在應用程式中正確地實例化、啟動與關閉 FluxSECS 通訊元件。

實例化與初始化

								FluxSECS.SECS secs = new FluxSECS.SECS();

// 初始化設定並訂閱 Log
secs.InitializeConfig(
    ConnectionPath: "Config/Connection.xml",
    GemDataPath: "Config/GemConfig.xml",
    StandardDataPath: "Config/Standard.xml",
    LicensePath: "Config/License.license",
    debugmode: true,
    monitor: (msg) => Console.WriteLine($"[MON] {msg}"),
    trace: (msg) => Console.WriteLine($"[TRC] {msg}")
);
							

啟動與關閉

  • Start(): 依據 Connection.xml 的設定 (HSMS) 啟動底層連線。
  • Close(): 正常關閉連線。若為 HSMS 連線中,會嘗試發送 Separate.Req 後再斷線。
  • Dispose(): 釋放物件所有資源,通常在程式結束時呼叫。

2.2 連線狀態管理

狀態定義

狀態名稱 詳細介紹
Disconnected 未連線
初始狀態,或網路/ComPort 已斷開。此時無法進行任何通訊。
Connected 物理連線已建立
  • HSMS: TCP Socket 已連線,但尚未進行 Select 握手。此時僅能發送控制訊息 (Select.Req),不能發送資料訊息。
  • HSMS: 在 Connected 階段仍需完成 Select 握手;正式資料訊息建議於 Selected 後開始收送。
NotSelected (HSMS 專用) 等待握手
TCP 已連線,正在進行 HSMS Select 握手程序 (T7 Timeout 計時中)。
若為 Active 模式,表示已發送 Select.Req 等待回覆;若為 Passive 模式,表示正在等待對方發送 Select.Req。
Selected 通訊就緒
HSMS Select 握手已成功完成 (T3~T8 Timer 運作正常)。
這是唯一可以正常收發 SxFy 資料訊息的狀態。

事件監聽

應用程式應訂閱 ConnectStateChanged 事件以掌握連線狀況。

								secs.ConnectStateChanged += (state) => 
{
    Console.WriteLine($"連線狀態變更: {state}");
    if (state == ConnectState.Selected)
    {
        // HSMS Selected 後,可開始主動發送資料
        Console.WriteLine("通訊已建立,可以傳送訊息。");
    }
};
							

2.3 SECS Message建構

FluxSECS 採用物件導向方式建構 SECS-II 訊息。所有訊息皆由 SecsMessage 容器與內部的 SecsItem 資料單元組成。

SecsItem (資料單元)

SecsItem 是 SECS-II Body 的最小資料單元:每一顆 Item 都有一個 格式 (SecsFormat),內容要嘛是 Scalar 值,要嘛是 List(巢狀子節點)

  • List:用 Items 儲存子節點(可巢狀)。
  • Scalar:用 Values 儲存值;FluxSECS 內部以「字串」保存,編碼時才轉成對應型別。
  • B(Binary):輸入可用十進位或十六進位;內部以十進位字串保存,但 SML/Log 會以 2 位十六進位顯示(例如 0x0A → 顯示 0A)。

支援的格式

SecsFormat SML 顯示 意義 範例
List L[n] 巢狀容器(子節點數量 n) new SecsItem()new SecsItem(SecsFormat.List)
B B[n] Binary (byte) new SecsItem { B_ = new[] { "0x00", "0xFF" } }
Boolean BOOLEAN[n] 布林(0/1 或 true/false) new SecsItem { Boolean = "true" }
ASCII A[n] ASCII 字串(n=byte 長度) new SecsItem { ASCII = "MDLN-01" }
JIS8 J[n] JIS8 字串 new SecsItem { JIS8 = "日本語" }
I1/I2/I4/I8 I1[n]... 有號整數(1/2/4/8 bytes) new SecsItem(SecsFormat.I4, "123")
U1/U2/U4/U8 U1[n]... 無號整數(1/2/4/8 bytes) new SecsItem(SecsFormat.U4, "1024")
F4/F8 F4[n]... 浮點數(4/8 bytes;允許科學記號) new SecsItem(SecsFormat.F8, "1.23E-4")

建立方式

方式 A:直接建立 Item(Scalar)
								// 單值
var u4 = new SecsItem(SecsFormat.U4, "100");

// 多值(例如 U4[3] 1 2 3)
var u4Multi = new SecsItem(SecsFormat.U4, new[] { "1", "2", "3" });

// ASCII(字串)
var mdln = new SecsItem { ASCII = "MDLN-01" };
							
方式 B:用 List 當容器,直接呼叫 Add_*(最簡潔)

SecsItem 本身是 List 時,呼叫 Add_U4/Add_ASCII/Add_B ...自動建立一顆子 Item並加入 List(你不需要自己 new 子節點)。

								// 建立 L,2 (MDLN, SOFTREV)
var root = new SecsItem(); // 預設就是 List
root.Add_ASCII("MDLN-01");
root.Add_ASCII("1.0.0");
							
方式 C:Object Initializer + L 初始化器(巢狀結構最清楚)
								var root = new SecsItem
{
    L =
    {
        new SecsItem { ASCII = "MDLN-01" },
        new SecsItem { ASCII = "1.0.0" },
        new SecsItem
        {
            L =
            {
                new SecsItem { U4 = "100" },
                new SecsItem { Boolean = "true" }
            }
        }
    }
};
							

收到訊息後取值

  • List 取子節點:可用索引器 root[0],或用路徑 root.Get(2,1,0)
  • Scalar 取值:用 Value(單值/合併字串)或 Values(字串陣列)。
								// 假設 Body 第一顆是 List
var root = msg.Items[0];

// L,2 (MDLN, SOFTREV)
string mdln = root[0].Value;
string softrev = root[1].Value;

// 也可以用 Get(路徑)
string first = root.Get(0).Value;
							

B(Binary) 的輸入規則小心踩雷

FluxSECS 的 B 型態允許你用「十進位」或「十六進位」字串輸入:

  • 十六進位判斷:以 0x 開頭,或字串包含 A~F/a~f
  • 內部保存:一律轉成十進位字串保存(例如 0xFF 會保存成 "255")。
  • 顯示/輸出:ToString / SML / Log 會顯示成兩位十六進位(例如顯示 FF)。
								// 這三種都可以(結果都是同一個 byte 0x0A)
var b1 = new SecsItem { B = "10" };     // 十進位
var b2 = new SecsItem { B = "0x0A" };   // 十六進位(0x)
var b3 = new SecsItem { B = "0A" };     // 十六進位(含 A~F)
							

Remark(SML 註解覆蓋)

若你有使用 Standard.xml 產生 SML 註解,SecsItem.Remark 可用來「覆蓋」該節點的註解(優先於 Standard.xml)。你也可以使用帶 remark 的 Add_* 多載一次加入值與註解。

								var root = new SecsItem();
root.Add_U4("1001", "DATAID");          // 加值 + 註解
root.Add_ASCII("LOT-001", "LOTID");     // 加字串 + 註解
							

SecsMessage (訊息容器)

SecsMessage 代表一筆完整的 SECS 交易,包含 Header 與 Body (Stream, Function, W-Bit)。

								// 範例:建立 S1F1 (Are You There), W-Bit = True
var msg = new SecsMessage(1, 1, true);
// S1F1 通常沒有 Body,所以不需要 Add Item
							

2.4 基礎訊息收發

主動發送 (SendPrimary)

用於發起新的交易 (Primary Message)。若 Reply=true,元件會自動啟動 T3 Timer 等待回覆。

								// 範例:發送 S1F13 (建立通訊請求)
var s1f13 = new SecsMessage(1, 13, true);
// 組裝 Body: L,2 (MDLN, SOFTREV)
var root = new SecsItem(SecsFormat.List);
root.Add_ASCII("MDLN-01"); // Model Name
root.Add_ASCII("1.0.0");   // Software Rev
s1f13.Add(root);

// 發送
secs.SendPrimary(s1f13);
							

回覆 (OnDataMessage) 範例

在 WinForm 應用程式中,SECS 事件是在背景執行緒觸發的。為了安全更新 UI,建議使用 InvokeBeginInvoke 回到 UI 執行緒,並使用 Switch-Case 進行訊息分流。

								// 在 Form_Load 或初始化時訂閱事件
secs.OnDataMessage += Secs_OnDataMessage;

private void Secs_OnDataMessage(TransactionType type, SecsMessage msg)
{
    // 切換到 UI 執行緒 (若需要更新 UI)
    this.Invoke((MethodInvoker)delegate
    {
        // 僅處理收到的 Primary 訊息
        if (type == TransactionType.PrimaryIn)
        {
            switch (msg.Stream)
            {
                case 1: // Stream 1
                    switch (msg.Function)
                    {
                        case 1: // S1F1 Are You There
                            // 回覆 S1F2
                            secs.Standard_S1F2(msg);
                            break;
                        case 13: // S1F13 Establish Comm
                            // 回覆 S1F14
                            secs.Standard_S1F14(msg, 0);
                            break;
                    }
                    break;

                case 2: // Stream 2
                    switch (msg.Function)
                    {
                        case 41: // S2F41 Host Command
                            // 自訂處理邏輯
                            HandleHostCommand(msg);
                            break;
                    }
                    break;
            }
        }
    });
}
							

3. GEM 標準指令庫

3.1 SnFx 模組概觀

SnFx 模組封裝了標準 GEM (SEMI E30) 常用功能。開發者可直接呼叫,無需手動組裝 SecsMessage

本章節列出目前 SnFx 已封裝的 Standard API(以 Standard_* 命名)。若某個 SxFy 未在清單中出現,代表目前版本尚未提供對應封裝。

API 方法 對應 SxFy 說明
Standard_SxF0(sMsg) SxF0 通用 Abort Transaction。收到 Primary 且 W=1 時回覆 Secondary。
GetS2F23SvidListByTraceId(trid) - 查詢某 TRID 最近一次 S2F23 指定的 SVID 清單(供整合端顯示/除錯)。

3.2 Stream 1: Equipment Status

API 方法 對應 SxFy 說明
Standard_S1F1(bool reply = true) S1F1 發送 Are You There Request。
Standard_S1F2(sMsg, mdln, softrev) S1F2 回覆 S1F1。需傳入原始 sMsg。
Standard_S1F3(svids = null, vidFormat = U4) S1F3 查詢 SVID
- svids: 若傳入 null 或空 List,代表查詢全部 (List 0)
- vidFormat: 指定送出的 SVID 格式 (預設 U4)。
Standard_S1F4(sMsg) S1F4 自動回覆 SVID 值。
Standard_S1F11(svids = null, vidFormat = U4) S1F11 查詢 SVID 定義 (NameList)
- svids: 若傳入 null 或空 List,代表查詢全部 (List 0)
Standard_S1F12(sMsg) S1F12 回覆 SVID 定義。
Standard_S1F13(mdln, softrev) S1F13 建立通訊請求。
- mdln: Model Name
- softrev: Software Revision
Standard_S1F14(sMsg, commAck, mdln, softrev) S1F14 回覆通訊請求。
- commAck: 0=Accepted, 1=Denied
- mdln: Equipment Model Name
- softrev: Equipment Software Revision
Standard_S1F15() S1F15 請求離線。
Standard_S1F16(sMsg) S1F16 回覆離線請求。
Standard_S1F17() S1F17 請求上線。
Standard_S1F18(sMsg, onlAck) S1F18 回覆上線請求。

3.3 Stream 2: Equipment Control

API 方法 對應 SxFy 詳細邏輯說明
Standard_S2F13(ecids = null, ecidFormat = U4) S2F13 查詢 ECID
- ecids: 若傳入 null 或空 List,代表查詢全部 EC (List 0)
- ecidFormat: 指定 ECID 格式 (預設 U4)。
Standard_S2F14(sMsg) S2F14 自動回覆 EC 值。
Standard_S2F29(ecids = null, ecidFormat = U4) S2F29 查詢 EC 定義 (NameList)
- ecids: 若傳入 null 或空 List,代表查詢全部 EC 定義 (List 0)
Standard_S2F30(sMsg) S2F30 回覆 EC 定義。
Standard_S2F17() S2F17 查詢時間。
Standard_S2F18(sMsg) S2F18 回覆系統時間。
Standard_S2F23(trid, dsper, totsmp, svids, svidFormat = U4) S2F23 Trace Initialize Send(Host → Equipment)。
- trid: Trace ID (ASCII)。
- dsper: 取樣週期(秒,ASCII,例如 "1.0")。
- totsmp: 總取樣次數(U4)。
- svids: 指定要送出的 SVID 清單(List)。
Standard_S2F24(sMsg, isAutoS6F1 = true) S2F24 回覆 S2F23(TIAACK)。
- isAutoS6F1: 若為 True,Equipment 端會依 DSPer 週期自動背景送出 S6F1 Trace Data。
Standard_S2F31(timeStr) S2F31 設定時間 (Set Time)。
Standard_S2F32(sMsg) S2F32 自動時間同步。
支援格式:12碼(yyMMddHHmmss), 14碼(yyyyMMddHHmmss), 16碼(yyyyMMddHHmmssff)。
Standard_S2F33_Define(rptDefs, idFormat) S2F33 定義 Report。
Standard_S2F33_UnDefine(rptIds, idFormat = U4) S2F33 刪除指定 Report(送出空 VID List 代表 Delete)。
Standard_S2F33_UnDefineAll() S2F33 刪除全部 Report(送出 L,0)。
Standard_S2F34(sMsg) 邏輯 S2F34 Define Report Acknowledge
1. 解析: 讀取 S2F33 訊息中的 RPTID 與 VID 清單。
2. 驗證: 檢查所有請求的 VID 是否存在於 GemConfig.xml。若有任何無效 VID,回覆 DRACK=4 (VID Invalid) 或 DRACK=2。
3. 更新: 若驗證通過,自動更新內部 Reports 集合(新增/刪除/修改)。
4. 回覆: 送出 S2F34,DRACK=0 (Accepted)。
Standard_S2F35_Link(linkDefs, idFormat) S2F35 連結 Event。
Standard_S2F35_UnLink(ceids, idFormat = U4) S2F35 解除指定 CEID 的 Report 連結(送出空 RPT List)。
Standard_S2F35_UnLinkAll() S2F35 解除全部 Event 連結(送出 L,0)。
Standard_S2F36(sMsg) 邏輯 S2F36 Link Event Ack
1. 解析: 讀取 S2F35 中的 CEID 與 RPTID。
2. 驗證: - 檢查 CEID 是否存在 (若否則回覆 LRACK=3)。
- 檢查 RPTID 是否已定義 (若否則回覆 LRACK=4)。
3. 更新: 若驗證通過,更新內部 CEs 集合的 Report 連結。
4. 回覆: 送出 S2F36,LRACK=0 (Accepted)。
Standard_S2F37(enable, ceids, idFormat) S2F37 啟用/停用 Event。
Standard_S2F38(sMsg) 邏輯 S2F38 Enable Event Ack
1. 解析: 讀取 S2F37 中的 CEED (Enable/Disable) 與 CEID 清單。
2. 驗證: 檢查 CEID 是否存在於 GemConfig.xml。若有任何 CEID 不存在,回覆 ERACK=1 (Denied)。
3. 更新: 若驗證通過,將對應 CE 的 Enable 屬性設為 True 或 False。
4. 回覆: 送出 S2F38,ERACK=0 (Accepted)。

3.4 Stream 5: Alarm

API 方法 對應 SxFy 詳細邏輯說明
SendAlarm(alid, isSet)
Standard_S5F1(...)
S5F1 發送警報報告
1. 檢查: 該 ALID 是否存在且 Enabled。
2. 計算 ALCD: 讀取 Config 中的 ALCD (Base Value)。
- 若 isSet = true (發生): ALCD |= 0x80 (Bit 7 設為 1)。
- 若 isSet = false (解除): ALCD &= 0x7F (Bit 7 設為 0)。
3. 發送: 組裝 S5F1 (L,3 ALCD, ALID, ALTX) 並發送。
Standard_S5F2(sMsg) S5F2 回覆 S5F1(ACKC5=0 Accepted)。
Standard_S5F3(alid, enable, idFormat) S5F3 啟用/停用警報請求
- alid: 警報 ID。
- enable: - true: 發送 ALED=0x80 (128) 代表 Enable。
- false: 發送 ALED=0x00 (0) 代表 Disable。
Standard_S5F4(sMsg) S5F4 回覆 S5F3。自動更新內部 Alarm Enable 屬性。
Standard_S5F5(alids = null, idFormat = U4) S5F5 查詢警報 (List Alarm)
- alids: 若傳入 null 或空 List,代表查詢全部警報 (List 0)
Standard_S5F6(sMsg) S5F6 回覆警報列表。
Standard_S5F7() S5F7 查詢「已啟用」警報。
Standard_S5F8(sMsg) S5F8 回覆已啟用警報。

3.5 Stream 6: Data Collection

API 方法 對應 SxFy 詳細邏輯說明
Standard_S6F2(sMsg) S6F2 回覆 S6F1(Trace Data Ack)。
SendEvent(ceid)
Standard_S6F11(...)
S6F11 發送事件報告 (Event Report)
呼叫此方法時,會執行以下自動化流程:
1. CEID 檢查: 確認 GemConfig.xml 中存在該 ceid 且已啟用。
2. Report 收集: 找出該 CEID 連結了哪些 Report (RPTID)。
3. VID 收集: 找出每個 Report 包含哪些 Variable (VID)。
4. 數值讀取: 依序讀取這些 VID 的當前值 (Current Value)
5. 發送: 依照 GEM S6F11 格式 (L,3 DATAID, CEID, RPTLIST) 組裝並發送。
Standard_S6F12(sMsg) S6F12 回覆 Event Ack。
Standard_S6F15(ceid, idFormat) S6F15 主動查詢 Event
idFormat 可指定 CEID 格式 (U4, U2, ASCII)。
ceid: 指定要查詢的事件 ID。
Standard_S6F16(sMsg) S6F16 回覆 Event Report Data。
Standard_S6F17(ceid) S6F17 請求 Annotated Event。
Standard_S6F18(sMsg) S6F18 回覆 Annotated Data。
Standard_S6F19(rptid) S6F19 請求 Individual Report。
Standard_S6F20(sMsg) S6F20 回覆 Report Data。

3.6 Stream 9: System Errors (S9Fx)

API 方法 對應 SxFy 說明
SendS9F1(SecsMessage sMsg) S9F1 Unrecognized Device ID。
SendS9F3(SecsMessage sMsg) S9F3 Unrecognized Stream Type。
SendS9F5(SecsMessage sMsg) S9F5 Unrecognized Function Type。
SendS9F7(SecsMessage sMsg) S9F7 Illegal Data。
SendS9F9(SecsMessage sMsg) S9F9 Transaction Timer Timeout。

4. GEM 資料模型與控制狀態

4.1 GEM 資料存取 (VID/EC)

FluxSECS 在記憶體中維護了一份完整的 GEM 資料模型 (載入自 GemConfig.xml)。應用程式應透過 API 更新這些資料,以確保自動回覆功能 (如 S1F4, S2F14, S6F11) 能取得正確數值。

VID (變數) 存取

								// 1. 設定單一字串值 (適合大多數純量 VID)
secs.SetVidValue("1001", "RUNNING");

// 2. 讀取單一字串值
string status = secs.GetVidValue("1001");

// 3. 設定複合結構值 (適合 List 型態的 VID)
var items = new SecsItem[] 
{ 
    new SecsItem(SecsFormat.ASCII, "SubItem1"), 
    new SecsItem(SecsFormat.U4, "100") 
};
secs.SetVidValues("2001", items);

// 4. 讀取複合結構值
SecsItem[] values = secs.GetVidValues("2001");
							

EC (設備常數) 存取

用於讀寫設備常數 (ECID)。

								// 1. 設定單一字串值
secs.SetEcValue("2001", "500");

// 2. 讀取單一字串值
string timeout = secs.GetEcValue("2001");

// 3. 設定複合結構值
var ecItems = new SecsItem[] { new SecsItem(SecsFormat.U4, "123") };
secs.SetEcValues("3001", ecItems);

// 4. 讀取複合結構值
SecsItem[] ecValues = secs.GetEcValues("3001");
							

4.2 GEM 控制狀態管理

控制狀態 (Control State) 是 GEM 標準中定義設備操作權限的核心狀態機。

狀態定義 (eControlState)

列舉值 說明
EqpOffLine 設備離線。
AttemptOnLine 嘗試連線。
HostOffLine Host 離線狀態。
OnLineLocal 連線中,但僅允許本地操作。
OnLineRemote 連線中,允許 Host 進行遠端控制。

狀態判定矩陣

FluxSECS 內部透過以下幾個布林旗標的組合,動態計算出當前的 ControlState

標準 SEMI 的情況 FluxSECS 會自己計算,若非標準請用以下提供的 API 轉換。

狀態轉換機制

自動轉換 (收到訊息時)

  • S1F13 (Establish Comm): 連線建立完成。
  • S1F15 (Req Offline): HostOnLine = false
  • S1F17 (Req Online):
    • 設定 HostOnLine = true
    • 關鍵邏輯:此時設備將根據 GemConfig.xml 中的 <DefaultOnlineState> 設定,自動決定進入 OnLineLocalOnLineRemote
      (0 = Local, 1 = Remote)。

手動轉換 (API)

API 方法 用途
SetCommunication(bool) 設定 OnLine (S1F13 狀態)。
SetHostOnLine(bool) 設定 HostOnLine (S1F17 狀態)。
SetRemote(bool) / SetLocal(bool) 切換 Local/Remote。
SetEQPOnLine(bool) 設備主動切換離線/上線。

事件監聽

									secs.ControlStateChanged += (state) => 
{
    Console.WriteLine($"GEM 控制狀態變更: {state}");
    if (state == eControlState.OnLineRemote)
    {
        // 開放遠端控制功能
    }
};
								

5. 診斷

5.1 日誌系統 (Logging)

FluxSECS 具備獨立 Log Thread,確保大量訊息記錄不會阻塞通訊處理。

兩層級日誌

層級 內容 用途 觸發條件
Monitor
(監控層)
Hex 原始封包 (TX/RX)、Header 解析、連線狀態變更。 確認網路連線是否正常、封包是否有送出。 訂閱 Monitor 事件。
Trace
(除錯層)
SML 結構內容、Timer 啟動/停止、內部邏輯流程、錯誤訊息。 開發階段除錯、分析 GEM 邏輯問題、S9F7 原因分析。 訂閱 Trace 事件 且 DebugMode=true

5.2 異常處理 (S9 Management)

當通訊發生異常時,FluxSECS 會依據 GemConfig.xml 的設定自動發送 System Errors (Stream 9)。

Function 名稱 觸發條件 開關設定
S9F1 Unrecognized Device ID 收到的 Device ID 與 Connection.xml 設定不符。 AutoS9F1
S9F3 Unrecognized Stream Type 收到的 Stream 未在 Standard.xml 中定義。 AutoS9F3
S9F5 Unrecognized Function Type 收到的 Function 未在 Standard.xml 中定義。 AutoS9F5
S9F7 Illegal Data 訊息結構、長度或格式不符合 Standard.xml 的定義。 AutoS9F7
S9F9 Transaction Timer Timeout 發送 Primary 後,在 T3 時間內未收到 Reply。 AutoS9F9