Batch/headless
前面的 Plugin 都是在互動的主程式裡試的。這一章講不開畫面的用法:在產線腳本、CI、.bat 裡呼叫主程式,
掛上你的 Plugin,執行它的自訂指令,然後依結果決定下一步。
兩個名詞
- Batch(批次):主程式以
--batch(或--run、--cmd)啟動,不開畫面,指令的輸出印在標準輸出,跑完就結束。 - headless:Plugin 掛載時沒有對應的面板。Batch 沒有畫面,所以掛上去的 Plugin 一定是 headless;
另外,如果你的 Plugin 宣告了「沒有面板」(
panel_mode是NX_PANEL_MODE_NONE),互動模式下掛載也是 headless(帶@p<N>也會被忽略)。 headless 的 Plugin 收不到任何「從畫面來的事件」(按鍵、widget 操作、繪圖),但init、probe、輪詢、自訂指令、cleanup都正常,見生命週期與執行緒。 這正是它的用途:讓自訂指令與背景工作不佔任何面板。
怎麼跑
nexus_tui.exe 與 nexus_gui.exe 都支援批次旗標,行為一樣。旗標有:
| 旗標 | 意思 |
|---|---|
--batch | 不開畫面,純文字輸出到標準輸出 |
--cmd "<指令>" | 執行一條指令,可以重複,最多 16 條,依出現順序執行 |
--run <script.lua> | 執行 Lua 腳本後結束,見Lua 自動化 |
--dongle <名稱> | 依名稱選後端,例如 mock。名稱不存在就列出實際掃到的清單並以非 0 結束,不會自動改用別的後端 |
--addr <hex> | 預設的 I2C 位址(7-bit,0x00~0x7F) |
--log-level <mask> | Log 等級遮罩 |
批次模式支援標準輸出重導向(> out.txt)。一個實際的例子(用第一個 Plugin 3的 hello_ic、模擬後端):
nexus_tui.exe --batch --dongle mock --cmd "p hello_ic" --cmd "hello" --cmd "read"輸出:
PLUGIN: switched to hello_ic (probe ok)
[hello_ic] hello_ic: hello!
[hello_ic] hello_ic: reg 0x00 = 0x00- Batch 只掃描
plugins\裡的 DLL。 - 批次沒有面板,所以
p hello_ic不需要(也不用)加@p<N>。 - 你的 handler 用
LogWrite寫的行,會在指令跑完後原樣印到標準輸出,前面帶[Plugin名稱]。 - Plugin 的
on_config_load會被呼叫,on_config_save永遠不會:批次只讀不寫config.ini,見設定持久化。
Exit Code:Plugin 指令失敗會反映在這裡
批次結束時的 Exit Code 是第一條失敗指令的錯誤碼絕對值,全部成功是 0,失敗那一條之後的指令不會再執行。
對 Plugin 自訂指令,規則是:
| 情況 | 結果 |
|---|---|
handler 回傳 ERR_OK | 繼續下一條,Exit Code 不受影響 |
handler 回傳其他值(例如 ERR_HW_OFFLINE,-40) | 往 stderr 印 cmd N ('...') failed: plugin command failed (see log above),停止後續指令,Exit Code 是 40 |
| 指令名稱不存在 | 印 unknown command,Exit Code 是 7 |
p <name>/plugin switch/plugin restart 之後 probe() 回報失敗(沒帶 force) | 批次會等 probe 跑完再回:往 stderr 印 nexus_tui: cmd N ('p X') failed: rc=-E: PLUGIN: switched to X (probe failed rc=-E; kept in failed state),停止後續指令,Exit Code 是 E(probe() 回傳碼的絕對值);probe() 或 on_config_load 崩潰回 ERR_CALLBACK_CRASHED(Exit Code 82);10 秒內等不到結果回 ERR_TIMEOUT(Exit Code 6)。通過(或沒實作 probe)印 (probe ok),帶 force 且探測失敗印 (probe failed; kept by force),兩者都繼續 |
下面是沒有接 dongle、也不帶 --dongle 時,這一行指令的實際輸出(hello_ic 的 read 把 ExecSync 的錯誤碼原樣回傳):
nexus_tui.exe --batch --cmd "p hello_ic force" --cmd "read" --cmd "hello"nexus_tui: cmd 2 ('read') failed: plugin command failed (see log above)
PLUGIN: switched to hello_ic (probe ok)
adapter scan: dir=...\dongles found=0 loaded=0 rejected=0
dongle connect failed (auto) (rc=-40) - hardware is offline - Try: check the dongle is plugged in, ...
[hello_ic] hello_ic: read 0x00 failed, rc=-40
job #2 failed: op=205 addr=0x00 offset=0x0000 len=0 (rc=-40) - hardware is offline - ...(p hello_ic force 讓沒有硬體時也能掛上。行尾的 ... 是我把長行截短了。)
(結束時 %ERRORLEVEL% 是 40,後面的 hello 沒有執行。)
這裡有兩個要注意的地方:
- 失敗要回傳錯誤碼。 如果你的 handler 只是寫一行錯誤 Log、卻
return ERR_OK,Batch 看到的是成功,Exit Code 是0。 自己的自訂指令處理函式,遇到錯誤就把錯誤碼回傳出去,就像hello_ic的read那樣。 - handler 要在 10 秒內做完。 Batch 最多等 10 秒。超過的話,這一條會被誤判成
unknown command。 要在批次裡跑的指令請設計成短的;長時間的工作拆成幾條指令。
想確認指令「做了什麼」,除了 Exit Code,也去看輸出的 Log(腳本可以從標準輸出解析)。
除錯批次的小訣竅
- 先在互動模式把指令跑通,再放進批次。
- 沒有硬體時,一律加
--dongle mock。 - 批次沒有掛載成功(例如
p hello_ic找不到)時,先確認plugins\裡真的有那顆 DLL、且架構與主程式相同(x86/x64),見架構要對:x86/x64。 - 用
--cmd "plugin list"看有沒有被掃到。