MQTT QoS 1 not working

Hi folks,
since my home automation / IoT devices grows I get the problem that mqtt messages get dropped. So I switched all mqtt nodes from QoS 0 to QoS 1 and hoped to get an easy fix. -> fail.
I am unsure why this does not work. When I watch the broker traffic / topics with mqtt.fx I still see the message have QoS 0 and the problem remains. Why is that ?


Although probably not causing your problem, but MQTT topics should not start with / separator, as it's purpose is to separate 2 topic levels.
For example SwitchCommandsA/lighting.

1 Like

Which versions of node-red (see that bottom of the Menu dropdown), nodejs (command node -v), and the mqtt nodes (in Manage Palette) are you using?

Also, how have you configured the MQTT In node?

[Edit] and which broker are you using?

  • node red is V2.2.2
  • nodejs is v14.18.1
  • The mqtt nodes I am using are coming with node red (v2.2.2) by default. I cannot find a version in "Managed Palette". - At least I guess these nodes get updates too when updating node red.
    The mqtt config:
    image

    image

    Th broker is mosquitto version 1.5.7

Yes, you are right, they are part of the core.

Rather than use a third party client use an MQTT In node to subscribe to the topic. Make sure you specify QoS 1 there too and see what you get. It works for me

Test flow. Note that the debug node is set to Complete Message so you can see the QoS

[{"id":"189aa4a4d572cdd9","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":2520,"wires":[["1d65cfb647cce860"]]},{"id":"703075d6505da00b","type":"debug","z":"bdd7be38.d3b55","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":470,"y":2580,"wires":[]},{"id":"a2cd79334f6b8714","type":"mqtt in","z":"bdd7be38.d3b55","name":"","topic":"test/qos","qos":"1","datatype":"auto","broker":"adf2dac3.b20fe8","nl":false,"rap":true,"rh":0,"inputs":0,"x":310,"y":2580,"wires":[["703075d6505da00b"]]},{"id":"1d65cfb647cce860","type":"mqtt out","z":"bdd7be38.d3b55","name":"","topic":"test/qos","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"adf2dac3.b20fe8","x":320,"y":2520,"wires":[]},{"id":"adf2dac3.b20fe8","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"tigger/LWT","birthQos":"0","birthPayload":"Online","birthMsg":{},"closeTopic":"tigger/LWT","closeQos":"0","closePayload":"Offline","closeMsg":{},"willTopic":"tigger.LWT","willQos":"0","willPayload":"Offline","willMsg":{},"sessionExpiry":""}]
1 Like

I suspect the QoS 0 value you see in MQTT FX is the subscription QoS not how the packet was published.

Remember, node-red is a client & so is MQTT FX. MQTT subscriptions have a QoS value to the broker just as publish have a QoS value to the broker.

The QoS part from node-red to broker is handled between the broker and the publishing client & the magic that makes it work is under the hood.

1 Like

+1 to that. I have just tried with MQTT Explorer and it also shows 0. I would have thought it (and MQTT.fx) should subscribe with QoS 2 so it would actually show the published QoS. Otherwise it is a waste of time showing anything, I think. I can't see anything in mqtt explorer settings that allow this to be changed.

1 Like

@Colin
Thx for your example.
wait what .... do you mean that I didn t need mosquitto because node red nodes do work without any installation of a broke because there is a broker implemented !?

@Steve-Mcl
Thanx for your explanation !
So QoS 1 is properly send but it then is no fix for my problem I guess.
Well.... I thought a bit and I think my implementation is the problem why it does not work as expected. All my light switches have subscribed to the topic "SwitchCommandsA" and look if the message contains their MAC == ID ....
Now the broker send with QoS 1 and is okay with anyone taking the message. Dam it. While coding the ESP stuff it seemed to be a nice thing.

No, you still need the broker.

1 Like

Everyone subscribing to the message is guaranteed to get it at least once.
How exactly do you know that messages are getting lost? Is there some particular circumstance under which this appears to happen?

Sorry for my late response. The problem is still not solved. I took some time to test things and make sure what could solve it.

The problem:
Devices sometimes do not get the command from the MQTT - broker. As a result the light does not turn of or on proper. The problem grows with more devices connected.
More devices does not only mean more workload to MQTT broker and devices it does mean more WiFi workload and that s where I guess the reason.

The solution (hopefully):
Make sure all my devices get the command from MQTT even under difficult conditions (lost connection...etc.).

Technical situation:
Not every device (ESP12) has its own topic. They are bundled in types that does mean. e.g. all switch have subscribed with QoS 0 to "SwitchCommandsA"
and publish with QoS 0 to "SwitchTypA". The ESPs deserialize the message and drop messages witch does not contains there ID.

In the past I thought "bundle switches to one topic" is good concept. At least from implementation perspective IF the switch acclivity and the number of switches is limited.
I still don t think this causes the current problems because I watched the activity and even on "one message per minute" my problem accrues.

Solving the problem first idea:
To make sure ESPs get the commands under all conditions:

  • ESPs need to subscribe the topic with QoS 1/2 instead of QoS 0.
  • Node Red needs to send with QoS 1/2 too.
  • Clean falg set to false.

I dropped this idea because I found this:

(Source: http://www.steves-internet-guide.com/mqtt-clean-sessions-example/ )

Solving the problem second idea:
According to the table (above) the device will get all messages one a reconnection. Since the device only needs the last message setting the retain flag should fix my problem.
I tested it out: switched the state of a light while it was disconnected from power and connected to power again: it worked while my tests.

BUT yesterday I it happened again. - The light didn´t switched off :frowning:

I tested again and found out that retain is coupled to one topic and will only deliver the LAST MESSAGE PER TOPIC. If the WiFi connection is lost to more than one device I properly run into that issue.

Solving the problem third idea:

  • Every device subscribe an own and a group topic like mqtt topic with retain flag and QoS 0.

The current code wise implementation (ESP8266):

...

#define MQTT_QOS 1

if (client_global.connect(id.c_str(), settingsMemory.mqtt_User.c_str(), settingsMemory.mqtt_Password.c_str())) 
{
  client_global.subscribe(settingsMemory.mqtt_Subscribe.c_str(), MQTT_QOS);    
  break;
} 
...

the fix (?):

...

#define MQTT_QOS 1

if (client_global.connect(id.c_str(), settingsMemory.mqtt_User.c_str(), settingsMemory.mqtt_Password.c_str())) 
{
  client_global.subscribe(settingsMemory.mqtt_Subscribe.c_str(), MQTT_QOS);    #
  client_global.subscribe(WiFi.macAddress().c_str(), MQTT_QOS);  
  break;
} 
...

Did I miss something ?

Those two appear to be in contradiction. You say in the first that the device only needs the last message, but then say that it is a problem for you.

You are right. Because of that my solution would be to give every device a specific topic to subscribe (mac address). As I described above many switches subscribe to the same topic. If something goes wrong (e.g. connection lost) then only the last / one message for this topic is retained. This will lead to my problem.

Do you mean that currently you publish messages for all devices to some/topic where the device that should take note is in, for example, msg.payload.id, or something along those lines anyway? If so then yes, move the id to the topic, so topic is some/topic/id. Then anything that wants access to all those messages can subscribe to some/topic/#, and can then parse the topic to get the id if necessary, and any devices that only want messages for themselves can subscribe to some/topic/my_id

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.