Pubsubclient prefix topic

Is it possible to have a prefix for a publish topic? For example the client id? Esphome does this by default. Such as: randomclientid/sensor/humidity

Reason for this is if there are multiple devices which all have a unique client id but the same topic of sensor/humidity they will all publish to the same topic.

I plan on deploying multiple Seeed XIAO esp32c3 devices, all with the same code. The code will extract the mac address to create a unique hostid so every single one will be unique. These will be deployed to multiple server rooms across the US for temp/humidity to a single mqtt host.

If it is possible, what is a good way to do it?

Of course it is possible. The topic name is just a string so you can concatenate it with another string to create a unique topic name

Where are you stuck ?

publish topic + clientID.

Made a little progress this morning.

What I am stuck with is how to concatenate it. I am ignorant on the how. I am admittingly not a programmer. Have just cobbled together code from various places. I have about 30 different things I want to publish(floats, doubles, etc) that already exist in the code so I want to simplify the publish lines as much as possible.

Here is the code that I think would be helpful to look at to start.

#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient client(espClient);

const char* mqtt_username = "mqtt";
const char* mqtt_password = "password";

String temp_str;
String hum_str;
String client_str;
char APssid[25];
char temp[50];
char hum[50];
char clientid[50];
int32_t chipid=ESP.getEfuseMac();
snprintf(APssid,25, "Sensor-%08X",chipid);

const char broker[] = "192.168.80.21";
int        port     = 1883;

//set interval for sending messages (milliseconds)
const long interval = 2000;
unsigned long prevMills = 0;

void initMQTT() 
{
  Serial.println("MQTT Starting...");
  client.setServer(broker, 1883);
}

void mqttreconnect() 
{
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting MQTT connection...");
    if (client.connect(APssid))
    //if (client.connect(APssid, mqtt_username, mqtt_password))
      {
      Serial.println("connected");
      } 
    else 
      {
      Serial.print("failed, rc=");
      Serial.println(client.state());
      // Wait 5 seconds before retrying
      delay(1000);
      }
  }
}

void mqttLoop() 
{
    if (!client.connected()) 
    {
    mqttreconnect();
    }
  client.loop();

  unsigned long mqttMills = millis();

  if (mqttMills - prevMills >= interval) {
    // save the last time a message was sent
    prevMills = mqttMills;
    
    // send message, the Print interface can be used to set the message contents
    
    client_str = String(APssid);
    client_str.toCharArray(clientid, client_str.length() + 1);
    //Serial.println("Sending MQTT Data");
    hum_str = String(Humidity);
    hum_str.toCharArray(hum, hum_str.length() + 1);
    client.publish(clientid "/sensor/Humidity", hum);
  }
}

Suppose that you have a topic named Humidity and a device named DHT11 then take a look at this

char topic[] = {"/Humidity"};
char device[] = {"DHT11"};
char fullTopic[30];

void setup()
{
  Serial.begin(115200);
  strcpy(fullTopic, device);  //copy device name to full topic
  strcat(fullTopic, topic);   //concatenate the topic name
  Serial.println(fullTopic);
}

void loop()
{
}
1 Like

ok, but in the above "dht11" is static. I wouldn't be able to use it unless I gave every single board a static name instead of it being based on the chipid.

Looking for a way to have the same sketch be used on hundreds of devices. Such as:
client.publish(clientID + "/sensor/humidity", hum);

Can you get the chipid into a variable ?

Yes. If you look at the code its APssid. It is what the wifi hostname is and is also used as the clientid for the client.connect

The code that I posted was an example of the use of the strcpy() and strcat() functions. Both will happily accept a variable as their arguments so you can ise APssid as the argument to strcpy() or you could create the full topic name in snprintf()

snprintf(APssid,25, "Sensor-%08X/Humidity",chipid);

I hope that it goes without saying that "/Humidity" could be replaced with a variable

Apricate the help, and appreciate "Teaching a man to fish".

Getting back to this now that I have got the circuit board design done and sent off.

Good luck with the fishing :grinning:

Thank you again.

Got it working. it was the strcpy/strcat that did it. Have all the sensors now reporting and each device shows up as I expect it to in mqtt explorer.

Now on to building out the web interface for this & the rest of the device.

Thanks again for leading the way to the answer.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.