登录 物联网通信控制台。您可在控制台创建产品、添加设备、并获取设备密钥。
按照物联网通信约束生成 username 字段,username 字段格式如下:
username字段的格式为: p r o d u c t i d {productid} productid{devicename}; s d k a p p i d ; {sdkappid}; sdkappid;{connid}; e x p i r y 注 意 : {expiry} 注意: expiry注意:{}表示变量,并非特定的拼接符号。
其中各字段含义如下:
productid:产品 ID。
devicename: 设备名称。
sdkappid:固定填12010126。
connid :一个随机字符串。
过期时间 :表示签名的有效期, 从1970年1月1日00:00:00 UTC 时间至今秒数的 UTF8 字符串。
用 base64 对设备私钥进行解码得到原始密钥 raw_key。
用第3步生成的 raw_key,通过 HMAC-SHA1 或者 HMAC-SHA256 算法对 username 生成一串摘要,简称 token。
按照物联网通信约束生成 password 字段,password 字段格式为:
password字段格式为: ${token};hmac签名方法
其中hmac签名方法字段填写第三步用到的摘要算法,可选的值有 hmacsha256 和 hmacsha1
最终将上面生成的参数填入对应的 mqtt connect 报文中。
将 clientid 填入到 MQTT 协议的 clientid 字段。
将 username 填入到 mqtt 的 username 字段。
将 password 填入到 mqtt 的 password 字段,即可接入到物联云通信平台。
通过 psk 方式接入端口默认为1883。若客户端支持 ca 证书,您也可以使用8883端口接入。
# 生成指定长度的随机字符串, 范围为数字和字母
def RandomConnid(length):
msg = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(length))
return msg
# 生成接入腾讯物联云平台需要的各参数
def tos_IotHmac(productID, devicename, devicePsk):
# 1. 生成connid为一个随机字符串,方便后台定位问题
connid = RandomConnid(5)
# 2. 生成过期时间,表示签名的过期时间,从纪元1970年1月1日 00:00:00 UTC 时间至今秒数的 UTF8 字符串
expiry = int(time.time()) + 60*60
# 3. 生成MQTT的clientid部分, 格式为${productid}${devicename}
clientid = "{}{}".format(productID, devicename)
# 4. 生成mqtt的username部分, 格式为${clientid};${sdkappid};${connid};${expiry}
username = "{};12010126;{};{}".format(clientid, connid, expiry)
# 5. 对username进行签名,生成token
# 此处为Python3 的写法, 需要进行类型转换
psk_b = base64.b64decode(devicePsk.encode('utf-8'))# 解码后为二进制串
psk1 = str(psk_b,"utf-8")# 按utf8编码成字符串
token = hmac.new( bytes(psk1, 'utf-8'), bytes(username, 'utf-8'), digestmod=hashlib.sha256).hexdigest()# 转换成utf-8的字节串
# 此处为Python2 的写法, Python2 隐式转换了数据编码
# token = hmac.new(devicePsk.decode("base64"), username, digestmod=hashlib.sha256).hexdigest()
# 6. 根据物联云通信平台规则生成password字段
password = "{};{}".format(token, "hmacsha256")
return {
"clientid": clientid,
"username": username,
"password": password
}
pass
# 腾讯云MQTT客户端信息结构
class Tos_CreatDevInfo(object):
def __init__(self, productID, devicename, devicePsk):
self.productID = productID
self.devicename = devicename
self.devicePsk = devicePsk
self.iotsite = '{}.iotcloud.tencentdevices.com'.format(productID)
self.iotport = 1883
def get_IotHmac_tos(self):
# 产生登录用信息
IotHmac_tos_list = tos_IotHmac(self.productID, self.devicename, self.devicePsk)
# print(IotHmac_tos_list)
return IotHmac_tos_list
# MQTT客户端类
class Tos_MqttClient(Tos_CreatDevInfo):
def __init__(self, productID, devicename, devicePsk):
super(Tos_MqttClient,self).__init__(productID, devicename, devicePsk)
# 密钥认证为1883, 证书认证为8883
self.port = 1883
# 云地址为 productID.iotcloud.tencentdevices.com
self.host = self.iotsite
# 生成客户端连接信息
self.client_dict = self.get_IotHmac_tos()
# 创建客户端
self.client = mqtt.Client(self.client_dict['clientid'])
# 设置用户名密码
self.client.username_pw_set(self.client_dict.get('username'), self.client_dict.get('password'))
# 定义Mqtt相关的回调函数
self.client.on_connect = on_connect_callback # 连接回调
self.client.on_message = on_message_callback # 收到消息回调
self.client.on_publish = on_publish_callback # 发布消息回调
self.client.on_subscribe = on_subscribe_callback # 订阅回调
self.client.on_disconnect = on_disconnect_callback # 断开连接回调
self.client.on_unsubscribe = on_unsubscribe_callback # 取消订回调
self.client.on_log = on_log_callback # 日志回调
pass
def connect(self):
self.client.connect(self.host, self.port, 60)
# self.client.loop_forever() # 阻塞式循环等待, 运行到这里, 后面的代码都运行不了
self.client.loop_start() # 非阻塞式循环等待
# 当代理响应连接请求时调用
def on_connect_callback(client, userdata, flags, ret):
print("Connected with result code " + str(ret))
print("userdata: {}, flags: {}".format(userdata, flags))
# 创建主题过滤器
topic_filter = "HRDQBHLDHS/Dev_001/data"
# 订阅该主题
client.subscribe(topic_filter)
pass
# 当与代理断开连接时调用
def on_disconnect_callback(client, userdata, flags, ret):
print("unConnected with result code " + str(ret))
print("userdata: {}, flags: {}".format(userdata, flags))
pass
# 当收到关于客户订阅的主题的消息时调用
index = 0
def on_message_callback(client, userdata, msg):
# print("client: {}; userdata: {}".format(client, userdata))
print(msg.topic + " " + msg.payload.decode("utf-8"))
# 发布消息(主题, 内容, qos)
global index
index += 1
# 创建主题过滤器
topic_filter = "HRDQBHLDHS/Dev_001/data"
# 收到一条订阅, 发布一条消息
client.publish(topic_filter , "hello world ...{}".format(index), 0)
print("send hello world {}...".format(index))
# 当使用使用publish()发送的消息已经传输到代理时被调用
def on_publish_callback(client, userdata, mid):
pass
# 当代理响应订阅请求时被调用
def on_subscribe_callback(client, userdata, mid, granted_qos):
pass
# 当代理响应取消订阅请求时调用
def on_unsubscribe_callback(client, userdata, mid):
pass
# 当客户端有日志信息时调用
def on_log_callback(client, userdata, level, buf):
pass
if __name__ == '__main__':
'''
产品ID: 腾讯物联网平台自动分配
设备名称: 自己起的设备名称
base64后密钥: 可以自己设置或者腾讯分配
'''
# 以下是的测试设备, 请换成自己的
tos_info = Tos_MqttClient("HRDQBHLDHS", "Dev_001", "dGlnZXJvdHMwMTIzNDU2Nzg5")
tos_info.connect()