【Python】使用Python模拟设备接入阿里云物联网的MQTT服务器

来源:互联网 发布:java软件工程师前景 编辑:程序博客网 时间:2024/06/16 11:30

前言

由于阿里云物联网套件关于设备认证的文档不够详细,笔者差不多摸索了几天才连接上MQTT。下面是使用Python模拟设备接入阿里云的MQTT。

概述

阿里云物联网套件提供两种接入方式:

  1. MQTT客户端域名直连(资源受限设备推荐)
  2. 先HTTPS发送授权后再连接MQTT(一些特殊增值服务,比如设备级别的引流)

本文主要介绍第一种接入方式,TCP直连,并提供Python代码示例。

主要参数

连接域名

<ProductKey>.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883

MQTT Connect报文参数

1、mqttClientId

mqttClientId = "<ClientId>"+"|securemode=3,signmethod=hmacsha1,timestamp=132323232|"

2、mqttUsername

使用&拼接<DeviceName><ProductKey>

mqttUsername = "<DeviceName>&<ProductKey>"

3、mqttPassword

把以下参数按字典键名排序,再把键名都拼接起来(没有分隔符)生成content,然后以DeviceSecret为盐,对content进行hma_sha1加密,最后二进制转为十六进制字符串表示。

  • clientId
  • deviceName
  • productKey
  • timestamp
mqttPassword = hmac_sha1(DeviceSecret, content).toHexString();

示例

假设

  • clientId = 12345
  • deviceName = device
  • productKey = pk
  • timestamp = 789
  • signmethod = hmacsha1

content拼接结果:clientId12345deviceNamedeviceproductKeypktimestamp789

注意:不用拼接signmethod参数。

对content以DeviceSecret为盐进行hmacsha1加签后,再转为十六进制字符串,最后结果:FAFD82A3D602B37FB0FA8B7892F24A477F851A14

注意:不需要base64。

最后总结一下生成的参数:

  • mqttHost = "pk.iot-as-mqtt.cn-shanghai.aliyuncs.com"
  • mqttPort = 1883
  • mqttClientId = "12345|securemode=3,signmethod=hmacsha1,timestamp=789|"
  • mqttUsername = "device&pk"
  • mqttPassword = "FAFD82A3D602B37FB0FA8B7892F24A477F851A14"

参数说明

参数 描述 ProductKey 产品Key。从iot套件控制台获取 DeviceName 设备名称。从iot套件控制台获取 DeviceSecret 设备密码,从iot套件控制台获取 signmethod 算法类型,hmacmd5hmacsha1 clientId 客户端自表示id,建议mac或sn timestamp 当前时间毫秒值,可选 securemode 目前安全模式,可选值有2(TLS直连模式)、3(TCP直连模式)

示例代码

填写自己的ProductKeyClientIdDeviceNameDeviceSecret

#!/usr/bin/python3# coding=utf-8import datetimeimport timeimport hmacimport hashlibimport math# 测试加密开关,不进行连接TEST = 0ProductKey = ""ClientId = "12345"  # 自定义clientIdDeviceName = ""DeviceSecret = ""# signmethodsignmethod = "hmacsha1"# signmethod = "hmacmd5"# 当前时间毫秒值us = math.modf(time.time())[0]ms = int(round(us * 1000))timestamp = str(ms)data = "".join(("clientId", ClientId, "deviceName", DeviceName,                "productKey", ProductKey, "timestamp", timestamp                ))# print(round((time.time() * 1000)))print("data:", data)if "hmacsha1" == signmethod:    ret = hmac.new(bytes(DeviceSecret, encoding="utf-8"),                   bytes(data, encoding="utf-8"),                   hashlib.sha1).hexdigest()elif "hmacmd5" == signmethod:    ret = hmac.new(bytes(DeviceSecret, encoding="utf-8"),                   bytes(data, encoding="utf-8"),                   hashlib.md5).hexdigest()else:    raise ValueErrorsign = retprint("sign:", sign)# ======================================================strBroker = ProductKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com"port = 1883client_id = "".join((ClientId,                     "|securemode=3",                     ",signmethod=", signmethod,                     ",timestamp=", timestamp,                     "|"))username = "".join((DeviceName, "&", ProductKey))password = signprint("="*30)print("client_id:", client_id)print("username:", username)print("password:", password)print("="*30)def secret_test():    DeviceSecret = "secret"    data = "clientId12345deviceNamedeviceproductKeypktimestamp789"    ret = hmac.new(bytes(DeviceSecret, encoding="utf-8"),                   bytes(data, encoding="utf-8"),                   hashlib.sha1).hexdigest()    print("test:", ret)# ======================================================# MQTT Initialize.--------------------------------------try:    import paho.mqtt.client as mqttexcept ImportError:    print("MQTT client not find. Please install as follow:")    print("pip install paho-mqtt")# ======================================================def on_connect(mqttc, obj, rc):    print("OnConnetc, rc: " + str(rc))    mqttc.subscribe("test", 0)def on_publish(mqttc, obj, mid):    print("OnPublish, mid: " + str(mid))def on_subscribe(mqttc, obj, mid, granted_qos):    print("Subscribed: " + str(mid) + " " + str(granted_qos))def on_log(mqttc, obj, level, string):    print("Log:" + string)def on_message(mqttc, obj, msg):    curtime = datetime.datetime.now()    strcurtime = curtime.strftime("%Y-%m-%d %H:%M:%S")    print(strcurtime + ": " + msg.topic + " " + str(msg.qos) + " " + str(msg.payload))    on_exec(str(msg.payload))def on_exec(strcmd):    print("Exec:", strcmd)    strExec = strcmd# =====================================================if __name__ == '__main__':    if TEST:        secret_test()        exit(0)    mqttc = mqtt.Client(client_id)    mqttc.username_pw_set(username, password)    mqttc.on_message = on_message    mqttc.on_connect = on_connect    mqttc.on_publish = on_publish    mqttc.on_subscribe = on_subscribe    mqttc.on_log = on_log    mqttc.connect(strBroker, port, 120)    mqttc.loop_forever()

参考资料

  • 阿里云物联网套件 > 设备端接入手册 > 设备基于MQTT接入 > 设备认证

终于知道之前为什么总是连接不上了!!!是因为之前官方文档对password加密的字段多了「signmethodhmacsha1」字符串!

阅读全文
0 0