MQTT - How to remove retained messages?

Just out of curiosity, how were you doing this? Was retain=true in effect?

Thanks to everyone for their responses, I must admit I didn’t expect this to become such a useful thread.

@DavidFW1960, yes I have seen that video and I have sent all those commands for my Sonoffs but I had some old Owntracks retained messages that I wanted to clear out.

Interestingly last night while I was messing around with this I restarted the Mosquitto add-on a few times while my Sonoff controlled lights were on and at some point they turned off. I must still have something not quite right :roll_eyes: Maybe I will try removing Mosquitto and re-adding it so I can start from scratch…

@123 First time I tried using the hassio MQTT Developer Tools page but I wasn’t setting the retain flag, partly because I didn’t think of it (doh!) but partly and perhaps because, I couldn’t see how to set it on that page.

Second time I tried using MQTT.fx but again I didn’t set the retain flag, this time entirely because I didn’t think of it.

It’s funny how sometimes some very small gaps in knowledge can lead to big misunderstandings. Thanks again for all the pointers.

if you shell into the hassio instance you can enter these commands and hit enter… :wink:

example:

mosquitto_pub -h IP-ADDRESS -p 1883 -u USERNAME -P PASSWORD -t “homeassistant/sensor/tradfri_motion_sensor_3_battery/state” -r -n

of course the topic can be any topic, and any level in that topic you need, or use # to delete all topics retained

You mean SSH will accept these commands??
I never knew that either. I thought it would only take a very few commands which were specific to HA e.g. shutting down or restarting.

But then I have very rarely had the need to use SSH.

Thanks for that info!

o yes:

core-ssh:~# mosquitto_pub --help
mosquitto_pub is a simple mqtt client that will publish a message on a single topic and exit.
mosquitto_pub version 1.4.15 running on libmosquitto 1.4.15.

Usage: mosquitto_pub [-h host] [-k keepalive] [-p port] [-q qos] [-r] {-f file | -l | -n | -m message} -t topic
                     [-A bind_address] [-S]
                     [-i id] [-I id_prefix]
                     [-d] [--quiet]
                     [-M max_inflight]
                     [-u username [-P password]]
                     [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]
                     [{--cafile file | --capath dir} [--cert file] [--key file]
                      [--ciphers ciphers] [--insecure]]
                     [--proxy socks-url]
       mosquitto_pub --help

 -A : bind the outgoing socket to this host/ip address. Use to control which interface
      the client communicates over.
 -d : enable debug messages.
 -f : send the contents of a file as the message.
 -h : mqtt host to connect to. Defaults to localhost.
 -i : id to use for this client. Defaults to mosquitto_pub_ appended with the process id.
 -I : define the client id as id_prefix appended with the process id. Useful for when the
      broker is using the clientid_prefixes option.
 -k : keep alive in seconds for this client. Defaults to 60.
 -l : read messages from stdin, sending a separate message for each line.
 -m : message payload to send.
 -M : the maximum inflight messages for QoS 1/2..
 -n : send a null (zero length) message.
 -p : network port to connect to. Defaults to 1883.
 -P : provide a password (requires MQTT 3.1 broker)
 -q : quality of service level to use for all messages. Defaults to 0.
 -r : message should be retained.
 -s : read message from stdin, sending the entire input as a message.
 -S : use SRV lookups to determine which host to connect to.
 -t : mqtt topic to publish to.
 -u : provide a username (requires MQTT 3.1 broker)
 -V : specify the version of the MQTT protocol to use when connecting.
      Can be mqttv31 or mqttv311. Defaults to mqttv31.
 --help : display this message.
 --quiet : don't print error messages.
 --will-payload : payload for the client Will, which is sent by the broker in case of
                  unexpected disconnection. If not given and will-topic is set, a zero
                  length message will be sent.
 --will-qos : QoS level for the client Will.
 --will-retain : if given, make the client Will retained.
 --will-topic : the topic on which to publish the client Will.
 --cafile : path to a file containing trusted CA certificates to enable encrypted
            communication.
 --capath : path to a directory containing trusted CA certificates to enable encrypted
            communication.
 --cert : client certificate for authentication, if required by server.
 --key : client private key for authentication, if required by server.
 --ciphers : openssl compatible list of TLS ciphers to support.
 --tls-version : TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1.
                 Defaults to tlsv1.2 if available.
 --insecure : do not check that the server certificate hostname matches the remote
              hostname. Using this option means that you cannot be sure that the
              remote host is the server you wish to connect to and so is insecure.
              Do not use this option in a production environment.
 --proxy : SOCKS5 proxy URL of the form:
           socks5h://[username[:password]@]hostname[:port]
           Only "none" and "username" authentication is supported.

See http://mosquitto.org/ for more information.

core-ssh:~#
2 Likes

Just as an alternative, you can use the mqtt.publish service from the services developer tools page.

2 Likes

Thanks! Much more useful than the MQTT page!

@DavidFW1960 Just a quick clarification about your automation. Do you not have any Sonoff basics? I ask because you are only publishing to ‘power1’, 2, 3 and 4. I only see retained messages for these topics on my 4 Channel Sonoff, all my basics only have ‘power’ (no numerical suffix).

I only have basics. The sonoff group is a catch all for all sonoff. (It’s a published automation on the Tasmota Github)

My guess is you have retain: true specified for your MQTT Lights in configuration.yaml. Ensure it is set to retain: false (which happens to be the default).

Ideally, you only want state topics to be retained, not command topics. Generally speaking, that means your MQTT lights in Home Assistant ought to be configured retain: false and the physical lights (using Tasmota, ESPurna, ESPEasy, etc) configured retain: true.

Why? Because if a command topic is retained, you’re telling the MQTT broker to supply the topic’s message to every subscriber upon connection. That’s rarely desirable.

For example, let’s say home/garage_door_opener/command is retained.

  • You command the door to open (command topic’s message is on).
  • Then someone closes the door manually (command topic’s message is still on).
  • The MQTT broker reboots and informs its subscribers of all its retained topics.
  • The garage door opener receives the command on.
  • Uh-oh, probably not the behavior you want!

Basically, all you retain are state topics. After the broker reboots (or a subscriber like Home Assistant reconnects) it reports to subscribers what’s currently on/off, opened/closed, etc (state topic) as opposed to instructing subscribers to turn on/off, open/close, etc (command topic).

3 Likes

@123 That’s a great explanation. Thanks.

Here’s the link

Not sure if this is possible in all settings, but this is the main reason I use MQTT only for state topics, and command via Api calls… Reporting a wrong state can be annoying but commanding a wrong command can be fatal…;-((

Also watch the video I linked to above. It’s well worth watching.

Yes I watched it when it came out and then again a few days ago. It is indeed very good but it also helps seeing it explained in writing.

1 Like

Agreed, it’s not always possible to be so ‘surgical’ and have retain=true used exclusively for state topics. Having said that, at the very least you are able to control the retain flag on a per device basis in Home Assistant. It would be far more encumbering if retain was a global setting for all of Home Assistant’s MQTT communications!

When determining who uses retain=true and who does not, the question is “Who is the controller and who is being controlled?”

  • The controller publishes commands so it should use retain=false.
  • The device being controlled publishes its state so it should use retain=true.

A sensor is a device that is not controlled but does publish its state. Most of the time it probably should publish it with retain=true. However, there may be some time-sensitive cases where you might not want the sensor’s value to be retained.

EDIT
FWIW, I had used an excellent product called Home Remote. It’s not a Home Automation system but a user-interface builder (whose client software runs on iOS, Android, and Windows) that can work with many, many different devices and protocols. I had created a UI that worked exclusively via MQTT. You quickly learn a lot about what things should/shouldn’t employ retain=true when using a phone app that you regularly connect and disconnect from the MQTT broker!

I guess if you are using MQTT discovery, the retain setting won’t be set in Home Assistant anyway as you remove the manual configuration of the switch and then the device controls it via the set options anyway.

I switched to discovery and removed all MQTT config from my configuration and everything seems to be ‘happy’ and working as I expect it to be.

Indeed, even in ‘non-discovery’ mode, where you explicitly define each MQTT entity, retain is false by default for all MQTT components.

Yes it is but almost everyone posting MQTT settings has that set to true I have noticed. (I used to as well before I saw that video and had a few chats when my switches were doing what I thought was weird stuff)
I have even seen people posting that retain should be true.

Perhaps they do it because of an incomplete understanding of how retain works. It’s the old ‘throw it against the wall and see if it sticks’ strategy! :slight_smile: Turn retain on and if it seems to fix something then all must be well.

Here’s a scenario that shows why ‘if it sticks to the wall’ can be misleading:

  • Use Home Assistant to turn on a light (publish command topic with retain=true).
  • MQTT Broker retains a copy of the message and passes it on to the light.
  • Light turns on.
  • Power failure!
  • Light and Home Assistant and MQTT Broker are off.
  • Power is restored.
  • Home Assistant and MQTT Broker come back to life.
  • MQTT Broker forwards the retained message to the light.
  • Light turns on.

Everything has been restored to its pre-power failure state so the user is lulled into believing all is well. Except, not really; we know this technique of retaining command topics is flawed (i.e. example above; garage door opener).

  • First, restoring a device’s state should, ideally, be the responsibility of the controller, namely Home Assistant, not the ‘middleman’ (the MQTT Broker). Alternately, it can be the responsibility of the device itself (which proceeds to report its state to the controller).

  • Second, it should be based on the device’s state prior to the power failure and not on, what is essentially, a cached command in the broker.

It’s almost a given that when someone complains that an MQTT device turned itself on/off “mysteriously”, they’re experiencing the anomaly outside of normal operating conditions. The “mystery” usually occurs when a link in the chain disconnects/reconnects, like after a restart of Home Assistant, or the MQTT Broker, or the device (or some combination of the above). That’s when the drawback of retaining command topics usually surfaces.

1 Like