network-programmingmqttmosquittopaho

MQTT "invalid protocol version" error with Ubuntu, mosquitto, and paho-mqtt


I'm currently working on an MQTT project using an NVIDIA Jetson running Ubuntu 18.04. I have installed mosquitto (version 2.0.15) as my MQTT broker and paho-mqtt (version 1.6.1) for my Python MQTT client.

I'm encountering an issue where I consistently receive an "invalid protocol version" error with an "mid" (message identifier) code of 1 when attempting to publish messages to my MQTT broker. I have double-checked my code and configuration, and I believe I am specifying the correct protocol version (MQTTv5) in my Python MQTT client as mosquitto v2.0.15 supports MQTTv5 and MQTTv3.1.

The broker server and publish client are running on the same device/network.

The MQTT broker is indeed running:

gabe@gabe-desktop:~$ systemctl status mosquitto
mosquitto.service - Mosquitto MQTT Broker
   Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2024-01-06 19:10:01 CET; 1h 35min ago
     Docs: man:mosquitto.conf(5)
           man:mosquitto(8)
 Main PID: 22604 (mosquitto)
    Tasks: 1 (limit: 4180)
   CGroup: /system.slice/mosquitto.service
           └─22604 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

Jan 06 19:10:01 gabe-desktop systemd[1]: Starting Mosquitto MQTT Broker...
Jan 06 19:10:01 gabe-desktop systemd[1]: Started Mosquitto MQTT Broker.

and port 1883 is listening on addresses: localhost:1883 and ip6-localhost:1883.

gabe@gabe-desktop:~$ netstat -at
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:sunrpc          0.0.0.0:*               LISTEN     
tcp        0      0 localhost:domain        0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN     
tcp        0      0 localhost:1883          0.0.0.0:*               LISTEN     
tcp        0      0 localhost:40283         0.0.0.0:*               LISTEN     
tcp        0      0 localhost:42269         0.0.0.0:*               LISTEN     
tcp        0      0 localhost:34941         0.0.0.0:*               LISTEN     
tcp        0      0 localhost:40451         0.0.0.0:*               LISTEN     
tcp        0      0 localhost:gpsd          0.0.0.0:*               LISTEN     
tcp        0      0 localhost:40283         localhost:47786         ESTABLISHED
tcp        0      0 gabe-desktop:35130      13.107.5.93:https       ESTABLISHED
tcp        0    108 gabe-desktop:ssh        Gabes-MBP:53006         ESTABLISHED
tcp        0      0 gabe-desktop:35140      13.107.5.93:https       ESTABLISHED
tcp        0      0 localhost:40283         localhost:47788         ESTABLISHED
tcp        0      0 localhost:47786         localhost:40283         ESTABLISHED
tcp        0      0 localhost:47788         localhost:40283         ESTABLISHED
tcp        0      0 localhost:40283         localhost:47272         CLOSE_WAIT 
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN     
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN     
tcp6       0      0 ip6-localhost:1883      [::]:*                  LISTEN     
tcp6       0      0 ip6-localhost:gpsd      [::]:*                  LISTEN

Here is the Python code and error when attempting to create a publish connection:

import paho.mqtt.client as mqtt


# MQTT broker information
BROKER_ADDRESS = "localhost"
PORT = 1883
TOPIC = "testing"
RESPONSE = {
    0: "connection succeeded",
    1: "connection failed - incorrect protocol version",
    2: "connection failed - invalid client identifier",
    3: "connection failed - the broker is not available",
    4: "connection failed - wrong username or password",
    5: "connection failed - unauthorized"
}


def on_publish(client, data, mid):
    print(f"Connected to broker with status: {mid}: {RESPONSE.get(mid, 'Unknown')}")


def main():

    client = mqtt.Client(client_id="jetson", protocol=mqtt.MQTTv5)
    # Set the callback function for when the publisher connects to the broker
    client.on_publish = on_publish
    # Connect to the broker
    client.connect(BROKER_ADDRESS, PORT)

    # Publish a message to the "testing" topic
    message = "Hello, world!"
    client.publish(TOPIC, message)

    # Keep client running "forever"
    client.loop_forever()


if __name__ == '__main__':
    main()
Connected to broker with status: 1: connection failed - incorrect protocol version

I also tried protocol version mqtt.MQTTv31 and received the same error.

All the resources online have to do ensuring the mosquitto config file is properly configured. However, I have double checked this and this seems to be the case.

To ensure the MQTT broker server was indeed running correctly I performed the following test in two separate terminals

Terminal 1:

gabe@gabe-desktop:~$ mosquitto_sub -h localhost -t test

Terminal 2:

gabe@gabe-desktop:~$ mosquitto_pub -h localhost -t test -m "hello world"

I get the "hello world" output in terminal 1.


Solution

  • def on_publish(client, data, mid):
        print(f"Connected to broker with status: {mid}: {RESPONSE.get(mid, 'Unknown')}")
    

    on_publish is "called when a message that was to be sent using the publish() call has completed transmission to the broker." and is passed:

    client: the client instance for this callback
    userdata: the private user data as set in Client() or userdata_set()
    mid: matches the mid variable returned from the corresponding publish() call, to allow outgoing messages to be tracked.

    You appear to be assuming that the mid indicates whether the connection is successful or not (as per the docs copied above; it does not). .

    So what is happening (well, what happens when I test your code) is that you are successfully connecting to the broker and then successfully publishing a message. However once the message has been transmitted your on_publish is called (which incorrectly prints an error message).

    I subject you intended something like:

    def on_connect(client, userdata, flags, reasonCode, properties):
        print(f"Connected to broker with status: {reasonCode}")
    
    def on_publish(client, data, mid):
        print(f"Publish completed: {mid}")
    
    
    def main():
        client = mqtt.Client(client_id="jetson", protocol=mqtt.MQTTv5)
        # Set the callback function for when the publisher connects to the broker
        client.on_connect = on_connect
        client.on_publish = on_publish
    ...