Search code examples
pythonpython-3.xmqttpublish-subscribepaho

paho-mqtt publish-subscribe not working from separate files in Python


I have two separate files for publishing and subscribing to test the mqtt protocol. I maintain a single config file to store the common parameters like client_id, broker name and topics.

config.py

broker = "iot.eclipse.org"

# Random alphanumeric string
uid = "id-sfgjrs45ys4jQPlk"

appliances = {
    "room1": [
        "appliance1",
        "appliance2",
        "appliance3",
        "appliance4",
        "appliance5"
    ],
    "room2": [
        "appliance1",
        "appliance2",
        "appliance3"
    ]
}

subscriber.py

import time
import paho.mqtt.client as mqtt
import config

broker = config.broker
client_id = config.uid

topics = list()
for room, appliances in config.appliances.items():
    for appliance in appliances:
        topics.append(room + "/" + appliance)

def on_message(client, userdata, message):
    print("Topic: " + message.topic)
    print("Message: " + message.payload.decode('utf-8'))

client = mqtt.Client(client_id=client_id)
client.on_message = on_message

print("Connecting to broker... " + broker)
client.connect(broker)

print("Subscribing ")
for topic in topics:
    client.subscribe(topic)

print("Listening")
client.loop_forever()

publisher.py

import time
import paho.mqtt.client as mqtt
import config

broker = config.broker
client_id = config.uid

topic = "room1/appliance1"
message = "off"

client = mqtt.Client(client_id=client_id)

print("Connecting to broker... " + broker)
client.connect(broker)

print("Publishing ")
client.publish(
    topic=topic,
    payload=message
)
time.sleep(1)
client.disconnect()

They seem to work fine if the subscriber.py and publisher.py are kept in the same file, like :

client.loop_start()
client.publish(
    topic=topic,
    payload=message
)
time.sleep(10)
client.loop_stop()

Here are the logs when both are executed:

Log for publisher.py

(ran while the subscriber.py was running)

Connecting to broker... iot.eclipse.org
Publishing 
Sending PUBLISH (d0, q0, r0, m1), 'b'room1/appliance1'', ... (3 bytes)
Sending DISCONNECT

Log for subsciber.py

Connecting to broker... iot.eclipse.org
Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=b'id-sfgjrs45ys4jQPlk'
Subscribing 
Sending SUBSCRIBE (d0, m1) [(b'room1/appliance1', 0)]
Sending SUBSCRIBE (d0, m2) [(b'room1/appliance2', 0)]
Sending SUBSCRIBE (d0, m3) [(b'room1/appliance3', 0)]
Sending SUBSCRIBE (d0, m4) [(b'room1/appliance4', 0)]
Sending SUBSCRIBE (d0, m5) [(b'room1/appliance5', 0)]
Sending SUBSCRIBE (d0, m6) [(b'room2/appliance1', 0)]
Sending SUBSCRIBE (d0, m7) [(b'room2/appliance2', 0)]
Sending SUBSCRIBE (d0, m8) [(b'room2/appliance3', 0)]
Listening
Received CONNACK (0, 0)
Received SUBACK
Received SUBACK
Received SUBACK
Received SUBACK
Received SUBACK
Received SUBACK
Received SUBACK
Received SUBACK
Sending PINGREQ
Received PINGRESP
Sending PINGREQ
Received PINGRESP
Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=b'id-sfgjrs45ys4jQPlk'
Received CONNACK (0, 0)

I cannot figure out what I am doing wrong such that the subscriber won't catch my messages.


Solution

  • This is because you are trying to connect from the two separate codes with the same client id uid.

    According to the specs here

    Each Client connecting to the Server has a unique ClientId.

    Try using different client IDs and the code should work fine