1

i've been trying to make this example running for many hours. I was building an example so my friend can learn some python but i've end up frustrated on my own.

My python knowledge is quite limited. Something is causing the program thread to finish no matter how much I try delaying the execution with time.sleep (i've removed that part of the code).

Expect result: sender container should be started after the receiver one. So the receiver is subscribed to the broker and waiting for messages.

Given result: receiver container starts and then dies.

Thanks in advance.

I have a docker compose as follows:

services:
  mqtt_broker:
    image: eclipse-mosquitto
    volumes:
      - "./mosquitto.conf:/mosquitto/config/mosquitto.conf"
  client_send:
    build:
      context: ./client_send/
    environment:
      BROKER_HOST: mqtt_broker
    depends_on:
      - client_receive
  client_receive:
    build:
      context: ./client_receive/
    environment:
      BROKER_HOST: mqtt_broker
    depends_on:
      - mqtt_broker

Then I have client code for each of these clients:

Receiver:

import os
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print("[receiver] Connected with result code " + str(rc))
    client.subscribe("sample_topic")

def on_message(client, userdata, msg):
    print("[receiver] got a message: " + str(msg.payload.decode()))
    client.loop_stop()

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

client.connect(os.environ["BROKER_HOST"], 1883, 60)
client.loop_start()

Sender:

import os
import paho.mqtt.client as mqtt

def run():
    print("[sender] will send a message")
    client.publish("sample_topic", "message from sender")
    client.loop_stop()

def on_connect(client, userdata, flags, rc):
    print("[sender] Connected with result code " + str(rc))
    run()

client = mqtt.Client()
client.on_connect = on_connect

client.connect(os.environ["BROKER_HOST"], 1883, 60)
client.loop_start()
k1r0s
  • 359
  • 3
  • 14
  • 1
    Add an `on_error` callback to both clients and also update the question with the logs from the broker container so we can see if/when the other containers connect – hardillb Nov 20 '22 at 17:51
  • I believe that these infos are not relevant. The info I need is how to make the receiver "wait for some connection" and then close it self – k1r0s Nov 20 '22 at 18:09
  • 1
    `loop_start()` does not block so the end of your program is reached and it terminates. Use `loop_forever()` instead (and then call `disconnect()` when you want the loop to exit). Note that using `depends_on` does not guarantee that the subscriber will have subscribed before the publisher runs (you may need a delay; a [healthcheck](https://docs.docker.com/engine/reference/builder/#healthcheck) is the proper method but probably overkill here). If this does not help then please edit the question and clarify the issue (including logs etc, as suggested by @hardillb, would be beneficial). – Brits Nov 20 '22 at 20:16

1 Answers1

0

I was using loop_forever without too much success bcoz print() calls were not logging anything since the main thread was blocked so I couldn't see if my code was working.

EDIT: previous paragraph is just not correct. loop_forever will work taking this into account: Python app does not print anything when running detached in docker

Finally got it working as suggested by @Brits (see comments) just by running exit or disconnecting the client (works using exit too)

I also keep the depends_on so the docker-compose.yml was not changed

This is the receiver:

import os
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print("[receiver] Connected with result code " + str(rc))
    client.subscribe("sample_topic")

def on_message(client, userdata, msg):
    print("[receiver] got a message: " + str(msg.payload.decode()))
    client.disconnect()

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

client.connect(os.environ["BROKER_HOST"], 1883, 60)
client.loop_forever()

As a side note, if the main thread is blocked you will never be able to see the output of the program even if you got the message back from the sender. If you don't disconnect the client it might actually work if your application does not rely on console output. Soo freeing the main thread allows for the system to release the output logs to docker.

k1r0s
  • 359
  • 3
  • 14
  • "main thread is blocked you will never.." - I've just tested your code without the `client.disconnect()` and it worked fine (received messages were printed). With `loop_forever()` everything runs on the main thread. You may have been experiencing [this issue](https://stackoverflow.com/a/29745541/11810946). – Brits Nov 21 '22 at 03:32
  • LOL, true, im going to modify the answer. Huge Thx! – k1r0s Nov 21 '22 at 14:46