阿里云 IOT Python 版本demo

前一段时间研究了一下阿里云IOT官网上的连接demo,有java和c版本的,但是暂时没有python版本,于是参考了java版本的设计思路,编写了一个python版本的客户端,代码如下

alidemo.py

import socket
import uuid
import time
from util import SignUtil
from hashlib import sha1
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
import os,logging
#定义一个列表
data = [1,3,2,5,7,6]
#定义一个元组作为字典索引
seq = ('productKey', 'deviceName', 'clientId', 'timestamp')

'''开启TLS时的认证文件目录'''
trust = 'F:/workspace/aliiot_python/root.cer' #修改为自己文件实际路径即可

'''日志格式配置'''
logging.basicConfig(level=logging.DEBUG,
                format='[%(filename)s]-(line:%(lineno)d)-[%(funcName)s]-%(message)s----%(asctime)s',
                datefmt='%y-%b %d %a %H:%M:%S')

class SimpleClient4IOT :

    def __init__(self, clientid=None):
        #这里是客户端需要的参数,改成自己生成的即可
        self.deviceName = "test"
        self.productKey = "3y7iXH9wQDt"
        self.secret = "IoW7r1E8WcEN2ROXEvPrH7e5V9B4tFJp"
        self.clientId = self.get_localhost_ip()

        #用于测试的topic
        self.subTopic = "/" + self.productKey + "/" + self.deviceName + "/get"
        self.pubTopic = "/" + self.productKey + "/" + self.deviceName + "/update"
        #MQTT服务器地址,TLS连接使用ssl开头,这里选择直连不加ssl
        self.targetServer = "ssl://" + self.productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:1883"
        self.targetServer1 =  self.productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com"
        self.targetServer2 =  "3y7iXH9wQDt.iot-as-mqtt.cn-shanghai.aliyuncs.com"


        dit = dict.fromkeys(seq)
        dit['productKey'] = self.productKey #这个是对应用户在控制台注册的 设备productkey
        dit['deviceName'] = self.deviceName #这个是对应用户在控制台注册的 设备name
        dit['clientId'] = self.clientId
        t = int(round(time.time()*1000)) #获取系统当前时间
        dit['timestamp'] = str(t)

        #客户端ID格式,两个||之间的内容为设备端自定义的标记,字符范围[0-9][a-z][A-Z]
        self.params = dit
        self.mqttclientId = self.clientId + "|securemode=2,signmethod=hmacsha1,timestamp=" + str(t) + "|"
        self.mqttUsername = self.deviceName + "&" + self.productKey #mqtt用户名格式
        self.mqttPassword = SignUtil.SignUtil().sign(sha1, self.secret, **self.params)#签名,固定使用hamc加密
        self.connec()
        time.sleep(1)#这里要加延时,否则订阅不成功,原因未知
        self.client.subscribe(subTopic)
        time.sleep(1)#这里要加延时,否则发送不成功,原因未知
        self.client.publish(pubTopic,message)
        self.client.loop_forever()
#         while True:
#             self.client.loop()


    def connec(self):
        logging.info("进行连接-服务器地址: " + self.targetServer1);  
        self.client = mqtt.Client(client_id=self.mqttclientId, clean_session=True, userdata=None, protocol=mqtt.MQTTv31)
        self.client.on_publish = self.on_publish
        self.client.on_connect = self.on_connect 
        self.client.on_disconnect = self.on_disconnect 
        self.client.on_message = self.on_message
        self.client.on_subscribe = self.on_subscribe  
        self.client.tls_insecure_set(True) #检查hostname的cert认证
        self.client.tls_set(trust) #设置认证文件
        self.setAutho() #设置用户名和密码
        self.client.connect( self.targetServer1 ,port=1883, keepalive=65) #向服务器发起连接

    def setAutho(self):
        self.client.username_pw_set(self.mqttUsername, self.mqttPassword)   


    #获得主机IP地址
    def get_localhost_ip(self):
        self.local_ip = socket.gethostbyname(socket.gethostname())
        return self.local_ip

    #获得主机MAC地址
    def get_localhost_mac(self): 
        mac=uuid.UUID(int = uuid.getnode()).hex[-12:] 
        return ":".join([mac[e:e+2] for e in range(0,11,2)])   




    #创建客户端标识
    def SetClientId(self):
        return self.get_localhost_ip()

    '''回调函数'''
    def on_connect(self, mqttc, obj, flags, rc):
#         print("Connection returned " + str(rc))
        if str(rc)=='0':
            logging.info("连接已被服务端接受")
        elif str(rc)=='1':
            logging.info("连接已拒绝,不支持的协议版本")
        elif str(rc)=='2':
            logging.info("连接已拒绝, 不合格的客户端标识符")
        elif str(rc)=='3':
            logging.info("连接已拒绝, 服务端不可用")
        elif str(rc)=='4':
            logging.info("连接已拒绝,无效的用户名或密码")

    def on_message(self, mqttc, obj, msg):
        print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
#         self.client.disconnect()

    def on_publish(self, mqttc, obj, mid):
        print("mid: "+str(mid))

    def on_subscribe(self, mqttc, obj, mid, granted_qos):
        print("Subscribed: "+str(mid)+" "+str(granted_qos))

    def on_log(self, mqttc, obj, level, string):
        print(string)

    def on_disconnect(self, client, userdata, rc):
        if rc != 0:
            print("连接断开,准备重新发起连接.")
            self.client.reconnect()


s = SimpleClient4IOT()

signutil.py 签名生成


    def sign(self, Method, key, **params):        
        """ 数字签名程序"""
        #字典排序生成规范化请求字符串
        sortedKey = sorted(params.iteritems(), key=lambda d:d[0] )
        temp = sortedKey[0]+sortedKey[1]+sortedKey[2]+sortedKey[3]
        list_str = ''.join(temp)
        return self.encryptHMAC(list_str, key, Method)

        """HMAC加密"""
    def encryptHMAC(self, content, key, Method):    
        a = hmac.new(key, content, Method)
        return a.digest().encode('hex').rstrip('')

跟java版本相比,python在选择服务器地址时用tcp直连加证书认证
server地址不加ssl,带上ssl地址解析失败,这点跟java客户端不一样。

运行结果:其中连接过程中有个重连动作,订阅了subtopic,云端发送一个消息,可以正常显示

阿里云 IOT Python 版本demo_第1张图片

完整项目地址:http://git.oschina.net/DSSDD/aliiot_python/tree/master

你可能感兴趣的:(测试工具,mqtt)