Laravel Workerman怎麼監聽MQTT?以下這篇文章跟大家介紹Laravel配合Workerman命令列監聽MQTT的方法,希望對大家有幫助。
公司是做物聯網的,常常有服務端透過PHP與物聯網設備透過MQTT協定通信,剛好PHP框架用的是Laravel,剛接觸的時候發現沒什麼比較接近的資料,自己摸索了一陣,已經在幾個項目使用上了,這裡將相關的步驟貼出來,方便以後自己查閱以及有類似需求的朋友參考。
眾所周知,PHP是一門專為Web設計的語言,絕大部分時間都是與Web Server通信,再後端一點,也是與別的後端語言配合做“前端”,其底層設計也限制了其本身更適合做Web那些事,所以如果想要用來服務端監聽MQTT,就需要別的庫來配合,這裡說的庫主要就兩個,分別是workerman及swoole,當前(2019.08)就服務端監聽MQTT實際使用體驗來說,分別如下:
workerman:
swoole:
綜上所述,我最後選擇了workerman,本文以workerman作為MQTT函式庫進行配置使用。
現代PHP開發composer應該是必不可少的了,基本上大點的框架都會推薦使用composer,所以這裡以composer來安裝Laravel,指令如下:
composer create-project --prefer-dist laravel/laravel workerman-mqtt '5.5.*'
Laravel指定版本為5.5.x,這是目前(2019.08)的唯一LTS版本,考慮到企業專案的穩定及安全,還是選擇LTS。專案名稱為workerman-mqtt,專門用這個來測試MQTT。
如果composer太慢,可以考慮使用阿里雲等國內composer來源加快安裝速度。
上面說了,用composer安裝workerman-mqtt很簡單,只需要一行指令:
➜ cd workerman-mqtt ➜ composer require workerman/mqtt Using version ^1.0 for workerman/mqtt ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 2 installs, 0 updates, 0 removals - Installing workerman/workerman (v3.5.20): Loading from cache - Installing workerman/mqtt (v1.0): Loading from cache workerman/workerman suggests installing ext-event (For better performance. ) Package phpunit/phpunit-mock-objects is abandoned, you should avoid using it. No replacement was suggested. Writing lock file Generating optimized autoload files Carbon 1 is deprecated, see how to migrate to Carbon 2. https://carbon.nesbot.com/docs/#api-carbon-2 You can run './vendor/bin/upgrade-carbon' to get help in updating carbon and other frameworks and libraries that depend on it. > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Package manifest generated successfully.
既然是使用Laravel配合workerman監聽MQTT,那artisan自然是不二的選擇了,能使用Laravel的元件,還能使用artisan指令管理監聽流程。建立相關指令檔:
➜ php artisan make:command mqtt Console command created successfully.
然後編輯產生的workerman-mqtt/app/Console/Commands/mqtt.php文件,將文件改成如下內容:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Workerman\Worker; class mqtt extends Command { protected $signature = 'mqtt {action}'; protected $description = 'PHP Server MQTT Client'; protected $client_id = 'php-server'; public function __construct() { parent::__construct(); } public function handle() { global $argv; $arg = $this->argument('action'); $argv [1] = $arg; $worker = new Worker(); $worker->count = 1; $worker->onWorkerStart = function () { $mqtt = new \Workerman\Mqtt\Client("mqtt://" . env('MQTT_HOST') . ":" . env('MQTT_PORT'), array( // 'ssl' => array( // 'local_cert' => base_path() . '/path/mqtt/client.crt', // 'local_pk' => base_path() . '/path/mqtt/client.key', // 'cafile' => base_path() . '/path/mqtt/ca.crt', // 'verify_peer' => false, // 'allow_self_signed' => true, // ), // $mqtt->transport = 'ssl'; 'username' => env('MQTT_USER'), 'password' => env('MQTT_PASSWORD'), 'debug' => env('MQTT_DEBUG'), 'client_id' => $this->client_id . mt_rand(0, 999), 'will' => [ 'topic' => 'status/' . $this->client_id, 'content' => 0, 'qos' => 2, 'retain' => true, ] )); $mqtt->onConnect = function ($mqtt) { $mqtt->subscribe('/iot/#'); }; $mqtt->onMessage = function ($topic, $data, $mqtt) { var_dump($topic); var_dump($data); //TODO 业务代码 //publish消息到topic $mqtt->publish('test', 'hello workerman mqtt'); }; $mqtt->connect(); }; Worker::runAll(); } }
然後到專案根目錄下面的.env檔案加入下面幾項:
MQTT_HOST=mqtt-broker.test MQTT_PORT=1883 MQTT_USER=username MQTT_PASSWORD=password MQTT_DEBUG=true
其中,onConnect裡面的subscribe後面是需要監聽的topic,當收到新消息的時候,onMessage裡面的topic是訊息的topic,data就是具體的訊息資訊了,有了這兩個,我們可以在onMessage裡面寫我們的業務邏輯,當然也可以引入Laravel框架本身的一些元件,像是資料庫、日誌等,也可以與別的服務比如說Redis、訊息佇列MQ等配合進行快取或使用訊息佇列等。
和別的artisan命令差不多,直接命令列運行就好了:
➜ php artisan mqtt start Workerman[artisan] start in DEBUG mode ------------------------------------- WORKERMAN -------------------------------------- Workerman version:3.5.20 PHP version:7.1.30 -------------------------------------- WORKERS --------------------------------------- proto user worker listen processes status tcp zoco none none 1 [OK] -------------------------------------------------------------------------------------- Press Ctrl+C to stop. Start success. -> Try to connect to mqtt://mqtt-broker.test:1883 -- Tcp connection established -> Send CONNECT package client_id:php-server-superuser-subscribe95 username:username password:password clean_session:1 protocol_name:MQTT protocol_level:4 <- Recv CONNACK package, MQTT connect success -> Send SUBSCRIBE package, topic:/iot/# message_id:1 <- Recv SUBACK package, message_id:1
注意別忘了後面的start,這是workerman本身所需的啟動參數。
因為workerman設定是常駐內存,正常情況下是在持續在監聽的,即使程式有bug被終止,workerman也會自動新建一個進程進行處理。
如果生產環境需要長期監聽處理MQTT數據,建議使用systemctl等指令來管理。
雖然到上面為止已經可以作為客戶端在服務端監聽MQTT的消息,但是這裡有個不足之處就是,我到目前沒找到辦法單獨呼叫這個函式庫在處理實際業務邏輯的時候publish訊息到指定的topic。
還有一點是,使用這個函式庫,不能同時執行兩個使用了這個函式庫的artisan指令,會有以下提示:
➜ php artisan mqtt start Workerman[artisan] start in DEBUG mode Workerman[artisan] already running
這個問題搜遍了全網也沒發現有解決的辦法。雖然可以透過Timer類別添加定時功能透過另類辦法解決,但是在需要效率的情況下,這並不是最優解,如果有別的方案,建議還是不要選擇PHP作為服務端來處理MQTT相關業務。
更多程式相關知識,請造訪:程式設計教學! !
以上是Laravel怎麼配合Workerman命令列監聽MQTT的詳細內容。更多資訊請關注PHP中文網其他相關文章!