Paho MQTT delivers "log: Caught exception in on_publish: 'int' object has no attribute 'topic'"

Question:

I wrote following python script:

import paho.mqtt.client as mqtt
import Adafruit_DHT
import time
import ssl
import logging

logging.basicConfig(level=logging.DEBUG, filename='/home/user/Dokumente/raspi.log', encoding='utf-8')

# Set up DHT22 sensor
dht_sensor = Adafruit_DHT.DHT22
dht_pin = 4  # GPIO pin number the sensor is connected to

username = 'simulation:mqttuser'
secret = 'ABCDEF'
host = '192.168.0.52'
port = 8883
clientID = 'raspi'
assetID = 'A1B2C3D4'


def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    logging.info("Connected with result code "+str(rc))


def on_publish(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))
    logging.info(msg.topic+" "+str(msg.payload))


def on_disconnect(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection.")
        logging.info(f"Unexpected disconnection. Reason: {mqtt.connack_string(rc)}")


def on_message(client, userdata, msg):
    print("message received ", str(msg.payload.decode("utf-8")))
    print("message topic=", msg.topic)
    print("message qos=", msg.qos)
    print("message retain flag=", msg.retain)


def on_log(client, userdata, level, buf):
    print("log: ", buf)
    # logging.info("log: ", buf)


mqtt_client = mqtt.Client(clientID)  # create new instance
mqtt_client.username_pw_set(username, password=secret)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
mqtt_client.tls_set_context(context)

# Callback functions
mqtt_client.on_connect = on_connect  # attach function to callback
mqtt_client.on_disconnect = on_disconnect
mqtt_client.on_publish = on_publish
mqtt_client.on_message = on_message
mqtt_client.on_log = on_log

mqtt_client.connect(host, port=port, keepalive=930)  # connect to broker; keepalive must be higher than time.sleep (see below)
mqtt_client.loop_start()  # start loop to process callbacks
mqtt_client.subscribe(f"simulation/{clientID}/writeattributevalue")


# Continuously read and send temperature values
while True:
    humidity, temperature = Adafruit_DHT.read_retry(dht_sensor, dht_pin)
    if humidity is not None and temperature is not None:
        result = mqtt_client.publish(f"simulation/{clientID}/writeattributevalue/temperature/{assetID}", round(temperature, 1))
        mqtt_client.publish(f"simulation/{clientID}/writeattributevalue/humidity/{assetID}", humidity)
        if result.rc == mqtt.MQTT_ERR_SUCCESS:
            logging.info("Message published successfully")
        else:
            logging.warning("Failed to publish message: " + mqtt.error_string(result.rc))
    else:
        print("Failed to read temperature sensor data")
    time.sleep(10)

# Disconnect MQTT client
mqtt_client.disconnect()
mqtt_client.loop_stop()

When executing it, following exception occurs:

log:  Sending CONNECT (u1, p1, wr0, wq0, wf0, c1, k930) client_id=b'raspi_musterstadt'
log:  Sending SUBSCRIBE (d0, m1) [(b'simulation/raspi_musterstadt/writeattributevalue', 0)]
log:  Sending PUBLISH (d0, q0, r0, m2), 'b'simulation/raspi_musterstadt/writeattributevalue/temperatur/7O1Rq2zsU4ByAgBUcFRq26'', ... (4 bytes)
log:  Received CONNACK (0, 0)
Connected with result code 0
log:  Received SUBACK
log:  Sending PUBLISH (d0, q0, r0, m3), 'b'simulation/raspi_musterstadt/writeattributevalue/luftfeuchtigkeit/7O1Rq2zsU4ByAgBUcFRq26'', ... (18 bytes)
log:  Caught exception in on_publish: 'int' object has no attribute 'topic'
log:  Caught exception in on_publish: 'int' object has no attribute 'topic'

Does someone know what the problem is? The ‘msg’ parameter of the ‘on_publish’ method has appearantly no topic or payload and I have no clue why. If I type in the print-statement print(msg) it delivers an integer value, counting up from 3 (next loop: 4, …). I appreciate any help!

Asked By: leolumpy

||

Answers:

From the docs:

on_publish(client, userdata, mid)

Called when a message that was to be sent using the publish() call has
completed transmission to the broker. For messages with QoS levels 1
and 2, this means that the appropriate handshakes have completed. For
QoS 0, this simply means that the message has left the client. The mid
variable matches the mid variable returned from the corresponding
publish() call, to allow outgoing messages to be tracked.

This callback is important because even if the publish() call returns
success, it does not always mean that the message has been sent.

The value is NOT the msg object it is just the mid (message id) as returned by the publish() message (for QOS 1 or 2) messages.

Answered By: hardillb