1 写在前面的话

请支持原创!转载和参考请附带链接谢谢!博客主页:

哈喽,各位读者你们好,大学生活即将结束,以后的工作很有可能不会从事物联网的工作,思考很久,决定将我在大学期间学习的财富整理一下,分享和帮助有需要的人,同时也感谢大家的支持!
本文讲描述如何自己编写一个桌面应用程序连接emqx物联网服务器,本文的重点是自己编写上位机连接物联网服务器,嵌入式硬件连接emqx服务器需要自行查看我的帖子,在物联那点事儿专栏里有描述。

2 环境安装与准备

2.1 所需环境与软件

  • Python环境 3以上就行吧
  • Pycharm IDE
  • python第三方库 pyqt5

2.2 第三方包的安装

mqtt包的安装

pip install paho.mqtt

pyqt5的安装

pip install PyQt5

3 设计实现

3.1 emqx服务器

使用emqx服务器作为本次物联网服务器,作为消息转发的云平台,可以自己用自己的云服务器搭建物联网服务器,也可以用emqx服务器的公用服务器。
公用emqx服务器地址:broker.emqx.io
端口:1883

broker = 'broker.emqx.io'
port = 1883
topic = "/test/pub"
topicSub = "/test/sub"
# generate client ID with pub prefix randomly
client_id = "xxxxxxxxxxxx"
user = 'xxxxxxxx'
pwd = 'xxxxx'

3.2 PyQt5

PyQt5 是提供了一个可视化交互的桌面应用程序,在开发起来相对比较容易,上手。

界面如下。

python 上位机框架 pyqt5上位机_python 上位机框架


主要是由文字label和按钮button组成。

3.3 连接emqx服务器

连接emqx服务器,从而与服务器建立连接作为通信基础。

def connect_mqtt() -> mqtt_client:
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.username_pw_set(user, pwd)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client

3.4 数据上下行的实现

3.4.1 订阅消息

数据上行,这里指的数据上行是嵌入式硬件将数据上报给emqx服务器从而到应用程序显示,最简单的例子就是温湿度的远程显示。
从订阅函数中接收到消息后解析并显示在前台上

def subscribe(client: mqtt_client):
    def on_message(client, userdata, msg):
        print("Received {} from {} topic".format(msg.payload.decode(), topic))
        message = msg.payload.decode()
        dictm = eval(message)
        print(type(dictm))
        print(dictm.get("airQ"))
        ui.label_4.setText(str(dictm.get("airQ")))
        ui.label_7.setText(str(dictm.get("Hum")) + "%")
        ui.label_6.setText(str(dictm.get("Temp")) + "°C")
        ui.label_5.setText(str(dictm.get("Light")) + "lux")
    client.subscribe(topic)
    client.on_message = on_message

3.4.1 发布消息

数据下行,这里指的数据下行是应用程序通过button按钮下发指定给到嵌入式硬件设备,最简单的例子就是远程控制用电器的开关。
发布消息函数体如下。

def publish(client, val):
    print("val",val)
    if val == "1":
        msg = '{"LED":1}'
    else:
        msg = '{"LED":0}'
    result = client.publish(topicSub, msg)
    status = result[0]
    if status == 0:
        print("Send {msg} to topic {topic}".format(msg=msg, topic=topic))
    else:
        print("Failed to send message to topic {topic}".format(topic=topic))

按钮信号与槽的绑定

self.pushButton.clicked.connect(self.publishon)
self.pushButton_2.clicked.connect(self.publishoff)

槽函数

def publishon(self):
        publish(client, "1")

    def publishoff(self):
        publish(client, "0")

3.4.3 多线程

在启动应用程序时,因为需要一直接收eqmx服务器的消息,所以最好将该部分的内容放到线程中实现最好!
线程函数体

def run():
    subscribe(client)
    client.loop_forever()

线程类

class ThreadSub(QThread):
    # 自定义信号
    def __init__(self):
        super(ThreadSub, self).__init__()
    def run(self):
        run()

启动程序时创建线程类并开启子线程,当然同时要在这连接客户端

if __name__ == '__main__':
    client = connect_mqtt()
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    MainWindow.setWindowTitle("智能养鸡场远程控制系统")
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    thread = ThreadSub()
    thread.start()
    sys.exit(app.exec_())

运行起来显示如下。

python 上位机框架 pyqt5上位机_python_02


完成代码工程已上传。

下载地址:

python 上位机框架 pyqt5上位机_python 上位机框架_03