Conditional debug

I've got conditional debug working in other sketches, as has been described many times here in the forum. For this project I've got a IoT device and I thought it would be a good idea to push debug messages to the web interface. I want to be able to have 3 levels of debug: off, to serial and to web interface. I've got the initial conditionals as:

#ifdef DEBUG
  #ifdef LIVEDEBUG

int pushDebug(const char *x) {
  char payload[strlen(x)+6];
  const char *first = "data: ";
  strcpy(payload,first);
  strcat(payload,x);
  server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
  server.sendHeader("Pragma", "no-cache");
  server.sendHeader("Expires", "-1");
  server.send(200, "text/event-stream", payload);
}
    #define D(x)    pushDebug(x)
  #else
    #define D(x)    Serial.print(x)
  #endif
#else
  #define D(x)
#endif

But I get a lot of type errors that honestly are above my understanding of types (still learning). Serial.print() accepts any type, but I have to define a type for x in pushDebug() or I get an x is not defined. This fails miserably when I pass pushDebug an int, for example (cannot convert 'ota_error_t' to 'const char*, cannot convert 'int' to 'const char*, ...).

Can I make pushDebug() accept any type? Or is this the completely wrong way of going about it? Or have I missed some other fundamentally basic thing (most probable)?

  char payload[strlen(x)+6];
  const char *first = "data: ";
  strcpy(payload,first);
  strcat(payload,x);

You just wrote outside of memory you own, because you didn't allow room for the terminating NULL. Anything that the program does after this is not guaranteed to be right.

Can I make pushDebug() accept any type?

No. C does not work that way. You could defeat all the rules and make it take a void *, which would allow you to pass it anything, but then you'd need the function to understand that it can get any type, and convert that unknown type to a string, which would be a nightmare.

Doing your debugging in a class, and overloading the printDebug() method all the same ways that the Print class overloads the print() method would be one approach.

Or, just make printDebug() accept strings, and handle the conversion of the values to string before calling the function. You could have just a few functions like printDebugInt() and printDebugFloat() that do the proper conversion and then call printDebug() with the resulting string.

PaulS:

  char payload[strlen(x)+6];

const char *first = "data: ";
 strcpy(payload,first);
 strcat(payload,x);



You just wrote outside of memory you own, because you didn't allow room for the terminating NULL. Anything that the program does after this is not guaranteed to be right.

Good catch. That was a typo; I was accounting for an extra character, but put a space that shouldn't be there. would

 char payload[strlen(x)+6];
  const char *first = "data:"; // 5 bytes
  strcpy(payload,first);
  strcat(payload,x);

this work?

I'll convert all the other calls to pushDebug() to use a string. Sounds like that's the easiest approach.

Thanks!

Would this work?

Yes, but why not let the compiler do all the counting?

  const char *first = "data:"; // 5 bytes
  char payload[strlen(first) + strlen(x) + 1];
  strcpy(payload,first);
  strcat(payload,x);

That way, if you ever change the string that first points to, you don't need to remember to change the 6.