Concat String + unsigned char + String

I need to concatenate String + unsigned char + String

 unsigned char auth[128];

String req = "{\"message-id\":\"002\",\"auth\":\"" + auth + "\",\"request-type\":\"Authenticate\"}";

I tried to convert auth to String but failed, I need the final result to be a string

webSocket.sendTXT(req);

Any idea on how can I achieve this?

But you started using a String..?

auth comes from here:

      unsigned char auth[128];
      memset(auth, 0, sizeof(auth));

      mbedtls_base64_encode(auth, sizeof(auth), &hashb64_len, sha256, sizeof(sha256));

and I need to build a String in order to create the text request

If you are really sure that you need it as a String

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  unsigned char auth[128] = {"some text in auth"};;
  char buffer[100];
  strcpy(buffer, "{\"message-id\":\"002\",\"auth\":\"");
  strcat(buffer, auth);
  strcat(buffer, "\",\"request-type\":\"Authenticate\"}");
  String outString = String(buffer);
  Serial.println(outString);
}

void loop()
{
}

I get this error message

sketch_jun13b:3:52: error: invalid operands of types 'const char [29]' and 'unsigned char [128]' to binary 'operator+'
 String req = "{\"message-id\":\"002\",\"auth\":\"" + auth + "\",\"request-type\":\"Authenticate\"}";
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~

Which is trying to tell you that the String + operator only works on Strings and needs at least one side the + to be a String.
Break the statement down into

 String req = "{\"message-id\":\"002\",\"auth\":\"";
 req += auth;
 req += "\",\"request-type\":\"Authenticate\"}";

However is auth null terminated? or just an array of bytes?
You may need to use
auth[hashb64_len] = '\0';
to terminate the array.
But check that hashb64_len is < sizeof(auth)

p.s. @UKHeliBob code will crash if hashn64_len turns out to be >40
replacing strcat wth strlcat will avoid the crash but still not give you the answer you want.

To be more precise, the code will crash if buffer is declared too small to hold the final string. I am well aware of that but what I posted was an example, not a solution

If you are really sure that you need it as a String

I am not sure, I just had a look at websocket library for the method sendTXT and I found I can pass different types.

    bool sendTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
    bool sendTXT(const uint8_t * payload, size_t length = 0);
    bool sendTXT(char * payload, size_t length = 0, bool headerToPayload = false);
    bool sendTXT(const char * payload, size_t length = 0);
    bool sendTXT(String & payload);
    bool sendTXT(char payload);

maybe need to forget String and build the message in a different way ?

It looks like you could use

bool sendTXT(char * payload, size_t length = 0, bool headerToPayload = false);

and not bother with the conversion to String, but I am not familiar with the library

bool sendTXT(char * payload, size_t length = 0, bool headerToPayload = false);

Seems like that's the one, then do I need to concatenate / append / put together the "parts" which look like this:

unsigned char auth[128];
unsigned char partA[128] = "{\"message-id\":\"002\",\"auth\":\"";
unsigned char partB[128] = "\",\"request-type\":\"Authenticate\"}";

BTW, I get this error from your example:

error: invalid conversion from 'unsigned char*' to 'const char*' [-fpermissive]
strcat(buffer, auth);
^

Just not sure the OP was clear on that :slight_smile:

Yes, you would do as in my example. Copy the first part to a char array then concatenate the other 2 parts to it

Please post a copy of your version of my example. It compiles OK for me so I suspect that your code and mine are different in some way

As an aside, have you noted the need to ensure that the buffer array is large enough to hold the final string ?

No Strings work just fine and no need to fuss about exactly how big to make Bob's buffer. Edit - if you look in the library code you will probably find they are using Strings all over the place. No. The websockets library I found uses c-strings underneath.

p.s. you need to check the hashn64_len to make sure the result was actually written.
even if you use @UKHeliBob strcat code your auth needs to be '\0' terminated.
Edit - looks like mbedtls_base64_encode does terminate the result and check there is space for the terminating '\0', so the memset(auth, 0, sizeof(auth)); is unnecessary

As I said strlcat is safer then strcat. This sketch, strlcpy_strlcat.ino, shows you how to use it and how to check for buffer overruns.

Just run the example with no other code..maybe the plattform ESP32?

As an aside, have you noted the need to ensure that the buffer array is large enough to hold the final string

Noted

Run the example and get this, wondering if something related to ESP32 and Arduino core?

In function 'void setup()':
55:53: error: 'strlcpy_P' was not declared in this scope
count = strlcpy_P(result, progStr1, sizeof(result));
^
75:53: error: 'strlcat_P' was not declared in this scope
count = strlcat_P(result, progStr2, sizeof(result));
^
exit status 1
'strlcpy_P' was not declared in this scope

It is the board type that is making the difference, but I don't know why.

Try this, which is neater anyway

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  unsigned char auth[128] = {"some text in auth"};;
  char buffer[400];  //plenty of room !
  sprintf(buffer, "{\"message-id\":\"002\",\"auth\":\"%s\",\"request-type\":\"Authenticate\"}", auth);
  Serial.print("buffer : ");
  Serial.println(buffer);
}

void loop()
{
}
1 Like

WORKS! Thanks for the guidance

That's good. Note that I deliberately went overboard with the size of the buffer array and it should be reduced to a more sensible size to suit your requirements

Than

Thanks I have updated the example. ESP32 and ESP8266 have strlcat and strlcpy but not the _P versions :frowning:
This is probably true for some other boards also

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