When using platformio, add this in lib_deps:

256dpi/MQTT @ ^2.5.2

Create 256mqtt.h and include it in the main source code, define the MQTT_HOST, MQTT_PORT and MQTT_TOPIC as well:

const char *mqtt_broker = "broker.emqx.io";  // EMQX broker endpoint
const char *mqtt_topic = "emqx/esp8266";     // MQTT topic
const char *mqtt_username = "emqx";  // MQTT username for authentication
const char *mqtt_password = "public";  // MQTT password for authentication
const int mqtt_port = 1883;  // MQTT port (TCP)

const char *lwt_topic = "esp8266/status";
const char *lwt_message = "device is offline now";
const int lwt_qos = 1;
const bool lwt_retain = true;

Code for mqtt.h (including Last Will and Testament (LWT):

#include <ESP8266WiFi.h>  // this is for ESP8266, change for ESP32
#include <MQTT.h>

WiFiClient espClient;
MQTTClient mqtt_client;

bool mqttconnected = false;

void messageReceived(String &topic, String &payload)
{
    Serial.println("incoming: " + topic + " - " + payload);
    // Note: Do not use the client in the callback to publish, subscribe or
    // unsubscribe as it may cause deadlocks when other things arrive while
    // sending and receiving acknowledgments. Instead, change a global variable,
    // or push to a queue and handle it in the loop after calling `client.loop()`.
}



void connectmqtt()
{
    Serial.print("\nconnecting...");
    while (!mqtt_client.connect(mqtt_clientid, mqtt_username, mqtt_password))
    {
        Serial.print(".");
        delay(1000);
    }
    mqtt_client.subscribe(mqtt_topic);
    mqtt_client.setWill(lwt_topic,lwt_message,lwt_retain,lwt_qos);
}

void initializemqtt()
{
    mqtt_client.begin(mqtt_broker, espClient);
    mqtt_client.onMessage(messageReceived);
    connectmqtt();
}

In the loop:

  mqtt_client.loop();

  if (!mqtt_client.connected()) {
    connectmqtt();
  }

To set will; Set a will message (last testament) that gets registered on the broker after connecting. setWill() has to be called before calling connect():

void setWill(const char topic[]);
void setWill(const char topic[], const char payload[]);
void setWill(const char topic[], const char payload[], bool retained, int qos);
void clearWill();

To Subscribe or Publish:

bool subscribe(const String &topic);
bool subscribe(const String &topic, int qos); 
bool subscribe(const char topic[]);
bool subscribe(const char topic[], int qos);

To Publish:

bool publish(const String &topic);
bool publish(const char topic[]);
bool publish(const String &topic, const String &payload);
bool publish(const String &topic, const String &payload, bool retained, int qos);
bool publish(const char topic[], const String &payload);
bool publish(const char topic[], const String &payload, bool retained, int qos);
bool publish(const char topic[], const char payload[]);
bool publish(const char topic[], const char payload[], bool retained, int qos);
bool publish(const char topic[], const char payload[], int length);
bool publish(const char topic[], const char payload[], int length, bool retained, int qos);

Advance options:

void setKeepAlive(int keepAlive);
void setCleanSession(bool cleanSession);
void setTimeout(int timeout);
void setOptions(int keepAlive, bool cleanSession, int timeout);

Below link:

https://registry.platformio.org/libraries/256dpi/MQTT https://github.com/256dpi/arduino-mqtt