+7(960) 250-82-68 spam@mirossa.ru


  MCU         C           1С         PHP       JAVA      разное 


Статьи
 
 

05 октября 2019 г

Arduino. http запрос. sim800c. Отладка.

Плата Arduino Uno и SIM800c GPRS/GSM Shield

драйвер для USB-UART CH340/CH341 (Windows)

Плата Arduino Uno и SIM900 GPRS/GSM Shield

Блок питания (например, такой)

Блок питания

код скетча.

#define INTERVALSEND 60000
#define response_size 100
#define data_buffer_size 301
#include <SoftwareSerial.h>

unsigned int TextToInt(char * DataLenRead);

SoftwareSerial GPRS(7, 8);
int onModulePin= 9;
unsigned long previous;
char response[response_size];  // это буфер для служебного текста ответов сервера
char data_buffer[data_buffer_size]; // это буфер для полезных данных, полученных из ответов сервера
char userText;
uint8_t  answer;

 uint8_t read_answer_httpread(const char * firstPart, const char * secondPart, const char * thirdPart, unsigned int * lengthData );
 uint8_t read_answer_HTTP_GPRS(const char * AtCommand, const char * expected_answer, char * DataLen);
 uint8_t get_SMSdata_http(void);

 
void setup()
  {
  GPRS.begin(19200); 
  Serial.begin(9600);
  Serial.println("Starting...");
  //pinMode(onModulePin,OUTPUT);
  //power_on(); // не работает
  delay(3000);
    
  }

void loop() 
  {

  //если отправляем 'g' через монитор порта, то запускается инициализация gprs.
  //далее  отправляем 'h' для http запросов.
  // http соединение каждый раз открывается , делается запрос и оно завершается. Но если возникла ошибка , то соединение не закрылось
  // и его инициализировать не нужно. Но так как пока http-запрос проходит полный цикл, то нужно закрыть незавершенное соединение
  // и это команда 't'. Закрыть gprs - 'q'.
  
  if (  Serial.available() > 0 ){
    
     userText = Serial.read();
     while ( Serial.available() > 0 )
          Serial.read();

     if (userText == 'g'){
      
          Serial.println("Start GPRS...");
          answer = start_GPRS();
          if (answer != 0)
              Serial.println("\nStart GPRS error.\n");
              //goto Ext1;  
     }
     
     if (userText == 'h') { /////--HTTP--/////
      
            Serial.println("\nBegin HTTP request.\n");
    
            answer = get_SMSdata_http();    // данные от вэб сервера пишу в data_buffer[]
            if (answer != 0){
              Serial.println("\nHTTP error.\n");
            //goto Ext1;
            }
    
           // обработка полученных данных
      
     }

     if (userText == 't') {
        read_answer_HTTP_GPRS("AT+HTTPTERM", "", NULL);
        Serial.println(response);
      }
	  
      if (userText == 'q') {
        read_answer_HTTP_GPRS("AT+SAPBR=0,1", "", NULL);
        Serial.println(response);
      }
     
}
 delay(3000);

} // main loop //////////////////////////////

unsigned int TextToInt(char * DataLenRead){

      unsigned int c, rez = 0;
  
      for ( c = 0; c < strlen(DataLenRead); c++ ){
    
          rez = rez * 10 + (unsigned int) DataLenRead[c] - 48; // 0x30h
      }

    return rez;
  }

              // переделать описание !
              // нужно парсить ответ сервера на команду AT+HTTPREAD
              // пересмотреть этот шаг  //1. в параметры команды AT+HTTPREAD передаем количество байт (получили на предыдущем шаге)
              // 2. вначале ответа получаем копию нашей команды (AT+HTTPREAD).
              // 3. далее должно быть типа "+HTTPREAD:175". Тут вытаскиваем фактическое количество полученных байт (в идеале такое же)
              // 4. после этого считываем ответ дальше и когда прочитали нужное (пришедшее) количество (т.е. 175), то
              // 5. начинаем "завершение" считывания. то есть в оставшемся куске должно быть подтверждающее "ОК" (здесь 
              // мы уже ВНЕ полезного ответа и "ОК" - это завершающие символы от сервера, а не часть полезных данных.
              // (за "ОК" будет ещё перевод строки \r\n)
uint8_t read_answer_httpread(const char * firstPart, const char * secondPart, const char * thirdPart, unsigned int * lengthData ){
      
      unsigned long previous;
      uint8_t x, y, answer;
      int avail;
      int c;

      char * istr;
      char DataLenRead[10];
      unsigned int poleznieBytes = 0, DataLenReadNumber;
      int pars = 0, stepP = 0;
      
      x = 0;
      y = 0;
      answer = 1;        // !!! решить вопрос . добавить в код возврат answer == 1, обработать "ERROR", сейчас только по timeout
      previous = millis();

      while( GPRS.available() > 0) 
          GPRS.read();    // Clean the input buffer
    memset(response, '\0', response_size);    // Initialize the string
    
    GPRS.println(firstPart);    // Отправка AT команды //!!! ТЕКСТ СТРАНИЦЫ. НУЖНО ПРЕДУСМОТРЕТЬ response/data_buffer "НУЖНОЙ ДЛИНЫ"
      
     while ( ((millis() - previous) < 15000) ){ //нужно добавить выход из цикла, когда прочитаны все данные. чтобы не зависать.
       
       if ( GPRS.available() > 0 ) {
          //Serial.println(avail, DEC);
          // if there are data in the UART input buffer, reads it and checks for the asnwer
          avail = GPRS.read();
          //Serial.write(avail);

          if ( stepP == 3 ){ // полезные данные закидываю в другой буфер
              data_buffer[y] = avail;
              y++;
          }else{          
              response[x] = avail;
              x++;
          }
          
        //парсинг ответа
        if ( stepP == 0 ){ 
          istr = strstr ( response + pars, firstPart);  //"AT+HTTPREAD"
          if ( istr != NULL ){
             pars = (istr - response) + 11; // "AT+HTTPREAD"
             stepP = 1;
          }
        } else if ( stepP == 1 ){
//Serial.write(avail);
          istr = strstr ( response + pars , secondPart); //"+HTTPREAD:"
          if ( istr != NULL ){
             pars = (istr - response) + 10; // "+HTTPREAD:"
             stepP = 2;
          }

           
        } else if ( stepP == 2 ){
//Serial.write(avail);
          istr = strstr ( response + pars , "\r\n");
          if ( istr != NULL ){
                  //*(response + pars) указывает на следующий символ после +HTTPREAD:
                  //и он может быть пробелом. нужно его пропустить
                  while ( *(response + pars) == ' ' )
                       pars++;
            
//Serial.println(" 2 - 3 ");
                  strncpy (DataLenRead, response + pars, istr - response - pars);
                  DataLenRead[istr - response - pars] = '\0';      // добавить в конец строки символ конца строки
//char test[40];
//sprintf(test, " *(response + pars) = %d , *(? -1) = %d,  *istr = %d", *(response + pars), *(response + pars - 1), (int)*istr);
//Serial.println(test);                  
//Serial.print("DataLenRead = ");
//Serial.print(DataLenRead);
//Serial.println("DataLenRead end ");     
                  pars = (istr - response) + 2; // это смещение на позицию за "\r\n" на начало полезных данных
                  //beginData = response + pars; //начало полезных данных
                  stepP = 3;
                  
                  DataLenReadNumber = TextToInt(DataLenRead);
                  *lengthData = DataLenReadNumber;
                  if ( DataLenReadNumber == 0 ){
                      stepP = 4;
                  }    
          }
          
        } else if ( stepP == 3 ){ //шаг считывания полезных данных
//Serial.println(" q3 ");
          poleznieBytes++;  // доделать : когда прочитано 0 байт

//Serial.println(DataLenReadNumber, DEC);
  
          if (  poleznieBytes == DataLenReadNumber ){
                stepP = 4; // после считывания полезных байт будет ожидать "OK\r\n"
                //pars += DataLenReadNumber; //будет указывать на  "OK\r\n"
                //endData = response + pars - 1; //конец полезных данных

                
          }
        } else if ( stepP == 4 ){
 //Serial.write(avail);
            istr = strstr ( response + pars , thirdPart); //"OK\r\n"
            if ( istr != NULL ){
              answer = 0;
              break; // всё прочитали . прерываем
            }
          
        }
        
        ///////////////
          
       }   
      }
       
    response[x] = '\0';
    //Serial.println(response); // вывод всего пришедшего ответа
    data_buffer[y] = '\0';

    //char test[10];
    //sprintf(test, "%u - %u", poleznieBytes, DataLenReadNumber);
    
    Serial.println(data_buffer);
    //Serial.println(test);
    //Serial.println("length data_buffer = ");
    //Serial.println(strlen( data_buffer )); 
    /*Serial.println(data_buffer[1]);
    Serial.println(data_buffer[2]);
    Serial.println(data_buffer[3]);*/
    
  return answer;
  }

  // обработка большинства команд завершается на stepP == 1
  uint8_t read_answer_HTTP_GPRS(const char * AtCommand, const char * expected_answer, char * DataLen){
      
      unsigned long previous;
      uint8_t x, answer;
      int avail;
      char * istr;
      int pars = 0, stepP = 0;
      char * cc, * ccEnd;
    
      x = 0;
      previous = millis();
      size_t sz, sz_ea;
      
      sz = strlen(AtCommand);
      sz_ea = strlen(expected_answer);
      
     answer = 1; // error

      while( GPRS.available() > 0) 
          GPRS.read();    // Clean the input buffer
    memset(response, '\0', response_size);    // Initialize the string
    
    GPRS.println(AtCommand);    // Отправка AT команды 
    
     while ( ((millis() - previous) < 10000) ){     // !!! timeout нужно скидывать, когда получаю байты данных                                         
       
       if ( GPRS.available() > 0 ) {
         
          avail = GPRS.read();          
          response[x] = avail;
          x++;
          
        //парсинг ответа
        if ( stepP == 0 ){ 
          istr = strstr ( response + pars, AtCommand);  
          if ( istr != NULL ){
//Serial.println(" 0 \n");
             pars = (istr - response) + sz; 
             stepP = 1;
          }
        } else if ( stepP == 1 ){
            istr = strstr ( response + pars , "OK\r\n");
            if ( istr != NULL ){
//Serial.println(" 1 \n");              
              answer = 0;
              if (sz_ea == 0){ //передана пустая строка в expected_answer (в этой команде ждем ОК и завершаем обарботку; )
                break;
                }
              // сюда пока попадает только, если отправлена команда "AT+HTTPACTION=0", требующая доп обработки
              pars = (istr - response) + 4;
              stepP = 2;
 //Serial.println(" 1-1 \n");              
              continue;
            }
            istr = strstr ( response + pars , "ERROR\r\n");
            if ( istr != NULL ){
             
              break;
            }
        }else if ( stepP == 2 ){
//Serial.write(avail);   //  например, +HTTPACTION: 0,606,0    // +HTTPACTION: 0,200,175
            istr = strstr ( response + pars, expected_answer);
            if ( istr != NULL ){
//Serial.println(" 2 \n");              
             pars = (istr - response) + sz_ea + 1; // пропускаем запятую. встаем на начало длины полученных данных
             cc = response + pars; // cc - начало длины данных
             stepP = 3;
             
            }
        }else if ( stepP == 3 ){
            ccEnd = strstr(cc, "\r\n"); // конец
            if ( ccEnd != NULL ){
 //Serial.println(" 3 \n");             
              //можно проверить на NULL
              strncpy (DataLen, cc, ccEnd - cc);
              DataLen[ccEnd - cc] = '\0';      // добавить в конец строки символ конца строки
              //Serial.println(DataLen);          // тут полученный размер (строка) который затем можно использовать в HTTPREAD
              break;
            }
        }
                  
       }
          
      }
       
    response[x] = '\0';
    //Serial.println(response); // вывод всего пришедшего ответа
  
  return answer;
  }  // read_answer_HTTP_GPRS()

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  uint8_t get_SMSdata_http(void){
    
    uint8_t answer = 0;
    char DataLen[15];
    unsigned int lengthData;
    int c;
    
  // баланс:
  /*Serial.println("Отправка: AT+CUSD=1,\"*100#\"");
  GPRS.println("AT+CUSD=1,\"*100#\"");    // Отправка AT команды
  delay(2000);
*/
    Serial.println("=== Отправка: AT+HTTPINIT\n");
    answer = read_answer_HTTP_GPRS("AT+HTTPINIT", "", NULL);
    if (answer != 0)
        return answer;
      //goto Ext1;
//00/////////SSL - эта версия устарела. сейчаc всюду TLS. Не нашёл ресурсов с ssl - не протестировал до конца///////
/*
    Serial.println("=== Отправка: AT+HTTPSSL=1\n");
    answer = read_answer_HTTP_GPRS("AT+HTTPSSL=1", "", NULL);
    if (answer != 0){
        //Serial.println(response); // вывод всего пришедшего ответа
        return answer;
    }
    Serial.println("=== Отправка: AT+HTTPSSL=1  - OK \n"); 
*/
       
  /*  while( GPRS.available() > 0) 
        Serial.write(GPRS.read());    // Clean the input buffer
    Serial.println("Отправка: AT+HTTPSSL?");    
    GPRS.println("AT+HTTPSSL?");    // Отправка AT команды
    delay(2000);
    x = 0;
    answer = 0;
 
     while (GPRS.available() != 0){    
       // if there are data in the UART input buffer, reads it and checks for the asnwer
       response[x] = GPRS.read();
       x++;
       }
    response[x] = '\0';
    Serial.println(response);
    
    // check if the desired answer  is in the response of the module
       if (strstr(response, "OK") != NULL){
         answer = 1;
       }
    
    //if (answer == 0)
      //goto Ext1;
 */     
//77////////////////

  Serial.println("Отправка: AT+HTTPPARA=\"CID\",1");    
    
    answer = read_answer_HTTP_GPRS("AT+HTTPPARA=\"CID\",1", "", NULL);
    
    if (answer != 0)
      return answer;
      //goto Ext1;

//88////////////////
    
    Serial.println("Отправка: AT+HTTPPARA=\"URL\",\"http://mirossa.ru/q756dd/fcl01/7a888tyt.php\"");    
    
    answer = read_answer_HTTP_GPRS("AT+HTTPPARA=\"URL\",\"http://mirossa.ru/q756dd/fcl01/7a888tyt.php?l=12&p=12\"", "", NULL);
    if (answer != 0){
      //Serial.println(response);
      return answer;
      //goto Ext1;
    }

//88////////// USER AGENT //////
    
    Serial.println("Отправка: USER AGENT");    
    
    answer = read_answer_HTTP_GPRS("AT+HTTPPARA=\"UA\",\"Go-http-clientQ/1.1\"", "", NULL);  // иначе в USER-AGENT будет "SIMCOM_MODULE"
    if (answer != 0){
      //Serial.println("USER AGENT error");
      return answer;
      //goto Ext1;
    }
    
//10////////////////////////////

  Serial.println("Отправка: AT+HTTPACTION=0");

    answer = read_answer_HTTP_GPRS("AT+HTTPACTION=0", "+HTTPACTION: 0,200", DataLen);  // нужно парсить! В sim900 так "+HTTPACTION:0,200",
                                          //  в sim800c так "+HTTPACTION: 0,200"  (с пробелом)
    if (answer != 0){ //error
        //Serial.println(response);
        return answer;
      //goto Ext1;
    }
    //отладка 
    Serial.println(DataLen);
    
//11//////////  AT+HTTPHEAD  читаем заголовки http-ответа ////////////////////
    Serial.println("Отправка: AT+HTTPHEAD"); 

     while( GPRS.available() > 0) 
         GPRS.read();    // Clean the input buffer
    
    GPRS.println("AT+HTTPHEAD");    // Отправка AT команды 

    previous = millis();
     while ( ((millis() - previous) < 5000) ){     // !!! timeout нужно скидывать, когда получаю байты данных                                         
       
       if ( GPRS.available() > 0 ) {
         
            Serial.write(GPRS.read());   // Теряются последние несколько символов. Это было из-за того, что скорость GPRS была
                                // установлена больше (19200), чем скорость обмена с монитором порта (9600).
       }   
     } 
    Serial.println("конец AT+HTTPHEAD");

    // пример ответа:
 /* AT+HTTPHEAD

    +HTTPHEAD: 154
    http/1.1 200 ok
    server: nginx
    date: sun, 18 aug 2019 15:01:27 gmt
    content-type: text/html; charset=utf-8
    content-length: 9
    connection: keep-alive
    
    
    OK
*/
//////////////////////////////////
  
    //Serial.println("Отправка: AT+HTTPREAD=0,175");
    Serial.println("=== Отправка: AT+HTTPREAD");
    
    //GPRS.println("AT+HTTPREAD=0,175");

  answer = read_answer_httpread("AT+HTTPREAD", "+HTTPREAD:", "OK\r\n", &lengthData );
  if (answer != 0) //error
      return answer;
      //goto Ext1;
  Serial.println("=== Успешно: AT+HTTPREAD");

  //отладка
    Serial.print("=== Получено полезных байт: ");
    Serial.println(lengthData, DEC);
    //Serial.print("=== Начало полезных байт");

    //for (c = 0; c < lengthData; c++  )
        //Serial.write( data_buffer[c] );
    //Serial.println("=== Конец полезных байт");
  //отладка
  
//12//////////////////////////////////////
//////////////////////////////////////////
//HTTPTERM:  
    Serial.println("Отправка: AT+HTTPTERM");    
    
    //answer = read_answer_HTTP_GPRS("AT+HTTPTERM");
    answer = read_answer_HTTP_GPRS("AT+HTTPTERM", "", NULL);
    
    if (answer != 0)
      return answer;
      //goto Ext1;

    /////////////
    return answer;
    
  } // get_SMSdata_http()
  
 ////////////////////////// для MTS ////////////////////////////////////////////////////////////////////////////////////////////// 
  uint8_t start_GPRS(void){
      uint8_t answer = 0;

      //11111111////////////

    answer = read_answer_HTTP_GPRS("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", "", NULL);
    
    if (answer != 0)
      return answer;
      //goto Ext1;

//222222222/////////

    answer = read_answer_HTTP_GPRS("AT+SAPBR=3,1,\"APN\",\"internet.mts.ru\"", "", NULL);
    if (answer != 0)
      return answer;
      //goto Ext1;
            
//33333333/////////

    answer = read_answer_HTTP_GPRS("AT+SAPBR=3,1,\"USER\",\"mts\"", "", NULL);
    if (answer != 0)
      return answer;
      //goto Ext1;
         
//4444////////////////////

    answer = read_answer_HTTP_GPRS("AT+SAPBR=3,1,\"PWD\",\"mts\"", "", NULL);
    if (answer != 0)
      return answer;
      //goto Ext1;
         
//555/////////////////

    answer = read_answer_HTTP_GPRS("AT+SAPBR=1,1", "", NULL);
    if (answer != 0)
      return answer;
      //goto Ext1;
      
//666///////////////

    return answer;
  }  // start_GPRS

  // программное включение питания
void power_on()
  {
  uint8_t answer;
  pinMode(onModulePin,OUTPUT);
  // checks if the module is started
  digitalWrite(onModulePin,LOW);
  delay(1000);
  digitalWrite(onModulePin,HIGH);
  delay(2000);
  digitalWrite(onModulePin,LOW);
  delay(3000);
/*  answer = read_answer_HTTP_GPRS("AT", "", NULL);
  
  if (answer != 0)
    {
    digitalWrite(onModulePin,LOW);
    delay(1000);
    digitalWrite(onModulePin,HIGH);
    delay(2000);
    digitalWrite(onModulePin,LOW);
    delay(3000);
    digitalWrite(onModulePin,HIGH);
    delay(3000);
    digitalWrite(onModulePin,LOW);
    // время ожидания ответа
    while(answer != 0)
      {  
      // Send AT every n seconds and wait for the answer   
      answer = read_answer_HTTP_GPRS("AT", "", NULL);    
      }
    }
 */
  }
Begin HTTP request.

=== Отправка: AT+HTTPINIT

Отправка: AT+HTTPPARA="CID",1
Отправка: AT+HTTPPARA="URL","http://mirossa.ru/q756dd/fcl01/7a888tyt.php"
Отправка: USER AGENT
Отправка: AT+HTTPACTION=0
178
Отправка: AT+HTTPHEAD
AT+HTTPHEAD

+HTTPHEAD: 179
http/1.1 200 ok
server: nginx
date: fri, 04 oct 2019 23:12:07 gmt
content-type: text/html; charset=utf-8
content-length: 178
connection: keep-alive
vary: accept-encoding


OK
конец AT+HTTPHEAD
=== Отправка: AT+HTTPREAD

<html><body>
<p>hello, . machine! and test testovich223?</p>
<p>second floor.</p>
<p>third machine.</p>
<p>Captan</p>
<p>sketch 1313</p>
<p>Next page is 57.</p>
</body></html>


=== Успешно: AT+HTTPREAD
=== Получено полезных байт: 178
Отправка: AT+HTTPTERM

AT+SAPBR=0,1

OK

https://alex-exe.ru/radio/wireless/gsm-sim900-gprs/
http://ak.ale31.ru/работа-c-at-командами-и-gprs-на-arduino/
https://www.raviyp.com/embedded/194-sim900-gprs-http-at-commands?start=1

Прошивка hex-файлов в Arduino

https://acdc.foxylab.com/avrdude
http://mega-avr.com.ua/programma-sinaprog-2-1-1-rus/

//запуск из консоли
C:\avrdude\avrdude.exe -C avrdude.conf -c arduino -P com3 -p m328p -U flash:w:"C:\avrdude\SoftwareSerialExample_PSP.ino.standard.hex":a -q

Комментарии




information