MQTT Node exhibits instability

Sorry, I missed this question when I posted my earlier response. The answer is no, node-red-start starts node-red running as a service, then shows the node red log and leaves the log display running. Breaking out of that will return you to a command prompt but leave node red running in the background.
Once node-red is running you can see the ongoing log using
node-red-log

... node-red-stop is just a wrapper for sudo systemctl stop nodered that is (to me at least) easier to remember - that goes with node-red-start and node-red-reload (stop then start :slight_smile: )

There's a big difference between node-red-start and node-red start, as we've often seen in forum posts.

Shame the commands weren't called start-node-red, stop-node-red and reload-node-red

Should NR (5?) interpret start, stop and reload as command line flags rather than flow file names?

It is interesting that node-red admin is treated as if node-red-admin had been run. Perhaps you are right, that stop, start and reload should be treated similarly. @dceejay?
That would certainly prevent some issues seen here regularly.

There is no node-red-admin .... node-red does have a bunch of command line options (see node-red --help ) of which admin is one.

All the node-red-* commands are added by the Pi/Linux install script that interact with systemctl and are not available on Windows and other OS. As these are operating system level commands it would be hard to cover all possible OS within the core of Node-RED.

I guess we could add a catcher for node-red stop and node-red start that says "Did you mean node-red-start?" but then that would break anyone who did have a flow called start...

I see you are right. I was confused by this output (on Ubuntu) when I run node-red admin

$ node-red admin
Usage:
   node-red-admin <command> [args] [--help] [--userDir DIR] [--json]

Which I think should say

$ node-red admin
Usage:
   node-red  admin <command> [args] [--help] [--userDir DIR] [--json]

Good catch. Once upon a time node-red-admin was indeed a separate script. But that did get built in as it was OS independent.

Yes, it does and thank you & all the other guys very much for your help with this.
I'd like to clarify my understanding of what happened and on a comment that you made.

Firstly, it appears like I had inadvertantly configured two MQTT clients each publishing to a different broker, one was localhost:1883 and the other Localhost:1883 and because they shared the same port there was conflict- is that correct?

Secondly, you made the comment "So now, with only one mqtt server node, with it's client-id field empty, is it all working as it should?". The thing is, I get the "one mqtt server node" part, but I have the client-id embedded in the Topic of the mqtt output node, which it must have. I'm just passing a string "trigger" to the mqtt output node and the only way that mqtt can publish this command is to have the target client_id in the Topic field. Did you mean something else or have I missed something?

That is the Shelly's client id, you can use that in the topic, just don't put it in the node-red server node client-id field, or you will confuse mosquitto as it will get two connections with the same id.

Client-id is nothing to do with topic - at least in node-red. I don't know the Shelly devices, but if they use the shelly's client id to specify the topic they use then that is nothing to do with node red. Client id is the id of the client. The clients are the various Shelly's, any other devices you have accessing mqtt, and node-red. They must all have unique ids. In node red you can leave the client id in the mqtt server node empty (and node-red will provide a unique id for you) and still publish or subscribe to the shelly's topic.

Not because they shared the same port (it is mosquitto that has the port, not node-red), but because they had the same client-id as each other or as one of the Shellys.

An analogy that may help. Imagine you are at a meeting of people not known to each other. Each of them may have a name tag to identify them. If there are two people at the meeting with same name then confusion can occur. The client-id is like a name tag. Mosquitto gets confused if two people with the same name tag try to meet it. When the second one arrives it forgets about the first one. That is what was meant by the error you saw

It says it has already been approached by someone with the name tag shelly1-E8DB84D4D51C and is now being approached by another with the same name. It can't cope with that so forgets about the first one.
This can make sense in some circumstances. Imagine that node red is running on a PC and Mosquitto is running on different machine on the network. If the PC has both a wired and wifi connection to the network then when node-red connects it may connect on the wired connection. If you then unplug the ethernet cable then node-red will try to reconnect to mosquitto via wifi. Mosquitto will then see that the same client-id is connecting from a different ip address so will discard the original connection and create a new one, and all will carry on working.

OK thanks for the analogy, but where did I use the second client ID (refer to my ealier uploaded Flow)? The Shelly client automatically sets its ID based on the device type and MAC addresss. The only other place where I specify an ID is in the Topic for the mqtt output node. I don't pass an object to this mqtt output node only a string "trigger". The client ID is only specified in the Topic and this should be OK. However, I do understand that there was a mqtt disconnection and re-connection by the shelly with the same id. I did powerdown the shelly and restart it again at one point.

If I interrogate the status of the Shelly device, I get the following response:

{"device":{"type":"SHSW-1","mac":"E8DB84D4D51C","hostname":"shelly1-E8DB84D4D51C","num_outputs":1},"wifi_ap":{"enabled":false,"ssid":"shelly1-E8DB84D4D51C","key":""},"wifi_sta":{"enabled":true,"ssid":"Bbox","ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null},"wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null},"ap_roaming":{"enabled":false,"threshold":-70},"mqtt":{"enable":true,"server":"192.168.1.75:1883","user":"pi","id":"shelly1-E8DB84D4D51C","reconnect_timeout_max":60,"reconnect_timeout_min":2,"clean_session":true,"keep_alive":60,"max_qos":2,"retain":false,"update_period":0},"coiot":{"enabled":true,"update_period":15,"peer":""},"sntp":{"server":"time.google.com","enabled":true},"login":{"enabled":false,"unprotected":false,"username":"admin"},"pin_code":"","name":null,"fw":"20230913-112003/v1.14.0-gcb84623","factory_reset_from_switch":true,"pon_wifi_reset":false,"discoverable":true,"build_info":{"build_id":"20230913-112003/v1.14.0-gcb84623","build_timestamp":"2023-09-13T11:20:03Z","build_version":"1.0"},"cloud":{"enabled":false,"connected":false},"timezone":"Europe/Paris","lat":43.896,"lng":1.8957,"tzautodetect":true,"tz_utc_offset":3600,"tz_dst":false,"tz_dst_auto":true,"time":"13:09","unixtime":1738498173,"debug_enable":false,"allow_cross_origin":false,"ext_switch_enable":false,"ext_switch_reverse":false,"ext_switch":{"0":{"relay_num":-1}},"actions":{"active":false,"names":["btn_on_url","btn_off_url","longpush_url","shortpush_url","out_on_url","out_off_url","lp_on_url","lp_off_url","report_url","report_url","report_url","ext_temp_over_url","ext_temp_under_url","ext_temp_over_url","ext_temp_under_url","ext_temp_over_url","ext_temp_under_url","ext_hum_over_url","ext_hum_under_url"]},"hwinfo":{"hw_revision":"prod-191217","batch_id":1},"mode":"relay","longpush_time":800,"relays":[{"name":null,"appliance_type":"General","ison":false,"has_timer":false,"default_state":"switch","btn_type":"toggle","btn_reverse":0,"auto_on":0,"auto_off":0,"power":0,"schedule":false,"schedule_rules":[]}],"ext_sensors":{},"ext_temperature":{},"ext_humidity":{},"eco_mode_enabled":true}

Ahhhh, I see it just NOW.
Looking at the shelly status response, I've configured the shelly client (192.168.1.69) to connect to the pi mqtt server (192.168.1.75) and also gave it the name shelly1-E8DB84D4D51C , thinking that they were asking for the shelly id. That's IT, right? So, what id should I specify for the mqtt broker or is this the field that you said I should leave empty. I suppose the shelly has my pi IP and mqtt port 1883 and that should be all it needs. Correct?

To be as clear as possible. Never use the same client ID in your client connections. Even if you think you want these two devices to talk to each other. That's simply not how mqtt works.

As (hopefully) an augmentation to Colin's analogy, the client ID is a unique identifier that identifies the connecting client. If there are more than one, the broker will simply disconnect the other one. This causes a disconnection/reconnection cycle.

To try and further bolster your understanding of mqtt architecture, it is a pub sub architecture. there is one broker and multiple clients. Clients do not talk to each other. They talk via a broker. For example, 1 client tells the broker "tell me when the light switch is operated" (subscribe). The second client tells the broker "I've just turned the light switch on" (publish). The broker tells every client who are listening (subscribers) that "the light switch is on".

So if my analogy makes sense to you, you should realise that putting the client ID into another client so that they can "talk to each other" does not make any sense as they only communicate to a broker for subscribing to topics and publishing to topics.

If everything is now working ok then don't worry about it. Where I have been assuming that you had specified an id is in this dialog

If you had specified an id in the Client ID field, and used the same id in both MQTT server nodes then that was the problem.

Thanks. Yes, I realise that; in my case I thought that the shelly config page was asking for the shelly client id not the mqtt server.

Just one last thank you to you all. The experts on this forum are really comitted, patient and very generous with their time - much appreciated.

1 Like

:slight_smile:

I never use it because my Node-RED instances in systemd are not called that.

What would be REALLY useful for everyone would be adding a default npm run script. That's what I do, I add a start and a restart run script for the specific instance. I don't bother with a stop script because - well, I've so rarely ever needed to stop my live instances of Node-RED :grin:

I agree that the systemd command is utterly un-rememberable, I can't ever remember how to spell it.

I really should improve my alternate installer. But there isn't much incentive. It does just enough to be useful to me and nobody else has ever asked for more.

Isn't that what the command node-red does?

Sort-of. But it is hidden. So if you happened to have given your systemd script a different name, it won't work. At least with an npm script, the entry is easy to see and easy to amend.

In addition, it is one less command to get confused by - was it node-red stop or node-red-stop? People clearly do get confused by this.

With npm, all you need to do is run npm run to see all the scripts and this is common for all npm packages. One less thing to remember.

So which package.json do you add the npm run script to ? the system installed one that Node-RED installs or the one that gets created in ~/.node-red by the user (or the editor) adding extra nodes ?