Flux SECS 完整技術文件
版本:V1.0 | 日期:2025-12-13
- 概觀與配置 Connection.xml / Standard.xml / GemConfig.xml 設定詳解。
- 核心開發指南 元件生命週期、連線狀態機、訊息建構、基礎收發。
- GEM 標準指令庫 S1F1, S2F23, S5F1, S6F11 等 SnFx API 詳解。
- GEM 資料與控制 GEM Data (VID/EC/Report) 與 Control State 狀態機。
- 診斷與進階 日誌系統 (Monitor/Trace) 與 S9 異常處理。
1. 概觀與配置
FluxSECS 是一套專為 .NET 環境設計的高效能 HSMS / SECS-II / GEM 通訊元件。它聚焦於 SEMI E37 (HSMS)、E5 (SECS-II) 與 E30 (GEM) 的實務整合。
本章目錄
1.1 產品簡介與架構
核心架構
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
|
角色:Host 或 Equipment。影響你在整合時「誰先送訊 / 誰回覆」的預期流程。 |
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 驗證流程
- 收到 Primary Message 後,以其 Stream/Function(SxFy) 在
Standard.xml尋找所有同 SxFy 的<SecsMessage ...>定義(即使Name不同也都納入)。 - 對每一組定義進行「結構比對」:由最外層
SecsItem開始遞迴驗證(格式、List 規則、Scalar 長度規則)。 - 若任一組定義「完全符合」則視為合法;若全部不符合且
AutoS9F7啟用,則回覆S9F7 (Illegal Data)。
1.4.2 欄位與數值意義
| 欄位 | 說明 |
|---|---|
SecsMessage/Name
|
同一個 SxFy 的「定義名稱」。用於區分多組定義(例如:S1F1 A、S1F1 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 有意義。
<SecsItem .../> 子節點的數量。
|
SecsItem/CheckLength
|
元素個數比對開關(預設為 True)。本專案規則:僅針對 Scalar(非 List)生效,並以 Min/Max 作為元素個數上下界。List 的數量規則不由 CheckLength 控制,請改用 Variables。
|
SecsItem/Min, Max
|
僅在 Scalar 且 CheckLength="True" 時使用。
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
|
物理連線已建立
|
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,建議使用 Invoke 或 BeginInvoke 回到 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>設定,自動決定進入OnLineLocal或OnLineRemote。
(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
|