剩余一个小时就要下班了,最近一直忙于物联网项目的开发。稍有空闲就是写一个小说。因此最近博客更新也比较少。今天分享的内容主要是用PHP监测MQTT客户端设备的在线离线状态。
MQTT协议中存在一个遗嘱消息,就是客户端在主动断开连接时可以向特定的Topic发送遗嘱消息。通过该机制我们可以监测到设备的离线请求。但是物联网应用中很多时候不能单纯的依赖遗嘱消息机制来监测,比如客户端突然断电、断网等造成的离线。这时客户端根本来不及做出请求响应,而且客户端也没办法预测什么时候会断电、断网。
那么怎么监测MQTT客户端在线或离线的状态呢?
其实MQTT协议建立在TCP协议基础上的一种通讯协议。在客户端断开与服务器连接的时候,会有一个Tcp clean事件来清理连接。知道了这个就好办多了。毕竟很多mqtt broker对于该事件是有反馈信息的,比如mosquito采用了$SYS系统级主题来反馈客户端连接和断开事件,再比如emqx则采用$event/client_connect来反馈客户端连接的事件。我们只需订阅相关的主题消息写相关的业务逻辑就可以了。
下面波波以emqx为例来分享PHP监测MQTT客户端在线和离线状态。
1、首先在emqx的管理端创建WebHook。
依次点击【规则引擎】、【资源】、【新建】创建一个WebHook资源。
2、创建事件监听规则。
3、编写Web响应接口。
示例代码片段:
- /**
- * 设备上下线通知
- */
- public function offevent(){
- $mqtt_auth = Config::get('mqtt_auth');
- $authorization = $this->request->header('Authorization');
- if($authorization !== $mqtt_auth){
- $this->result([],'403','权限验证失败','json');
- }
- $data = $this->request->post();
- $cache_key = 'GT'.mb_substr(trim($data['clientid']),0,36,'UTF-8');
- $cache = Cache::store('redis')->get($cache_key);
- $program = Db::name("SystemProgram")->where(['gateway_id'=>$cache['aid']])->value('id');
- if(!emptyempty($cache) && $program > 0){
- switch ($data['metadata']['rule_id']){
- case 1:
- //PLC连接事件处理
- $msg = ['uuid'=>$cache['uuid'],'aid'=>$cache['aid'],'type'=>1,'addtime'=>date("Y-m-d H:i:s",intval($data['timestamp'])),
- 'program_id'=>$program,'sockname'=>$data['sockname'],'content'=>"设备已上线"];
- Db::name("SystemGatewayLogs")->insert($msg);
- case 2:
- //PLC掉线事件处理
- $msg = ['uuid'=>$cache['uuid'],'aid'=>$cache['aid'],'type'=>1,'addtime'=>date("Y-m-d H:i:s",intval($data['timestamp'])),
- 'program_id'=>$program,'sockname'=>$data['sockname'],'content'=>$data['reason']];
- Db::name("SystemGatewayLogs")->insert($msg);
- default:
- break;
- }
- }
- $this->result([],200,'请求成功','json');
- }
其实对于客户端在线和离线的状态,大家也不必存放在数据库中。数据持久化有很多种方法,我们也可以放在redis集群中。
关于MQTT客户端的状态监听就写这么多吧,下班咯~~