PHP监测MQTT客户端在线离线状态

剩余一个小时就要下班了,最近一直忙于物联网项目的开发。稍有空闲就是写一个小说。因此最近博客更新也比较少。今天分享的内容主要是用PHP监测MQTT客户端设备的在线离线状态。

MQTT协议中存在一个遗嘱消息,就是客户端在主动断开连接时可以向特定的Topic发送遗嘱消息。通过该机制我们可以监测到设备的离线请求。但是物联网应用中很多时候不能单纯的依赖遗嘱消息机制来监测,比如客户端突然断电、断网等造成的离线。这时客户端根本来不及做出请求响应,而且客户端也没办法预测什么时候会断电、断网。

那么怎么监测MQTT客户端在线或离线的状态呢?

其实MQTT协议建立在TCP协议基础上的一种通讯协议。在客户端断开与服务器连接的时候,会有一个Tcp clean事件来清理连接。知道了这个就好办多了。毕竟很多mqtt broker对于该事件是有反馈信息的,比如mosquito采用了$SYS系统级主题来反馈客户端连接和断开事件,再比如emqx则采用$event/client_connect来反馈客户端连接的事件。我们只需订阅相关的主题消息写相关的业务逻辑就可以了。

下面波波以emqx为例来分享PHP监测MQTT客户端在线和离线状态。

1、首先在emqx的管理端创建WebHook。

依次点击【规则引擎】、【资源】、【新建】创建一个WebHook资源。

PHP监测MQTT客户端在线离线状态

2、创建事件监听规则。

emqx创建事件监听规则

3、编写Web响应接口。

示例代码片段:

  1. /**
  2.      * 设备上下线通知
  3.      */
  4.     public function offevent(){
  5.         $mqtt_auth = Config::get('mqtt_auth');
  6.         $authorization = $this->request->header('Authorization');
  7.         if($authorization !== $mqtt_auth){
  8.             $this->result([],'403','权限验证失败','json');
  9.         }
  10.         $data = $this->request->post();
  11.         $cache_key = 'GT'.mb_substr(trim($data['clientid']),0,36,'UTF-8');
  12.         $cache = Cache::store('redis')->get($cache_key);
  13.         $program = Db::name("SystemProgram")->where(['gateway_id'=>$cache['aid']])->value('id');
  14.         if(!emptyempty($cache) && $program > 0){
  15.             switch ($data['metadata']['rule_id']){
  16.                 case 1:
  17.                     //PLC连接事件处理
  18.                     $msg = ['uuid'=>$cache['uuid'],'aid'=>$cache['aid'],'type'=>1,'addtime'=>date("Y-m-d H:i:s",intval($data['timestamp'])),
  19.                         'program_id'=>$program,'sockname'=>$data['sockname'],'content'=>"设备已上线"];
  20.                     Db::name("SystemGatewayLogs")->insert($msg);
  21.                 case 2:
  22.                     //PLC掉线事件处理
  23.                     $msg = ['uuid'=>$cache['uuid'],'aid'=>$cache['aid'],'type'=>1,'addtime'=>date("Y-m-d H:i:s",intval($data['timestamp'])),
  24.                         'program_id'=>$program,'sockname'=>$data['sockname'],'content'=>$data['reason']];
  25.                     Db::name("SystemGatewayLogs")->insert($msg);
  26.                 default:
  27.                     break;
  28.             }
  29.         }
  30.         $this->result([],200,'请求成功','json');
  31.     }

其实对于客户端在线和离线的状态,大家也不必存放在数据库中。数据持久化有很多种方法,我们也可以放在redis集群中。

关于MQTT客户端的状态监听就写这么多吧,下班咯~~

波波
你想把广告放到这里吗?

发表评论

您必须 登录 才能发表留言!