Thanks to @mrlowalowa, @developer_bt, @ScruffR, @RWB, etc… for their amazing work on Electron and SMS.
I managed to receive SMS and process it using third party SIM. Whenever an Call or SMS is received, the interrupt on the RI_UC will be triggered. Also we can read the SMS using AT+CMGR
Command. The syntax is AT+CMGR=<index>
. The index
is the index of the memory at which the message is stored. Here the key is to find the index of the last SMS. For this purpose we can use AT+CPMS?
command. This command returns the details of the selected SMS Storage. We can parse the last storage index from this command return value. For a more detailed explanation please refer to this link.
Here is a sample program that turn on the LED on D7 on/off when SMS is received from a predefined number. If you send the text D7=HIGH then it turns on the LED, if you send the text D7=LOW then it turns off the LED. If you send the text deleteall then it delete all the SMS (Warning, it will delete all the SMS, so use it with care. This is just to included for testing purpose only).
Hope this helps!
#define TIMEOUT 10000
#define CMD_NONE 0
#define CMD_DELETE_ALL 1
#define LED_PIN D7
// Replace with a phone number, the application will only process
// the SMS received from this number
#define AUTHORIZED_PHONE_NUMBNER "<replace with a mobile number>"
void riInterrupt(void);
int state = LOW;
bool isCallRecognized = false;
char szReturn[32] = "";
int maxIndex = 1;
int ledState = LOW;
int command = CMD_NONE;
int phoneCallback(int type, const char* buf, int len, char* param){
Serial.print("Phone Callback: ");
if(strncmp(&buf[2], "+CMGR:", 6) == 0){
Serial.write((const uint8_t*)&buf[2], len - 2);
Serial.println();
char szState[32];
char szPhoneNumber[18];
sscanf(&buf[9], "%[^/','],%[^/','],%s", szState, szPhoneNumber);
maxIndex++;
strcpy(szPhoneNumber, &szPhoneNumber[1]);
szPhoneNumber[strlen(szPhoneNumber) - 1] = 0;
if(strcmp(AUTHORIZED_PHONE_NUMBNER, szPhoneNumber) == 0){
Serial.println("SMS detected");
isCallRecognized = true;
}
Serial.print("Phone Number ");
Serial.print(szPhoneNumber);
Serial.print(", ");
Serial.print(szState);
Serial.println();
}
else if(strncmp(&buf[2], "+CPMS:", 6) == 0){
char szData[13];
Serial.write((const uint8_t*)&buf[2], len - 2);
Serial.println();
sscanf(&buf[9], "%[^/','], %d", szData, &maxIndex);
maxIndex++;
Serial.print("Current Index ");
Serial.print(maxIndex);
Serial.print(", ");
Serial.print(szData);
Serial.println();
}
else{
Serial.write((const uint8_t*)buf, len - 2);
Serial.println();
if(isCallRecognized){
isCallRecognized = false;
if(strncmpi(buf, "deleteall", 9) == 0){
Serial.println("Delete all command received.");
command = CMD_DELETE_ALL;
}
else{
char szPin[3];
char szState[5];
sscanf(buf, "%[^/'=']=%s", szPin, szState);
Serial.println();
Serial.print(szPin);
Serial.print("=");
Serial.print(szState);
Serial.println();
if(strcmpi(szPin, "D7") == 0){
if(strcmpi(szState, "HIGH") == 0){
ledState = HIGH;
}
else if(strcmpi(szState, "LOW") == 0){
ledState = LOW;
}
}
}
}
}
state = LOW;
return WAIT;
}
void setup(){
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(RI_UC, INPUT_PULLUP);
attachInterrupt(RI_UC, riInterrupt, CHANGE);
Cellular.command(phoneCallback, szReturn, TIMEOUT, "AT+CMGF=1\r\n");
Cellular.command(phoneCallback, szReturn, TIMEOUT, "AT+CPMS?\r\n");
}
void loop(){
digitalWrite(LED_PIN, ledState);
if(CMD_DELETE_ALL == command){
Cellular.command(phoneCallback, szReturn, TIMEOUT, "AT+CMGD=1,4\r\n");
command = CMD_NONE;
}
else if(state == HIGH){
char szCommand[32];
sprintf(szCommand, "AT+CMGR=%d\r\n", maxIndex);
Serial.println();
Serial.print("Sending command: ");
Serial.print(szCommand);
Serial.println();
Cellular.command(phoneCallback, szReturn, TIMEOUT, szCommand);
}
}
void riInterrupt(){
state = digitalRead(RI_UC);
}
Demo Video