Number of characters in a String

Hey everyone, I am trying to get the number of characters that are in a String. The text is getting sent over from NodeRed to the public HiveMQ broker and to my Serial Monitor. However when I use the length function in Arduino it only prints out 1s and not the actual character numbers. I will paste the part of my code in here. Thanks in advance!

void callback(char* topic, byte* payload, unsigned int length) {
  //Serial.print("Weergave payload=");
  for (int i = 0; i < length; i++) {
    playingsong = ((char)payload[i]);
    int CharacterLength = Serial.print(playingsong.length());
  }
  Serial.println();
}

Broker
Monitor

Are you looking for strlen?

(What data type is "playingsong"?
I'm guessing a String. Hard to tell from your snippet)

What's this for?

  • The payload is a pointer to an array of chars, not a String
  • You are setting playingsong to a single character of the array in each step of the for loop.
  • I assume, but can't tell, that playingsong is declared as a String but you only ever assign a single character to it
  • If you want to know the length of the payload then why not use the conveniently named length variable passed to the callback() function ?

Oh yes my bad, I forgot to add that in. "playingsong" is indeed a String. That is for getting the song name out of the void callback. So if I would say "Serial.print(playingsong);" it would print the name.

I've checked many websites on how to do this and some use strnlen and others say Mystring.length(); but both versions don't work.

Yes "playingsong' is indeed a String, I forgot to put that in sorry. So if I would say "Serial.print(playingsong);" it would print out the song name. I've tried printing out the length veriable as you mentioned but still no luck. This is my code now

void callback(char* topic, byte* payload, unsigned int length) {
  //Serial.print("Weergave payload=");
  for (int i = 0; i < length; i++) {
    playingsong = ((char)payload[i]);
    Serial.print(length);
  }
  Serial.println();
}

What is the value of the parameter "length"?

This is what it corresponds to


void callback(char* topic, byte* payload, unsigned int length) {
  //Serial.print("Weergave payload=");
  for (int i = 0; i < length; i++) {
    playingsong = ((char)payload[i]);
    Serial.print(length);
  }
  Serial.println();
}

Broker

Please explain what you think that does.

Are you receiving the song name one character at a time?
I only ask because IT IS REALLY HARD TO TELL FROM THE SNIPPET YOU POSTED.

Sure, so this stores the song name in the var "playingsong". This just makes it easier to read and understand. I receive the song name instantly so it's not one character at a time. And I'm sorry I thought the code would be a bit too long to post in here but I will add it in now. I appreciate your help and time.

#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>

const char* ssid = "Sint-Rembert Techniek";
const char* password = "Dt16Mc6UJa35";
const char* mqtt_server = "broker.mqtt-dashboard.com";

LiquidCrystal_I2C lcd(0x3F, 16, 2);
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;
String playingsong = "";
String nextsong = "";

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  //Serial.print("Weergave payload=");
  for (int i = 0; i < length; i++) {
    playingsong = ((char)payload[i]);
    Serial.print(length);
  }
  Serial.println();
}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // ... and resubscribe
      client.subscribe("ThiboSpotify");
    }
    else {
      Serial.print("failed, rc=");
      Serial.println(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  unsigned long now = millis();
  //int Clength = playingsong.length();
  //Serial.print(Clength);
  //for (int i = 0; i < Clength; i++) {
    // scroll one position left:
    //lcd.scrollDisplayLeft();
    // wait a bit:
    //delay(400);
  }

The payload is not a String. Payload is an array of characters. The for loop in your callback is converting the character array to a String. After the for loop is done, then print the String length of playsong.

Though serial printing from a callback is not good practice.

Is it, or is it simply setting playingsong to each character in the array in turn ?

Maybe the original had a '+=' rather than a simple assignment.

Sorry, I was not done editing yet.

Whatever the origin of the sketch, the irony is that the posted sketch does not need to use a String or a for loop in order to print the payload

void callback(char* topic, byte* payload, unsigned int length)
{
  char messageBuffer[30];
  memcpy(messageBuffer, payload, length);
  messageBuffer[length] = '\0';
  Serial.printf("%s\n", messageBuffer);
}

If String is to be used. I'd declare the String and in setup(), set the String to a reserve() size. Say 100. Then I'd use playingsong.concat( String(((char)payload[i]) ) to put data into the String reserved space and use "" to empty the String reserved space. Otherwise using String may create memory holes and consume ram and cause a system crash.

reserve() - Arduino Reference

I'm getting more confused as this thread goes on. Can you back away from the code and explain what you are trying to do, because every explanation seems slightly different. My understanding is that you are trying to put the payload into a String variable called playing song, in which case this:

playingsong= String((const char*)payload);

should be all you need, assuming payload is null-terminated. Or, if it's not null-terminated and you need to use the length variable,

playingSong = String((const char*)payload, length); 

should work.
But if you need to know the length of the String, isn't that what "length" already is?
What am I missing?

It won't be

Fair enough. I'm working with a similar application ATM where I'm getting the song & artist from a Bluetooth A2DP message, so I figured this might be doing the same thing.

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