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 是提供了一个可视化交互的桌面应用程序,在开发起来相对比较容易,上手。
界面如下。
主要是由文字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_())
运行起来显示如下。
完成代码工程已上传。