Search code examples
python-2.7mqttraspberry-pi4paho

Mqtt paho handlers aren't being called


I am working on a python 2.7 script that runs on Raspberrypi. This Raspberry is v4 and has a grovepi hat. A button and a LCD display are connected to this hat.

So I have been using the paho mqtt library, but I can't figure out why my callbacks (on_message and on_intrusion) aren't being called. Here is my code :

import time
import LCDDisplay
import paho.mqtt.client as paho
import grovepi
import threading

broker_ip = '192.168.1.23'
broker_port = 1883
turn_on_topic = 'GreenHouse/Security/TurnOn'
intrusion_topic = 'GreenHouse/Security/IntrusionDetected'
message_topic = 'GreenHouse/Message'
message_display_duration = 5.0

button_port = 3
last_message = 'Initial display'

def display_last_message():
    print('Timer starting')
    LCDDisplay.setText(last_message)
    LCDDisplay.setRGB(160,240,70)

message_timer = threading.Timer(message_display_duration, display_last_message)

def on_message(client, userdata, msg):
    print('Message received')
    LCDDisplay.setText('Message received')
    LCDDisplay.setRGB(60,190,250)
    if message_timer.is_alive():
        message_timer.cancel()
        message_timer = threading.Timer(message_display_duration, display_last_message)
    message_timer.start()

def on_intrusion(client, userdata, msg):
    LCDDisplay.setText('ALERT - INTRUSION DETECTED')
    LCDDisplay.setRGB(240,65,65)

if __name__=="__main__":
    display_last_message()
    print('Connecting to broker...')
    mqttClient = paho.Client('Button_LCD_Main')
    mqttClient.message_callback_add(message_topic, on_message)
    mqttClient.message_callback_add(intrusion_topic, on_intrusion)
    mqttClient.connect(broker_ip, broker_port, 60)

    print('Starting loop and button check')
    mqttClient.loop_start()
    grovepi.pinMode(button_port,"INPUT")
    time.sleep(2) # Wait for button to initialize
    try:
        while True:
            button_output = grovepi.digitalRead(button_port)
            if button_output == 1:
                print('Button activated')
                mqttClient.publish(turn_on_topic)
                time.sleep(1)
            else:
                time.sleep(0.2)
    finally:
        mqttClient.loop_stop()
        mqttClient.disconnect()

I checked that the Raspberry can access my broker using 'sudo mosquitto_sub -h <broker_ip> -t 'MyTopic' -q 0, and it works. I also tested the LCD and the button using individual script and they work perfectly. Moreover, the LCD display the 'Initial display' string at the beginning of the program, and I get this output on the console :

Timer starting
Connecting to broker...
Starting loop and button check

But the strangest thing is that the 'publish' works (I also checked it, but using a node-red server with mqtt in nodes). I also triple checked the topics url.

Si I'm confused, could you help me ?


Solution

  • Calling mqttClient.message_callback_add(topic, handler) doesn't actually subscribe to the topic, it just sets up a specific handler for that topic.

    You must still call mqttClient.subscribe(topic) in order to get the broker to send you the matching messages.

    The best solution is to add a on_connect callback to handle the subscription

    ...
    def on_connect(client, userdata, flags, rc):
      client.subscribe(intrusion_topic)
      client.subscribe(message_topic)
    
    ...
    if __name__=="__main__":
        display_last_message()
        print('Connecting to broker...')
        mqttClient = paho.Client('Button_LCD_Main')
        mqttClient.message_callback_add(message_topic, on_message)
        mqttClient.message_callback_add(intrusion_topic, on_intrusion)
        mqttClient.on_connect = on_connect
        mqttClient.connect(broker_ip, broker_port, 60)
    ...