Contrôler ma maquette dotée d'un module GSM via interface web - Commande HTTP ?

Bonjour à tous ! :slight_smile:

Je me tourne à nouveau vers vous car j’ai besoin de conseils pour la réalisation de mon projet.

Mon matériel :
-Une carte Flip&Click (équivalent DUE)
sur laquelle sont disposés :
-Un module SD
-Un module BLE RN4020
-Un module GPS LEA6S
-Un module GSM SIM800h

Premier temps : Pouvoir contrôler l’ensemble de mes composants à l’aide d’une interface Web et pouvoir lire la réponse à l’écran.

Second temps : Faire en sorte que mon module GSM diffuse de l’information de façon régulière sur mon interface web. Exemple : <Une heure, Une position GPS, Une adresse MAC d’appareil BLE>.

En pratique :
-Je tape une commande dans un formulaire de mon interface.
-Cette commande est transmise au module GSM qui va la diffuser au module concerné (bus série).
-Le module concerné valide ou non cette commande et retourne une réponse au module GSM.
-Cette réponse est rapatriée sur mon interface web.
-Le GSM me remonte toutes les informations que les composants lui diffusent (disons chaque minute).

La carte SD est là pour faire une sorte de logging intermédiaire entre : (le BLE, le GPS) et (le GSM). J’entends par là que le modules BLE et GPS écrivent sur la carte SD, puis ces fichiers sont envoyés sur l’interface par le biais du module GSM.

J’ai actuellement un automate dans lequel j’implémente mes fonctionnalités, à terme je souhaiterais y rajouter la communication avec une interface web que j’espère justement réaliser avec votre aide :stuck_out_tongue:

Voici le code que j’ai en partie piqué à un membre (crédit : J-M-L, le meilleur) qui me permet d’envoyer des commandes à mon module GSM :

#define SIM800_RESET_PIN 77
#define PWKEY 6
const char * NETWORK_REGISTRATION_STR = "AT+CREG=1\r\r\nOK\r\n";
const char * TEXT_MODE_STR = "AT+CMGF=1\r\r\nOK\r\n";
const char * INIT_HTTP_STR = "AT+HTTPINIT\r\r\nOK\r\n";
const char * HTTP_SESSION_STR ="AT+HTTPPARA=\"CID\",1\r\r\nOK\r\n";

// --------------------------------------
// waitForString wait max for duration ms
// while checking if endMarker string is received
// on the GSM Serial port
// returns a boolean stating if the marker
// was found
// --------------------------------------

boolean waitForString(const char * endMarker, unsigned long duration)
{

  int localBufferSize = strlen(endMarker); // we won't need an \0 at the end
  char localBuffer[localBufferSize];
  int index = 0;
  boolean endMarkerFound = false;
  unsigned long currentTime;

  memset(localBuffer, '\0', localBufferSize); // clear buffer

  currentTime = millis();
  while (millis() - currentTime <= duration) {
    if (Serial1.available() > 0) {
      if (index == localBufferSize) index = 0;
      localBuffer[index] = (uint8_t) Serial1.read();
      Serial.print(localBuffer[index]);
      endMarkerFound = true;
      for (int i = 0; i < localBufferSize; i++) {
        if (localBuffer[(index + 1 + i) % localBufferSize] != endMarker[i]) {
          endMarkerFound = false;
          break;
        }
      }
      index++;
    }
    if (endMarkerFound) break;
  }
  return endMarkerFound;
}

// --------------------------------------
// espATCommand executes an AT commmand
// checks if endMarker string is received
// on the GSM Serial port for max duration ms
// returns a boolean stating if the marker
// was found
// --------------------------------------

boolean gsmATCommand(const char * command, const char * endMarker, unsigned long duration)
{
  Serial1.println(command);
  return waitForString(endMarker, duration);
}

void setup(){

Serial.begin(9600); while (!Serial);
Serial1.begin(9600); while (!Serial1);

// Pin definition
pinMode(SIM800_RESET_PIN, OUTPUT);
pinMode(PWKEY, OUTPUT);
digitalWrite(PWKEY, HIGH);
delay(1000);
digitalWrite(SIM800_RESET_PIN, LOW);
delay(100);
digitalWrite(SIM800_RESET_PIN, HIGH);
delay(2000);

Serial.println("Sending AT+CREG=1...");
// Network registration
if(gsmATCommand("AT+CREG=1", NETWORK_REGISTRATION_STR, 1000)){
}else{//traitement erreur
  }
delay(1000);

Serial.println("Sending AT+CMGF=1...");
// Set GSM to text mode
if(gsmATCommand("AT+CMGF=1",TEXT_MODE_STR, 1000)){
}else{//traitement erreur
  }
delay(1000);

Serial.println("Sending AT+HTTPINIT...");
// Initialize HTTP
if(gsmATCommand("AT+HTTPINIT",INIT_HTTP_STR, 1000)){
}else{//traitement erreur
  }
delay(1000);

Serial.println("Sending AT+HTTPPARA=\"CID\",1...");
// Set HTTP session
if(gsmATCommand("AT+HTTPPARA=\"CID\",1",HTTP_SESSION_STR, 1000)){
}else{//traitement erreur
  }

}
void loop(){
}

On aperçoit déjà quelques commandes liées au HTTP.

-J’imagine que je dois configurer mon module en serveur ?
-Récupérer son adresse IP ?
-Quels commandes vais-je devoir utiliser ?
-Vais-je avoir besoin d’un hébergeur dans le cadre de mes tests (pour l’interface) ?
-Quelles pistes de réflexions dois-je avoir ?
-Y-a-t’il une méthode plus adaptée ?

Merci à tous pour vos futurs messages !

Vous pourriez commencer par étudier le code de ce tuto et le la librairie associée

(Attention il se peut que votre opérateur bloque le traffic entrant direct)

Je ne vais pas pouvoir utiliser ceci. J’ai ce message à l’exécution :

ATTENTION : la bibliothèque GSM prétend être exécutable sur la (ou les) architecture(s) (avr) et peut être incompatible avec votre carte actuelle qui s’exécute sur (sam).

Il existe bien une librairie pour ma puce SIM800H :
https://github.com/stanleyhuangyc/Freematics/tree/master/libraries/SIM800

Alors j’ai essayé d’utiliser ce code :

Quand je lance ce programme (post #1) j’ai ce retour au niveau de la commande AT+CREG? :
“Error code:1”

Je suis donc allé voir dans la librairie à quoi correspond ce code.

La fonction concernée est la suivante (on rentre dans le “if (!success)” ) :

byte CGPRS_SIM800::setup(const char* apn)
{
  bool success = false;
  for (byte n = 0; n < 30; n++) { 
    if (sendCommand("AT+CREG?", 2000)) {
        char *p = strstr(buffer, "0,");
        if (p) {
          char mode = *(p + 2);
#if DEBUG
          con.print("Mode:");
          con.println(mode);
#endif
          if (mode == '1' || mode == '5') {
                Serial.println("debug3");
            success = true;
            break;
          }
        }
    }
    delay(1000);
  }
  if (!success)
    return 1;

  if (!sendCommand("AT+CGATT?"))
    return 2;

  if (!sendCommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\""))
    return 3;

  SIM_SERIAL.print("AT+SAPBR=3,1,\"APN\",\"");
  SIM_SERIAL.print(apn);
  SIM_SERIAL.println('\"');
  if (!sendCommand(0))
    return 4;

  sendCommand("AT+SAPBR=1,1", 10000);
  sendCommand("AT+SAPBR=2,1", 10000);

  sendCommand("AT+CMGF=1");    // sets the SMS mode to text
  sendCommand("AT+CPMS=\"SM\",\"SM\",\"SM\""); // selects the memory

  if (!success)
    return 5;

  return 0;
}

J’en déduit que “success” est à false, donc que “mode” et ni égal à 1 ni égal à 5 mais au delà de ça je n’arrive pas à savoir ce qui bloque. De plus, pourquoi fait-on 30 fois “AT+CREG?” dans cette fonction ?

Ils ne le font pas 30 fois quand la commande passe ils font un break; qui sort de la boucle

J'ignore ce que j'ai touché, mais ça à marché, enfin, c'est passé à l'étape suivante :

Voici la réponse complète :

Resetting...>AT
[1]AT

OK

>AT+CSCLK=1
[1]
AT+CSCLK=1

OK

>AT+IPR=115200
[0]

Call Ready

SMS Ready

>ATE0
[0]
>AT+COPN
[0]
>AT+CFUN=1
[1]AT+CFUN=1

OK

OK
Setting up network...>AT+CREG?
[1]
AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[0]
>AT+CREG?
[1]AT+CREG?

+CREG: 0,0

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,4

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,2

OK

>AT+CREG?
[1]AT+CREG?

+CREG: 0,5

OK

debug3
>AT+CGATT?
[1]
AT+CGATT?

+CGATT: 0

OK

>AT+SAPBR=3,1,"Contype","GPRS"
[1]
AT+SAPBR=3,1,"Contype","GPRS"

OK

[1]
AT+SAPBR=3,1,"APN","connect"

OK

>AT+SAPBR=1,1
[0]AT+SAPBR=1,1

ERROR

>AT+SAPBR=2,1
[1]AT+SAPBR=2,1

+SAPBR: 1,3,"0.0.0.0"

OK

>AT+CMGF=1
[1]
AT+CMGF=1

OK

>AT+CPMS="SM","SM","SM"
[1]
AT+CPMS="SM","SM","SM"

+CPMS: 0,25,0,25,0,25

OK

OK
>AT+HTTPINIT
[1]AT+HTTPINIT

OK

>AT+HTTPPARA="CID",1
[1]AT+HTTPPARA="CID",1

OK

[1]
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error
[1]1,0
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK

Connect error

J'ai compris ce qui n'allait pas... le mode a finit par passer à 5 ce qui correspond à "Registered, roaming" dans la documentation des commandes AT.

C'est très étrange, j'ai lancé le programme plusieurs fois et ça à fonctionné la dernière fois.

Bon, maintenant il m'est impossible de me connecter à l'url je ne comprend pas pourquoi, les données mobiles sont activées et j'arrive à acceder au site depuis mon téléphone.

La fonction de la librairie concernée est la suivante :

bool CGPRS_SIM800::httpConnect(const char* url, const char* args)
{
    // Sets url
    SIM_SERIAL.print("AT+HTTPPARA=\"URL\",\"");
    SIM_SERIAL.print(url);
    if (args) {
        SIM_SERIAL.print('?');
        SIM_SERIAL.print(args);
    }

    SIM_SERIAL.println('\"');
    if (sendCommand(0))
    {
        // Starts GET action
        SIM_SERIAL.println("AT+HTTPACTION=0");
        httpState = HTTP_CONNECTING;
        m_bytesRecv = 0;
        m_checkTimer = millis();
    } else {
        httpState = HTTP_ERROR;
    }
    return false;
}

Quelle est la signification de "if (sendCommand(0))" ?

si vous regardez le code de la librairie

    // send AT command and check for expected response
    byte sendCommand(const char* cmd, unsigned int timeout = 2000, const char* expected = 0);

ils ont des valeurs par défaut pour les autres paramètres donc if (sendCommand(0)) ça appelle la fonction avec un pointeur NULL comme commande (donc rien ne sera envoyé au modem comme commande), un timeout de 2000ms et "rien" attendu en retour qui veut dire qu'il attend un "OK\r" --> en effet si vous lisez le code ils font un

if (strstr(buffer, [color=red]expected ? expected : "OK\r"[/color])) {

comme expected est NULL, ça attend donc "OK\r"

vous avez essayé à la main certaines de ces commandes AT pour vous assurer que votre module les supporte (les firmwares évoluent)

D’accord, il ne reçoit donc pas “OK\r”.

J’ai essayé d’envoyer les commandes à la main comme vous dites, en utilisant le programme du #1 de ce post, et en ajoutant ceci :

//[...]
const char * test = "OK\r";
//[...]
delay(1000);
Serial.println("Sending AT+HTTPPARA=\"URL\",\"...");
// Specify url
gsmATCommand("AT+HTTPPARA=\"URL\",\"http://arduinodev.com/datetime.php\"",test, 1000);

delay(1000);
Serial.println("Sending AT+HTTPACTION=0");
// Start GET action
gsmATCommand("AT+HTTPACTION=0",test, 1000);
//[...]

Voici le résultat :

//[...]
AT+HTTPPARA="CID",1

OK
Sending AT+HTTPPARA="URL","...

SMS Ready
AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"

OK
Sending AT+HTTPACTION=0

Pas de réponse à “AT+HTTPACTION=0”. Je ne reçoit pas non plus OK\r quoi…

Cela s’explique si mon opérateur bloque le traffic entrant direct ou bien ce n’est pas encore incriminant ? (Je n’ai pas encore vérifié ce point).

vous avez quelque chose à la place des "..." ?

Ce n'est qu'un Serial.println("Sending AT+HTTPPARA=\"URL\",\"...");

Vous avez encore perdu vos lunettes ? :P

LOL - oui :slight_smile:

AT+HTTPACTION=0 c’est un demande de lecture donc il faut balancer des ordres ensuite

essayez avec cette séquence (à vérifier si c’est OK sur un 800, de mémoire il me semble que c’était comme ça sur un 900)

AT+HTTPPARA=“URL”,“http://arduinodev.com/datetime.php
AT+HTTPPARA=“CID”,1
AT+HTTPACTION=0
AT+HTTPREAD <<-- LA DEMANDE DE LECTURE
WAIT=6
AT+HTTPTERM

En effet il me manquait un bout !

Mais dans tout les cas AT+HTTPACTION=0 est supposée me renvoyer quelque chose de ce genre :

OK +HTTPACTION:0,200,4

En lisant le buffer je vois ERROR (on ne le vois pas dans ce jeu d'essai).

En ajoutant : AT+HTTPREAD WAIT=6 AT+HTTPTERM

Et en séparant tout les caractères par un '|' j'ai ceci :

Sending AT+HTTPPARA="URL","...
|
|
|
|A|T|+|H|T|T|P|P|A|R|A|=|"|U|R|L|"|,|"|h|t|t|p|:|/|/|a|r|d|u|i|n|o|d|e|v|.|c|o|m|/|d|a|t|e|t|i|m|e|.|p|h|p|"|
|
|
|O|K|
Sending AT+HTTPACTION=0
|
|Sending AT+HTTPREAD 
Sending WAIT=6
Sending AT+HTTPTERM
|A|T|+|H|T|T|P|T|E|R|M|
|
|
|E|R|R|O|R|
|
|
|

On remarque que la commande HTTPACTION=0 renvoie (surement) \r\n et WAIT=6 ne renvoie rien du tout.

Enfin on remaque que AT+HTTPTERM retourne ERROR.

jetez un oeil ici pour la commande GET sur un 800 ou encore là

En regardant vos liens de près j'ai envoyé ces commandes :

AT+CREG=1 AT+HTTPINIT AT+HTTPPARA="CID",1 AT+HTTPPARA="URL","http://arduinodev.com/datetime.php" AT+HTTPACTION=0 AT+HTTPREAD

J'ai laissé de côté "WAIT=6" car cette commande est ni dans la documentation, ni dans vos liens.

J'ai eu ce retour :

AT+CREG=1
+CREG: 2

AT+HTTPINIT
OK

AT+HTTPPARA="CID",1
OK

AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"
OK

AT+HTTPACTION=0
+HTTPACTION: 0,601,0

AT+HTTPREAD
OK

AT+HTTPTERM
OK

La commande HTTPACTION=0 retourne 601 ce qui correspond à "Network Error". dans le premier lien de votre post précédent il y a une manip indiquée pour ce cas, je l'ai donc suivie :

AT+SAPBR=3,1,"APN","matooma.m2m" AT+SAPBR=1,1 AT+CREG=1 AT+HTTPINIT AT+HTTPPARA="CID",1 AT+HTTPPARA="URL","http://arduinodev.com/datetime.php" AT+HTTPACTION=0 AT+HTTPREAD

Bon bah c'est pas glorieux... :

AT+SAPBR=3,1,"APN","matooma.m2m" OK AT+SAPBR=1,1 ERROR

En fait c'est quoi le second paramètre d'AT+SAPBR ? La doc indique que c'est le "cid" aussi appelé "Bearer profile identifier". Moi j'ai mis '1' comme dans l'exemple mais j'en sais rien en réalité..

Faut-il que je m’inquiète de savoir si ma carte multi-opérateurs bloque le trafic entrant ??

Après de nombreux tests je me retourne vers vous…

J’ai pu effectuer une requête GET avec ma propre carte SIM mais je n’arrive toujours pas à en faire de même avec la carte SIM de mon projet.

Avec la carte de mon téléphone, en utilisant le jeu d’instructions suivant :

//Set pin number
AT+CPIN="xxxx"

//Network registration
AT+CREG=1

//set APN
AT+SAPBR=3,1,“APN”,"sl2sfr"

//leave settings command mode, re-open the bearer
AT+SAPBR=1,1

//init http
AT+HTTPINIT

//Set HTTP session
AT+HTTPPARA=“CID”,1

//Specify URL
AT+HTTPPARA=“URL”,"http://arduinodev.com/datetime.php"

//Specify action (GET)
AT+HTTPACTION=0

//Read data
AT+HTTPREAD

//End connection
AT+HTTPTERM

J’obtiens la donnée 20170526074014 et le status 200 (OK) mais pas du premier coup, mais bon ça fonctionne quoi…

Avec le même jeu d’instruction en utilisant la carte de mon projet (sans CPIN car inutile pour cette carte, et en précisant l’APN adapté) j’ai ce résultat :

AT+CREG=1
OK

AT+SAPBR=3,1,"APN","matooma.m2m"
OK

AT+SAPBR=1,1
ERROR

//HTTPINIT ne s'est même pas affiché

AT+HTTPPARA="CID",1
ERROR

AT+HTTPPARA="URL","http://arduinodev.com/datetime.php"
ERROR

AT+HTTPACTION=0
ERROR

//AT+HTTPREAD ne s'est même pas affiché

AT+HTTPTERM
ERROR

J’ai également essayé de rajouter :

AT+SAPBR=0,1
AT+SAPBR=1,1

Avant de configurer l’APN. Cette manip était indiquée dans votre premier lien, pour fermer et re-ouvrir la connexion si on augmente le solde des données mobiles (j’ai essayé au cas où, mais ma carte a un forfait internet illimité) et rien a changé.

Personne ne rencontre ce genre de problème ?

Merci, je désespère un peu^^