Laravel怎么配合Workerman命令行監聽MQTT

laravel+workerman怎么監聽mqtt?下面本篇文章給大家介紹一下laravel配合workerman命令行監聽mqtt的方法,希望對大家有所幫助。

Laravel怎么配合Workerman命令行監聽MQTT

公司是做物聯網的,經常有服務端通過PHP與物聯網設備通過MQTT協議通信,恰好PHP框架用的是Laravel,剛接觸的時候發現沒什么比較接近的資料,自己摸索了一陣,已經在幾個項目使用上了,這里將相關的步驟貼出來,方便以后自己查閱以及有類似需求的朋友參考。

寫在開始

眾所周知,PHP是一門專為Web設計的語言,絕大部分時間都是與Web Server通信,再后端一點,也是與別的后端語言配合做“前端”,其底層設計也限制了其本身更適合做Web那些事,所以如果想要用來服務端監聽MQTT,就需要別的庫來配合,這里說的庫主要就兩個,分別是workerman及swoole,當前(2019.08)就服務端監聽MQTT實際使用體驗來說,分別如下:

workerman:

  • 安裝簡單,一行composer命令就能安裝好 【相關推薦:《workerman》】
  • MQTT庫使用的人多,更新日期更近
  • 支持MQTT TLS/SSL加密
  • 文檔詳細

swoole:

  • 安裝相比workerman復雜,每個運行環境都要單獨安裝,可能需要編譯環境。
  • MQTT使用的人較少,更新時間比較久遠
  • 文檔少,能查找到的資料也少
  • 不支持TLS/SSL加密,如果需要加密的環境可能不是很友好

綜上所述,我最終選擇了workerman,本文以workerman作為MQTT庫進行配置使用。

安裝Laravel,已安裝可省略

現代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源加快安裝速度。

安裝workerman-mqtt

上面說了,用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. > IlluminateFoundationComposerScripts::postAutoloadDump > @php artisan package:discover Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Package manifest generated successfully.

新建artisan命令

既然是使用Laravel配合workerman監聽MQTT,那artisan自然是不二的選擇了,能使用Laravel的組件,還能使用artisan命令管理監聽進程。創建相關命令文件:

?  php artisan make:command mqtt Console command created successfully.

然后編輯生成的workerman-mqtt/app/Console/Commands/mqtt.php文件,將文件改成如下內容:

<?php  namespace AppConsoleCommands;  use IlluminateConsoleCommand; use WorkermanWorker;  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 WorkermanMqttClient("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等配合進行緩存或者使用消息隊列等。

執行mqtt命令

和別的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相關業務。

更多編程相關知識,請訪問:workerman!!

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享