作業4 準備工作 (Node-Red 程式說明)
這個 Node-RED 流程的目的是將 Telegram(電報)聊天指令 轉換為 MQTT 訊息,以實現對遠端裝置(例如物聯網設備)上的 LED 燈 進行控制。
1. 接收 Telegram 指令
節點:
telegram receiver(Telegram 接收器)功能: 監聽在特定 Telegram 機器人 (
@alextest999_bot) 上,由特定聊天 ID (7965218469) 發送的訊息。它只會處理作為指令(開頭為/)的訊息。
節點:
function(提取內容)功能: 從 Telegram 訊息物件中提取純文字內容 (
msg.payload.content),並將其設置為新的訊息負載 (msg.payload),以便後續處理。
2. 處理指令與生成 MQTT 訊息
節點:
function(根據指令發佈 MQTT 訊息)功能: 這是核心邏輯,負責將接收到的 Telegram 指令轉換為對應的 MQTT 主題和負載。
MQTT 主題: 所有指令的 MQTT 主題均為 alex9ufo/rfid/led。
指令與負載對應關係:
| Telegram 指令 | MQTT 負載 (payload) | 預期動作 (對應遠端 LED) |
/on | "on" | 開啟 LED 燈 (可能為綠色) |
/off | "off" | 關閉 LED 燈 |
/flash | "flash" | 使 LED 燈交替閃爍 |
/timer | "timer" | 啟動定時功能 (LED 於 10 秒後關閉) |
3. 發佈 MQTT 訊息
節點:
mqtt out(MQTT 輸出)功能: 將上一步驟生成的 MQTT 訊息(包含主題和負載)發佈到配置的 MQTT 代理程式 (Broker) HiveMQ (
broker.hivemq.com:1883)。QoS (服務品質): 設為
1(至少發送一次)。Retain (保留標誌): 設為
true。這會讓 Broker 儲存此主題的最後一條訊息,確保任何新連線的訂閱者都能立即收到最新的指令狀態。
這個流程主要的功能是接收、解析來自 MQTT 的指令,並根據指令執行三項主要動作:
更新 Dashboard 上的虛擬 LED 狀態。
執行定時關閉和閃爍等進階控制邏輯。
發佈 LED 的文字狀態 (ON/OFF/FLASH/TIMER) 到另一個 MQTT 主題。
1. 接收 MQTT 指令與初步處理
節點:
mqtt in(MQTT 輸入)主題:
alex9ufo/rfid/led功能: 訂閱並接收前一個流程發佈的 LED 控制指令 (
on,off,flash,timer)。
節點:
function(global.set)功能: 將接收到的原始指令 (
on,off,flash,timer) 存儲為一個 Global 變數myledStatus。這個變數的目的是讓流程中的其他節點(特別是處理閃爍邏輯的節點)能夠知道當前的控制模式,以決定是否繼續執行閃爍邏輯。
節點:
function(路由/指令解析)功能: 這是流程的核心分岔點。它解析收到的文字指令 (
msg.payload),並將其轉換為布林值 (true或false),然後根據指令將訊息導向到四個不同的輸出端口:輸出 1 (
on): 設定msg.payload = true(LED 開啟)。輸出 2 (
off): 設定msg.payload = false(LED 關閉)。輸出 3 (
flash): 設定msg.payload = true(啟動閃爍,LED 初始狀態為開啟)。輸出 4 (
timer): 設定msg.payload = true(啟動定時器,LED 初始狀態為開啟)。
2. 視覺化與狀態發佈
節點:
ui_led(儀表板 LED)功能: 將接收到的布林值 (
true/false) 視覺化在 Node-RED Dashboard 上。true顯示 綠色 LED (開啟)。false顯示 紅色 LED (關閉)。
節點:
function(根據指令發佈 MQTT 訊息) 和mqtt out(ledStatus)主題:
alex9ufo/rfid/ledStatus功能: 這個分支的目的是將 LED 的文字狀態發佈到一個新的 MQTT 主題。
接收到的指令 (
on,off...) 被轉換為大寫狀態字串 (ON,OFF,FLASH,TIMER),然後發佈出去。這讓其他系統可以訂閱此主題,即時得知 LED 的控制模式。
3. 進階控制邏輯 (閃爍與定時)
A. 閃爍 (Flash) 邏輯
節點:
delay(閃爍計時器)接收到
flash指令後,將訊息延遲 500 毫秒 (0.5 秒) 後發送。
節點:
function(global.get)功能: 檢查 Global 變數
myledStatus的值。只有當myledStatus等於'flash'時,才讓訊息通過第一個輸出端口。如果不是'flash'(表示使用者已切換到其他模式,如on或off),則停止訊息流。
節點:
function(反轉狀態)功能: 將當前訊息的布林值負載反轉 (
msg.payload = !msg.payload),也就是將true變成false,或將false變成true。
循環: 反轉後的訊息會被重新送回
delay節點,然後再次被檢查和反轉。這個循環會不斷地讓 Dashboard 上的 LED 在綠色 (true) 和紅色 (false) 之間快速切換,實現閃爍效果,直到global.get節點檢測到模式已不再是'flash'為止。
B. 定時 (Timer) 邏輯
節點:
delay(定時 10 秒)接收到
timer指令後,訊息會被延遲 10 秒。
節點:
function(關閉)功能: 10 秒延遲結束後,此節點將
msg.payload設置為false。
動作: 將
false訊息發送給ui_led,從而在 10 秒後自動關閉 Dashboard 上的虛擬 LED。
這個流程的作用是接收前一個流程發佈的 LED 狀態訊息,並將其格式化後,以聊天訊息的形式回傳給 Telegram 使用者,從而實現即時的狀態確認。
1. 接收 LED 狀態
節點:
mqtt in(ledStatus)主題:
alex9ufo/rfid/ledStatus功能: 訂閱並接收 LED 的文字狀態 (
ON,OFF,FLASH,TIMER)。這些訊息是由第二個流程中的mqtt out節點發佈的。
2. 格式化訊息內容
節點:
function(根據指令發佈 MQTT 訊息)功能: 這個節點將接收到的 大寫 狀態代碼 (
ON,OFF等) 轉換為一條更具描述性的 聊天訊息。轉換規則: | 接收到的 MQTT 負載 | 輸出訊息負載 (
msg.payload) | | :-----------------: | :--------------------------------: | |"ON"|"LED Status: on"| |"OFF"|"LED Status: off"| |"FLASH"|"LED Status: flash"| |"TIMER"|"LED Status: timer"|
3. 準備 Telegram 訊息格式
節點:
template功能: Telegram Sender 節點需要一個特定的 JSON 格式訊息才能發送聊天訊息。此模板節點就是用來生成這個 JSON 結構:
JSON{ "chatId": 7965218469, "type": "message", "content": "{{payload}}" // 這裡會插入上一步驟格式化後的狀態文字 }它確保訊息被發送到正確的聊天 ID (
7965218469),並將上一步驟生成的狀態文字作為訊息內容 (content) 傳遞。
4. 發送 Telegram 通知
節點:
telegram sender(Telegram 發送器)功能: 根據上一步驟生成的 JSON 訊息,透過配置好的 Telegram 機器人 (
@alextest999_bot),將 LED 的當前狀態訊息發送給使用者。
這個流程是為 Node-RED Dashboard 的 「資料表」 群組設計的,允許使用者輸入記錄的 ID,並將該筆資料從 rfid_logs 資料表中讀取出來,顯示在表格元件上。
1. 取得查詢 ID
節點:
ui_numeric(ID)功能: 這是 Dashboard 上的數字輸入框,讓使用者輸入要查詢的資料記錄 ID。
輸出: 使用者輸入的值作為
msg.payload傳遞給下一個節點。
節點:
function(flow.set)功能:
將接收到的 ID 值儲存到 Flow 變數
delete_id中 (flow.set('delete_id', idno),儘管變數名稱包含 "delete",但在此流程中用於查詢)。將 ID 值作為
msg.payload傳遞給下一個節點。
目的: 儲存 ID 主要是為了讓後續的查詢按鈕即使沒有直接接收到 ID 也能工作(例如,如果使用者先輸入 ID 但又點擊按鈕)。
2. 觸發查詢與組合 SQL 語句
節點:
ui_button(查詢一筆)功能: 這是 Dashboard 上的按鈕。當使用者點擊它時,流程開始執行查詢操作。
節點:
function(組合查詢一筆 SQL)功能: 這是生成資料庫查詢指令的核心節點。
它嘗試從 Flow 變數
delete_id中取得 ID,如果沒有,則使用輸入的msg.payload。它建構一個參數化的 SQL 查詢語句,並將其設置為
msg.topic:SQLSELECT id, date, time, LEDorRFID, memo FROM rfid_logs WHERE id = $id將實際的 ID 值(變數
id)作為陣列[id]設置為msg.payload。SQLite 節點會使用這個陣列來替換$id參數,防止 SQL 注入。
輸出:
msg.topic包含 SQL 查詢語句,msg.payload包含查詢參數。
3. 執行資料庫查詢
節點:
sqlite(RFID)功能: 連接到名為
rfid_node-red.db的 SQLite 資料庫。操作: 執行由
msg.topic提供的 SQL 查詢語句。輸出: 查詢結果(通常是一個包含資料物件的陣列)會被放在
msg.payload中,傳遞給下一個節點。
4. 顯示結果
節點:
ui_table(設定資料表)功能: 這是 Dashboard 上的表格元件。
操作: 接收
msg.payload中的資料陣列,並根據預先定義的欄位(ID、星期、時間、LED或RFID、備註)將單筆記錄顯示在 Dashboard 的表格上。
這個流程是為 Dashboard 的 「資料表」 群組設計的,功能是根據使用者提供的 ID,從 rfid_logs 資料表中刪除對應的記錄,並立即在 Dashboard 上更新顯示最新的資料。
1. 取得刪除目標 ID
節點:
ui_numeric(ID)功能: Dashboard 上的數字輸入框,用於輸入要刪除的資料記錄 ID。
節點:
function(flow.set)功能: 將輸入的 ID 儲存到 Flow 變數
delete_id中 (flow.set('delete_id', idno))。這是為了確保後續的刪除按鈕能夠讀取到目標 ID。
2. 觸發刪除操作
節點:
ui_button(刪除一筆)功能: 當使用者點擊此按鈕時,流程開始執行刪除操作。
節點:
function(組合刪除一筆 SQL)功能: 這是刪除操作的核心。
它從 Flow 變數
delete_id或直接從msg.payload獲取目標 ID。它建構一個參數化的 SQL 刪除語句,並設置為
msg.topic:SQLDELETE FROM rfid_logs WHERE id= $id將實際的 ID 值作為陣列
[id]設置為msg.payload,用於 SQLite 節點的參數化處理。
節點:
sqlite(RFID)功能: 連接到
rfid_node-red.db資料庫,並執行由msg.topic提供的DELETE語句,完成資料刪除。
3. 刷新資料表 (重新查詢)
節點:
function(組合顯示所有SQL)功能: 在刪除操作完成後,此節點負責生成一個新的
SELECT查詢語句,以取得資料庫的最新內容。查詢語句:
SELECT id, date, time, LEDorRFID, memo FROM rfid_logs ORDER BY id DESC LIMIT 50目的: 查詢最新的 50 筆記錄,並按 ID 降序排列。
節點:
sqlite(RFID)功能: 執行上一步驟生成的
SELECT查詢,從資料庫中獲取最新的資料集。
節點:
ui_table(設定資料表)功能: 接收最新的資料陣列,並將其顯示在 Dashboard 的表格元件上,從而實現 資料即時刷新 的效果。
這個流程設計用於 Dashboard 的 「資料表」 群組,提供一個簡單的按鈕來執行一個預定義的 SQL 查詢,將資料庫 rfid_logs 表格的最新數據呈現給使用者。
1. 觸發查詢
節點:
ui_button(顯示最新50筆)功能: 這是 Dashboard 上的按鈕,標籤為「顯示全部設定」。當使用者點擊這個按鈕時,它會觸發流程,向資料庫請求最新的資料。
輸出: 點擊後發出一個空訊息 (
msg.payload = "")。
2. 組合 SQL 語句
節點:
function(組合顯示所有SQL)功能: 這個節點接收來自按鈕的觸發訊號,並建構用於查詢資料庫的 SQL 語句,將其設置為
msg.topic:SQLSELECT id, date, time, LEDorRFID, memo FROM rfid_logs ORDER BY id DESC LIMIT 50SQL 語句解析:
SELECT ... FROM rfid_logs: 選擇rfid_logs表格中指定的欄位 (id,date,time,LEDorRFID,memo)。ORDER BY id DESC: 根據id欄位進行降序排序(即最新的記錄 ID 最大,會排在最前面)。LIMIT 50: 只回傳最新的 50 筆記錄。
3. 執行資料庫查詢
節點:
sqlite(RFID)功能: 連接到名為
rfid_node-red.db的 SQLite 資料庫。操作: 執行由
msg.topic提供的 SQL 查詢語句。輸出: 查詢結果(包含最新 50 筆記錄的陣列)會被放在
msg.payload中。
4. 顯示結果
節點:
ui_table(設定資料表)功能: 這是 Dashboard 上的表格元件。
操作: 接收
msg.payload中的資料陣列,並將所有記錄根據預設的欄位定義(ID、星期、時間、LED或RFID、備註)顯示在 Dashboard 的表格上。
這個 Node-RED 流程主要負責兩個獨立的功能:設定系統操作模式和 管理底層的 SQLite 資料庫結構(建立或刪除表格)。
Node-RED 程式功能說明 (模式設定與資料庫管理)
1. 系統控制模式設定
這個部分讓使用者可以在 Dashboard 上選擇系統當前的操作模式。
節點:
ui_dropdown(控制模式 - 模式選擇)功能: 提供下拉式選單,讓使用者選擇兩種模式之一:
新增 (
create): 用於新增 RFID 標籤或記錄。比對 (
verify): 用於比對 RFID 標籤,執行存取控制等操作。
輸出: 將選定的模式字串 (
create或verify) 作為msg.payload輸出。
節點:
function(暫存模式)功能: 將接收到的模式字串 (
msg.payload) 儲存到 Flow 變數mode中 (flow.set('mode', msg.payload))。目的: 這個 Flow 變數可以在流程中的其他地方被讀取,以便遠端裝置或流程的其他部分知道系統當前應執行「新增」還是「比對」邏輯。
2. 資料庫結構管理 (建立與刪除)
這個部分允許使用者透過 Dashboard 按鈕來管理 rfid_logs 資料表(Table)。
A. 建立資料庫表格
節點:
inject(建立資料庫) &ui_button(建立資料庫)功能: 兩個觸發源:
inject節點(用於手動或自動啟動)和ui_button(用於 Dashboard 上的點擊)。
節點:
function(建立資料庫 SQL)功能: 建構用於建立
rfid_logs資料表的 SQL 語句,並設置為msg.topic。SQLCREATE TABLE IF NOT EXISTS rfid_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT NOT NULL, time TEXT NOT NULL, LEDorRFID TEXT, memo TEXT )CREATE TABLE IF NOT EXISTS確保只有當表格不存在時才建立,避免報錯。
節點:
sqlite(RFID)功能: 連接到
rfid_node-red.db資料庫並執行CREATE TABLE語句。
B. 刪除資料庫表格
節點:
ui_button(刪除資料庫)功能: Dashboard 上的按鈕,用於觸發刪除資料表的操作。
節點:
function(刪除資料庫 SQL)功能: 建構用於刪除
rfid_logs資料表的 SQL 語句,並設置為msg.topic。SQLDROP TABLE IF EXISTS rfid_logsDROP TABLE IF EXISTS確保只有當表格存在時才刪除,避免報錯。
節點:
sqlite(RFID)功能: 連接到資料庫並執行
DROP TABLE語句,永久刪除rfid_logs資料表及其所有內容。
這個 Node-RED 流程的核心功能是處理從遠端裝置(例如 RFID 讀取器)接收到的 RFID 卡片唯一識別碼 (UID),並根據系統當前的 操作模式(先前在 Flow 變數中設定),執行 「新增」記錄 的操作。
Node-RED 程式功能說明 (RFID 卡號新增記錄)
這個流程是處理 RFID 讀取事件和將數據寫入 SQLite 資料庫的關鍵部分,它利用了在前面流程中設定的 mode 變數來決定是否執行新增操作。
1. 接收 RFID 卡號
節點:
mqtt in(接收 UID)主題:
alex9ufo/rfid/UID功能: 監聽並接收遠端裝置(如讀卡器)讀取到的 RFID 卡片 UID。這個 UID 作為
msg.payload傳入。
2. 判斷模式與暫存卡號
節點:
function([新增]卡號號碼)功能:
讀取模式: 取得 Flow 變數
mode的值(flow.get('mode')),該值應為'create'或'verify'。暫存 UID: 將當前讀取的 UID 儲存到 Flow 變數
uid中 (flow.set('uid', msg.payload)),以便後續的節點存取。模式判斷: 檢查當前的操作模式是否為
'create'(新增)。輸出: 只有當模式是
'create'時,它才會繼續傳遞訊息,並將msg.payload格式化為[新增]卡號號碼 + UID的字串。如果模式不是'create',則流程停止 (return null)。
節點:
ui_text(Dashboard 顯示)功能: 將格式化後的訊息(例如:
[新增]卡號號碼 1A2B3C4D)顯示在 Dashboard 介面上,提供即時的視覺回饋,告知使用者當前的 UID 已被接收並準備新增。
3. 組合資料庫新增 SQL
節點:
function(組合新增 SQL)功能: 準備將記錄寫入
rfid_logs資料表所需的資料和 SQL 語句。獲取資料: 讀取 Flow 變數
uid作為LEDorRFID欄位的內容;msg.payload(此時為[新增]卡號號碼 + UID字串)作為memo欄位的內容。生成時間戳: 獲取 Node-RED 伺服器的當前時間,並提取日期 (
dateOnly) 和時間 (timeOnly)。建構 SQL: 建立參數化的
INSERT INTOSQL 語句:SQLINSERT INTO rfid_logs (date, time, LEDorRFID, memo) VALUES ($dateOnly, $timeOnly, $LEDorRFID, $memo)設置參數: 將所有提取的變數按順序組合成
msg.payload陣列:[dateOnly, timeOnly, LEDorRFID, memo]。
輸出: 準備好的 SQL 語句 (
msg.topic) 和參數 (msg.payload)。
4. 執行新增與資料表刷新
節點:
sqlite(RFID - 寫入)功能: 連接到
rfid_node-red.db資料庫,執行INSERT語句,將 RFID 讀取事件記錄到rfid_logs表格中。
節點:
link out&link in(連結)功能: 使用 Link 節點將訊息從寫入操作傳遞到另一個流程部分。
節點:
function(組合顯示所有SQL) ->sqlite->ui_table功能: 這是標準的資料表刷新流程(與前一個流程相同)。在成功新增記錄後,它會自動觸發一個查詢,獲取最新的 50 筆記錄,並更新 Dashboard 上的表格,確保使用者能立即看到新增加的 RFID 記錄。
這個 Node-RED 流程的功能非常單純且重要:在 Node-RED 程式啟動時,自動透過 Telegram 機器人向特定使用者發送一條包含系統狀態和可用命令的幫助訊息。
Node-RED 程式功能說明 (啟動通知與幫助訊息)
1. 流程啟動觸發
節點:
inject(注入節點)功能: 此節點配置為
once: true且帶有短暫延遲 (onceDelay: 0.1)。目的: 確保當整個 Node-RED 流程部署或啟動時,只會自動觸發一次訊息,作為系統已上線的通知訊號。
2. 組合幫助訊息內容
節點:
function(啟動時發送 Help 訊息給Telegram)功能: 定義並生成要發送的文字內容。
內容: 包含一個啟動確認訊息 (
🎉 程式已啟動!) 以及所有可用的 Telegram 遠端控制命令及其功能說明:/on/off/flash/timer/mode/status
備註: 由於 Telegram Sender 節點的設定 (
Parse Mode: "Markdown",在下一個節點定義),函式中對斜線 (/) 使用了雙斜線轉義 (\\/),以確保 Telegram 訊息能正確顯示斜線,不被誤判為 Markdown 格式標記。
3. 準備 Telegram 訊息格式
節點:
template(訊息格式)功能: 將上一步的純文字內容格式化為 Telegram Sender 節點所需的 JSON 結構。
JSON 結構: 包含目標聊天 ID (
7965218469)、訊息類型 (message)、實際內容 ({{payload}}),並指定解析模式為 Markdown。
4. 發送通知
節點:
telegram sender(Telegram 發送器)功能: 透過配置好的 Telegram 機器人 (
@alextest999_bot),將包含系統命令列表的訊息發送給目標聊天 ID 的使用者。
這個 Node-RED 流程專注於 RFID 卡號的比對(驗證)功能。它的主要任務是接收一個 RFID 卡號 (UID),然後查詢 SQLite 資料庫,判斷該卡號是否已經被記錄。
Node-RED 程式功能說明 (RFID 卡號比對與回饋)
這個流程設計用於系統處於 比對模式 (verify) 時。當遠端裝置讀取到 RFID 卡號時,系統會比對這個卡號是否在 rfid_logs 資料庫中,並將結果即時回饋給使用者(透過 Dashboard 和 Telegram)。
1. 接收 RFID 卡號
節點:
mqtt in(接收 UID)主題:
alex9ufo/rfid/UID功能: 接收遠端讀卡器讀取的 RFID 卡號 (UID) 作為
msg.payload。
節點:
inject(查詢所有 UID)功能: 作為手動或測試觸發點,可以直接跳過 MQTT 輸入,觸發比對邏輯(雖然其名稱「查詢所有 UID」與實際功能不符,實際是觸發比對)。
2. 建立 SQL 查詢
節點:
function(建立 SQL 查詢)功能:
讀取模式: 取得 Flow 變數
mode的值 (flow.get('mode'))。暫存 UID: 將當前讀取的 UID 儲存到 Flow 變數
uid中 (flow.set('uid', msg.payload))。模式判斷: 只有當
mode等於'verify'(比對模式) 時,才執行後續邏輯。如果不是'verify',則不傳遞訊息(如果前一個流程已執行新增操作,此處應停止,避免重複執行)。建構 SQL: 建立參數化的
SELECT查詢語句:SQLSELECT * FROM rfid_logs WHERE LEDorRFID = $uid LIMIT 1目的: 查詢
rfid_logs資料表中是否有任何記錄的LEDorRFID欄位與當前 UID 相符。LIMIT 1是為了提高效率,因為只要找到一筆符合的記錄,即可確認比對成功。
設置參數: 將 UID 作為陣列
[uid]設置為msg.payload。
3. 執行資料庫查詢
節點:
sqlite(查詢 rfid_logs)功能: 連接到
rfid_node-red.db資料庫,執行 SQL 查詢。輸出: 查詢結果(可能是一個包含匹配記錄物件的陣列,或是一個空陣列)傳遞給下一個節點。
4. 處理比對結果
節點:
function((Result Processor))功能: 旨在將 SQLite 查詢結果處理成一個包含所有匹配 UID 的列表。
備註: 雖然這個節點被設計用來提取 UID 列表,但在這個特定的單筆比對流程中,它更像是一個過渡或除錯節點,將陣列結構傳遞給
Status Checker。
節點:
function(Status Checker)功能: 判斷比對結果的成功或失敗,並生成回饋訊息。這個節點具有兩個輸出埠:
判斷成功: 檢查
msg.payload(SQLite 的結果陣列)是否為非空陣列 (dbResults.length > 0)。成功 (Found): 設置
msg.payload = '比對正確 卡號:' + outputUid,並從 輸出埠 1 傳遞訊息。
判斷失敗: 否則(陣列為空,表示未找到)。
失敗 (Not Found): 設置
msg.payload = '比對錯誤',並從 輸出埠 2 傳遞訊息。
5. 發送回饋與通知
節點:
ui_text(Dashboard 顯示)功能: 接收
Status Checker節點輸出的結果訊息,並即時顯示在 Dashboard 介面上(例如:比對正確 卡號: [UID]或比對錯誤)。
節點:
template->telegram sender功能: 與其他流程相似,將
Status Checker生成的結果訊息格式化為 Telegram JSON 格式,然後透過 Telegram 機器人回覆使用者,實現遠端即時通知。












沒有留言:
張貼留言