Problems with String and const char*

Hi. I'm having troubles setting apn and user in tinyGsmClient.
If I define String apn="live.vodafone.com";
then call
modem.gprsConnect(apn.c_str(), user, pwd)
in debug window I see
AT+SAPBR=3,1,"APN","live.vodafone.com"

OK
However, if I read the apn name from a line inside a file in my sdcard (the same apn name obviously), I get
AT+SAPBR=3,1,"APN","live.vodafone.com"

ERROR

So: defining the String at the beginning isn't the same as reading the same data from SD?

Imagine for a moment that we can't see your code. How then could anyone help you?

apn.c_str is not a const char*.

Try const char apn[18] = "live.vodafone.com";

The address is simply apn, no dot anything.
This is a const char array string that can be stored in flash, saving RAM.

Actually, it is. See WString.h:

const char* c_str() const { return buffer; }

then why's it no work?

It does, go back and read Post #1.

It's the second part that doesn't work. The reason why not is a mystery since @davidk decided not to post any code.

First of all, thanks for trying to help despite lack of the code.
Here's my code:

#include "FS.h"
#include "SD.h"

#define SIM800L_IP5306_VERSION_20190610

#include "utilities.h"  //this is for Lilygo T-call SIM800 board I use

#define SCK  14
#define MISO  2
#define MOSI  15
#define CS  13
SPIClass spi = SPIClass(VSPI);

// Define the serial console for debug prints, if needed

#define TINY_GSM_MODEM_SIM800      // Modem is SIM800
#define TINY_GSM_RX_BUFFER   1024  // Set RX buffer to 1Kb
#include <TinyGsmClient.h>
#define RXD2 26
#define TXD2 27
#define SerialAT   Serial2
const char apn2[] = "live.vodafone.com";
const char gprsUser[] = "live";
const char gprsPass[] = "";
String apn;//="live.vodafone.com";//, gprsUser, gprsPass;



#define DUMP_AT_COMMANDS

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif

#include <ArduinoHttpClient.h>
TinyGsmClient client(modem);

int i;

void setup()
{ int i;
  Serial.begin(115200); delay(1500); Serial.println("Hello!");

  // Start power management
    if (setupPMU() == false) {
        Serial.println("Setting power error");
    }
    // Some start operations
  setupModem(); 
  SerialAT.begin(115200, SERIAL_8N1, RXD2, TXD2);
  delay(6000);
  if (!modem.init()) {
    Serial.println("Failed to initialize modem");
    delay(2000);
  }
  SerialAT.println("AT"); //Once the handshake test is successful, it will back to OK
  delay(200);
  initSDcard();  
  readInternet(SD, "/internet.txt"); 
  delay(10000);
}


void loop()
{  
  
    connectGPRS(); 
    disconnectGPRS();
    delay(60000);
  
}

void connectGPRS(void)
{ 
  if (!modem.gprsConnect(apn.c_str(), gprsUser, gprsPass))
  //if (!modem.gprsConnect(apn2, gprsUser, gprsPass))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" success");

    if (modem.isGprsConnected())
    {
        Serial.println("GPRS connected");
    }

}

void disconnectGPRS(void)
{
  modem.gprsDisconnect(); Serial.println("GPRS disconnected");
}


char readInternet(fs::FS &fs, const char * path)
{ //return 0 daca e OK
  String kkk;
  Serial.printf("Reading file: %s\n", path);
  File file = fs.open(path);
  if(!file){
    Serial.println("Failed to open file for reading");
    return(1);
  }
  apn=file.readStringUntil('\n');
  Serial.print("APN:"); Serial.println(apn);
  file.close();
  return(0);
}

unsigned char initSDcard() //returneaza 0 daca e OK
{
  spi.begin(SCK, MISO, MOSI, CS);
  if (!SD.begin(CS,spi,80000000)) {
  Serial.println("Card Mount Failed");
  } 
  
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  return 0; 
}

Now, as I said in the first post, I isolated the faulty spot.
If I connect with apn2 (see the commented line) it works.

The output is:
Hello!

AT

OK

ATE0

OK

AT+CMEE=0

OK

AT+CLTS=1

OK

AT+CBATCHK=1

OK

AT+CPIN?
OK

SD Card Size: 7497MB

Reading file: /internet.txt

APN:live.vodafone.com

AT+CIPSHUT

OK

AT+CGATT=0

Call Ready

SMS Ready

+CTZV: +12,1

*PSUTTZ: 2023,10,5,12,47,40,"+12",1
ERROR

AT+CGACT=1,1

OK

AT+SAPBR=1,1

ERROR

AT+SAPBR=2,1

+SAPBR: 1,3,"0.0.0.0"
AT+CIPQSEND=1

OK

AT+CIPRXGET=1

OK

AT+CSTT="live.vodafone.com ","live",""

ERROR

fail

AT+CIPSHUT

SHUT OK

AT+CGATT=0

OK

GPRS disconnected

My bad. From Post #7:

It appears I misread Post #1. I thought it said "apn.c_str()" did work.

String apn="live.vodafone.com";

then call modem.gprsConnect(apn.c_str(), gprsUser, gprsPass) works

What's not working is populating the string with apn=file.readStringUntil('\n');
Please note in debug window I can see the apn is also correct in the non-working situation!

right... I was going off the error code words, if the compiler says no then find another way is kind of reflex kicked in.

But replacing a String with a smaller array that can be stored in flash which String cannot.... hey, I tried.

To me, String objects don't make sense in less than large deeply organized code where object privacy makes sense.
But up to that, using C methods to operate on buffers makes sense.

can you cast it as const?

Right before the call to 'modem.gprsConnect()', try printing out all the individual bytes of 'apn.c_str()', in HEX , up to and including the terminating NULL byte. Look for any hidden, non-printable characters in there.

1 Like

Thanks gfvalvo for the tip.
The printed data:
live.vodafone.comSize of apn.c_str()=4
6c 69 76 65 2e 76 6f 64 61 66 6f 6e 65 2e 63 6f 6d 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Note the apn.c_str()=4 ???? where did this came from? Probably this returns the size of the pointer...
Another issue might be the 0x0d? Should have been zero here?
The code for the above print:

Serial.printf(apn.c_str()); Serial.printf("Size of apn.c_str()=%d \n",sizeof(apn.c_str()));
for(i=0; i<32; i++){
    Serial.printf("%02x ",apn.c_str()[i]);
}

From the sizeof which returned the size of the pointer that points to the c string..
try strlen() instead to get length of string..

good luck.. ~q

the hex data shows 17 printable chars and a carriage return (0D) before the terminating zero.

1 Like

Nice catch @qubits-us.

I'd be willing to bet that's the problem.

It's the Carriage Return at the end of the line in the SD card file you read:

apn = file.readStringUntil('\n');

Probably best not to include it. Or, strip it out before using the String.

Yep, that's the real problem. Forcing this 17th character (0D) to 0 solved the issue.

18th char but it's not the count but the 0D being "illegal" that matters.
You used a read until function where if you read and buffered each char as it arrived, you could 'vet' your data to filter out errors.

The data source tacks an ASCII CR on every line sent. Serial Monitor has an option to do that and some things need the CR. Mine is set to add LF, Line Feed = 10. BTW, I hate line entry user input!

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