第一條無副作用 Flow:Inject、Change、Debug
用手動 Inject 建立字串訊息,經 Change 改寫 msg.payload,最後只在 Debug sidebar 觀察。流程不含 Home Assistant Action、不寫檔、不發網路請求,也不設定啟動或週期自動 Inject。
為何需要本章
第一條 Flow 的目的不是控制燈,而是證明你理解 Node-RED 的最小執行模型:節點收到一個 message object、處理它,再沿 wire 傳給下一個節點。若一開始就接上真實照明或通知,即使結果「有動」,你也很難分辨是訊息、條件、Home Assistant 連線或 Action 設定哪一層正確。
本章以客廳環境監測的「資料標記」作為想像情境,但只處理範例文字。你按一次 Inject 按鈕,Change 把 msg.payload 從「原始訊息」改成「已完成安全轉換」,Debug 只顯示 payload。沒有真實 entity ID、位置、端點、憑證或私人內容。
核心觀念:msg、節點與 wire
Node-RED runtime 在節點間傳遞 JavaScript object,慣稱 msg。msg.payload 是常用資料欄位,但不是 message 的全部;msg.topic 常用來描述訊息主題,runtime 也會處理 _msgid 等識別資訊。不要假定每個 node 都只讀寫 payload;日後使用節點前要看 Help。
| 元件 | 本 Flow 的責任 | 不做的事 |
|---|---|---|
| Inject | 你按按鈕時建立 msg.payload 字串「原始訊息」 | 不使用 interval、不使用 schedule、不在啟動時自動 inject |
| Change | 把 msg.payload設為字串「已完成安全轉換」 | 不執行 JavaScript、不呼叫 Home Assistant |
| Debug | 把 msg.payload 顯示在 editor Debug sidebar | 不輸出 console、不設 node status、不顯示 complete message |
| Wire | 定義 Inject → Change → Debug 的訊息路徑 | 畫面左右順序本身不會傳訊 |
Change node 屬於 Node-RED core function nodes,但本例使用它的視覺化規則,不需要 Function node。這能先把「資料轉換」與「自行撰寫 JavaScript」分開。Debug node 屬於 core common nodes,僅作觀測;Debug 顯示成功不代表未來的設備動作已完成。
手動建立 Inject → Change → Debug
- 建立獨立 workspace tab。
新增一個 flow tab,名稱可設「第一個流程」。不要在既有家庭自動化 tab 內練習,以便把 Modified Flows 的影響限制在新的 flow。
- 拖入 Inject 並關閉所有自動觸發。
從 Palette 拖入 Inject。Payload 類型選 string,值填「原始訊息」;不要設定 repeat 或排程,並確定啟動時自動 Inject 未啟用。名稱可設「手動送出範例訊息」。
- 拖入 Change 並設定單一規則。
建立「Set
msg.payloadto string已完成安全轉換」,名稱可設「改寫訊息內容」。不要用環境變數、flow/global context 或真實家庭資料。 - 拖入 Debug 並限制輸出。
Debug 輸出選
msg.payload,啟用 sidebar,關閉 system console 與 node status;名稱可設「檢視轉換結果」。限制欄位可降低不必要資料暴露。 - 依序連接 wires。
從 Inject 的輸出連到 Change 輸入,再從 Change 輸出連到 Debug 輸入。確認沒有支線連到 Action、HTTP Request、File、MQTT 或任何裝置節點。
- 在 Deploy 前做差異檢查。
確認 dirty changes 只有新 tab 與三個節點,Inject 沒有 automatic/interval schedule,Debug 只輸出 payload。選 Modified Flows 前先確認該新 flow 不含其他既有節點。
- 受控 Deploy 一次。
選 Modified Flows,確認影響僅是這個新 flow,再按 Deploy。若 editor 顯示 unknown、invalid 或 unused config 警告,停止並修正,不要忽略。不要連續按 Deploy。
- 只手動 Inject 一次並觀察。
開啟 Debug sidebar,按 Inject 左側按鈕一次。預期看到
msg.payload的字串值「已完成安全轉換」。記錄結果後可停用 Debug,避免日後累積輸出。
Flow 目標與安全護欄
這條 Flow 模擬日後把感測資料標準化,但刻意不讀取 Home Assistant。它提供四個可驗收目標:
- 可控制:只有人手按 Inject 才開始,測試時機由你決定。
- 可預測:無論 Inject 的原始字串為何,固定 Change rule 都把 payload 設成指定字串。
- 可觀察:Debug 明確只顯示 payload,能把輸入與處理結果分開驗證。
- 無外部副作用:沒有 Action、HTTP、MQTT、File、Exec、serial 或通知節點;輸出只到 editor sidebar。
「無副作用」在本章是有限定義:runtime 仍會建立 message、執行節點並產生 Debug UI 資料,但不對 Home Assistant entity、外部服務、檔案或實體裝置做動作。Debug 內容本身仍可能成為敏感資料面,因此只用人工字串。
為什麼不用真實門窗或燈光 ID
真實 entity ID 會把範例綁定個人環境,公開匯出時也可能透露空間與設備。更重要的是,一旦接上 HA state 或 Action,就必須處理 connection、unknown、unavailable、目標驗證、權限與回復。這些應在後續章節逐層加入。
逐節點設定與可匯入安全範例
Inject:只允許人工起點
設定 payload type 為 string,值為「原始訊息」。repeat 與 crontab 保持空值,once 為 false。這三項都必須檢查,因為 automatic Inject 會在 runtime 啟動或重新部署後自行送訊息,不符合本章成功定義。topic 可保持空字串。
Change:明確寫入 property 與資料型別
規則是 Set property msg.payload to string「已完成安全轉換」。這不是把整個 msg 換成字串:Change 只更新 object 的 payload property,其他 runtime 欄位仍可能存在。日後若要保留原始資料,應另建 property;本章為了讓結果單純,直接覆寫。
Debug:只看需要欄位
把 output property 設為 msg.payload,sidebar 開啟、console 與 status 關閉。若選 complete msg,可能看到 topic、識別欄位及上游加入的其他資料;本例沒有必要。當你看到單一輸出時,先展開值並確認型別是字串,而不只是視覺文字相同。
安全 Flow JSON
你也可以檢視或匯入站內的 01-first-flow.json。檔案只含一個 tab、手動 Inject、Change 與 Debug,once 為 false,沒有 credentials、真實 IDs 或 endpoints。匯入前仍應先閱讀 JSON,使用 Import 的 new flow 選項隔離內容,確認預覽只有三個 nodes,再依 Deploy 前檢核處理。手動建立仍是本章主要路徑,因為能讓你理解每個欄位。
觀察 msg,而不是只看「成功」
按 Inject 一次後,第一個 message 至少帶有 payload;Change 收到 object 後把 payload 改寫,Debug 取得處理後的同一條邏輯訊息路徑。Debug sidebar 通常會讓你看到 property 名稱、值、資料型別提示與來源節點;UI 細節以目前安裝版本為準,不以未固定截圖宣稱。
| 觀察點 | 預期 | 若不符代表什麼 |
|---|---|---|
| 觸發時機 | 只在按下 Inject 後 | 若 Deploy 後自行出現,Inject 的 once 或排程可能未關閉 |
| 輸出 property | msg.payload | 若顯示整個 object,Debug complete 設定不符 |
| 值 | 「已完成安全轉換」 | Change rule、wire 或 Deploy 狀態需檢查 |
| 型別 | string | 若是 number、boolean 或 object,typed input 選擇錯誤 |
| 次數 | 每按一次對應一次 | 多次輸出可能有重複 wires、額外 Inject 或其他 flow |
_msgid 等欄位說明 msg 是 object;不要依賴其具體值,也不要把任何 runtime identifier 當成跨流程的永久業務 ID。下一章會更完整討論 payload、topic、物件與陣列。
把觀測與設備完成分開
未來流程可能是「感測器事件 → 條件 → Action → Debug」。Action 後的 Debug 只證明某個訊息走到該處,不一定證明燈具達到預期狀態;可靠設計還要觀察 Home Assistant state、timeout 與錯誤路徑。本章故意不製造這種模糊。
完成檢核、停止與下一步
- workspace 有一個獨立練習 tab,只有 Inject、Change、Debug 三個 nodes 與兩條 wires。
- Inject 使用 string「原始訊息」,
repeat/crontab為空,啟動自動 Inject 關閉。 - Change 只有一條規則:把
msg.payload設為 string「已完成安全轉換」。 - Debug 只輸出
msg.payload到 sidebar,不輸出 system console 或 node status。 - 部署前差異只有本練習;Modified Flows 的影響範圍已確認,沒有忽略 editor warning。
- 每按 Inject 一次只出現一次預期字串;Deploy 或 restart 不會自動輸出。
- 完成後停用 Debug 或至少清空 sidebar;匯出內容不含 secrets、真實 IDs、私人 endpoint 或家庭資料。
若你需要暫停練習,可停用 tab 或 Debug 後依相同部署檢核處理;不要把未部署的編輯狀態誤認為 runtime 已停。下一章會在這個無外部副作用基礎上比較資料型別與完整 msg。
故障排除
- 按 Inject 沒有 Debug 輸出:確認三個 nodes 已連線、Debug active 且 sidebar tab 開啟;再確認受控 Deploy 成功。不要為了測試連上 Action。
- 輸出仍是「原始訊息」:檢查 wire 是否繞過 Change、Change rule 是否指定
msg.payload,以及 typed value 是否為 string;修改後重新做 scope 檢核。 - Deploy 後不用按就出現訊息:立即檢查 Inject 的
once、repeat 與 schedule。全部關閉後再 Deploy;本章禁止 automatic Inject。 - 一次按鈕出現兩筆以上:檢查重複 wires、另一個相同 Inject、Debug node 重複或其他 tab。可用來源 node 名稱辨識,但不要依賴真實環境資料。
- Debug 顯示完整 object:把 Debug output 從 complete msg 改為
msg.payload。公開求助前清空既有訊息,避免其他 flow 的敏感內容混入。 - Import 顯示 unknown node:不要安裝陌生 package。本站 JSON 只用 Node-RED 5.0.2 核心 Inject、Change、Debug;核對匯入檔案與 runtime 基線。
- Deploy 警告其他 flows 也有變更:停止部署。先分離或回復不屬於本練習的 dirty changes;不要用 Full 把未知變更一併送出。
固定來源與範例
- Node-RED 5.0.2 固定提交:runtime message、core common nodes 與 core function nodes。
- 5.0.2 Inject/Debug 固定原始碼與 5.0.2 Change 固定原始碼。
- Node-RED 官方 Working with messages、官方第一條 Flow 教學;本章設定以固定 5.0.2 與安全範例校正。
- 本站安全範例 01-first-flow.json:匯入前可直接檢查,沒有 automatic Inject、credentials 或外部節點。