Persistent Client with Mosquitto not working as intended

Hello,

i've got a problem regarding persistent sessions when connecting from Node-RED to my Mosquitto broker.

Im currently running Node-RED v2.2.2 and Nodejs v14.19.1 on my Raspberry Pi. The server running the mqtt.js-script i'll mention later is running Nodejs v.16.15.1.

Regarding mqtt, i'm using the nodes that are contained in the basic Node-RED installation.

The mosquitto broker is configured to use mqtts and mqtt v5 and the basic stuff is working fine. I can send messages, i can receive messages and the will and birth messages are working as expected aswell.

Also i've set persistence true and persistent_client_expiration 14d in my mosquitto.conf.

When i connect to the broker with my mqtt.js script, where the client is set to clean: false and sessionExpiryInterval: 2592000 i can see in the mosquitto.db that the client has the values Session expiry time: 0 and Session expiry interval: 2592000. For this client everything works perfectly, when i reconnect i don't receive any old retained messages and missed messages are received. I can also see that the missed messages are sent in the mosquitto.log file

However, when i connect with a client from Node-RED where the Use clean start-Box isn't checked and the Session Expiry (secs) is set to 2592000, this client has Session expiry time: 0 and Session expiry interval: 0 in the mosquitto.db. In this case it seems like i don't receive any old retained messages, but i also don't receive any missed messages. This is also confirmed by the mosquitto.log, where it doesn't mention any messages that are sent to the client when it connects.

The messages i want to receive are all sent with qos: 2. For subscription in NodeRED i use a dynamic subscription with the following function node in front:

msg.action = "subscribe";
msg.topic = {topic:flow.get("mqtt_topic") + "/some_topic", qos:2, nl:false, rap:true, rh:true};
return msg;

This subscription is triggered by an inject node that is injected once 0.1 seconds after flow startup.

The messages are neither received when i stop Node-RED, send the message, and then restart Node-RED nor when i unplug the network cable, wait for the last will to trigger, send the message and then plug it in again. When i don't wait for the last will when just unplugging the network cable the message gets through because the client hasn't officially disconnected from the broker yet.

Is there anything wrong with my subscription configuration or are there any other settings in the Node-RED mqtt-broker node i have to set?

To me it looked like those two settings are the only ones related to persistent sessions in the broker node.

Or do you have any other idea why it might not work like i expect it to?

Before digesting your full post and attempting any sort of test, can I recommend that you upgrade to Node-red V2.2.3 (or better still node-red v3.0.2).
There were a number of MQTT issues fixed in V3.0 that were back ported to V2.2.3.

If you can, upgrade an repeat your tests.

If you still have an issue, I would suggest you create a minimal flow (and step by step instructions) that demonstrate your issues (this way, others can try it and report back on what they find).

Hello Steve,

thanks for answering so quickly. I didn't notice Node-RED 2.2.3 got released. I've seen now that it was mentioned in the end of the 3.0 blog post.

I've upgraded to v2.2.3 for now as i don't have the time currently to test if everything will still work on v3.

Sadly the problems still remains with 2.2.3 as it did with 2.2.2. :frowning:

I've built a small flow, that should be usable to test. I've tried to enter all the settings that should be needed to understand my configuration, without leaking anything.

[
    {
        "id": "66665620ee0f942d",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "10e93a9230f786ee",
        "type": "mqtt in",
        "z": "66665620ee0f942d",
        "name": "Subscribe",
        "topic": "",
        "qos": "2",
        "datatype": "auto",
        "broker": "652b515d2702868a",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 1,
        "x": 680,
        "y": 480,
        "wires": [
            [
                "6077501aadbc3fd5"
            ]
        ]
    },
    {
        "id": "6ddf714390eb2e63",
        "type": "inject",
        "z": "66665620ee0f942d",
        "name": "inject",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "0.1",
        "topic": "",
        "x": 370,
        "y": 480,
        "wires": [
            [
                "cc85799bd023dbb2"
            ]
        ]
    },
    {
        "id": "cc85799bd023dbb2",
        "type": "function",
        "z": "66665620ee0f942d",
        "name": "Set MQTT Topic",
        "func": "msg.action = \"subscribe\";\nmsg.topic = {topic:\"some/random/topic\", qos:2, nl:false, rap:true, rh:true};\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 520,
        "y": 480,
        "wires": [
            [
                "10e93a9230f786ee"
            ]
        ]
    },
    {
        "id": "6077501aadbc3fd5",
        "type": "debug",
        "z": "66665620ee0f942d",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 830,
        "y": 480,
        "wires": []
    },
    {
        "id": "652b515d2702868a",
        "type": "mqtt-broker",
        "name": "",
        "broker": "",
        "port": "8883",
        "tls": "12e956d8a888d3bb",
        "clientid": "clientid",
        "autoConnect": true,
        "usetls": true,
        "protocolVersion": "5",
        "keepalive": "60",
        "cleansession": false,
        "birthTopic": "some/other/topic",
        "birthQos": "2",
        "birthRetain": "true",
        "birthPayload": "Client online",
        "birthMsg": {},
        "closeTopic": "some/other/topic",
        "closeQos": "2",
        "closeRetain": "true",
        "closePayload": "Client offline",
        "closeMsg": {},
        "willTopic": "some/other/topic",
        "willQos": "2",
        "willRetain": "true",
        "willPayload": "Client offline",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": "2592000",
        "credentials": {
            "user": "",
            "password": ""
        }
    },
    {
        "id": "12e956d8a888d3bb",
        "type": "tls-config",
        "name": "",
        "cert": "",
        "key": "",
        "ca": "",
        "certname": "",
        "keyname": "",
        "caname": "",
        "servername": "",
        "verifyservercert": false,
        "alpnprotocol": "",
        "credentials": {}
    }
]

As far as the mosquitto.conf goes, those are the most important settings (the persistent_client_expiration is set to 14 days so if i forget to set a value in the client configuration, the client won't be kept forever):

persistence true
persistence_location /var/lib/mosquitto/
persistent_client_expiration 14d
autosave_interval 300

log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
log_type debug
log_type subscribe
log_type unsubscribe

listener 8883 0.0.0.0
require_certificate false

For TLS i use a selfsigned OpenSSL certificate. I don't check for the certificate on the clients, since there won't be an easy way to update the certificates when the Raspberry Pis will be used in production, so the certificate has to be valid for a long time. That's also why the TLS Configuration in Node-RED is completely empty.

I think that should be all setup wise. Now to get to the problem:

When i start the flow, the birth message is sent, and while the Raspberry Pi is connected to the internet, all communication is going smooth.

Also Mosquitto realises, that the client wants a persistent session, since the client is added to the persistence-file that is stored in the persistence-location mentioned in the mosquitto.conf.

The big problem is, that the client has Session expiry interval: 0, even though i set it to 2592000 in Node-RED.

Now i disconnect the Node-RED client (either by stopping the node-red service or by unplugging the network cable), and i send a message to the subscribed topic. Now open the mosquitto.log-file with tail -f. When the client reconnects, mosquitto doesn't send the missed message. But acknowledges that the client has subscribed to the topic.

I would doubt my mosquitto configuration is the issue. As i mentioned in my original post, when i connect a persistent client via mqtt.js, everything works as expected. That client gets missed messages and has the correct Session Expiry Interval: 2592000 in the mosquitto.db.

I hope the explanation of what im trying to do is understandable.

@maxw thanks for the info. I have my suspicions on the reason for this issue but i dont want this to get forgotten (the forum fills up with too much interesting noise to use it for tracking) - could i please request that you raise a new issue on the node-red repository? I dont want this to get missed. Thanks so far.

Please drop link to the issue raised in this thread & a link in the issue to this thread (so forum and github users can trace this) - ta.

Thanks for the help so far. I've now opened an issue in the github repository:

1 Like