PubSubClient not working. Solved

I am using esp8266’s as sensors connecting to Home Assistant through a Mosquitto MQTT broker. I have several sensors that are set up and working properly. I tried today to add another sensor and cannot get it to transfer information to the broker.
Using MQTTspy I have verified that the broker is receiving data from the other sensors. I also verified that I can publish a value from MQTTspy and have it show up on the Home Assistant user interface.
The esp8266 thinks it is sending data to the broker, but MQTTspy doesn’t see it.

The code is a bit of a mashup. I hope that I won’t offend somebodies sensibility with my coding style.

This code has worked in the past. The only thing that I can guess is wrong is a problem with a library update.
Perhaps somebody with a sharp eye will discern something that I am doing incorrectly.

Here is some diagnostic output from the Arduino com port.

INFO: Connecting to [redacted]
..........
INFO: WiFi connected
INFO: IP address: 
192.168.1.177
INFO: Attempting MQTT connection...INFO: connected
29.28
0.00
68.92
State topic: bme280_1
Data: {"pressure":"29.28","humidity":"0.00","temperature":"68.92"}
Message length: 61

INFO: Closing the MQTT connection
INFO: Closing the Wifi connection

This is the code running on the esp8266. I have omitted the credentials for obvious reasons.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "credentials.h"

#include <stdint.h>
#include "SparkFunBME280.h"
#include "Wire.h"

//Global sensor object
BME280 mySensor;

WiFiClient wifiClient;
PubSubClient client(wifiClient);

// function called to publish the temperature and the humidity
void publishData(float p_pressure, float p_humidity, float p_temperature) {
  // create a JSON object
  // doc : https://github.com/bblanchon/ArduinoJson/wiki/API%20Reference
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  // INFO: the data must be converted into a string; a problem occurs when using floats...
  root["pressure"] = (String)p_pressure;
  root["humidity"] = (String)p_humidity;
  root["temperature"] = (String)p_temperature;
//  root.prettyPrintTo(Serial);
//  Serial.println("");

  char data[200];
  root.printTo(data, root.measureLength() + 1);
  client.publish(MQTT_SENSOR_TOPIC, data, true);
  
// diagnostic print
  Serial.print("State topic: ");
  Serial.println(MQTT_SENSOR_TOPIC);
  Serial.print("Data: ");
  Serial.println(data);
  Serial.print("Message length: ");
  Serial.println(root.measureLength() + 1);
  Serial.println();


}

// function called when a MQTT message arrived
void callback(char* p_topic, byte* p_payload, unsigned int p_length)
{
}

void reconnect()
{
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("INFO: Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD))
    {
      Serial.println("INFO: connected"); \
    }
    else
    {
      Serial.print("ERROR: failed, rc=");
      Serial.print(client.state());
      Serial.println("DEBUG: try again in 5 seconds");
    }
    // Wait 5 seconds before retrying
    delay(5000);
  }
}


void setup()
{

  //***Driver settings********************************//

  //specify I2C address.  Can be 0x76(default) or 0x77
  mySensor.settings.commInterface = I2C_MODE;
  mySensor.settings.I2CAddress = 0x76;

  //***Operation settings*****************************//

  //renMode can be:
  //  0, Sleep mode
  //  1 or 2, Forced mode
  //  3, Normal mode
  mySensor.settings.runMode = 3; //Normal mode

  //tStandby can be:
  //  0, 0.5ms
  //  1, 62.5ms
  //  2, 125ms
  //  3, 250ms
  //  4, 500ms
  //  5, 1000ms
  //  6, 10ms
  //  7, 20ms
  mySensor.settings.tStandby = 6;

  //filter can be off or number of FIR coefficients to use:
  //  0, filter off
  //  1, coefficients = 2
  //  2, coefficients = 4
  //  3, coefficients = 8
  //  4, coefficients = 16
  mySensor.settings.filter = 4;

  //tempOverSample can be:
  //  0, skipped
  //  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
  mySensor.settings.tempOverSample = 4;

  //pressOverSample can be:
  //  0, skipped
  //  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
  mySensor.settings.pressOverSample = 4;

  //humidOverSample can be:
  //  0, skipped
  //  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
  mySensor.settings.humidOverSample = 4;


  // init the serial
  Serial.begin(115200);
  Serial.print("Program Started\n");
  Serial.print("Starting BME280... result of .begin(): 0x");

  //Calling .begin() causes the settings to be loaded
  delay(10);  //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up.
  Serial.println(mySensor.begin(), HEX);

  // init the WiFi connection
  Serial.println();
  Serial.println();
  Serial.print("INFO: Connecting to ");
  WiFi.mode(WIFI_STA);
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("INFO: WiFi connected");
  Serial.println("INFO: IP address: ");
  Serial.println(WiFi.localIP());

  // init the MQTT connection
  client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
  client.setCallback(callback);
}

void loop()
{
  if (!client.connected())
  {
    reconnect();
  }
  client.loop();
  {
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)

    delay(2000);

    float p = mySensor.readFloatPressure();
    float h = mySensor.readFloatHumidity();
    float t = mySensor.readTempF();

    if (isnan(p) || isnan(h) || isnan(t))
    {
      Serial.println("ERROR: Failed to read from sensor!");
      return;
    }
    else
    {
      // Adjusted for elevation of 202m and converted Pa to inHg.
      p = (p + 2514.05) * 0.0002952998751;
      Serial.println(p);
      Serial.println(h);
      Serial.println(t);
      publishData(p, h, t);
    }

    Serial.println("INFO: Closing the MQTT connection");
    client.disconnect();

    Serial.println("INFO: Closing the Wifi connection");
    WiFi.disconnect();

    ESP.deepSleep(SLEEPING_TIME_IN_SECONDS * 120, WAKE_RF_DEFAULT);
    delay(500); // wait for deep sleep to happen
  }
}
void publishData(float p_pressure, float p_humidity, float p_temperature) {
  // create a JSON object
  // doc : https://github.com/bblanchon/ArduinoJson/wiki/API%20Reference
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  // INFO: the data must be converted into a string; a problem occurs when using floats...
  root["pressure"] = (String)p_pressure;

You can’t cast a float to a String! At least not meaningfully.

While you may be right about casting a float to a string , that isn't the problem.
The same code is working on six other modules. I just can't create a new module. I even tried reprogramming a working module and it no longer works.

The problem might be deep sleeping before the data has left the ESP8266. One solution is to wait for the connection to finish the close handshake after calling disconnects. I would also add a loop count exit so the CPU does not get stuck in the loop and drain your battery.

while mqttClient.connected() OR tcpClient.connected() {
    delay(short time such as 10 ms)
}
delay(a bit more just in case of lingering data)

Now deepsleep

Thanks to all, but especially @gdsports. You nailed it...almost.
The problem was closing the wifi connection before the message completed.
Your suggestion of adding a test for closed wifi and mqtt before sleep is a good one. I implimented that and still had the problem. I added a delay after publishing the data and before closing the connections, all works correctly. Mosquitto is accepting the data and Home Assistant is publishing data again.

      publishData(p, h, t);
      delay(20); //wait for data to be published.
    }

    Serial.println("INFO: Closing the MQTT connection");
    client.disconnect();



    Serial.println("INFO: Closing the Wifi connection");
    WiFi.disconnect();

        while (client.connected() || (WiFi.status() == WL_CONNECTED))

    {
      Serial.println("Waiting for shutdown before sleeping");
      delay(10);
    }
    delay(10);



    ESP.deepSleep(SLEEPING_TIME_IN_SECONDS * 60, WAKE_RF_DEFAULT);
    delay(500); // wait for deep sleep to happen
  }

below is the diagnostic output from the Arduino serial port. I still have to understand this business of casting a float to a string. For my limited range of data it seems to be working correctly.

Starting BME280... result of .begin(): 0x58


INFO: Connecting to [redacted]
..........
INFO: WiFi connected
INFO: IP address: 
192.168.1.177
INFO: Attempting MQTT connection...INFO: connected
Float data from sensor: 
28.68
0.00
69.46
State topic: bme280_1
Data: {"pressure":"28.68","humidity":"0.00","temperature":"69.46"}
Message length: 61

INFO: Closing the MQTT connection
INFO: Closing the Wifi connection

I still have to understand this business of casting a float to a string.

The proper thing to do is to pass the float to the String constructor:

  root["pressure"] = String(p_pressure);

The String class knows how to make a String object that wraps a string instance that contains the representation of a float.

Telling the compiler to treat the memory location where the float bytes are stores as though the memory location contained a String object is wrong.