Go Down

Topic: Réception de SMS (Read 1 time) previous topic - next topic

33bert51

Bonjour,

La réception de SMS pour permettre de commander principalement des relais pour éclairage, chauffage, simulation de présence... peut-être utile.
Evidemment, il y a déjà des topics à ce sujet mais j'ai eu quelques des difficultés à les mettre en place pour diverses raisons.

Voici une solution de récupération du contenu d'un SMS, c'est un exemple parmi d'autres...

Le matériel :
- Module Iduino Uno
- GPRS Shield SIM900 (geeetech)

Ma seule librairie SoftwareSerial.h est inévitable.
Il n'y a pas de contrôle de dépassement de mémoire, mes messages doivent donc faire moins de 30 octets, suffisant pour un protocole simple.

Code: [Select]
SoftwareSerial Sim900(7,8);

// variables
char bufRecSim900[512];     // buffer de réception
int cptRecSim900;           // compteur
char bufIndexSMS[10];       // pour memorisation index du message
int  cptIndex;
char bufIndex[10];          // pour l'index en chaine de caracteres brut
char *ptrIndex;             // pointeur tempraire pour traitement de l'index

char cmdSim900[30];         // pour les commandes à destination du Sim900
int litSMS=0;               // drapeau pour signaler que la prochaine ligne est le contenu du SMS
bool recommence=true;       // pour la boucle de lecture des données venant du SIM
char c;                     // pour traiter un caractère


Initialisation du Sim900 (et de la liaison série avec le PC pour vérification)
Code: [Select]
void setup()
{
  Sim900.begin(19200);  // the GPRS baud rate
  Serial.begin(19200);  // le PC pour verification
  delay(500);
}


Dans la boucle, deux parties :
Code: [Select]
void loop()
{
  // lecture des données qui arrivent du Sim900
  // traitement des données
}


Première partie, lecture des données :
on attend la réception d'un caractère NL ou CR qui signale qu'une ligne a été reçue (=> cptRecSim900 = 64), on peut la traiter.
Code: [Select]
if (Sim900.available()) {
        while(Sim900.available()) {
            // utilisation de peek pour rechercher le caractère NL et CR
            c = Sim900.peek();
            switch(c) {
                case '\x0a' :
                case '\x0d' :
                    Sim900.read();
                    if (cptRecSim900 > 0) {
                        bufRecSim900[cptRecSim900++] = '\x0a';
                        bufRecSim900[cptRecSim900++] = '\0';
                        cptRecSim900 = 64;
                    }
                break;
                default :
                    bufRecSim900[cptRecSim900++] = Sim900.read();
                break;
            }
            if(cptRecSim900 == 64) break;
        }
    }


Dans la seconde partie qui s'exécute si cptRecSim900 = 64, on y trouve 3 parties :
- Attente du code "+CMTI:" qui signale qu'un message est arrivé
          => récupération de l'index
          => envoie de la commande pour lire le message "AT+CMGR=<index>\r"
Code: [Select]
// On attend un +CMTI:
        if (strstr(bufRecSim900, "+CMTI:")) {
            // Un nouveau message est arrivé, il faut récupérer l'index du message
            // Le format est "+CMTI: "SM",<index>"
            ptrIndex = strchr(bufRecSim900, ',');
            // L'index se trouve juste après le caractère ',' donc du pointeur ptr + 1
            ptrIndex++;
            sprintf(bufIndex, "%s", ptrIndex);
            cptIndex = 0;
            // il faut enlever les caracteres parasites comme \x0a             
            while(1)  {
                if ( (bufIndex[cptIndex] < '\x30') || (bufIndex[cptIndex] > '\x39') )  {
                      bufIndex[cptIndex] = '\0';
                      // on sort du while
                      break;
                }
                cptIndex++;
            }
            sprintf(cmdSim900, "AT+CMGR=%s\r", bufIndex);
            Sim900.write(cmdSim900);
        }


- Attente du code "+CMGR" qui indique que la ligne suivante est le message ==> litSMS = 1
Code: [Select]
// on peut comparer le début de ligne
        if (strstr(bufRecSim900, "+CMGR:")) {
            litSMS = 1;
        }


- Si litSMS, alors lecture du message et donc traitement...
Code: [Select]
if (litSMS)  {
            // c'est ici que l'on passe au traitement du contenu du SMS
            // dans mon cas, je l'affiche...
            Serial.print(bufRecSim900);
            // on repasse le drapeau à 0 pour l'attente d'un nouveau SMS
            litSMS = 0;
        }


Attention, il faut tester le drapeau litSMS en premier ! et de repasser le cptRecSim900 à 0...
Code: [Select]
 #include <SoftwareSerial.h>
 
SoftwareSerial Sim900(7,8);

// variables
char bufRecSim900[512];     // buffer de réception
int cptRecSim900;           // compteur
char bufIndexSMS[10];       // pour memorisation index du message
int  cptIndex;
char bufIndex[10];          // pour l'index en chaine de caracteres brut
char *ptrIndex;             // pointeur tempraire pour traitement de l'index

char cmdSim900[30];         // pour les commandes à destination du Sim900
int litSMS=0;              // drapeau pour signaler que la prochaine ligne est le contenu du SMS
bool recommence=true;       // pour la boucle de lecture des données venant du SIM
char c;                     // pour traiter un caractère

void setup()
{
  Sim900.begin(19200);  // the GPRS baud rate
  Serial.begin(19200);  // le PC pour verification
  delay(500);
}
void loop() {
    if (Sim900.available()) {
        while(Sim900.available()) {
            // utilisation de peek pour rechercher le caractère NL et CR
            c = Sim900.peek();
            switch(c) {
                case '\x0a' :
                case '\x0d' :
                    Sim900.read();
                    if (cptRecSim900 > 0) {
                        bufRecSim900[cptRecSim900++] = '\x0a';
                        bufRecSim900[cptRecSim900++] = '\0';
                        cptRecSim900 = 64;
                    }
                break;
                default :
                    bufRecSim900[cptRecSim900++] = Sim900.read();
                break;
            }
            if(cptRecSim900 == 64) break;
        }
    }
    // si cptReception = 64, la ligne est entière
    if (cptRecSim900 ==64) {
        if (litSMS)  {
            // c'est ici que l'on passe au traitement du contenu du SMS
            // dans mon cas, je l'affiche...
            Serial.print(bufRecSim900);
            // on repasse le drapeau à 0 pour l'attente d'un nouveau SMS
            litSMS = 0;
        }
        // on peut comparer le début de ligne
        if (strstr(bufRecSim900, "+CMGR:")) {
            litSMS = 1;
        }
        // On attend un +CMTI:
        if (strstr(bufRecSim900, "+CMTI:")) {
            // Un nouveau message est arrivé, il faut récupérer l'index du message
            // Le formt est "+CMTI: "SM",<index>"
            ptrIndex = strchr(bufRecSim900, ',');
            // L'index se trouve juste après le caractère ',' donc du pointeur ptr + 1
            ptrIndex++;
            sprintf(bufIndex, "%s", ptrIndex);
            cptIndex = 0;
            // il faut enlever les caracteres parasites comme \x0a             
            while(1)  {
                if ( (bufIndex[cptIndex] < '\x30') || (bufIndex[cptIndex] > '\x39') )  {
                      bufIndex[cptIndex] = '\0';
                      // on sort du while
                      break;
                }
                cptIndex++;
            }
            sprintf(cmdSim900, "AT+CMGR=%s\r", bufIndex);
            Sim900.write(cmdSim900);
        }
        // la ligne a ete traite, cptRecSim900 repasse à 0
        cptRecSim900 = 0;
    }
}

Voilà !

Go Up