打造專屬物聯網平台:使用 WordPress + PHP + MQTT 實現雙向監控與控制系統

在物聯網(IoT)的實作中,我們常常需要一個集中化的管理平台來即時查看感測器數據,或者遠端控制硬體設備(例如繼電器)。雖然市面上有很多現成的雲端物聯網平台(如 ThingSpeak 或 Adafruit IO),但如果您想擁有完全的控制權、自訂漂亮的版面,且不希望受到數據傳輸量的限制,自建平台是最佳選擇!

本教學將帶您利用最流行的 WordPress 網站系統,結合 MQTT 協定Node-Red 中介軟體,打造一個專屬的遠端物聯網監控與控制平台。

本文學習重點:

  1. WordPress 平台快速建置(使用 Docker Compose)
  2. 安裝 PHP 環境的 MQTT 函式庫(php-mqtt/client)
  3. 撰寫前端監控 MQTT 的 PHP 程式(配合 MQTT Lens 測試)
  4. 撰寫 WordPress 後端控制台監控外掛
  5. 配合 Node-Red 進行 MQTT 與資料庫的雙向串接

系統架構設計

在開始建置之前,讓我們先看一下系統的資料流向架構圖:

物聯網雙向監控系統架構圖

在這個架構中:

  • 感測器/硬體設備:發布(Publish)感測數據到 MQTT Broker,並訂閱(Subscribe)控制指令主題。
  • Node-Red:作為中介橋樑,隨時訂閱 MQTT 數據,並將其自動寫入 WordPress 資料庫(MySQL)中。
  • WordPress 網站
  • 前端網頁/後端控制台:直接從 MySQL 讀取最新的感測器數據並顯示。
  • 控制按鈕:按下按鈕時,透過 publish.php 呼叫 PHP MQTT 客戶端,將控制訊號發布給 MQTT 經紀人(Broker),進而即時控制硬體繼電器。

一、WordPress 平台建置 (Docker Compose)

我推薦使用 Docker ComposePortainer 上快速部署 WordPress 與 MySQL 資料庫。以下是建置 Stacks 的 YAML 設定檔:

version: '3.3'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: your_root_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: wordpress_password

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "8080:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: wordpress_password
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wordpress_data:/var/www/html

volumes:
  db_data:
  wordpress_data:

Portainer 部署步驟:

  1. 進入 Portainer 管理介面,選擇 StacksAdd stack
  2. 填入 Stack 名稱(例如 wp-iot-site),並將上述的 YAML 內容貼入編輯器中。
  3. 依照您的需求,修改 WORDPRESS_DB_USER 與相關密碼設定,接著點選下方 「Deploy the stack」 部署。
Portainer Stack 部署畫面
MySQL 環境變數設定
  1. 安裝完成後,可以使用 Nginx Proxy Manager 等反向代理工具設定域名(DNS),即可連線至您的域名開始設定 WordPress 初始安裝步驟。
Nginx 反向代理設定

二、安裝 PHP 環境的 MQTTClient

為了讓 WordPress 能夠發送和接收 MQTT 訊息,我們需要使用 PHP 的 MQTT 客戶端函式庫(這裡推薦使用 php-mqtt/client)。

  1. 進入 WordPress 容器的 Terminal 終端機模式(在 Portainer 中點擊網頁版 Console 圖示)。
Portainer Console 連接
  1. 按下 「Connect」 連接:
連線終端機
  1. 因為是全新的 Linux 環境,我們先安裝 vimzip/unzip 等基本工具:
    apt-get update
    apt-get install -y vim zip unzip
  1. 接著,切換到 WordPress 的外掛目錄 /wp-content/plugins/,建立一個名為 mqttconn 的自訂外掛資料夾:
    cd /var/www/html/wp-content/plugins/
    mkdir mqttconn
    cd mqttconn
  1. 在該目錄下,我們要使用 Composer 來安裝 php-mqtt/client
    # 如果系統中沒有 Composer,可以快速下載並安裝
    curl -sS https://getcomposer.org/installer | php
    
    # 使用 composer 安裝 php-mqtt 函式庫
    php composer.phar require php-mqtt/client
安裝 php-mqtt client 過程

三、撰寫前端監控 PHP 程式

1. 安裝 PHP 代碼插入外掛

為了能在 WordPress 網頁中直接插入 PHP 程式碼,我們需要安裝一個安全的外掛:Insert PHP Code Snippet。這個外掛可以讓您將 PHP 程式碼打包成一個 Shortcode(短代碼),非常方便在一般頁面或區塊編輯器中使用。

安裝 Insert PHP Code Snippet 外掛

2. 撰寫 MQTT 發送腳本 (publish.php)

/var/www/html/ 目錄下建立一個 publish.php 檔案,當使用者在網頁上點擊控制按鈕時,網頁會透過 Ajax 請求此檔案,向 MQTT Broker 發送控制指令:

<?php
// 引入 composer 自動載入檔
require_once __DIR__ . '/wp-content/plugins/mqttconn/vendor/autoload.php';

use PhpMqtt\Client\MqttClient;
use PhpMqtt\Client\ConnectionSettings;

// 取得 Ajax 傳入的參數值
$action = isset($_GET['action']) ? $_GET['action'] : '';

if ($action === 'on' || $action === 'off') {
    $server   = 'your_mqtt_broker_ip';  // MQTT Broker 的 IP 或是域名
    $port     = 1883;                   // 連接埠
    $clientId = 'wp_web_client_' . rand(1, 1000);
    
    $mqtt = new MqttClient($server, $port, $clientId);
    
    $connectionSettings = (new ConnectionSettings())
        ->setKeepAliveInterval(60)
        ->setLastWillTopic('last/will')
        ->setLastWillMessage('client disconnected')
        ->setLastWillQualityOfService(1);
        
    $mqtt->connect($connectionSettings, true);
    
    // 將 action (on/off) 發布至指定的 MQTT 主題
    $mqtt->publish('office/relay1', $action, 0);
    $mqtt->disconnect();
    
    echo json_encode(['status' => 'success', 'message' => 'Relay set to ' . $action]);
} else {
    echo json_encode(['status' => 'error', 'message' => 'Invalid action']);
}
publish.php 程式碼圖示

3. 在 Snippet 外掛中建立前端控制介面

打開 WordPress 後台的 PHP Code Snippets 面板,點擊「Add New PHP Code Snippet」,建立一個名為 mqtt_front_control 的片段,內容貼上以下 HTML/PHP/JS 混排程式:

<?php
global $wpdb;
// 自資料庫中取得最新的感測器數據(這裡以資料表 iot_sensor_data 為例)
$latest_data = $wpdb->get_row("SELECT * FROM iot_sensor_data ORDER BY id DESC LIMIT 1");
$temperature = $latest_data ? $latest_data->temperature : '--';
$humidity    = $latest_data ? $latest_data->humidity : '--';
?>

<div style="background: #1e293b; color: #fff; padding: 2rem; border-radius: 12px; max-width: 500px; margin: 1.5rem auto; font-family: system-ui;">
    <h3 style="margin-top: 0; color: #38bdf8; text-align: center;">遠端辦公室監控面板</h3>
    
    <div style="display: flex; justify-content: space-around; margin: 1.5rem 0;">
        <div style="text-align: center;">
            <div style="font-size: 0.85rem; color: #94a3b8;">即時溫度</div>
            <div style="font-size: 2.2rem; font-weight: bold; color: #f43f5e;" id="temp-val"><?php echo $temperature; ?> °C</div>
        </div>
        <div style="text-align: center;">
            <div style="font-size: 0.85rem; color: #94a3b8;">即時濕度</div>
            <div style="font-size: 2.2rem; font-weight: bold; color: #0ea5e9;" id="hum-val"><?php echo $humidity; ?> %</div>
        </div>
    </div>
    
    <hr style="border-color: #334155; margin: 1.5rem 0;">
    
    <h4 style="text-align: center; margin-bottom: 1rem;">電器遠端控制</h4>
    <div style="display: flex; justify-content: center; gap: 1rem;">
        <button onclick="controlRelay('on')" style="background: #22c55e; color: white; border: none; padding: 0.75rem 2rem; border-radius: 6px; font-weight: bold; cursor: pointer; transition: 0.2s;" onmouseover="this.style.opacity=0.9" onmouseout="this.style.opacity=1">開啟繼電器</button>
        <button onclick="controlRelay('off')" style="background: #ef4444; color: white; border: none; padding: 0.75rem 2rem; border-radius: 6px; font-weight: bold; cursor: pointer; transition: 0.2s;" onmouseover="this.style.opacity=0.9" onmouseout="this.style.opacity=1">關閉繼電器</button>
    </div>
    <div id="control-status" style="text-align: center; margin-top: 1rem; font-size: 0.9rem; color: #94a3b8;"></div>
</div>

<script>
function controlRelay(action) {
    const statusDiv = document.getElementById('control-status');
    statusDiv.innerText = '傳送指令中...';
    
    fetch('/publish.php?action=' + action)
        .then(response => response.json())
        .then(data => {
            if (data.status === 'success') {
                statusDiv.innerHTML = '<span style="color: #22c55e;">指令傳送成功:繼電器已' + (action === 'on' ? '開啟' : '關閉') + '</span>';
            } else {
                statusDiv.innerHTML = '<span style="color: #ef4444;">錯誤: ' + data.message + '</span>';
            }
        })
        .catch(err => {
            statusDiv.innerHTML = '<span style="color: #ef4444;">連線失敗</span>';
            console.error(err);
        });
}
</script>
新增 PHP Snippet

4. 插入短代碼到網頁中

儲存後,會獲得一個 Shortcode(例如 [xyz-ips snippet="mqtt-front-control"])。只要將其複製並貼在您希望顯示監控面板的 WordPress 頁面即可。

貼入 Shortcode 工具

四、配合 Node-Red 進行後端自動化處理

為了讓資料庫的數據隨時保持最新,我們需要一個後端訂閱服務。雖然可以直接用 PHP 寫一個無窮迴圈的訂閱 daemon,但更推薦且最穩定的方式是搭配 Node-Red

1. 建立資料表 (MySQL)

我們需要在 WordPress 所在的 MySQL 資料庫中,新增一個用於存放感測器數據的資料表:

CREATE TABLE `iot_sensor_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `temperature` float NOT NULL,
  `humidity` float NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
建立 MySQL 資料表

2. Node-Red 架構設定

在 Docker 中快速啟動一個 Node-Red 容器,並在 Stacks 中設定它連線至同一個網絡環境下:

Node-Red 網絡設定

拉取以下節點建置資料流:

  1. MQTT in:訂閱感測器發布的 Topic(如 office/sensor)。
  2. Function:將接收到的 JSON 格式感測數據(含溫度與濕度),轉換為 MySQL 寫入語法:
    var data = JSON.parse(msg.payload);
    msg.topic = "INSERT INTO iot_sensor_data (temperature, humidity) VALUES (" + data.temp + ", " + data.hum + ");";
    return msg;
  1. MySQL Node:執行該 SQL 指令,將數據寫入 WordPress 的資料庫中。
Node-Red 流程圖

現在只要感測器每隔幾秒發送一次數值,Node-Red 就會即時自動寫入資料庫,WordPress 的前端監控頁面就能隨時讀取最新數值!


五、撰寫後端控制台監控外掛

如果您不想讓這些監控和控制功能對前台讀者公開,最佳的做法是將它們做成一個 WordPress 後端控制台(Dashboard)選單頁面。我們可以透過編寫一個簡單的自訂外掛來實現。

在剛才建立的 /wp-content/plugins/mqttconn/ 下,建立主外掛檔案 mqttconn.php

<?php
/*
Plugin Name: MQTT Web Controller
Description: 專屬物聯網 MQTT 雙向監控與 Relay 控制後台外掛
Version: 1.0
Author: Terry Lee
*/

if (!defined('ABSPATH')) {
    exit;
}

// 註冊控制台選單項目
add_action('admin_menu', 'mqtt_controller_menu');

function mqtt_controller_menu() {
    add_menu_page(
        '物聯網監控中心',      // 瀏覽器標題
        '物聯網監控',          // 後台選單顯示文字
        'manage_options',      // 權限要求
        'mqtt-monitor-page',   // 網址 Slug
        'mqtt_monitor_page_html', // 顯示內容的 Callback 函數
        'dashicons-cloud',     // 選單圖示
        6                      // 位置順序
    );
}

function mqtt_monitor_page_html() {
    global $wpdb;
    $latest_data = $wpdb->get_row("SELECT * FROM iot_sensor_data ORDER BY id DESC LIMIT 1");
    $temperature = $latest_data ? $latest_data->temperature : '--';
    $humidity    = $latest_data ? $latest_data->humidity : '--';
    ?>
    <div class="wrap">
        <h1>物聯網監控管理後台</h1>
        <p>在這裡您可以即時監看辦公室的環境感測數據,並對連接的硬體設備送出控制指令。</p>
        
        <div style="background: #fff; padding: 20px; border: 1px solid #ccd0d4; border-radius: 4px; max-width: 600px; margin-top: 20px;">
            <h2>環境數據狀態 (MQTT)</h2>
            <table class="form-table">
                <tr>
                    <th>即時溫度</th>
                    <td><strong style="font-size: 24px; color: #d94f5c;"><?php echo $temperature; ?> °C</strong></td>
                </tr>
                <tr>
                    <th>即時濕度</th>
                    <td><strong style="font-size: 24px; color: #2b7bb9;"><?php echo $humidity; ?> %</strong></td>
                </tr>
            </table>
            
            <hr>
            
            <h2>遠端電器控制 (Relay 繼電器)</h2>
            <p>點選下方按鈕,向 MQTT Topic <code>office/relay1</code> 發送控制指令:</p>
            <div style="margin: 20px 0;">
                <button onclick="controlRelay('on')" class="button button-primary button-large" style="background:#46b450; border-color:#46b450; text-shadow:none;">開啟繼電器</button>
                <button onclick="controlRelay('off')" class="button button-secondary button-large" style="background:#dc3232; border-color:#dc3232; color:#fff; text-shadow:none; margin-left:10px;">關閉繼電器</button>
            </div>
            <div id="control-status" style="font-weight: bold; margin-top: 15px; color: #555;"></div>
        </div>
    </div>

    <script>
    function controlRelay(action) {
        const statusDiv = document.getElementById('control-status');
        statusDiv.innerText = '傳送 MQTT 指令中...';
        
        jQuery.ajax({
            url: '/publish.php',
            data: { action: action },
            dataType: 'json',
            success: function(data) {
                if (data.status === 'success') {
                    statusDiv.innerHTML = '<span style="color: #46b450;">✔ 指令傳送成功:繼電器已' + (action === 'on' ? '開啟' : '關閉') + '</span>';
                } else {
                    statusDiv.innerHTML = '<span style="color: #dc3232;">❌ 錯誤: ' + data.message + '</span>';
                }
            },
            error: function() {
                statusDiv.innerHTML = '<span style="color: #dc3232;">❌ 伺服器通訊失敗</span>';
            }
        });
    }
    </script>
    <?php
}
外掛程式碼第 1 部分
外掛程式碼第 2 部分

啟用與測試後台面板

  1. 進入 WordPress 後台,點選 「外掛」 列表,會看到我們剛才建立的 「MQTT Web Controller」 外掛。
  2. 點選 「啟用」
啟用 MQTT Web Controller 外掛
  1. 啟用後,左側側邊欄會出現 「物聯網監控」 功能選單。點擊進去,即可看到專屬的後台監控與繼電器開關控制介面!
後台控制介面畫面

結論與展示影片

本篇文章說明了如何將一個普通的 WordPress 網站改造成功能強大的物聯網即時雙向監控與控制平台。透過 PHP-MQTT 函式庫可以主動發送控制訊號至硬體,而利用 Node-Red 監聽 MQTT 訂閱並寫入 MySQL,讓前台及後端網頁能即時查看環境中的溫濕度感測器數值。

您可以配合 Chrome / 擴充套件的 MQTT Lens 來模擬 publish/subscribe 發送和接收 MQTT 訊息進行測試。

如果您對本系統的建置需要更詳細的實作細節,我特別錄製了一段操作展示與設定說明的 YouTube 影片,歡迎觀看:

📺 MQTT 網站監控實作說明影片 (YouTube)

如果您在建置專屬 IoT 平台的過程中有任何問題,或者有特殊的物聯網需求,非常歡迎與我聯絡討論!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端