本文将介绍设备如何使用 ProductID、DeviceName 和设备密钥生成 MQTT 连接参数,并完成设备身份认证和上线。
功能介绍
设备密钥认证使用平台为每台设备生成的独立设备密钥(DeviceSecret)验证设备身份。设备使用 DeviceSecret 对 MQTT Username 进行 HMAC 签名,并将签名结果组成 Password;平台校验通过后,设备即可上线。
注意:
本文中的 DeviceSecret 也称为 PSK。DeviceSecret 属于敏感凭证,请妥善保管。
认证流程
设备密钥认证流程参见下图:

认证参数
设备身份参数(设备三元组)
参数 | 参数来源 | 说明 | 是否保密 |
ProductID | 产品详情页或设备详情页。 | 标识设备所属产品。 | 否 |
DeviceName | 设备详情页。 | 标识产品下的具体设备。 | 否 |
DeviceSecret | 设备详情页或动态注册。 | 用于生成 MQTT 认证签名。 | 是 |
注意:
ProductSecret 是产品级密钥,主要用于动态注册等产品级操作,不能代替 DeviceSecret 进行设备 MQTT 认证。
MQTT 连接参数
参数 | 取值或生成方式 | 说明 |
Broker Address | 广州: ${ProductID}.iotcloud.tencentdevices.com曼谷: ${ProductID}.ap-bangkok.iothub.tencentdevices.com | MQTT 服务器地址。 |
Broker Port | 1883(通用)8883(TLS+PSK 加密接入) | 密钥认证设备接入端口。 |
Client ID | ${ProductID}${DeviceName} | ProductID 与 DeviceName 直接拼接。 |
Username | ${ClientID};${sdkappid};${connid};${expiry} | 参与设备签名计算。 |
Password | ${token};${签名算法} | 使用 DeviceSecret 生成。 |
KeepAlive | 0~900秒 | MQTT 连接保活时间。 |
${}表示变量,不是实际的拼接字符。连接域名和端口应以设备所属地域及控制台当前信息为准。各扩展字段含义如下:
字段 | 说明 |
sdkappid | 固定填写 12010126。 |
connid | 客户端生成的随机字符串,用于区分连接。 |
expiry | 签名过期时间,使用 Unix 时间戳,单位为秒。 |
token | 使用 DeviceSecret 对完整 Username 进行 HMAC 计算得到的摘要。 |
签名算法 | 支持 hmacsha256或hmacsha1,建议使用hmacsha256。 |
使用 Python 连接平台
本节使用 Python 脚本连接物联网开发平台。当脚本返回认证成功且控制台设备状态显示为在线时,即表示设备密钥认证接入完成。
本示例仅验证设备认证和上线,不包含 Topic 发布、订阅及物模型消息通信。
前提条件
开始接入前,请确认已完成以下准备:
已创建认证方式为密钥认证的产品。
已在产品下创建设备。
已获得设备的 MQTT 连接参数。
本地环境已安装 Python 3。
本地网络能够访问平台 MQTT 接入域名的 1883 端口。
获取设备连接参数
控制台字段 | 脚本配置项 |
MQTT 服务器地址 | Broker Address |
端口号 | Broker Port |
Client ID | Client ID |
Username | Username |
Password | Password |
准备运行环境
建议在虚拟环境中安装依赖和运行代码。
安装 Paho MQTT 客户端:
# Windows PowerShellpython -m pip install "paho-mqtt>=2.1,<3.0"# Linux && macOS Shellpython3 -m pip install "paho-mqtt>=2.1,<3.0"
Paho MQTT 是 Python MQTT 客户端库。本示例使用 MQTT 3.1.1及 Callback API VERSION2。
安装完成后,可执行以下命令确认版本:
# Windows PowerShellpython -m pip show paho-mqtt# Linux && macOS Shellpython3 -m pip show paho-mqtt# 输出中的 Version 应为 2.1.0。
创建连接脚本
将以下代码保存为
mqtt_connect.py:#!/usr/bin/env python3# -*- coding: utf-8 -*-import getpassimport sysfrom importlib.metadata import PackageNotFoundError, versiontry:import paho.mqtt.client as mqttexcept ImportError:mqtt = Nonedef required_input(prompt):"""读取必填参数并清除首尾空格。"""value = input(prompt).strip()if not value:raise ValueError("输入内容不能为空")return valuedef get_port():"""读取并校验MQTT端口号。"""port_text = input("端口号(直接回车使用1883):").strip()if not port_text:return 1883try:port = int(port_text)except ValueError as exc:raise ValueError("端口号必须是整数") from excif not 1 <= port <= 65535:raise ValueError("端口号必须在1~65535范围内")return portdef check_paho_version():"""检查Paho MQTT是否安装且支持Callback API VERSION2。"""install_command = (f'"{sys.executable}" -m pip install "paho-mqtt==2.1.0"')if mqtt is None:raise ImportError("未安装Paho MQTT客户端。\\n"f"请使用当前Python环境执行:\\n{install_command}")try:installed_version = version("paho-mqtt")except PackageNotFoundError:installed_version = "未知"if not hasattr(mqtt, "CallbackAPIVersion"):raise RuntimeError(f"当前Paho MQTT版本为{installed_version},""不支持Callback API VERSION2。\\n"f"请使用当前Python环境执行:\\n{install_command}")print(f"Paho MQTT版本:{installed_version}")def main():check_paho_version()print("\\n请输入设备详情页中的MQTT连接参数。")print("输入内容仅在本次程序运行期间使用,不会保存到文件。\\n")broker = required_input("MQTT服务器地址:")if "://" in broker:raise ValueError("MQTT服务器地址不能包含协议前缀,""请勿输入tcp://或mqtt://")if any(char in broker for char in "${}"):raise ValueError("MQTT服务器地址不能包含${},""请将${ProductID}替换为真实ProductID")port = get_port()client_id = required_input("ClientId:")username = required_input("Username:")# Password输入时不会显示在终端中。password = getpass.getpass("Password(输入内容不会显示):").strip()if not password:raise ValueError("Password不能为空")def on_connect(client,userdata,connect_flags,reason_code,properties,):if reason_code == 0:print("\\n认证成功,设备已连接物联网开发平台。")print(f"MQTT服务器:{broker}")print(f"端口号:{port}")print("请前往控制台查看设备在线状态和上下线日志。")else:print(f"\\nMQTT连接失败,返回码:{reason_code}。""\\n请检查ClientId、Username、Password及设备状态。")client.disconnect()def on_connect_fail(client, userdata):print("\\n网络连接失败,请检查以下内容:"f"\\n- MQTT服务器地址:{broker}"f"\\n- 端口号:{port}""\\n- DNS解析及网络访问状态")def on_disconnect(client,userdata,disconnect_flags,reason_code,properties,):if reason_code != 0:print(f"\\n连接异常断开,返回码:{reason_code}")client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2,client_id=client_id,clean_session=True,protocol=mqtt.MQTTv311,)client.username_pw_set(username=username,password=password,)client.on_connect = on_connectclient.on_connect_fail = on_connect_failclient.on_disconnect = on_disconnect# 不输出Username和Password等认证信息。print("\\n连接配置:")print(f"MQTT服务器:{broker}")print(f"端口号:{port}")print(f"ClientId:{client_id}")print("\\n正在建立MQTT连接。")print("程序将保持连接,按Ctrl+C退出。")client.connect(host=broker,port=port,keepalive=60,)try:client.loop_forever()finally:client.disconnect()if __name__ == "__main__":try:sys.exit(main())except KeyboardInterrupt:print("\\n用户终止连接。")sys.exit(0)except Exception as exc:print(f"\\n运行失败:{exc}")sys.exit(1)
运行连接脚本
执行:
# Windows PowerShellpython mqtt_connect.py# Linux && macOS Shellpython3 mqtt_connect.py
# 运行成功后依次输入MQTT服务器地址:端口号(直接回车使用1883):ClientId:Username:Password(输入内容不会显示):
连接成功时,程序输出类似:
正在连接:******.iotcloud.tencentdevices.com:1883ClientId:******程序将保持连接,按Ctrl+C退出。认证成功,设备已连接物联网开发平台。请前往控制台查看设备在线状态。
程序会持续运行并保持 MQTT 连接。需要断开连接时,按下
Ctrl+C。验证设备上线
问题排查
网络连接失败
检查以下内容:
Broker Address 是否与设备详情页一致。
端口号是否正确。
本地 DNS 是否能够解析 MQTT 服务器域名。
防火墙或网络策略是否限制目标域名和端口。
相关域名是否已加入白名单。
认证失败
检查以下内容:
ClientId、Username 和 Password 是否属于同一设备。
复制参数时是否包含多余空格或换行。
Username 中的 expiry 是否已过期。
是否使用了重新生成前的旧连接参数。
Broker 中的 ProductID 是否与设备所属产品一致。
出现 HMAC sign error
如果连接参数由设备自主生成,请检查:
ProductID 和 DeviceName 是否正确。
DeviceSecret 是否属于当前设备。
DeviceSecret 是否完成 Base64解码。
参与签名的 Username 是否与连接时使用的 Username 完全一致。
HMAC 算法是否与 Password 中的算法名称一致。
expiry 是否晚于当前设备时间。
脚本连接成功,但设备未显示在线
检查:
是否进入了正确的实例和设备。
ClientId 是否对应当前 DeviceName。
脚本是否仍在运行。
上下线日志中是否存在新的连接记录。
是否有另一个客户端使用相同 ClientId 建立连接。