基本上Mqtt的 SERVER(Broker)建議不要用php來稿,實在太吃力不討好了。
直接用Mosquitto 伺服器來處理就好,可以參閱 在linux上安裝mqtt server(MQTT Broker)
所以這邊只講如何訂閱跟發布,反正php其實也本來就不需要當server,他只要跟大家一樣去訂閱主題就可以知道消息內容了
首先我們是採用php-mqtt/client 這個很多人用的套件。原本我是想看有沒有原生的code來做拉,不過發現實在有困難,還是用composer 來安裝套件,幾秒就搞定了(當然首先你必須先安裝composer )
你先切換到你要使用MQTT的網頁路徑上(如:/var/www/html/davidou/MQTT)
之後只要下指令
composer require php-mqtt/client
輸入yes就安裝完成了,安裝時composer應該會提示你盡量不要用root等權限安裝,是避免有些套件可以取得root權限比較有安全上的疑慮,你不在乎的話就無所謂…
安裝完畢後,你應該可以看到你得資料夾下就會有多一些檔案跟資料夾出來了
<?php
require_once 'vendor/autoload.php'; // 請確保已經安裝了相關的套件,並將 autoload 檔案的路徑更新為正確的位置
use PhpMqtt\Client\MqttClient;
try {
$server = '192.168.1.31'; // MQTT 代理伺服器的位址,包括通訊協定和連接埠
$port = 1883;
$clientId = 'davidouIDD'; // 客戶端 ID,用於識別不同的客戶端
$mytopic = '/mqtt/#'; // 要訂閱的主題
$mqtt = new \PhpMqtt\Client\MqttClient($server, $port, $clientId);
$mqtt->connect();
$mqtt->publish($mytopic, 'Hello World!', 0);
$mqtt->disconnect();
} catch (ConnectingToBrokerFailedException $e) {
echo "連接到 MQTT 代理伺服器失敗:{$e->getMessage()}\n";
} catch (DataTransferException $e) {
echo "資料傳輸錯誤:{$e->getMessage()}\n";
} catch (MqttClientException $e) {
echo "MQTT 用戶端錯誤:{$e->getMessage()}\n";
}
?>
<?php
require_once 'vendor/autoload.php'; // 請確保已經安裝了相關的套件,並將 autoload 檔案的路徑更新為正確的位置
use PhpMqtt\Client\MqttClient;
try {
$server = '192.168.1.31'; // MQTT 代理伺服器的位址,包括通訊協定和連接埠
$port = 1883;
$clientId = 'ddd123'; // 客戶端 ID,用於識別不同的客戶端
$mytopic = '/mqtt/#'; // 要訂閱的主題
$mqtt = new \PhpMqtt\Client\MqttClient($server, $port, $clientId);
$mqtt->connect();
$mqtt->subscribe( $mytopic, function ($topic, $message) {
echo sprintf("Received message on topic [%s]: %s\n", $topic, $message);
echo "收到".$message;
//這邊當然你可以再加入妳其他的邏輯判斷之類的程式碼
}, 0);
$mqtt->loop(true);
$mqtt->disconnect();
} catch (ConnectingToBrokerFailedException $e) {
echo "連接到 MQTT 代理伺服器失敗:{$e->getMessage()}\n";
} catch (DataTransferException $e) {
echo "資料傳輸錯誤:{$e->getMessage()}\n";
} catch (MqttClientException $e) {
echo "MQTT 用戶端錯誤:{$e->getMessage()}\n";
}
?>
之後你就可以去終端機下指令 php mqtt_subscribe.php
[root@davidouVM MQTT]# php mqtt_subscribe.php
Received message on topic [/mqtt/go]: 測試
收到測試Received message on topic [/mqtt/go]: 測試123
收到測試123
但是如果你的broker需要帳號密碼驗證的話,你就必須再加上一些程式碼
$username = 'abc'; // 你的使用者名稱
$password = '123'; // 你的密碼
$connectionSettings = (new \PhpMqtt\Client\ConnectionSettings)
->setUsername($username)
->setPassword($password);
//把 $mqtt->connect()改為下列這行
$mqtt->connect($connectionSettings, true);
這邊還有其他的參數可以參考
$connectionSettings = (new \PhpMqtt\Client\ConnectionSettings)
// 連接到代理時用於身份驗證的用戶名。
->setUsername(null)
// 連接到代理時用於身份驗證的密碼。
->setPassword(null)
// 連接超時定義了客戶端嘗試與代理建立套接字連接的最大秒數。
// 該值不能小於 1 秒。
->setConnectTimeout(60)
// 套接字超時是套接字連接的最大空閒時間(以秒為單位)。
// 如果在給定的秒數內沒有讀取或發送數據,則套接字將關閉。
// 該值不能小於 1 秒。
->setSocketTimeout(5)
// 重新發送超時是客戶端在發送未確認消息的副本之前等待的秒數。
// 該值不能小於 1 秒。
->setResendTimeout(10)
// 保持活動間隔是客戶端在向代理發送保持活動信號(ping)之前將等待而不
//發送消息的秒數。 該值不能小於 1 秒,也不能大於 65535 秒。 一個合理
//的值是 10 秒(默認值)。
->setKeepAliveInterval(10)
// 如果客戶端突然斷開連接時代理應該以客戶端的名義發布最後的遺囑消息,
// 則此設置定義將發布消息的主題。 僅當同時配置了此設置和最後遺囑消息
// 時,才會發布最後遺囑消息。
->setLastWillTopic(null)
// 如果客戶端突然斷開連接時代理應該以客戶端的名義發布最後的遺囑消息,
// 此設置定義將要發布的消息。 僅當配置了此設置以及最後遺囑主題時,
// 才會發布遺囑消息。
->setLastWillMessage(null)
// 如果被觸發,客戶端的最後一條消息將被發布的服務質量級別。
->setLastWillQualityOfService(0)
// 此標志確定是否保留客戶端的最後一條消息(如果它被觸發)。 使用此設置
// 可以方便地通過在最後遺囑中發布保留的離線狀態和在線狀態作為連接時的
// 第一條消息來發出客戶端離線的信號。
->setRetainLastWill(false)
// 此標志確定是否應將 TLS 用於連接。 用於連接代理的端口必須支持 TLS
// 連接。
->setUseTls(false)
// This flag determines if the peer certificate is verified, if TLS is used.
->setTlsVerifyPeer(true)
// 此標志確定是否驗證了對等方名稱,是否使用了 TLS。
->setTlsVerifyPeerName(true)
// 此標志確定是否應接受對等方的自簽名證書。 將此設置為 TRUE 意味著存在
// 安全風險,應避免用於生產場景和公共服務。
->setTlsSelfSignedAllowed(false)
// 如果使用 TLS,則用於驗證對等證書的證書頒發機構證書的路徑。
->setTlsCertificateAuthorityFile(null)
// 如果使用 TLS,則包含用於驗證對等證書的證書頒發機構證書的目錄的路徑。
->setTlsCertificateAuthorityPath(null)
// 用於身份驗證的客戶端證書文件的路徑(如果使用 TLS)。客戶端證書必須
// 是 PEM 編碼的。 它可以選擇包含頒發者的證書鏈。
->setTlsClientCertificateFile(null)
// 用於身份驗證的客戶端證書密鑰文件的路徑(如果使用 TLS)。 此選項還需
// 要使用 ConnectionSettings::setTlsClientCertificateFile()。
->setTlsClientCertificateKeyFile(null)
// 用於解密客戶端證書私鑰的密碼短語,如果使用 TLS,則反過來用於身份驗
// 證。 此選項還需要使用ConnectionSettings::setTlsClientCertificateFile()
// 和 ConnectionSettings::setTlsClientCertificateKeyFile()。
->setTlsClientCertificateKeyPassphrase(null);