首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
基于Swoole使用MQTT协议连接阿里云物联网平台设备实现消息订阅
阿里云物联网平台为设备提供安全可靠的连接通信能力,支撑设备数据采集上云,我们这里认为阿里云物联网平台是 MQTT 服务端,那么我们自己的设备作为客户端,应该如何实现消息订阅? 阿里云没有提供 PHP 的 SDK,而 MQTT 是一个通用协议,我们可以使用 PHP 实现 MQTT 协议解析相关代码,同时也可以使用 Swoole 作为 MQTT 服务端或客户端 [Simps 框架](https://github.com/simple-swoole/simps) 基于 Swoole 的`TCP Server`和`Co\Client`集成了 MQTT 服务端和客户端 这篇文章就以 [Simps 框架](https://github.com/simple-swoole/simps) 作为演示,实现 MQTT 客户端连接阿里云物联网平台设备进行消息订阅 ### 创建产品/设备 使用物联网平台的第一步是在云端创建产品和对应设备,我们需要前往[阿里云物联网平台](https://iot.console.aliyun.com)创建产品和设备,具体操作请[参考文档](https://help.aliyun.com/document_detail/73705.html) 创建完成后分别在产品详情和设备详情中获取设备证书(`ProductKey`、`ProductSecret`、`DeviceName`和`DeviceSecret`),后面连接时需要用到 ### 代码实现 示例代码放在了 GitHub 上:[simps-cloud/aliyun-iot](https://github.com/simps-cloud/aliyun-iot),可以使用 composer 进行安装或者直接使用 git clone 源码 ```shell composer create-project simps-cloud/aliyun-iot git clone git@github.com:simps-cloud/aliyun-iot.git ``` ## 实现说明 下面我们分别来说明一下对应的代码实现,使用 Swoole 作为客户端可以保证我们`recv`到一个完整的 MQTT 包,然后解析对应的数据包即可 ### 配置文件 创建`config/aliyuniot.php`配置文件 `client_id`是 MQTT 建立连接时需要指定的 ClientID,保证全局唯一就可以 将我们刚才获取的设备证书信息,写入到对应的配置文件中 ```php return [ // 连接域名 'host' => "{$YourProductKey}.iot-as-mqtt.{$region}.aliyuncs.com", // 端口默认1883 'port' => 1883, // 心跳 'keepalive' => 300, // clientID 'client_id' => "d812edc1-18da-2085-0edf-a4a588c296d1", 'device_name' => "", 'device_secret' => "", 'product_key' => "", 'product_secret' => "", ]; ``` ### 连接密码 MQTT 建立连接时需要指定的 Password,而这个密码有阿里云的要求:需要把提交给服务器的参数(ProductKey、DeviceName、timestamp 和 clientId)按字典排序并拼接后,使用`hmacsha256`方法和设备的`DeviceSecret`,加签生成 Password > [文档](https://help.aliyun.com/document_detail/73742.html) 中解释了一下 clientId、securemode 等参数,其实是说连接时的参数,而不是 Password 的生成,不要被误导了,实际上只需要关注 content 的值就可以... ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-pwd.png) 而对于的签名算法类型,PHP 可以使用`hash_hmac`函数来实现,所以密码生成可以封装为: ```php /** * @param $config * @param string $signmethod 签名算法类型。支持hmacmd5,hmacsha1和hmacsha256,默认为hmacmd5 */ function signAliIot($config, $signmethod = "hmacmd5") { $sign_config = [ 'clientId' => $config['client_id'], 'productKey' => $config['product_key'], 'deviceName' => $config['device_name'], ]; ksort($sign_config); $data = ""; foreach ($sign_config as $key => $item) { $data .= $key . $item; } switch ($signmethod){ case "hmacmd5": $sign = hash_hmac('md5', $data, $config['device_secret']); break; case "hmacsha1": $sign = hash_hmac('sha1', $data, $config['device_secret']); break; case "hmacsha256": $sign = hash_hmac('sha256', $data, $config['device_secret']); break; } return strtoupper($sign); } ``` > Password 生成没有加时间戳参数,我测试的时候加上时间戳会导致连接失败,返回错误码是 4,username 或 password 格式错误 ### 连接 Password 我们搞定之后就可以开始连接了,参考代码[bin/subscribe.php](https://github.com/simps-cloud/aliyun-iot/blob/master/bin/subscribe.php) 使用`Simps\Client\MQTTClient`进行连接操作 > 我们收到消息时,如果 QoS 是 1,根据 MQTT 协议我们需要回复 ACK,否则它会推送多次 ```php $buffer = $client->recv(); var_dump($buffer); if (is_array($buffer)) { switch ($buffer['cmd']) { case 9: echo "收到订阅确认消息\r\n"; break; case 3: echo "收到订阅消息:{$buffer['content']}\r\n"; // 收到消息如果是qos 1 需要回复 if ($buffer['qos'] === 1) { $client->sendBuffer(['cmd' => MQTT::PUBACK, 'message_id' => $buffer['message_id']], false); // 4 } break; } } ``` 执行命令启动订阅 ```shell php bin/subscribe.php ``` 这个时候我们去访问阿里云控制台中的设备详情,会发现 DeviceName 旁边的`在线`标识 可以测试一下延迟,测试网络延迟时将会向设备发送一条 QoS1 的空消息,会看到网络延迟,表示我们客户端是正常的 ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-1.png) 但这样还不够,如何发送指定消息到客户端呢? 依旧在设备详情中点击`Topic列表`->`自定义 Topic`,就可以看到发布消息的按钮,我们可以点击进入填写发布消息内容并选择对应的 QoS 等级,阿里云暂不支持 QoS2,所以只有 0 和 1 我们来发一个`Hello,Simps.` ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-2.png) Simps 的 MQTTClient 也支持发布功能,这里简单说明一下,执行命令启动并访问一次 ```shell php bin/simps.php http:start curl http://127.0.0.1:9501/ ``` 这里需要查看 [阿里云日志服务](https://iot.console.aliyun.com/lk/monitor/log) ,会看到一条`设备到云消息`的记录,我们查看一下 ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-3.png) 以上就是基于 Swoole 使用 MQTT 协议进行 TCP 连接通信,支持请前往点个 Star:[Simps](https://github.com/simple-swoole/simps) 、[Swoole](https://github.com/swoole/swoole-src) 当然也可以使用 Swoole 来实现一个 MQTT 服务端,Simps 也提供了相应的封装,参考[Simps 文档](https://simps.io/#/zh-cn/mqtt/server) 任何个人或团体,未经允许禁止转载本文:[《基于 Swoole 使用 MQTT 协议连接阿里云物联网平台设备实现消息订阅》](https://qq52o.me/2752.html),谢谢合作!
发布于4年前 · 19 次浏览 · 来自
分享
鲁飞
阿里云物联网平台为设备提供安全可靠的连接通信能力,支撑设备数据采集上云,我们这里认为阿里云物联网平台是 MQTT 服务端,那么我们自己的设备作为客户端,应该如何实现消息订阅? 阿里云没有提供 PHP 的 SDK,而 MQTT 是一个通用协议,我们可以使用 PHP 实现 MQTT 协议解析相关代码,同时也可以使用 Swoole 作为 MQTT 服务端或客户端 [Simps 框架](https://github.com/simple-swoole/simps) 基于 Swoole 的`TCP Server`和`Co\Client`集成了 MQTT 服务端和客户端 这篇文章就以 [Simps 框架](https://github.com/simple-swoole/simps) 作为演示,实现 MQTT 客户端连接阿里云物联网平台设备进行消息订阅 ### 创建产品/设备 使用物联网平台的第一步是在云端创建产品和对应设备,我们需要前往[阿里云物联网平台](https://iot.console.aliyun.com)创建产品和设备,具体操作请[参考文档](https://help.aliyun.com/document_detail/73705.html) 创建完成后分别在产品详情和设备详情中获取设备证书(`ProductKey`、`ProductSecret`、`DeviceName`和`DeviceSecret`),后面连接时需要用到 ### 代码实现 示例代码放在了 GitHub 上:[simps-cloud/aliyun-iot](https://github.com/simps-cloud/aliyun-iot),可以使用 composer 进行安装或者直接使用 git clone 源码 ```shell composer create-project simps-cloud/aliyun-iot git clone git@github.com:simps-cloud/aliyun-iot.git ``` ## 实现说明 下面我们分别来说明一下对应的代码实现,使用 Swoole 作为客户端可以保证我们`recv`到一个完整的 MQTT 包,然后解析对应的数据包即可 ### 配置文件 创建`config/aliyuniot.php`配置文件 `client_id`是 MQTT 建立连接时需要指定的 ClientID,保证全局唯一就可以 将我们刚才获取的设备证书信息,写入到对应的配置文件中 ```php return [ // 连接域名 'host' => "{$YourProductKey}.iot-as-mqtt.{$region}.aliyuncs.com", // 端口默认1883 'port' => 1883, // 心跳 'keepalive' => 300, // clientID 'client_id' => "d812edc1-18da-2085-0edf-a4a588c296d1", 'device_name' => "", 'device_secret' => "", 'product_key' => "", 'product_secret' => "", ]; ``` ### 连接密码 MQTT 建立连接时需要指定的 Password,而这个密码有阿里云的要求:需要把提交给服务器的参数(ProductKey、DeviceName、timestamp 和 clientId)按字典排序并拼接后,使用`hmacsha256`方法和设备的`DeviceSecret`,加签生成 Password > [文档](https://help.aliyun.com/document_detail/73742.html) 中解释了一下 clientId、securemode 等参数,其实是说连接时的参数,而不是 Password 的生成,不要被误导了,实际上只需要关注 content 的值就可以... ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-pwd.png) 而对于的签名算法类型,PHP 可以使用`hash_hmac`函数来实现,所以密码生成可以封装为: ```php /** * @param $config * @param string $signmethod 签名算法类型。支持hmacmd5,hmacsha1和hmacsha256,默认为hmacmd5 */ function signAliIot($config, $signmethod = "hmacmd5") { $sign_config = [ 'clientId' => $config['client_id'], 'productKey' => $config['product_key'], 'deviceName' => $config['device_name'], ]; ksort($sign_config); $data = ""; foreach ($sign_config as $key => $item) { $data .= $key . $item; } switch ($signmethod){ case "hmacmd5": $sign = hash_hmac('md5', $data, $config['device_secret']); break; case "hmacsha1": $sign = hash_hmac('sha1', $data, $config['device_secret']); break; case "hmacsha256": $sign = hash_hmac('sha256', $data, $config['device_secret']); break; } return strtoupper($sign); } ``` > Password 生成没有加时间戳参数,我测试的时候加上时间戳会导致连接失败,返回错误码是 4,username 或 password 格式错误 ### 连接 Password 我们搞定之后就可以开始连接了,参考代码[bin/subscribe.php](https://github.com/simps-cloud/aliyun-iot/blob/master/bin/subscribe.php) 使用`Simps\Client\MQTTClient`进行连接操作 > 我们收到消息时,如果 QoS 是 1,根据 MQTT 协议我们需要回复 ACK,否则它会推送多次 ```php $buffer = $client->recv(); var_dump($buffer); if (is_array($buffer)) { switch ($buffer['cmd']) { case 9: echo "收到订阅确认消息\r\n"; break; case 3: echo "收到订阅消息:{$buffer['content']}\r\n"; // 收到消息如果是qos 1 需要回复 if ($buffer['qos'] === 1) { $client->sendBuffer(['cmd' => MQTT::PUBACK, 'message_id' => $buffer['message_id']], false); // 4 } break; } } ``` 执行命令启动订阅 ```shell php bin/subscribe.php ``` 这个时候我们去访问阿里云控制台中的设备详情,会发现 DeviceName 旁边的`在线`标识 可以测试一下延迟,测试网络延迟时将会向设备发送一条 QoS1 的空消息,会看到网络延迟,表示我们客户端是正常的 ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-1.png) 但这样还不够,如何发送指定消息到客户端呢? 依旧在设备详情中点击`Topic列表`->`自定义 Topic`,就可以看到发布消息的按钮,我们可以点击进入填写发布消息内容并选择对应的 QoS 等级,阿里云暂不支持 QoS2,所以只有 0 和 1 我们来发一个`Hello,Simps.` ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-2.png) Simps 的 MQTTClient 也支持发布功能,这里简单说明一下,执行命令启动并访问一次 ```shell php bin/simps.php http:start curl http://127.0.0.1:9501/ ``` 这里需要查看 [阿里云日志服务](https://iot.console.aliyun.com/lk/monitor/log) ,会看到一条`设备到云消息`的记录,我们查看一下 ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202005/aliyun-iot-3.png) 以上就是基于 Swoole 使用 MQTT 协议进行 TCP 连接通信,支持请前往点个 Star:[Simps](https://github.com/simple-swoole/simps) 、[Swoole](https://github.com/swoole/swoole-src) 当然也可以使用 Swoole 来实现一个 MQTT 服务端,Simps 也提供了相应的封装,参考[Simps 文档](https://simps.io/#/zh-cn/mqtt/server) 任何个人或团体,未经允许禁止转载本文:[《基于 Swoole 使用 MQTT 协议连接阿里云物联网平台设备实现消息订阅》](https://qq52o.me/2752.html),谢谢合作!
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
还没有评论!
微信公众号
热门内容
作者其它话题
- thinkphp5.1在使用think-swoole的时候报错unsupported option [host]
- WSL 下服务器响应数据过大无法接收
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。