Help! Store Phone Number to SIM

Hello!

I have a GSM shield (antenova) connected to an Arduino UNO. I am currently using it to control LEDs. I am practicing for my diy home automation :smiley:

I need to store up to 5 phone numbers to control my GSM module. I want to enter all the number once so I don’t need to change it everytime I power on the GSM module.

Since I don’t want to buy/add an SD card shield or store data to the EEPROM, I want to store/write phone numbers to the SIM card.

I can’t find a noob friendly library that I can use in this project but I found a code (that works) which can read a certain name from the phone book. It uses AT Commands.

#include <GSM.h>
GSM gsmAccess(true);
int sizer = 200;
char myNumber[200];
int timeout = 5000; // in milli seconds

void setup()
{
  Serial.begin(9600);

  boolean notConnected = true;

  Serial.println("Connecting to the GSM network");

  while(notConnected){
    if(gsmAccess.begin() == GSM_READY) // Note: I do not require PIN #
      notConnected = false;
    else {
      Serial.println("Not connected, trying again");
      delay(1000);
    }
  }

  Serial.println("Connected");

  theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");  
  int start1 = millis();   
  while((millis() - start1) < timeout){
    theGSM3ShieldV1ModemCore.theBuffer().read();
  }   
  Serial.print("Set to look at SIM card storage");

  // search for contact name "test"
  theGSM3ShieldV1ModemCore.println("AT+CPBF=\"test\"");  
  start1 = 0;
  start1 = millis();   
  while((millis() - start1) < timeout && !theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", myNumber, sizer)){
    theGSM3ShieldV1ModemCore.theBuffer().read();
  }   
  Serial.print("Got contact number");

  // print out the phone of "test"
  Serial.println(myNumber);

}

void loop()
{

}

I checked if it is possible to store numbers on the SIM

On the Contents Table,
3.2.26 AT+CPBF Find phonebook entries
3.2.28 AT+CPBS Select phonebook memory storage
3.2.29 AT+CPBW Write phonebook entry*

Here’s the list of AT Commands:

*This means I can write numbers to the SIM :wink: Yey!

I just need to know how

Can you tell me what is the opposite of extractSubtring() so that I could learn to store to the sim?

Can you tell me what is the opposite of extractSubtring() so that I could learn to store to the sim?

Is extractSubstring() a method of some class? There isn't an "opposite of a function". There might be another function that does something that might be considered of what some function does.

But, with no context, you'll get no help.

It’s a method of class GSM3CircularBuffer. I found it at GSM3CircularBuffer.h [line 175-182]

 /** Extract a substring from circular buffer
 @param from Initial byte position
 @param to Final byte position
 @param buffer Buffer for copy substring
 @param bufsize Buffer size
 @return true if successful, false if substring does not exists
 */
 bool extractSubstring(const char* from, const char* to, char* buffer, int bufsize);

Correct me if I’m wrong, it checks if the contact exist and returns true/false.

You are right that there is no opposite of a function, I’m sorry it’s not what I meant.
I’m not familiar with GSM library, I just need a code to write an entry to the sim.

Correct me if I'm wrong, it checks if the contact exist and returns true/false.

It appears to get the data from where one pointer points to to where another pointer points to, and puts that data where a third pointer points. It returns true or false, depending on whether it was logical to do the copy, or not.

If you ask it to copy the characters between two pointers that are 257 characters apart into an array that can hold 12 characters, that is a fail.

It does NOT, I would guess, determine if the copy string equals anything, so your assertion that it checks if a contact exists appears to be wrong.

Without seeing the actual code, and how it is called, though, one can only guess.

Is this the code? I got it from GSM3CircularBuffer.cpp [line 195-231]

bool GSM3CircularBuffer::extractSubstring(const char* from, const char* to, char* buffer, int bufsize)
{
 byte t1;
 byte h2;
 byte b;
 int i;
 
//DEBUG
//Serial.println("Beginning extractSubstring");
//Serial.print("head,tail=");Serial.print(int(head));Serial.print(",");Serial.println(int(tail));
 
 if(!locate(from, head, tail, 0, &t1))
 return false;
 
//DEBUG
//Serial.println("Located chain from.");

 t1++; //To point the next.
 if(!locate(to, t1, tail, &h2, 0))
 return false;
 
//DEBUG 
//Serial.println("Located chain to.");
/*Serial.print("t1=");Serial.println(int(t1));
Serial.print("h2=");Serial.println(int(h2));*/


 for(i=0,b=t1;i<bufsize, b!=((h2) & __BUFFERMASK__); i++, b=(b+1)& __BUFFERMASK__)
 buffer[i]=theBuffer[b];
 buffer[i]=0;

//DEBUG 
//Serial.println("");
//Serial.println("Finishing extractSubstring"); 
 
 return true; 
}

PaulS:
It appears to get the data from where one pointer points to to where another pointer points to, and puts that data where a third pointer points. It returns true or false, depending on whether it was logical to do the copy, or not.
…
It does NOT, I would guess, determine if the copy string equals anything, so your assertion that it checks if a contact exists appears to be wrong.

Could you explain this part of the code? I will understand it better, I think most of my assumptions are wrong

  // search for contact name "test"
  theGSM3ShieldV1ModemCore.println("AT+CPBF=\"test\"");  //1
  start1 = 0;
  start1 = millis();   
  while((millis() - start1) < timeout && !theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", myNumber, sizer)){ //2
    theGSM3ShieldV1ModemCore.theBuffer().read(); //3
  }   
  Serial.print("Got contact number");

1: send AT command to gsm module
2: loops every five second and if it wasn’t able to do the copy.
why do i need blink without delay here?
3: why is this always called?

I tried

theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\""); and

theGSM3ShieldV1ModemCore.println("AT+CPBF=\"test\"");

without the

theGSM3ShieldV1ModemCore.theBuffer().read();

and it still works. So I tried to use AT+CPBW to write to Sim but it still doesn't work :( I don't know what to do

here's my curret code:

// Get remote number
          sms.remoteNumber(senderNumber, 20);
          Serial.println(senderNumber);
          
          //get no and store to sim
          if(adminOne == false){
            theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");           
            // write contact name "User1"
            theGSM3ShieldV1ModemCore.println("AT+CPBW=" + String(senderNumber) + ",145,\"User1\"");
            Serial.println("User1 Saved!");
          } 
          else if(adminTwo == false) {
            theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");           
            // write contact name "User1"
            theGSM3ShieldV1ModemCore.println("AT+CPBW=" + String(senderNumber) + ",145,\"User2\"");
            Serial.println("User2 Saved!");
          }

I tried placing no1 at the beginning "AT+CPBW=1," + String(senderNumber) + ",145,\"User1\"" and using 129 instead of 145 but it still can't store phonebook entry to my sim

here's the AT command description |500x420

here's my curret code:

Really? That's ALL of it? That crap won't even compile!

Sorry Paul

here’s the code:

#include <GSM.h>

int gsmPin = 13;

boolean adminOne = false; // if the admin exist
boolean adminTwo = false;

const int smsInterval = 500;
unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousSmsMillis = 0;

//---GSM
GSM gsmAccess;
GSM_SMS sms;

int sizer = 200;
char adminOneNum[100];
char adminTwoNum[100];
int timeout = 5000; // in milli seconds

#define PINNUMBER ""

char senderNumber[15];
char IMEI[20] = "861074025900000"; // changed the last five digits to '0'

boolean start = true;

void setup() { 
  // initialize serial communications and wait for port to open:
  Serial.begin(9600);
  
  digitalWrite(gsmPin, LOW);
 
  Serial.println("Sensor Alarm Message Sender");
  // connection state
  boolean notConnected = true;

  // Start GSM shield
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while(notConnected) {
    if(gsmAccess.begin(PINNUMBER)==GSM_READY) {
      notConnected = false;
      digitalWrite(gsmPin, HIGH);
      delay(100);
    }
    else {
      Serial.println("Not connected");
      delay(1000);
    }
  }
  Serial.println("Connected\n");
  
  readSIM();
}

void loop() {  
  currentMillis = millis();  
  
  if(adminOne == true || adminTwo == true){
    Serial.println("1 Admin");
    delay(100);

    // If there are ay SMS available    
    checkSms();  
  }
  else{    
    Serial.println("No available admin");
    delay(100);

    // Set admin for controller    
    checkSms();
    
    if(start == true) {
      Serial.println("Writing Admin1");
      theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");           
      // write contact name "User1"
      theGSM3ShieldV1ModemCore.print("AT+CPBW=,");
      theGSM3ShieldV1ModemCore.print("639155211111"); // changed last four digits to '1'
      theGSM3ShieldV1ModemCore.println(",129,\"User1\"");
      
      readSIM();
      start = false;
    }
  }
}

// SMS
void checkSms() {
  if (millis() - previousSmsMillis >= smsInterval) {
    if(sms.available()) {
      char rx;
      char commMsg[200];
      byte index = 0; 
    
      Serial.print("\nMESSAGE RECEIVED FROM: ");   
      // Get remote number
      sms.remoteNumber(senderNumber, 20);
      Serial.println(senderNumber);
      
      boolean authorized = checkNum();
      //Serial.println(authorized);
          
      // Read message bytes and print them
      commMsg[index] = '\0';
      while(rx = sms.read()) {
        //Serial.println(rx);
        commMsg[index] = rx;
        index++;
        commMsg[index] = '\0'; 
      }
      //Serial.println(commMsg);
      
      char* header = strtok(commMsg, ",");
      char* dataMsg = strtok(NULL, ",");
      
      Serial.println(header);
      Serial.println(dataMsg);
      
      if(authorized) {
        if(strcmp(header, "UPDT") == 0) { // update
          // check if sender is authorized
          Serial.println("*Apply Changes*");     
        }
        else {
          Serial.print("Already Registered as Administrator");
        }
      }
      else {        
        if(strcmp(header, "INIT") == 0) { // initialize
          if(strcmp(dataMsg, IMEI) == 0) {          
            char* incomingNum = strtok(senderNumber, "+");           
          
            //get no and store to sim
            if(adminOne == false){
              Serial.println("Writing Admin1");
              Serial.println(incomingNum); 
              theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");           
              // write contact name "User1"
              theGSM3ShieldV1ModemCore.print("AT+CPBW=,");
              theGSM3ShieldV1ModemCore.print(String(incomingNum));
              theGSM3ShieldV1ModemCore.println(",129,\"User1\"");
              
              readSIM();
              if(adminOne == true) {
                Serial.println("User1 Saved!");
              }
            } 
            else if(adminTwo == false) {
              Serial.println("Writing Admin2");
              theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");           
              // write contact name "User1"
              theGSM3ShieldV1ModemCore.print("AT+CPBW=,");
              theGSM3ShieldV1ModemCore.print(incomingNum);
              theGSM3ShieldV1ModemCore.println(",129,\"User2\"");
              
              readSIM();
              if(adminTwo == true) {
                Serial.println("User2 Saved!");
              }
            }
            else {
              Serial.println("No Slots Left");
            }
          }
          else {
            Serial.println("Invalid Code!");
          }
        }
      }

      Serial.println("END OF MESSAGE\n");       
      previousSmsMillis += smsInterval;  
      
      index = 0;
      commMsg[index] = '\0';  
      
      // Delete message from modem memory
      sms.flush();    
    }
  } 
}

void readSIM() {
  Serial.println("Reading...");
  theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");  
//  int start1 = millis();   
//  while((millis() - start1) < timeout){
//    theGSM3ShieldV1ModemCore.theBuffer().read();
//  }   

  // search for contact name "User1"
  theGSM3ShieldV1ModemCore.println("AT+CPBF=\"User1\"");  
  adminOne = theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", adminOneNum, sizer);
  if(adminOne) {
    Serial.print("User1 exist: ");
    Serial.println(adminOneNum);
  }
//  start1 = 0;
//  start1 = millis();   
//  while((millis() - start1) < timeout && !theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", adminNumOne, sizer)){
//    theGSM3ShieldV1ModemCore.theBuffer().read();
//  }
  theGSM3ShieldV1ModemCore.println("AT+CPBF=\"User2\"");  
  adminTwo = theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", adminTwoNum, sizer);
  if(adminTwo) {
    Serial.print("User2 exist: ");
    Serial.println(adminTwoNum);
  }
// search for contact name "User2"
//  start1 = 0;
//  start1 = millis();   
//  while((millis() - start1) < timeout && !theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", adminNumTwo, sizer)){
//    theGSM3ShieldV1ModemCore.theBuffer().read();
//  }
}

boolean checkNum() {
  if(strcmp(senderNumber, adminOneNum) == 0) {
    return true;
  }
  else if(strcmp(senderNumber, adminTwoNum) == 0) {
    return true;
  }
  else {
    return false;
  }
}

here’s the result:

Sensor Alarm Message Sender
Connected

Reading...
No available admin
Writing Admin1
Reading...
No available admin
No available admin
No available admin
No available admin
No available admin
No available admin

Can I read and write phonebook entries to sim card using the gsm shield?

I can separately read/add phonebook entries using AT commands.

#include <GSM.h>
GSM gsmAccess(true);
int sizer = 200;
char myNumber[200];
int timeout = 5000; // in milli seconds
int start1 = 0;

void setup()
{
  Serial.begin(9600);

  boolean notConnected = true;

  Serial.println("Connecting to the GSM network");

  while(notConnected){
    if(gsmAccess.begin() == GSM_READY) // Note: I do not require PIN #
      notConnected = false;
    else {
      Serial.println("Not connected, trying again");
      delay(1000);
    }
  }

  Serial.println("Connected");

  // --- WRITE ---

  Serial.println("Set SIM");  
  theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");  
  start1 = 0;
  start1 = millis();   
  while((millis() - start1) < timeout){
    Serial.print(theGSM3ShieldV1ModemCore.theBuffer().read());
    theGSM3ShieldV1ModemCore.theBuffer().read();
  } 
  
  Serial.println("Write to SIM");
  theGSM3ShieldV1ModemCore.println("AT+CPBW=4,\"09155210000\",,\"User\"");  
  start1 = 0;
  start1 = millis();   
  while((millis() - start1) < timeout){
    Serial.print(theGSM3ShieldV1ModemCore.theBuffer().read());
    theGSM3ShieldV1ModemCore.theBuffer().read();
  }
  
  // --- READ ---

  Serial.println("Set SIM");
  theGSM3ShieldV1ModemCore.println("AT+CPBS=\"SM\"");  
  start1 = 0;
  start1 = millis();   
  while((millis() - start1) < timeout){
    Serial.print(theGSM3ShieldV1ModemCore.theBuffer().read());
    theGSM3ShieldV1ModemCore.theBuffer().read();
  } 

  Serial.println("Read SIM");
  // search for contact name "test"
  theGSM3ShieldV1ModemCore.println("AT+CPBF=\"Jia\"");  
  start1 = 0;
  start1 = millis();   
  while((millis() - start1) < timeout && !theGSM3ShieldV1ModemCore.theBuffer().extractSubstring(",\"", "\",", myNumber, sizer)){
    Serial.print(theGSM3ShieldV1ModemCore.theBuffer().read());
    theGSM3ShieldV1ModemCore.theBuffer().read();
  }   
  
  if(strcmp(myNumber, "") == 0) {
  }
  else {
    Serial.print("User exist: ");
    Serial.println(myNumber);
  }
}

void loop()
{

}

I used the code from StackExchange. I just need to place ‚Äú‚ÄĚ before and after the number.

The problem is… I cannot write and read at the same time. I need to comment one function to make it work. But I need to check/read the sim to confirm I have stored the phonebook entry.

I tried placing a 20 sec delay after the ‚Äėwrite‚Äô but it still does not work.

I just need to place ‚Äú‚ÄĚ before and after the number.

Why?

  start1 = 0;
  start1 = millis();

This just looks stupid. What is the purpose of setting start1 to 0 nanoseconds before you overwrite it?

  while((millis() - start1) < timeout){
    Serial.print(theGSM3ShieldV1ModemCore.theBuffer().read());
    theGSM3ShieldV1ModemCore.theBuffer().read();
  }

Read and print one character. Read and discard the next character. Repeat. Why?

Why are you discarding every other character?

You do this everywhere you try to read a response. Wud t ok f lf eey etr u? (Would it work if I left every other letter out?)

I got the code fromhttp://arduino.stackexchange.com/questions/1370/getting-the-contacts-storing-contacts-to-sim-card

I don't know the process. Thank you for explaining.

PaulS:

  while((millis() - start1) < timeout){

Serial.print(theGSM3ShieldV1ModemCore.theBuffer().read());
    theGSM3ShieldV1ModemCore.theBuffer().read();
  }



Read and print one character. Read and discard the next character. Repeat. Why?

Why are you discarding every other character?

You do this everywhere you try to read a response. Wud t ok f lf eey etr u? (Would it work if I left every other letter out?)

What should replace the while? is theGSM3ShieldV1ModemCore.theBuffer().read(); necessary?

I need some help.

can i change the Number to write on Sim to a char?

theGSM3ShieldV1ModemCore.println("AT+CPBW=4,\"013544354\",,\"User\"");

like

char nr[20] = "123456";

theGSM3ShieldV1ModemCore.println("AT+CPBW=4,\nr\",,\"User\"");

Nothing works .....

Just for my curiosity... This doesn't bypass the need for knowledge to solve your original question...

I believe you're trying to save recipient numbers - to be used when sending SMS alarm messages.

Why use the SIM memory? To send a message, you currently have to read the number back from SIM, then use it to compose your text message header.

Why not save the numbers in the local EEPROM, and bypass the SIM memory altogether? It just seems slightly tidier if you aren't taking the SIM out for some other reason.