Skip to content Skip to sidebar Skip to footer

Use Paho-mqtt With Pyqt

How I can use callback function from QThread? Callback function on_message does not print any data. In run() I connect to mqtt-broker and subscribe on topic. on_message must work w

Solution 1:

It is not necessary to use threads, just follow the logic of Qt: let's use signals. In the following code I show an advance of the library of an MQTT client that I am implementing that at least up to now implements what you want, in next days I will add more functionalities.

from PyQt5 import QtCore, QtWidgets
import paho.mqtt.client as mqtt


classMqttClient(QtCore.QObject):
    Disconnected = 0
    Connecting = 1
    Connected = 2

    MQTT_3_1 = mqtt.MQTTv31
    MQTT_3_1_1 = mqtt.MQTTv311

    connected = QtCore.pyqtSignal()
    disconnected = QtCore.pyqtSignal()

    stateChanged = QtCore.pyqtSignal(int)
    hostnameChanged = QtCore.pyqtSignal(str)
    portChanged = QtCore.pyqtSignal(int)
    keepAliveChanged = QtCore.pyqtSignal(int)
    cleanSessionChanged = QtCore.pyqtSignal(bool)
    protocolVersionChanged = QtCore.pyqtSignal(int)

    messageSignal = QtCore.pyqtSignal(str)

    def__init__(self, parent=None):
        super(MqttClient, self).__init__(parent)

        self.m_hostname = ""
        self.m_port = 1883
        self.m_keepAlive = 60
        self.m_cleanSession = True
        self.m_protocolVersion = MqttClient.MQTT_3_1

        self.m_state = MqttClient.Disconnected

        self.m_client =  mqtt.Client(clean_session=self.m_cleanSession,
            protocol=self.protocolVersion)

        self.m_client.on_connect = self.on_connect
        self.m_client.on_message = self.on_message
        self.m_client.on_disconnect = self.on_disconnect


    @QtCore.pyqtProperty(int, notify=stateChanged)defstate(self):
        return self.m_state

    @state.setterdefstate(self, state):
        if self.m_state == state: return
        self.m_state = state
        self.stateChanged.emit(state) 

    @QtCore.pyqtProperty(str, notify=hostnameChanged)defhostname(self):
        return self.m_hostname

    @hostname.setterdefhostname(self, hostname):
        if self.m_hostname == hostname: return
        self.m_hostname = hostname
        self.hostnameChanged.emit(hostname)

    @QtCore.pyqtProperty(int, notify=portChanged)defport(self):
        return self.m_port

    @port.setterdefport(self, port):
        if self.m_port == port: return
        self.m_port = port
        self.portChanged.emit(port)

    @QtCore.pyqtProperty(int, notify=keepAliveChanged)defkeepAlive(self):
        return self.m_keepAlive

    @keepAlive.setterdefkeepAlive(self, keepAlive):
        if self.m_keepAlive == keepAlive: return
        self.m_keepAlive = keepAlive
        self.keepAliveChanged.emit(keepAlive)

    @QtCore.pyqtProperty(bool, notify=cleanSessionChanged)defcleanSession(self):
        return self.m_cleanSession

    @cleanSession.setterdefcleanSession(self, cleanSession):
        if self.m_cleanSession == cleanSession: return
        self.m_cleanSession = cleanSession
        self.cleanSessionChanged.emit(cleanSession)

    @QtCore.pyqtProperty(int, notify=protocolVersionChanged)defprotocolVersion(self):
        return self.m_protocolVersion

    @protocolVersion.setterdefprotocolVersion(self, protocolVersion):
        if self.m_protocolVersion == protocolVersion: returnif protocolVersion in (MqttClient.MQTT_3_1, MQTT_3_1_1):
            self.m_protocolVersion = protocolVersion
            self.protocolVersionChanged.emit(protocolVersion)

    #################################################################    @QtCore.pyqtSlot()defconnectToHost(self):
        if self.m_hostname:
            self.m_client.connect(self.m_hostname, 
                port=self.port, 
                keepalive=self.keepAlive)

            self.state = MqttClient.Connecting
            self.m_client.loop_start()

    @QtCore.pyqtSlot()defdisconnectFromHost(self):
        self.m_client.disconnect()

    defsubscribe(self, path):
        if self.state == MqttClient.Connected:
            self.m_client.subscribe(path)

    ################################################################## callbacksdefon_message(self, mqttc, obj, msg):
        mstr = msg.payload.decode("ascii")
        # print("on_message", mstr, obj, mqttc)
        self.messageSignal.emit(mstr)

    defon_connect(self, *args):
        # print("on_connect", args)
        self.state = MqttClient.Connected
        self.connected.emit()

    defon_disconnect(self, *args):
        # print("on_disconnect", args)
        self.state = MqttClient.Disconnected
        self.disconnected.emit()


classWidget(QtWidgets.QWidget):
    def__init__(self, parent=None):
        super(Widget, self).__init__(parent)

        lay = QtWidgets.QVBoxLayout(self)
        self.lcd_number = QtWidgets.QLCDNumber()
        lay.addWidget(self.lcd_number)

        self.client = MqttClient(self)
        self.client.stateChanged.connect(self.on_stateChanged)
        self.client.messageSignal.connect(self.on_messageSignal)

        self.client.hostname = "broker.hivemq.com"
        self.client.connectToHost()

    @QtCore.pyqtSlot(int)defon_stateChanged(self, state):
        if state == MqttClient.Connected:
            print(state)
            self.client.subscribe("shok2")

    @QtCore.pyqtSlot(str)defon_messageSignal(self, msg):
        try:
            val = float(msg)
            self.lcd_number.display(val)
        except ValueError:
            print("error: Not is number")


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Based on this answer I have created a library to use paho with PyQt5 and PySide2: https://github.com/eyllanesc/qtmqtt

Solution 2:

Do you have to create the method on_connect use the subscribe on on_connect method not on run.

defon_connect(self, client, userdata, flags, rc):
    print"Connected", rc
    client.subscribe("shok2")

defrun(self):
    msg = subscribe.simple("shok2", hostname="broker.hivemq.com")
    print("%s %s" % (msg.topic, msg.payload))
    mqttc = mqtt.Client()
    mqttc.on_subscribe = self.on_subscribe
    mqttc.on_message = self.on_message
    mqttc.on_connect = on_connect
    mqttc.connect("broker.hivemq.com")
    mqttc.loop_forever()

Post a Comment for "Use Paho-mqtt With Pyqt"