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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy