背景信息
随着物联网领域企业的业务规模逐渐扩大、终端设备不断增多,自建MQTT集群水平扩展和持续运维的成本越来越高,急需寻找一个高可靠、高安全、低成本、免运维的物联网全托管服务,同时保证已经在全国各地铺货的存量设备零改造,实现MQTT服务的迁移。
阿里云物联网平台推出的云网关完美解决了企业设备规模壮大后遇到的稳定性和可扩展性瓶颈,迁移过程设备端无需改动,仅调整MQTT域名指向阿里云IoT实例创建的云网关域名即可。
使用限制
- 设备接入地址是域名,且用户有对域名CNAME重定向的权限。 
- MQTT协议KeepAlive的时间范围是30s~1200s。 
步骤一:设备接入
- 购买阿里云物联网平台的尊享型企业版实例。 
- 创建云网关产品。设备接入云网关有两种认证方式: 说明- 本示例使用Ubuntu操作系统。 - (推荐)一方认证- 用户上传设备认证信息(username、password),由物联网平台完成验证。 - 生成和保存证书。 - 登录Ubuntu操作系统。 
- 执行以下命令生成设备端和服务端的根证书文件 - root-ca.crt。- openssl req \ -new \ -newkey rsa:2048 \ -days 365 \ -nodes \ -x509 \ -subj "/C=CN/O=Aliyun IOT/CN=IoT CA" \ -keyout root-ca.key \ -out root-ca.crt
- 根据根证书文件 - root-ca.crt,自定义服务端证书。- 执行以下命令生成服务端密钥文件 - server.key。- openssl genrsa -out server.key 2048
- 执行命令 - touch openssl.cnf新建文件- openssl.cnf。
- 执行命令 - vi openssl.cnf进入文件,填入以下内容后按Esc键,输入- :wq保存。- [policy_match] countryName = cn stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [req] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_req prompt = no [req_distinguished_name] commonName = Server [req_ext] subjectAltName = @alt_names [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = *.mqtt.iothub.aliyuncs.com DNS.2 = *.igw.iothub.aliyuncs.com
- 执行以下命令生成服务端请求文件 - server.csr。- openssl req -new -key server.key -config openssl.cnf -out server.csr
- 执行以下命令生成服务端证书文件 - server.crt。- openssl x509 -req -days 365 -sha256 -in server.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out server.crt -extensions v3_req -extfile openssl.cnf
- 执行以下命令验证服务端证书。 - openssl verify -CAfile root-ca.crt server.crt
 
 
- 返回物联网平台控制台,单击目标企业版实例的卡片,在左侧导航栏,选择设备管理>云网关。按照下图配置参数,更多参数说明请参见创建云网关产品(MQTT)。  
- 配置证书。 - 选择证书配置方式为手动输入。 
- 配置服务端证书为生成的 - server.crt文件,服务端证书私钥为生成的- server.key文件。
 
 - 三方认证- 物联网平台转发(HTTPS请求)设备认证信息(Username、Password、Clientid),由用户完成认证。如果设备的Username和Password相同,只有Clientid不同,此时适合使用三方认证。 - 您可以选择阿里云函数计算或外部HTTPS,作为三方认证的调用方式。本示例采用函数计算FC作为三方认证调用方式。函数计算的更多信息,请参见快速创建函数。 - 登录函数计算控制台, 
- 创建服务。 - 在顶部菜单栏,选择地域,然后在服务列表页面,单击创建服务。 
- 在左侧导航栏,单击服务及函数。配置名称、描述等信息,然后单击确定。 
 
- 创建函数。 - 在顶部菜单栏,选择地域,然后在服务列表页面,单击目标服务。 
- 在函数管理页面,单击创建函数。按下图配置参数,然后单击确定。  
 
- 编写处理函数脚本。以下脚本解析HTTPS请求body中的username,并将username当作deviceName返回。根据实际使用场景,也可以将clientid作为deviceName返回。 - var getRawBody = require('raw-body'); var body = require('body'); exports.handler = (req, resp, context) => { getRawBody(req, function(err, body) { var resp_body = {}; var recv_body = JSON.parse(body.toString()); console.log(JSON.stringify(recv_body)); resp_body.deviceName = recv_body["username"]; resp.send(JSON.stringify(resp_body, null, ' ')); }); }
- 拷贝函数的公网访问地址,作为物联网平台云网关产品的设备认证HTTPS URL。  
 
- 生成和保存证书。 - 登录Ubuntu操作系统。 
- 执行以下命令生成设备端和服务端的根证书文件 - root-ca.crt。- openssl req \ -new \ -newkey rsa:2048 \ -days 365 \ -nodes \ -x509 \ -subj "/C=CN/O=Aliyun IOT/CN=IoT CA" \ -keyout root-ca.key \ -out root-ca.crt
- 根据根证书文件 - root-ca.crt,自定义服务端证书。- 执行以下命令生成服务端密钥文件 - server.key。- openssl genrsa -out server.key 2048
- 执行命令 - touch openssl.cnf新建文件- openssl.cnf。
- 执行命令 - vi openssl.cnf进入文件,填入以下内容后按Esc键,输入- :wq保存。- [policy_match] countryName = cn stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [req] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_req prompt = no [req_distinguished_name] commonName = Server [req_ext] subjectAltName = @alt_names [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = *.mqtt.iothub.aliyuncs.com DNS.2 = *.igw.iothub.aliyuncs.com
- 执行以下命令生成服务端请求文件 - server.csr。- openssl req -new -key server.key -config openssl.cnf -out server.csr
- 执行以下命令生成服务端证书文件 - server.crt。- openssl x509 -req -days 365 -sha256 -in server.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out server.crt -extensions v3_req -extfile openssl.cnf
- 执行以下命令验证服务端证书。 - openssl verify -CAfile root-ca.crt server.crt
 
- 单击目标企业版实例的卡片,在左侧导航栏,选择设备管理>云网关。配置如下参数,更多参数说明,请参见创建云网关产品(MQTT)。 - 协议为MQTT。 
- 认证类型为三方认证。 
- 三方认证调用方式为函数计算FC。 
 
- 配置证书。 - 选择证书配置方式为手动输入。 
- 配置服务端证书为生成的 - server.crt文件,服务端证书私钥为生成的- server.key文件。
 
 
 
- 注册设备认证信息。 - 一方认证- 上传设备信息。 - 登录物联网平台控制台。 
- 在实例概览页面,单击目标尊享型实例。 
- 在左侧导航栏选择,找到已创建的云网关产品,单击右侧操作栏的管理设备。 
- 在设备页面,单击批量添加。  
- 在批量添加设备对话框,单击下载.csv模板下载表格模板。  
- 在模板中填写SN、MQTT Username和MQTT Password,然后保存文件。 重要- MQTT Username和MQTT Password必填,SN可不填。 
- MQTT Username支持英文字母、数字、短划线(-)、下划线(_)、at(@)、英文句号(.)和英文冒号(:),长度限制为4~32个字符。MQTT Username在产品维度下不可重复。 
- MQTT Password 支持英文字母、数字、短划线(-)、下划线(_)、at(@)、英文句号(.)和英文冒号(:),长度限制为1~32个字符。 
- 一个文件中最多可包含1万条设备记录。请不要导入重复的设备。 
  
- 回到批量添加设备对话框,单击上传文件,将填好的表格上传至物联网平台控制台,单击确认。  - 若批量上传的设备列表中有不合法的输入信息,将出现错误提示。请单击下载不合法列表,查看不合法的输入信息,并进行修正,再重新上传文件。  
 
 - 三方认证- 三方认证方式不需要提前上传设备信息,物联网平台会在设备建连三方认证成功后,创建设备。 
步骤二:应用开发
用户的业务服务器,可以通过物联网平台服务端订阅能力实现设备上报消息的实时订阅。也可以通过物联网平台提供的API对设备进行下行控制。
服务端订阅设备消息
设备连接物联网平台后,数据直接上报至物联网平台,平台上的数据可以通过AMQP通道流转至您的服务器。本文为您介绍通过配置AMQP服务端订阅,实现企业服务器通过接入AMQP客户端,接收车辆设备数据的完整流程。
- 为消息消费端配置消费组身份,用于企业服务器通过消费组获取转发的消息。 - 在左侧导航栏,选择消息转发>服务端订阅。 
- 单击消费组列表页签,单击创建消费组。 
- 在创建消费组对话框中,设置消费组名称为车辆数据,单击确认。 
- 在创建消费组对话框中,设置消费组名称为车机,单击确认。创建消费组成功后,跳转到消费组详情页面,查看消费组ID。复制并保存消费组ID值,用于AMQP客户端接入。 
 
- 为目标云网关产品配置服务端订阅,用于您的服务器直接订阅产品下多种类型的消息。 - 在左侧导航栏,选择消息转发>服务端订阅。 
- 在服务端订阅页面的订阅列表页签下,单击创建订阅。 
- 在创建订阅对话框,按下图配置参数后,单击确认。推送消息类型默认配置为设备上报消息、设备状态变化通知。更多消息类型,请参见配置AMQP服务端订阅。  
 
- 在Ubuntu系统执行以下命令,下载AMQP服务端订阅的Demo文件。 说明- 本步骤的AMQP Demo文件使用Java语言。 - wget https://linkkit-export.oss-cn-shanghai.aliyuncs.com/quick_deploy/amqp-demo.zip
- 执行以下命令,解压文件。 - unzip amqp-demo.zip
- 在 - amqp-demo/src/main/java/com/aliyun/iotx/demo/AmqpClient.java文件中,参照下表,修改JMS客户端接入物联网平台代码中的参数值。说明- 文件中添加了结束程序的代码 - (Thread.sleep(60 * 1000);),即程序启动成功,运行一分钟后会结束。实际场景中,您可根据业务需求自行设置程序启动逻辑。- 参数 - 示例 - 说明 - accessKey - LTAI************************** - 登录物联网平台控制台,将鼠标移至账号头像上,然后单击AccessKey管理,获取AccessKey ID和AccessKey Secret。 - accessSecret - yourAccessKeySecret - iotInstanceId - iot-cn-6ja*** - 实例ID。您可在控制台的实例概览页面查看。 - productKey - k00p**** - 产品key,可以通过设备管理>设备详情页查看 - deviceName - de*** - 设备name,可以通过设备管理>设备详情页查看 - consumerGroupId - VWhGZ2QnP7kxWpeSSjt****** - 已创建的车辆数据消费组ID。 - clientId - 12345 - 客户端ID,可自定义,长度不可超过64个字符。建议设置为您的AMQP客户端所在服务器UUID、MAC地址、IP等唯一标识,方便您识别区分不同的客户端。AMQP客户端接入成功后,在控制台的车辆数据的消费组详情页面,显示该参数。 - connectionCount - 4 - 启动AMQP客户端的连接数,最大不超过64个。用于实时消息推送的扩容。消费组详情页面会以${clientId}+"-"+数字形式,显示连接的客户端。其中数字最小值为0。 - host - iot-***.amqp.iothub.aliyuncs.com - AMQP接入域名。您可在控制台中实例的实例详情页面,单击查看开发配置,单击AMQP页签查看。 
- 在 - pom.xml文件中,已添加相关Maven依赖。在- amqp-demo根目录执行以下命令,重新加载Maven变更,构建项目。在- amqp-demo/target目录下生成可部署的JAR包。- mvn clean package
- 在 - amqp-demo/target目录执行以下命令,运行生成的JAR包。- java -jar demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar
- 返回类似如下日志信息,表示AMQP客户端已接入物联网平台并成功接收消息。  
云端下发消息给设备
设备连接到物联网平台后,您可以通过物联网平台提供的云端API向设备发送指令。
本步骤基于Java SDK使用说明,调用Pub接口通过自定义Topic向设备发布消息。
- 在服务端订阅设备消息时下载的 - amqp-demo/src/main/java/com/aliyun/iotx/demo/AmqpClient.java文件中:- 在文件开头添加以下依赖。 - import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.iot.model.v20180120.PubRequest; import com.aliyuncs.iot.model.v20180120.PubResponse; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile;
- 在 - processMessage方法中添加以下代码块。- try { DefaultProfile.addEndpoint("cn-shanghai", "cn-shanghai", "Iot", "iot.cn-shanghai.aliyuncs.com"); } catch (Exception e) { System.out.println("DefaultProfile exception"); } IClientProfile profile = DefaultProfile.getProfile("cn-shanghai", "${accessKey}", "${accessSecret}"); DefaultAcsClient defaultAcsClient = new DefaultAcsClient(profile); PubRequest pubRequest = new PubRequest(); pubRequest.setIotInstanceId("${instanceId}"); pubRequest.setProductKey("${productKey}"); // 要发送的消息主体。您需要将消息原文转换成二进制数据,并进行Base64编码,从而生成消息主体。注意您的设备收到的会是Base64解码后的数据。 pubRequest.setMessageContent("eyJ0ZXN0IjoidGFzayBwdWIgYnJvYWRjYXN0In0="); // 发送给设备的topic,您可以自定义 pubRequest.setTopicFullName("/${productKey}/${deviceName}/user/get"); PubResponse response = null; try { response = defaultAcsClient.getAcsResponse(pubRequest); } catch (Exception e) { logger.error("执行失败:e:" + e.getMessage()); }- 参数 - 示例 - 说明 - accessKey - LTAI************************** - 登录物联网平台控制台,将鼠标移至账号头像上,然后单击AccessKey管理,获取AccessKey ID和AccessKey Secret。 - accessSecret - ****** - InstanceId - iot-cn-6ja*** - 实例ID。您可在控制台的实例概览页面查看。 - productKey - k00p**** - 产品key,可以通过设备管理>设备详情页查看。 - deviceName - device1 - 设备名称,可以通过设备管理>设备详情页查看。 
 
- 在 - amqp-demo根目录执行以下命令,重新加载Maven变更,构建项目。在- amqp-demo/target目录下生成可部署的JAR包。- mvn clean package
- 在 - amqp-demo/target目录执行以下命令,运行上一步骤生成的JAR文件。- java -jar demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar
步骤三:存量设备迁移
- 更新设备的接入域名。 - 创建云网关设备完成后,需更新设备的接入域名: 
- 若设备已配置接入域名,可配置CNAME解析到云网关连接域名(云网关URL)。域名解析详细操作,请参见云解析DNS。 
- 若设备未配置接入域名,需将云网关URL配置到设备中。更多信息,请参见MQTT协议的设备接入。 
 
- 云网关URL获取方法,请参见查看云网关URL。 
 
- 将设备接入物联网平台。 - 在Ubuntu系统执行以下命令,安装GCC和Make。 - sudo apt-get install gcc make
- 执行以下命令,获取Demo文件。 - wget https://linkkit-export.oss-cn-shanghai.aliyuncs.com/quick_deploy/LinkSDKdemo.zip
- 执行以下命令,解压Demo文件。 - unzip LinkSDKdemo.zip
- 打开 - ./LinkSDKdemo/demos/mqtt_x509_auth_demo.c文件,配置如下参数。- 参数 - 说明 - 示例值 - client_cert - 在步骤一配置自定义证书时生成 - client.crt、- client.key和- root-ca.crt。
- 依次在命令行执行以下命令,并将输出结果填入这三个参数。 - sed 's/^/\"/g;s/$/\\r\\n\" \\/g' client.crt
- sed 's/^/\"/g;s/$/\\r\\n\" \\/g' client.key
- sed 's/^/\"/g;s/$/\\r\\n\" \\/g' root-ca.crt
 
 - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIICx*****JD\r\n" \ - ... - "Hb4id*******VKsg==\r\n" \ - "-----END CERTIFICATE-----\r\n" - client_private_key - "-----BEGIN RSA PRIVATE KEY-----\r\n" \ - "MIIE***********************uDR\r\n" \ - … - "qws************************fEPh\r\n" \ - "-----END RSA PRIVATE KEY-----\r\n" - server_root_ca - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIC4j********EwJD\r\n" \ - ... - "OTEx********AoM\r\n" \ - "-----END CERTIFICATE-----" - MQTT_HOST - 云网关URL和云网关端口。 
- 在左侧导航栏,选择设备管理> 云网关。 
 - iot-0******t-0****E.igw.iothub.aliyuncs.com - MQTT_PORT - 1883 - USER_NAME - 设备的MQTT UserName、设备的MQTT PassWord、设备的Product Key。 
- 在左侧导航栏,选择设备管理> 设备。单击目标设备的DeviceName/备注名称,在页面上方查看。 
 - Dev********01 - PASSWORD - devp********01 - PRODUCT_KEY - g1********p 
- 在Link SDK根目录下。执行 - make命令编译,生成的可执行文件为- ./output/mqtt-x509-auth-demo。
- 在Link SDK根目录下,执行以下命令,运行可执行文件。 - ./output/mqtt-x509-auth-demo- 在设备端查看运行结果。 - [1691724132.669][LK-0313] MQTT user calls aiot_mqtt_connect api, connect establish tcp connection with server(host='iot-0*****t-02****E.igw.iothub.aliyuncs.com', port=[1883]) success to establish tcp, fd=5 local port: 63275 [1691724132.696][LK-1000] establish mbedtls connection with server(host='iot-0*****t-02****E.igw.iothub.aliyuncs.com', port=[1883]) [1691724132.780][LK-1000] success to establish mbedtls connection, (cost 45366 bytes in total, max used 52318 bytes) [1691724132.827][LK-0313] MQTT connect success in 158 ms AIOT_MQTTEVT_CONNECT [1691724132.827][LK-0309] sub: /k00***/Device001URN001/user/get [1691724132.828][LK-0309] pub: /k00****/Device001URN001/user/update [LK-030A] > 68 65 6C 6C 6F 20 77 6F 72 6C 64 21 | hello world!
 
- 设备连接成功后。 - 在左侧导航栏,选择设备管理>设备,查看设备状态。  
- 在左侧导航栏,选择监控运维>日志服务,查看设备上报的消息及日志。  
 
相关链接
- 云网关设备接入物联网平台实现通信的详细说明,请参见消息通信说明。 
- 您可使用MQTT.fx工具模拟云网关设备接入物联网平台进行通信。具体操作,请参见设备使用MQTT.fx接入(一方认证)。