Read body of message and write to string

Based on this code which returns all text messages that are unread

modem = SerialAT which is Serial1

void Check_Balance()
{
  CheckBalanceCount++;                         // increment x by one and returns the old value of x
  String smsNumber = "2424";                   //Skinny is the Operator
  String smsMessage2 = "BAL";                  //Request the balance of the account
  
  if (CheckBalanceCount >= 80) {              //Check balance once a week 604800 300 is 5 minutes
    CheckBalanceCount = 0;
    modem.sendAT("+CMGD=0,2");                 //0 param starting index # mesgs be deleted. 2 param only read messages should be deleted
    modem.waitResponse(5000L);
    modem.sendAT("+CMGF=1");                   //Set the message format to text mode
    modem.waitResponse(1000L);
    modem.sendAT("+CMGS=\"",smsNumber,"\"");   // Send a message to the number 2424
    modem.waitResponse(1000L);
    SerialAT.print(smsMessage2);               //Write the SMS message
    modem.waitResponse(1000L);
    SerialAT.write(CR);                        // Send the Ctrl+Z character to terminate the message
    modem.waitResponse(5000L);
    pDBGln("+CMGS Sent BALANCE request");
    //modem.sendAT("+CMGL=\"ALL\"");            //All messages
    //modem.sendAT("+CMGD=1");                  //Read and delete message
     modem.waitResponse(5000L);               //Wait up to 5 seconds for the message response
    modem.sendAT("+CMGL=\"REC UNREAD\"");   //Received unread messages e.g. new message
     modem.waitResponse(5000L);               //Wait up to 5 seconds for the message response
  delay(5000);
 }
}

So this will text 2424 with BAL to then list unread messages

Output is

OK
AT+CMGD=0,2
OK
AT+CMGF=1
OK
AT+CMGS="2424"
> 
+CMGS: 169
OK
+CMGS Sent BALANCE request
AT+CMGL="REC UNREAD"
+CMGL: 0,"REC UNREAD","2424","","23/03/05,13:41:00+52"
Hi! Your Skinny balance is
$11.70 credit
For your account info, text INFO to 2424.


I now want to read the body of the text message and write to a string? So where do I start, my end goal is to check the balance on the SIM as a string to then send via MQTT. So in the out put above is the string was Message I want it to reflect the balance which is 11.70.

Advice where to start please?

How are you currently printing out the response received from the modem?

Please post ALL your code.

Thanks total code is few 1000 lines now and hard to remove private info.

Prints out all messages prior it delete all read so technically only ever one sms unread

modem.sendAT("+CMGL=\"REC UNREAD\"");

Send 2424 BAL to operator and it returns balance

AT+CMGL="REC UNREAD"
+CMGL: 0,"REC UNREAD","2424","","23/03/05,13:41:00+52"
Hi! Your Skinny balance is
$11.70 credit
For your account info, text INFO to 2424.

So in essence I just want to write 11.70 to a string to use with a MQTT publish.

Hope this makes sense.

Assuming that you are capturing the response from the modem in a char array(?)... then you could use something like below, to parse the array and look for the "$" character to locate the amount. Then keep reading until you find the trailing space.

char buffer [] = "Hi! Your Skinny balance is $11.70 credit.  For your account info, text INFO to 2424.";
char amount[10];
uint8_t idx = 0;

void setup()
{
  Serial.begin(115200);
  
  char * ptr = strstr(buffer, "$") + 1;

  while (*ptr != ' ')
  {
    amount[idx++] = *ptr;
    ptr++;
  } 
  amount[idx] = '\0'; 

  Serial.println(buffer);
  Serial.println(amount);
}

void loop()
{}

Thanks and no to char array, not at this stage need some guidance on what I should do here.

the command +CMGR AT command, sms_message_body which looks to be the better way than listing.

You will need the responses from the modem held in a buffer ... as you need to parse that buffer to look for responses you are interested in.

Depending on your modem, I usually prefer AT+CMGRD as it deletes the message after reading it... so you don't need an extra call to delete it.

The both commands require the message ID to be passed... which you can get from the +CMTI URC that is generated when the message arrives.

Modem is a Sim 7600, output is as follows

14:29:44.937 -> AT+CMGF=1
14:29:44.937 -> 
14:29:44.937 -> OK
14:29:44.937 -> AT+CNMI=2,1
14:29:44.984 -> 
14:29:44.984 -> OK
14:29:44.984 -> AT+CMGS="2424"
14:29:44.984 -> 
14:29:44.984 -> > 
14:29:47.401 -> 
14:29:47.401 -> +CMGS: 2
14:29:47.401 -> 
14:29:47.401 -> OK
14:29:47.401 -> +CMGS Sent BALANCE request
14:29:47.401 -> AT+CMGL="REC UNREAD"
14:29:47.492 -> 
14:29:47.492 -> +CMGL: 0,"REC UNREAD","2424","","23/03/08,14:27:49+52"
14:29:47.492 -> Hi! Your Skinny balance is
14:29:47.492 -> $11.45 credit
14:29:47.492 -> For your account info, text INFO to 2424.
14:29:47.492 -> 
14:29:47.492 -> OK
14:29:47.492 -> AT+CMGRD=0
14:29:47.537 -> 
14:29:47.537 -> +CMGRD: "REC READ","2424","","23/03/08,14:27:49+52"
14:29:47.537 -> Hi! Your Skinny balance is
14:29:47.537 -> $11.45 credit
14:29:47.537 -> For your account info, text INFO to 2424.
14:29:47.572 -> 
14:29:47.572 -> OK

Revised code which puts the following into message:

15:13:18.068 -> AT+CMGF=1
15:13:18.116 -> 
15:13:18.116 -> OK
15:13:18.116 -> AT+CNMI=2,1
15:13:18.116 -> 
15:13:18.116 -> OK
15:13:18.116 -> AT+CMGS="2424"
15:13:18.116 -> 
15:13:18.116 -> > 
15:13:20.800 -> 
15:13:20.800 -> +CMGS: 19
15:13:20.800 -> 
15:13:20.800 -> OK
15:13:20.800 -> +CMGS Sent BALANCE request
15:13:20.800 -> AT+CMGL="REC UNREAD"
15:13:20.845 -> 
15:13:20.845 -> +CMGL: 0,"REC UNREAD","2424","","23/03/08,15:11:23+52"
15:13:20.845 -> Hi! Your Skinny balance is
15:13:20.845 -> $11.45 credit
15:13:20.845 -> For your account info, text INFO to 2424.
15:13:20.845 -> 
15:13:20.845 -> OK
15:13:20.845 -> AT+CMGRD=0
15:13:21.954 -> message: 
15:13:21.954 -> +CMGRD: "REC READ","2424","","23/03/08,15:11:23+52"
15:13:21.954 -> Hi! Your Skinny balance is
15:13:21.954 -> $11.45 credit
15:13:21.954 -> For your account info, text INFO to 2424.
15:13:21.954 -> 
15:13:21.954 -> OK

void Check_Balance()
{
  CheckBalanceCount++;                         // increment x by one and returns the old value of x
  String smsNumber = "2424";                   //Skinny is the Operator
  String smsMessage2 = "BAL";                  //Request the balance of the account
  
  if (CheckBalanceCount >= 100) {           //Check balance once a week 604800 300 is 5 minutes
    CheckBalanceCount = 0;
    //modem.sendAT("+CMGD=0,2");                 //0 param starting index # mesgs be deleted. 2 param only read messages should be deleted
    //modem.waitResponse(5000L);
    modem.sendAT("+CMGF=1");                   //Set the message format to text mode
    modem.waitResponse(1000L);
    modem.sendAT("+CNMI=2,1");                 //Enable SMS message notifications
    modem.waitResponse(1000L);
    //modem.sendAT("+CMGS=\"",smsNumber,"\"");   //Send a message to the number 2424
    String command = "+CMGS=\"" + smsNumber + "\"";
    modem.sendAT(command);
    modem.waitResponse(1000L);
    SerialAT.print(smsMessage2);               //Write the SMS message
    modem.waitResponse(1000L);
    SerialAT.write(CR);                        //Send the Ctrl+Z character to terminate the message
    modem.waitResponse(5000L);
    pDBGln("+CMGS Sent BALANCE request");

    String data;
    modem.sendAT("+CMGL=\"REC UNREAD\"");   //Received unread messages e.g. new message
    modem.waitResponse(5000L);   //Wait up to 5 seconds for the message response and store it in the string variable
    modem.sendAT("+CMGRD=0");   // Send AT+CMGR command to read the SMS message at index 1 then deletes it
    //modem.waitResponse(5000);  //Wait up to 5 seconds for the message response
    //SerialAT.readString();
    data = SerialAT.readString();
    Serial.print("message: ");
    Serial.println(data);
    delay(5000);
      }
    }

Ok, so the information is now held in a String variable, called "data".

You need to parse that variable to get the amount. Pretty much as I showed you in the previous post.

String data = {"Hi! Your Skinny balance is $11.45 credit  For your account info, text INFO to 2424."};

void setup()
{
  Serial.begin(115200);
  Serial.println(getAmount(data));
}

void loop()
{}


String getAmount(String buffer)
{
  
  char amount[10];
  uint8_t idx = 0;

  char * ptr = strstr(buffer.c_str(), "$") + 1;

  while (*ptr != ' ')
  {
    amount[idx++] = *ptr;
    ptr++;
  } 
  amount[idx] = '\0'; 

  return amount;
}

You would probably want to make things more robust... in case you don't find an amount for example, but hopefully you get the idea.

PS. Avoid Strings if you can... better to just use C-strings (0x00 terminated char array).

Many thanks, will revise but this code is now working

void Check_Balance()
{
  CheckBalanceCount++;                         // increment x by one and returns the old value of x
  String smsNumber = "2424";                   //Skinny is the Operator
  String smsMessage2 = "BAL";                  //Request the balance of the account
  
  if (CheckBalanceCount >= 86400) {           //Check balance once a day 86400 or per week 604800
    CheckBalanceCount = 0;
    //modem.sendAT("+CMGD=0,2");                 //0 param starting index # mesgs be deleted. 2 param only read messages should be deleted
    //modem.waitResponse(5000L);
    modem.sendAT("+CMGF=1");                   //Set the message format to text mode
    modem.waitResponse(1000L);
    modem.sendAT("+CNMI=2,1");                 //Enable SMS message notifications
    modem.waitResponse(1000L);
    //modem.sendAT("+CMGS=\"",smsNumber,"\"");   //Send a message to the number 2424
    String command = "+CMGS=\"" + smsNumber + "\"";
    modem.sendAT(command);
    modem.waitResponse(1000L);
    SerialAT.print(smsMessage2);               //Write the SMS message
    modem.waitResponse(1000L);
    SerialAT.write(CR);                        //Send the Ctrl+Z character to terminate the message
    modem.waitResponse(5000L);
    pDBGln("+CMGS Sent BALANCE request");

    String data;
    modem.sendAT("+CMGL=\"REC UNREAD\"");   //Received unread messages e.g. new message
    modem.waitResponse(5000L);   //Wait up to 5 seconds for the message response and store it in the string variable
    modem.sendAT("+CMGRD=0");   // Send AT+CMGR command to read the SMS message at index 1 then deletes it
    data = SerialAT.readString();
    Serial.print("message: ");
    Serial.println(data);
    
    String balanceMessage = data.substring(data.indexOf("$"));  // extract portion of message that contains balance
    balanceMessage.trim();                                      // remove any leading/trailing white space
    float balance = balanceMessage.substring(1).toFloat();      // extract numeric value of balance
    Serial.print("Balance: ");
    Serial.println(balance);

    //mqtt.publish(topicCredit, balance);// Publish Balance to MQTT
    mqtt.publish(topicCredit, String(balance).c_str());
    delay(5000);
      }
    }

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