ESP8266 subscribed to MQTT but callback not called if topic only changes a little

Hi,

First post here, please bear with me and let me know if I posted in the wrong category.

I am monitoring a solar inverter with an ESP32 (s3 devkit), then publishing sensor values (battery voltage, current, etc.) to HA. All the sensors are published under one device (let’s call it “inverter”), which is created through MQTT discovery.
Everything works fine, HA UI gets updated, and I can see the state topic being updated when connecting MQTT Explorer.

I am now building a control board for a water heater with a ESP8266 (NodeMCU/LolinV3). It creates another device through MQTT discovery, updates its state topic regularly and provides a command topic. All of that works fine (HA’s UI gets updated, and I get the messages on the ESP8266 when I control the device from HA)

Now I want to retrieve the battery voltage from the inverter on that second device, so I know if I can start the heater or not. I therefore tried to subscribe to the inverter’s state topic (homeassistant/device/inverter/state) but I am not receiving anything from HA, unless the topic changes drastically.

The inverter state topic looks like this:
{ battery_voltage: 52.1, battery_current: 5.6, ... }
It is getting updated every 30s. A typical update will see small changes in values (for example: 52.1 to 52.2) and the JSON properties names never change.
The problem is, I do not receive any callback for those typical updates (either if some value gets changed by the inverter itself of if I change them manually in MQTT explorer for testing).
However, if I completely change the topic format with MQTT explorer, for example to this:
{ test: 123.456 }
then I receive the message just fine.

I looked here and everywhere and couldn’t find any help on this issue. More details:

  • I am using PubSubClient on both ESPs
  • I am using the default MQTT broker in HA (Mosquitto add-on)
  • I set up a simple username/password on the Mosquitto broker
  • MQTT connection is fine and monitored (reconnect if disconnected, client.loop() called in main loop: the state and command topic work just fine and I almost never saw a reconnection, meaning it is always connected)
  • I am calling subscribe after connection is established (and re-subscribe after a reconnection)

As I am completely lost on this, any idea would be appreciated. Thanks in advance :slight_smile:

I have no idea how that is possible. Any update on the topic should be pushed by the broker to clients subscribed to the topic. That’s how MQTT works.

1 Like

I finally found the issue…

TL/DR: Increase the PubSubClient buffer size.

Longer explanation if it might help others in the future:

The inverter is publishing about 20 values. The whole JSON + the topic name results in a MQTT packet of about 500 bytes.
PubSubClient default send/receive buffer is only 256 bytes so obviously the packet will be dropped.

When I publish data, I’ve implemented a mechanism that tries to publish with PubSubClient.publish() which uses the internal buffer and if that fails (most likely because the payload is too big) then publishes with PubSubClient.beginPublish/write/endPublish.
(this is especially useful to publish the quite long discovery messages without having to use a huge internal buffer)

But, while this works just fine when publishing, but it can not be done when subscribing.
The send/receive buffer needs to be set with PubSubClient.setBufferSize to make sure it’s large enough to be able to receive the longest payload that might be published on the topic you’re subscribing to.

And there’s no warning/log of any sort that a packet is dropped, so it took me a while to figure it out…anyway, glad it works now :slight_smile: