How to use vprintf on a wificlient tcpclient.vprintf(format, args);

Hi,
I want to write formatted data using an argument list to a TCP socket running on a ESP8266.
I do using vsprintf(buf2, format,args); to a buffer and then use TCPclient.print(buf2); to print it to the TCPclient.printf(buf2);.
I would like to use it direct without the use of a buffer but don't know if that is possible using tcpclient.vprintf(format, args);

Does anyone know if this is possible? because my platform.io indicates not to know that tcpclient.vprintf(format, args); code.
Thanks

void TCPhandler::printf(const char* format, ... ) { 
    uint16_t n; 
    va_list args;
    va_start (args, format);
    
    vsprintf(buf2,format,args);     // tcpclient.vprintf(format, args) is better but not avaialble.
    
    switch(state) {

        case TCP_PRINT:     { 
            if (TCPclient.connected()) TCPclient.print(buf2);
            else    if (SERIAL_connected) { 
                        Serial.printf(buf2);
                        state=SERIAL_PRINT;
                    }
        }
        break;

if the compiler says it does not exist, then it does not :slight_smile:

the Print class does not support vprintf(), only printf()

i often use sprintf() since printf() is not available and then do Serial.print(s) of the formatted string as well as sending the formatted string over bluetooth or wifi

gcjr:
i often use sprintf() since printf() is not available and then do Serial.print(s) of the formatted string as well as sending the formatted string over bluetooth or wifi

if you follow my link in my previous post, you'll see that printf is available (on ESP).

gcjr:
i often use sprintf() since printf() is not available and then do Serial.print(s) of the formatted string as well as sending the formatted string over bluetooth or wifi

Thanks for your support the problem is Printf doesn't support an argument list and can't be used for that reason.

the problem is Printf doesn't support an argument list

Under what circumstances is that true ?

have you tried to run

va_list args;
va_start (args, format);
if (TCPclient.connected()) TCPclient.printf(format,args);
va_end (args);

————

And if you want full support for vprintf, you can... The beauty of open source is that you can extend the librairies to suit your needs...

So you locate on your computer the following files (on my Mac they are in ~/Library/Arduino15/packages/esp8266/hardware/esp8266/2.7.4/cores/esp8266)
Print.h

add line 84 the following déclaration

       /* ********************************************************************** */
        /* J-M-L TESTING */
        /* ********************************************************************** */
        size_t vprintf(const char * format, va_list arg);
        size_t vprintf_P(PGM_P format, va_list arg);
        /* ********************************************************************** */

then you go to Print.cpp and add at line 103 (or anywhere, just for coherence)

/* ********************************************************************** */
/* J-M-L TESTING */
/* ********************************************************************** */
size_t Print::vprintf(const char * format, va_list arg) {
  char temp[64];
  char* buffer = temp;
  size_t len = vsnprintf(temp, sizeof(temp), format, arg);
  if (len > sizeof(temp) - 1) {
    buffer = new (std::nothrow) char[len + 1];
    if (!buffer) {
      return 0;
    }
    vsnprintf(buffer, len + 1, format, arg);
  }
  len = write((const uint8_t*) buffer, len);
  if (buffer != temp) {
    delete[] buffer;
  }
  return len;
}

size_t Print::vprintf_P(PGM_P format, va_list arg) {
  char temp[64];
  char* buffer = temp;
  size_t len = vsnprintf_P(temp, sizeof(temp), format, arg);
  if (len > sizeof(temp) - 1) {
    buffer = new (std::nothrow) char[len + 1];
    if (!buffer) {
      return 0;
    }
    vsnprintf_P(buffer, len + 1, format, arg);
  }
  len = write((const uint8_t*) buffer, len);
  if (buffer != temp) {
    delete[] buffer;
  }
  return len;
}
/* ********************************************************************** */

You save both files, and voilà, the Print class now supports vprintf() and vprinf_P()

Here is an example code to test this out:

const char progmemFormat[] PROGMEM = "Testing with %s, number=%d, Hexspeak=0x%X\n";

void testVprintf (const char * format, ... )
{
  va_list args;
  va_start (args, format);
  Serial.vprintf(format, args);
  va_end (args);
}

void testVprintf_P (PGM_P format, ... )
{
  va_list args;
  va_start (args, format);
  Serial.vprintf_P(format, args);
  va_end (args);
}

void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println(F("\n\nWelcome to vprintf() extension"));
  Serial.printf("Testing with %s, number=%d, Hexspeak=0x%X\n", "RAM format printf", 10, 0xDEADBEEF);
  Serial.printf_P(progmemFormat, "PROGMEM format printf", 20, 0xBADCAFFE);

  testVprintf ("Testing with %s, number=%d, Hexspeak=0x%X\n", "RAM format vprintf", 30, 0xCAFEBABE);
  testVprintf_P(progmemFormat, "PROGMEM format vprintf", 42, 0xFEE4ABED);
}

void loop() {}

Serial Monitor (@ 115200 bauds) will show

[color=purple]

Welcome to vprintf() extension
Testing with RAM format printf, number=10, Hexspeak=0xDEADBEEF
Testing with PROGMEM format printf, number=20, Hexspeak=0xBADCAFFE
Testing with RAM format vprintf, number=30, Hexspeak=0xCAFEBABE
Testing with PROGMEM format vprintf, number=42, Hexspeak=0xFEE4ABED
[/color]

that being said, a similar code calling just printf does work too

const char progmemFormat[] PROGMEM = "Testing with %s, number=%d, Hexspeak=0x%X\n";

void testVprintf (const char * format, ... )
{
  va_list args;
  va_start (args, format);
  Serial.printf(format, args);
  va_end (args);
}

void testVprintf_P (PGM_P format, ... )
{
  va_list args;
  va_start (args, format);
  Serial.printf_P(format, args);
  va_end (args);
}

void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println(F("\n\nWelcome to vprintf() extension"));
  Serial.printf("Testing with %s, number=%d, Hexspeak=0x%X\n", "RAM format printf", 10, 0xDEADBEEF);
  Serial.printf_P(progmemFormat, "PROGMEM format printf", 20, 0xBADCAFFE);

  testVprintf ("Testing with %s, number=%d, Hexspeak=0x%X\n", "RAM format vprintf", 30, 0xCAFEBABE);
  testVprintf_P(progmemFormat, "PROGMEM format vprintf", 42, 0xFEE4ABED);
}

void loop() {}

same output

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