一、前言

本文介绍如何使用AT指令MQTT接入阿里云物联网平台,包括一机一密、一型一密两种方式。上车前我们先阅读以下几个文档:


  • AT+MQTT 指令使用
  • MQTT-TCP连接通信
  • 基于MQTT通道的设备动态注册
二、一机一密接入

一机一密认证方法,即为每个设备烧录其唯一的设备证书(ProductKey、DeviceName和DeviceSecret),对安全性要求较高的应优先考虑使用一机一密认证方法接入。
1.创建设备
我们进入阿里物联网平台创建一个产品,创建方法
这里我用模组的MAC地址作为deviceName创建一个设备,三元组为:

[color=rgba(0, 0, 0, 0.75)]DeviceNameProductKeyDeviceSecret
c82b968ebe5ca1gh70UicfDa566b66936eafac4c8fe75316069ba11

通过阅读阿里云文档 MQTT-TCP连接通信得知,我们需要通过MQTT接入需要得到以下几个参数:


  • 接入域名和端口
    公共实例的接入域名:${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com,端口固定为1883
    其中:

  • ${YourProductKey}:请替换为设备所属产品的ProductKey。可登录物联网平台控制台,在对应实例的设备详情页获取。
  • ${YourRegionId}:请参见地域和可用区
    这里我们ProductKey为a1gh70UicfD,地区我选择shanghai,所以我们接入域名为:
    a1gh70UicfD.iot-as-mqtt.cn-shanghai.aliyuncs.com

  • mqttClientId
    mqttClientId由客户端ID(clientId)、安全模式(securemode)、签名算法类型(signmethod)和时间戳(timestamp)拼接而成。
    这里我选择设备MAC地址作为clientId,安全模式选择3(TCP直连模式),签名算法选择hmacmd5,不选时间戳。则得到mqttClientId为:
    c82b968ebe5c|securemode=3,signmethod=hmacmd5|
  • 用户名mqttUsername
    mqttUsername由deviceName和productKey拼接成,由我的三元组可得到mqttUsername为:
    c82b968ebe5c&a1gh70UicfD
  • 密码mqttPassword
    计算方法:sign_hmac(DeviceSecret,content)
    sign_hmac为签名算法,这里我选择hmacmd5;
    DeviceSecret即为三元组中的DeviceSecret;
    content为clientId、deviceName、ProductKey 的拼接:clientIdc82b968ebe5cdeviceNamec82b968ebe5cproductKeya1gh70UicfD 。
    即对clientIdc82b968ebe5cdeviceNamec82b968ebe5cproductKeya1gh70UicfD进行hmacmd5加密,加密密钥为a566b66936eafac4c8fe75316069ba11,加密结果我们可以用在线工具获得mqttPassword为
    7cbf1bf3f2e5cfe950f9c8391253700b

hmacmd5算法也可以用C语言方法实现:HmacMD5算法

到这里我们就已经得到了一机一密所需要的所有连接参数,下面我们用AT指令来实战一下:

AT+CWMODE=1
  • AT+CWJAP="TP-LINK_B741","cc123456789"
  • AT+MQTTUSERCFG=0,1,"","","",0,0,""
  • AT+MQTTUSERNAME=0,"c82b968ebe5c&a1gh70UicfD"
  • AT+MQTTPASSWORD=0,"7cbf1bf3f2e5cfe950f9c8391253700b"
  • AT+MQTTCLIENTID=0,"c82b968ebe5c|securemode=3\,signmethod=hmacmd5|"
  • AT+MQTTCONN=0,"a1gh70UicfD.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883,1
  • //注意Topic中的ProductKey和DeviceName应根据自己的三元组替换
  • AT+MQTTSUB=0,"/a1gh70UicfD/c82b968ebe5c/user/get",1  
  • AT+MQTTPUB=0,"/sys/a1gh70UicfD/c82b968ebe5c/thing/event/property/post","{"method":"thing.event.property.post"\,"id":"198370833"\,"params":{"powerstate":0}\,"version":"1.0.0"}",1,0  
  • 复制代码

    正常交互 LOG 如下:
    阿里云平台接收到模组发布的消息日志如下

    三、一型一密接入

    阅读本章节前请务必先理解前文【二、一机一密接入】。一型一密认证方式下,同一产品下所有设备只需烧录相同的产品证书(ProductKey和ProductSecret)。设备发送激活请求时,物联网平台进行身份确认,认证通过,下发设备接入所需信息。一型一密较一机一密而言,安全性没有一机一密高,但无需为每台设备都烧录不同的三元组,方便生产。
    一型一密认证接入,首先我们需要开启动态注册
    我再用另一个模组的MAC地址作为deviceName创建一个设备

    [color=rgba(0, 0, 0, 0.75)]ProductKeyProductSecretDeviceName
    a1gh70UicfDXTQ7IYbKMXnbDuQH30aea41fcbb8

    注意区分ProductSecret和DeviceSecret,不要复制错

    通过阅读阿里云文档基于MQTT通道的设备动态注册得知,我们动态注册请求需要获取以下参数(均以公共实例为例):


    • 接入域名和端口
      和一机一密一样,接入端口为1883,接入域名为
      a1gh70UicfD.iot-as-mqtt.cn-shanghai.aliyuncs.com
    • mqttClientId
      mqttClientId的拼接参数为
      clientId+"|securemode=2,authType=xxxx,random=xxxx,signmethod=xxxx|"
      其中:
      clientId我使用模组MAC地址30aea41fcbb8 ;
      securemode取固定值2;
      authType:选择一型一密预注册认证方式,值为register
      random:随机数12345
      signmethod:签名算法选择hmacmd5
      即得到mqttClientId为:
      30aea41fcbb8|securemode=2,authType=register,random=12345,signmethod=hmacmd5|
    • mqttUserName
      mqttUsername由deviceName和productKey拼接成,由我的三元组可得到mqttUsername为:
      30aea41fcbb8&a1gh70UicfD
    • mqttPassword:
      计算方法:sign_hmac(productSecret,content)
      sign_hmac为签名算法,这里我选择hmacmd5;
      productSecret即为三元组中的productSecret;
      content为deviceName、productKey、random的拼接:
      deviceName30aea41fcbb8productKeya1gh70UicfDrandom12345
      即对deviceName30aea41fcbb8productKeya1gh70UicfDrandom12345进行hmacmd5加密,加密密钥为XTQ7IYbKMXnbDuQH,加密结果我们可以用在线工具获得mqttPassword为:
      a66c7f87c3c931b12869fe664b470e0e
      hmacmd5算法也可以用C语言方法实现:HmacMD5算法

      动态注册成功返回三元组deviceSecret,productKey,deviceName,接下来我们需要先断开mqtt连接,用返回的三元组重新发起mqtt连接。重新发起的mqtt连接方法步骤和一机一密一模一样,我们按照一机一密的方法得到:
      mqttClientId:12345|securemode=3,signmethod=hmacmd5|
      mqttUserName:30aea41fcbb8&a1gh70UicfD
      mqttPassword:d48294fe16f5904a70691167a54f8d45
      整个AT指令流程为:
    AT+CWMODE=1
  • AT+CWJAP=“AIOT@FAE”,“fae12345678”
  • AT+MQTTUSERCFG=0,2,"","","",0,0,"" //动态注册只支持使用TLS建立连接,不支持TCP直连
  • AT+CIPSTAMAC?
  • AT+MQTTUSERNAME=0,“30aea41fcbb8&a1gh70UicfD”
  • AT+MQTTPASSWORD=0,“a66c7f87c3c931b12869fe664b470e0e”
  • AT+MQTTCLIENTID=0,“30aea41fcbb8|securemode=2,authType=register,random=12345,signmethod=hmacmd5|”
  • AT+MQTTCONN=0,“a1gh70UicfD.iot-as-mqtt.cn-shanghai.aliyuncs.com”,1883,1
  • AT+MQTTCLEAN=0
  • AT+MQTTUSERCFG=0,1,"","","",0,0,""
  • AT+MQTTUSERNAME=0,“30aea41fcbb8&a1gh70UicfD”
  • AT+MQTTPASSWORD=0,“d48294fe16f5904a70691167a54f8d45”
  • AT+MQTTCLIENTID=0,“12345|securemode=3,signmethod=hmacmd5|”
  • AT+MQTTCONN=0,“a1gh70UicfD.iot-as-mqtt.cn-shanghai.aliyuncs.com”,1883,1
  • AT+MQTTSUB=0,"/sys/a1gh70UicfD/30aea41fcbb8/thing/service/property/set",1
  • AT+MQTTPUB=0,"/sys/a1gh70UicfD/30aea41fcbb8/thing/event/property/post","{“method”:“thing.event.property.post”,“id”:“198370833”,“params”:{“LightStatus”:0},“version”:“1.0.0”}",1,0
  • 复制代码

    正常交互 LOG 如下:

    这样我们就已经连上了。量产的时候可把模组的mac地址表格上传到阿里物联网平台的方式添加设备。具体细节可在阿里云开工单咨询。

    四、订阅&发布

    通过查询我的阿里云后台,物模型通信 Topic 列表如下图所示

    这里我仅以属性的设置和上报为例。

    4.1 订阅

    设备要接收来自云端下发的属性设置,则应订阅topic:/sys/a1gh70UicfD/30aea41fcbb8/thing/service/property/set

    AT+MQTTSUB=0,"/sys/a1gh70UicfD/30aea41fcbb8/thing/service/property/set",1  
  • //注意topic里面的ProductKey、DeviceName应根据自己的三元组替换掉
  • 复制代码


    订阅成功之后我们在阿里云后台下发一个属性设置给模组


    我的模组成功收到了云端下发的属性设置

    4.2 发布

    设备属性上报,topic应为/sys/a1gh70UicfD/30aea41fcbb8/thing/event/property/post,假如我需要上报工作状态(LightStatus)为0,则指令为

    AT+MQTTPUB=0,"/sys/a1gh70UicfD/30aea41fcbb8/thing/event/property/post","{"method":"thing.event.property.post"\,"id":"123"\,"params":{"LightStatus":0}\,"version":"1.0.0"}",1,0
  • //注意topic里面的ProductKey、DeviceName应根据自己的三元组替换掉
  • 复制代码

    查一下设备日志,可以看到云端已经收到了


    设置实时刷新后,后台的工作状态实时显示为我上报的状态

    五、总结

    一机一密安全性更高、一型一密更方便生产,具体选用哪种方式,需按照实际应用场景而定。