In the last post, we have seen how to control devices and measure Temperature and Humidity using NodeMCU.
NodeMCU publishes the temperature and humidity data to MQTT server and subscribe the led state and relay states topics, while Android application subsribes the temperature and humidity data and publishes the relay states based on the button presses to the MQTT Server.
In this post, I am going to extend the Publish and Subscription part to PC also, by this we can publish and subscribe for the same topic using multiple clients on different platforms.
The language of choice in this case is Python, and we have already played with Python and MQTT earlier, plus we also know how to create beautiful User Interfaces using PyQt5 in Python.
Prerequisite to Understand this Post
Before starting this post, you must understand, how to get started with MQTT using Python, and you can learn this from the following link.
Getting Started with MQTT Using Python
Next, you need to learn how to design user interfaces in Python Using PyQt5 and you can learn this from the following link.
Design GUI in Python Using PyQt5
Finally the most important part, in this post we will be publishing the temperature and humidity data using NodeMCU and DHT11 sensor and subscribing the relay states packets, so to get the NodeMCU software, use the following link.
Control Devices Using Android Phone and NodeMCU using CloudMQTT Server
Note:
This project is an extended version of our last post on Python and MQTT, and complete explanation of Python software modules is given there.
To Understand the Python Code use the following Link:
Click Here to download the complete code along with PyQt5 UI file.
Most of the code is generated automatically using pyuic5.exe by providing Qt Designer file as input, you can learn this complete steps by reading the post "Design User Interface in Python Using PyQt5"
Software available on GitHub
NodeMCU publishes the temperature and humidity data to MQTT server and subscribe the led state and relay states topics, while Android application subsribes the temperature and humidity data and publishes the relay states based on the button presses to the MQTT Server.
In this post, I am going to extend the Publish and Subscription part to PC also, by this we can publish and subscribe for the same topic using multiple clients on different platforms.
The language of choice in this case is Python, and we have already played with Python and MQTT earlier, plus we also know how to create beautiful User Interfaces using PyQt5 in Python.
Prerequisite to Understand this Post
Before starting this post, you must understand, how to get started with MQTT using Python, and you can learn this from the following link.
Getting Started with MQTT Using Python
Next, you need to learn how to design user interfaces in Python Using PyQt5 and you can learn this from the following link.
Design GUI in Python Using PyQt5
Finally the most important part, in this post we will be publishing the temperature and humidity data using NodeMCU and DHT11 sensor and subscribing the relay states packets, so to get the NodeMCU software, use the following link.
Control Devices Using Android Phone and NodeMCU using CloudMQTT Server
The following is the User Interface which is developed in Python using PyQt5.
Have a look at the following video, to view the Python User Interface, Publishing and Subscribing Topics.
Have a look at the following video, to view the Python User Interface, Publishing and Subscribing Topics.
Python Software
The complete python software is given below.
The complete python software is given below.
The base code for this used from the following post, with few changes, as most of the things are same, so please have a look at this post again to understand the Python code.
This project is an extended version of our last post on Python and MQTT, and complete explanation of Python software modules is given there.
To Understand the Python Code use the following Link:
import os import codecs import pickle import paho.mqtt.client as mqtt from PyQt5 import QtCore, QtGui, QtWidgets global server_info global led_state global load1_state global load2_state global load3_state global load4_state led_state = False load1_state = False load2_state = False load3_state = False load4_state = False filename = 'settings.txt' def save_file(): with open(filename, "wb") as myFile: pickle.dump(server_info, myFile) if os.path.exists(filename): # Read Dictionary from this file with open(filename, "rb") as myFile: server_info = pickle.load(myFile) else: # Create Dictionary Using Default parameters server_info = { "Server_Address":"m14.cloudmqtt.com", \ "Server_Port":"18410", \ "Username": "setsmjwc", \ "Password":"apDnKqHRgAjA"} save_file() # Callback Function on Connection with MQTT Server def on_connect( client, userdata, flags, rc): print ("Connected with Code :" +str(rc)) if rc == 0: # Subscribe Topic from here client.subscribe("home/#") # Enable Disconnect Button and Enable Others ui.connect_btn.setDisabled(True) # ui.server_add.setEnabled(False) Don't use this ui.server_add.setDisabled(True) ui.server_port.setDisabled(True) ui.username.setDisabled(True) ui.password.setDisabled(True) ui.disconnect_btn.setEnabled(True) ui.led_btn.setEnabled(True) ui.load1_btn.setEnabled(True) ui.load2_btn.setEnabled(True) ui.load3_btn.setEnabled(True) ui.load4_btn.setEnabled(True) ui.statusBar.setStatusTip("Connected") # Callback Function on Receiving the Subscribed Topic/Message def on_message( client, userdata, msg): # print the message received from the subscribed topic #print ( str(msg.payload) ) #print ( str(len(msg.payload) )) if len(msg.payload) == 5: message = msg.payload message = message.decode() # default decoding utf-8 temp, humidity = message.split(',') ui.temp.setText(temp) ui.humidity.setText(humidity) def save_server_add(): global server_info server_info["Server_Address"] = ui.server_add.text() save_file() def save_server_port(): server_info["Server_Port"] = ui.server_port.text() save_file() def save_username(): server_info["Username"] = ui.username.text() save_file() def save_password(): server_info["Password"] = ui.password.text() save_file() client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message def connect_with_server(): global server_info client.username_pw_set(server_info["Username"], server_info["Password"]) client.connect(server_info["Server_Address"], int(server_info["Server_Port"]), 60) client.loop_start() def disconnect_with_server(): client.loop_stop() client.disconnect() # Enable Connect Button and Disable Others ui.connect_btn.setEnabled(True) ui.server_add.setEnabled(True) ui.server_port.setEnabled(True) ui.username.setEnabled(True) ui.password.setEnabled(True) ui.disconnect_btn.setDisabled(True) ui.led_btn.setDisabled(True) ui.load1_btn.setDisabled(True) ui.load2_btn.setDisabled(True) ui.load3_btn.setDisabled(True) ui.load4_btn.setDisabled(True) ui.statusBar.setStatusTip("Not Connected") def led_state_toggle(): global led_state if led_state == True: client.publish("led", '0' ) led_state = False ui.led_btn.setText("Led Off") else: client.publish("led", '1' ) led_state = True ui.led_btn.setText("Led On") def load1_state_toggle(): global load1_state if load1_state == True: client.publish("load1", '0') load1_state = False ui.load1_btn.setText("Load1 Off") else: client.publish("load1", '1') load1_state = True ui.load1_btn.setText("Load1 On") def load2_state_toggle(): global load2_state if load2_state == True: client.publish("load2", '0') load2_state = False ui.load2_btn.setText("Load2 Off") else: client.publish("load2", '1') load2_state = True ui.load2_btn.setText("Load2 On") def load3_state_toggle(): global load3_state if load3_state == True: client.publish("load3", '0') load3_state = False ui.load3_btn.setText("Load3 Off") else: client.publish("load3", '1') load3_state = True ui.load3_btn.setText("Load3 On") def load4_state_toggle(): global load4_state if load4_state == True: client.publish("load4", '0') load4_state = False ui.load4_btn.setText("Load4 Off") else: client.publish("load4", '1') load4_state = True ui.load4_btn.setText("Load4 On") class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(306, 231) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.connect_btn = QtWidgets.QPushButton(self.centralwidget) self.connect_btn.setGeometry(QtCore.QRect(220, 10, 75, 31)) self.connect_btn.setObjectName("connect_btn") self.disconnect_btn = QtWidgets.QPushButton(self.centralwidget) self.disconnect_btn.setEnabled(False) self.disconnect_btn.setGeometry(QtCore.QRect(220, 70, 75, 31)) self.disconnect_btn.setObjectName("disconnect_btn") self.temp_lbl = QtWidgets.QLabel(self.centralwidget) self.temp_lbl.setGeometry(QtCore.QRect(10, 120, 69, 18)) self.temp_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.temp_lbl.setAlignment(QtCore.Qt.AlignCenter) self.temp_lbl.setObjectName("temp_lbl") self.humid_lbl = QtWidgets.QLabel(self.centralwidget) self.humid_lbl.setGeometry(QtCore.QRect(110, 120, 69, 18)) self.humid_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.humid_lbl.setAlignment(QtCore.Qt.AlignCenter) self.humid_lbl.setObjectName("humid_lbl") self.temp = QtWidgets.QLabel(self.centralwidget) self.temp.setGeometry(QtCore.QRect(10, 140, 31, 18)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.temp.setFont(font) self.temp.setLayoutDirection(QtCore.Qt.LeftToRight) self.temp.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.temp.setObjectName("temp") self.c_lbl = QtWidgets.QLabel(self.centralwidget) self.c_lbl.setGeometry(QtCore.QRect(50, 140, 21, 18)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.c_lbl.setFont(font) self.c_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.c_lbl.setAlignment(QtCore.Qt.AlignCenter) self.c_lbl.setObjectName("c_lbl") self.humidity = QtWidgets.QLabel(self.centralwidget) self.humidity.setGeometry(QtCore.QRect(110, 140, 31, 18)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.humidity.setFont(font) self.humidity.setLayoutDirection(QtCore.Qt.LeftToRight) self.humidity.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.humidity.setObjectName("humidity") self.percent_lbl = QtWidgets.QLabel(self.centralwidget) self.percent_lbl.setGeometry(QtCore.QRect(150, 140, 21, 18)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.percent_lbl.setFont(font) self.percent_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.percent_lbl.setAlignment(QtCore.Qt.AlignCenter) self.percent_lbl.setObjectName("percent_lbl") self.led_btn = QtWidgets.QPushButton(self.centralwidget) self.led_btn.setEnabled(False) self.led_btn.setGeometry(QtCore.QRect(220, 110, 71, 51)) self.led_btn.setObjectName("led_btn") self.layoutWidget = QtWidgets.QWidget(self.centralwidget) self.layoutWidget.setGeometry(QtCore.QRect(10, 10, 71, 91)) self.layoutWidget.setObjectName("layoutWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setObjectName("verticalLayout") self.server_add_lbl = QtWidgets.QLabel(self.layoutWidget) self.server_add_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.server_add_lbl.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.server_add_lbl.setObjectName("server_add_lbl") self.verticalLayout.addWidget(self.server_add_lbl) self.server_port_lbl = QtWidgets.QLabel(self.layoutWidget) self.server_port_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.server_port_lbl.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.server_port_lbl.setObjectName("server_port_lbl") self.verticalLayout.addWidget(self.server_port_lbl) self.username_lbl = QtWidgets.QLabel(self.layoutWidget) self.username_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.username_lbl.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.username_lbl.setObjectName("username_lbl") self.verticalLayout.addWidget(self.username_lbl) self.password_lbl = QtWidgets.QLabel(self.layoutWidget) self.password_lbl.setLayoutDirection(QtCore.Qt.LeftToRight) self.password_lbl.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.password_lbl.setObjectName("password_lbl") self.verticalLayout.addWidget(self.password_lbl) self.layoutWidget1 = QtWidgets.QWidget(self.centralwidget) self.layoutWidget1.setGeometry(QtCore.QRect(90, 10, 111, 100)) self.layoutWidget1.setObjectName("layoutWidget1") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setObjectName("verticalLayout_2") self.server_add = QtWidgets.QLineEdit(self.layoutWidget1) self.server_add.setMaxLength(30) self.server_add.setObjectName("server_add") self.verticalLayout_2.addWidget(self.server_add) self.server_port = QtWidgets.QLineEdit(self.layoutWidget1) self.server_port.setMaxLength(30) self.server_port.setObjectName("server_port") self.verticalLayout_2.addWidget(self.server_port) self.username = QtWidgets.QLineEdit(self.layoutWidget1) self.username.setMaxLength(30) self.username.setObjectName("username") self.verticalLayout_2.addWidget(self.username) self.password = QtWidgets.QLineEdit(self.layoutWidget1) self.password.setMaxLength(30) self.password.setEchoMode(QtWidgets.QLineEdit.Password) self.password.setObjectName("password") self.verticalLayout_2.addWidget(self.password) self.layoutWidget2 = QtWidgets.QWidget(self.centralwidget) self.layoutWidget2.setGeometry(QtCore.QRect(10, 170, 281, 31)) self.layoutWidget2.setObjectName("layoutWidget2") self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget2) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.horizontalLayout.setObjectName("horizontalLayout") self.load1_btn = QtWidgets.QPushButton(self.layoutWidget2) self.load1_btn.setEnabled(False) self.load1_btn.setObjectName("load1_btn") self.horizontalLayout.addWidget(self.load1_btn) self.load2_btn = QtWidgets.QPushButton(self.layoutWidget2) self.load2_btn.setEnabled(False) self.load2_btn.setObjectName("load2_btn") self.horizontalLayout.addWidget(self.load2_btn) self.load3_btn = QtWidgets.QPushButton(self.layoutWidget2) self.load3_btn.setEnabled(False) self.load3_btn.setObjectName("load3_btn") self.horizontalLayout.addWidget(self.load3_btn) self.load4_btn = QtWidgets.QPushButton(self.layoutWidget2) self.load4_btn.setEnabled(False) self.load4_btn.setObjectName("load4_btn") self.horizontalLayout.addWidget(self.load4_btn) MainWindow.setCentralWidget(self.centralwidget) self.statusBar = QtWidgets.QStatusBar(MainWindow) self.statusBar.setObjectName("statusBar") MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Weather Monitor")) self.connect_btn.setText(_translate("MainWindow", "Connect")) self.disconnect_btn.setText(_translate("MainWindow", "Disconnect")) self.temp_lbl.setText(_translate("MainWindow", "Temperature")) self.humid_lbl.setText(_translate("MainWindow", "Humidity")) self.temp.setText(_translate("MainWindow", "0")) self.c_lbl.setText(_translate("MainWindow", "C")) self.humidity.setText(_translate("MainWindow", "0")) self.percent_lbl.setText(_translate("MainWindow", "%")) self.led_btn.setText(_translate("MainWindow", "Led Off")) self.server_add_lbl.setText(_translate("MainWindow", "Server Add :")) self.server_port_lbl.setText(_translate("MainWindow", "Server Port :")) self.username_lbl.setText(_translate("MainWindow", "Username :")) self.password_lbl.setText(_translate("MainWindow", "Password :")) self.load1_btn.setText(_translate("MainWindow", "Load1 Off")) self.load2_btn.setText(_translate("MainWindow", "Load2 Off")) self.load3_btn.setText(_translate("MainWindow", "Load3 Off")) self.load4_btn.setText(_translate("MainWindow", "Load4 Off")) # Main Program Starts from Here self.statusBar.setStatusTip("Not Connected") # Update Server Information global server_info self.server_add.setText(server_info["Server_Address"]) self.server_port.setText(server_info["Server_Port"]) self.username.setText(server_info["Username"]) self.password.setText(server_info["Password"]) # Button Press Events self.connect_btn.clicked.connect( connect_with_server ) self.disconnect_btn.clicked.connect( disconnect_with_server ) self.led_btn.clicked.connect( led_state_toggle ) self.load1_btn.clicked.connect(load1_state_toggle) self.load2_btn.clicked.connect(load2_state_toggle) self.load3_btn.clicked.connect(load3_state_toggle) self.load4_btn.clicked.connect(load4_state_toggle) self.server_add.editingFinished.connect( save_server_add ) self.server_port.editingFinished.connect( save_server_port ) self.username.editingFinished.connect( save_username ) self.password.editingFinished.connect( save_password ) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) app.setStyle('Fusion') MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
Click Here to download the complete code along with PyQt5 UI file.
Most of the code is generated automatically using pyuic5.exe by providing Qt Designer file as input, you can learn this complete steps by reading the post "Design User Interface in Python Using PyQt5"
Software available on GitHub
Had a wonderful time while reading your article. Thanks admin.
ReplyDeleteJava Training in Chennai
ReactJS Training in Chennai
AngularJS Training in Chennai
Python Training in Chennai
Python Training institute in Chennai