如何从Arduino一个接一个地请求两个不同的URL?

时间:2017-04-27 17:56:21

标签: arduino gps gsm

在下面的代码段中,我使用带有Arduino UNO的GPS SKG13BL获取纬度,经度,时间,日期和速度,然后每隔5秒通过GSM模块将其发送到数据库。如果GPS返回的速度(存储到s)大于0,那么其他LED发光也会很低。在此代码段之后,我通过调用URL来执行数据库插入。这很好,并且按照我的想法获得了结果。

代码:

#include <NeoSWSerial.h>

//#include <SoftwareSerial.h>
#include <AltSoftSerial.h>
#include <NMEAGPS.h>

NeoSWSerial GSM(2, 3); // RX, TX: Connect TXD to RX & RXD to TX

static const int RXPin = 8, TXPin = 9;  //when looking from antenna of gps , Last TTL pin is to be connected to 8 and second one to 9
AltSoftSerial gpsPort(RXPin, TXPin);
static const uint32_t GPSBaud = 9600;

NMEAGPS gps;
gps_fix fix;
uint8_t fixCount = 0;
char dt[15],tm[15],lati[10],longi[10],rno[13]="kl-05-jb-007";
//int block = 0;

enum _parseState {
  PS_DETECT_MSG_TYPE,

  PS_IGNORING_COMMAND_ECHO,

  PS_HTTPPARA_RESPONSE,

  PS_HTTPACTION_TYPE,
  PS_HTTPACTION_RESULT,
  PS_HTTPACTION_LENGTH,

  PS_HTTPREAD_LENGTH,
  PS_HTTPREAD_CONTENT
};

enum _actionState {
  AS_IDLE,
  AS_WAITING_FOR_RESPONSE
};

byte actionState = AS_IDLE;
unsigned long lastActionTime = 0;

int s;

byte parseState = PS_DETECT_MSG_TYPE;
char buffer[160],url[160];
byte pos = 0;

int contentLength = 0;

void resetBuffer() {
  memset(buffer, 0, sizeof(buffer));
  pos = 0;
}

void sendGSM(const char* msg, int waitMs = 500) {
  GSM.println(msg);
  while(GSM.available()) {
    parseATText(GSM.read());
  }
  //delay(waitMs);
}

void setup()
{
  GSM.begin(9600);
  Serial.begin(9600);
  gpsPort.begin(GPSBaud);
  pinMode(13, OUTPUT); //pin 13 to be connected to positive of LED via a resistor
  Serial.println(F("Hinder LOADING....."));
  Serial.println(F("obtain gps and store data to database"));
  Serial.println(F("Testing by : "));
  Serial.println(F("Nikhil,Muthumani and Mathews"));
  Serial.println();

  sendGSM("AT+SAPBR=3,1,\"APN\",\"vodafone\"");  
  delay(500);
  sendGSM("AT+SAPBR=1,1",3000);
  delay(500);
  sendGSM("AT+HTTPINIT"); 
  delay(500); 
  sendGSM("AT+HTTPPARA=\"CID\",1");
  delay(500);
}

void loop()
{ 
  unsigned long now = millis();
  while (gps.available( gpsPort )) {
    fix = gps.read();
     //Serial.println(F("b"));
    // Once every 5 seconds...    
    if (++fixCount >= 5) {
       //Serial.println(F("a"));
      displayInfo();
      if(s>0) // Change led state when speed greater than 0 or less than 0
         digitalWrite(13, HIGH);
      else
         digitalWrite(13, LOW);
      //send the next report if previous one is finished
      if ( actionState == AS_IDLE ) {
      sprintf(url, "AT+HTTPPARA=\"URL\",\"http://hinder.000webhostapp.com/HInsert.php?rno=%s&lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",rno,lati,longi,s,dt,tm );
      sendGSM(url);
     // lastActionTime = now;
      parseState = PS_HTTPPARA_RESPONSE; // a new state
      actionState = AS_WAITING_FOR_RESPONSE;
      fixCount = 0;
    }

    }
  }

/*  if ((gps.statistics.chars < 10) && (millis() > 5000)) {
     Serial.println( F("No GPS detected: check wiring.") );
     while(true);
     block=1;
    }*/

  while(GSM.available()) {
    //lastActionTime = now;
    parseATText(GSM.read());
  }
 }


void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (fix.valid.location) {
    dtostrf( fix.latitude(),7,5,lati);
    //sprintf(lati,"%d",fix.latitude(),5);
    Serial.print(lati);
    Serial.print( ',' );
    dtostrf( fix.longitude(),8,5,longi);
    //sprintf(longi,"%d",fix.longitude(),5);
    Serial.print(longi);
  } else {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Speed: ")); 
  if (fix.valid.speed) {
    s=fix.speed_kph();
    Serial.print(s);
    Serial.print(F(" KMPH "));
  } else {
    Serial.print(F("INVALID"));
  }

  // Shift the date/time to local time
  NeoGPS::clock_t localSeconds;
  NeoGPS::time_t  localTime;
  if (fix.valid.date && fix.valid.time) {
    using namespace NeoGPS; // save a little typing below...

    localSeconds = (clock_t) fix.dateTime; // convert structure to a second count
    localSeconds += 5 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE; // shift timezone
    localTime = localSeconds;              // convert back to a structure
  }

  Serial.print(F("  Date : "));
  if (fix.valid.date) {
    sprintf(dt,"%02d/%02d/20%d",fix.dateTime.date,fix.dateTime.month,fix.dateTime.year);
    Serial.print(dt);
  } else {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Time : "));
  if (fix.valid.time) {
    if (localTime.hours>12)localTime.hours-=12;//To convert 24 hr format to 12 hr format
    sprintf(tm,"%02d:%02d:%02d",localTime.hours,localTime.minutes,localTime.seconds);
    Serial.print(tm);
    //block=1;
  } else {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}

void parseATText(byte b) {

  buffer[pos++] = b;

  if ( pos >= sizeof(buffer) )
    resetBuffer(); // just to be safe

  /*
   // Detailed debugging
   Serial.println();
   Serial.print("state = ");
   Serial.println(state);
   Serial.print("b = ");
   Serial.println(b);
   Serial.print("pos = ");
   Serial.println(pos);
   Serial.print("buffer = ");
   Serial.println(buffer);*/

  switch (parseState) {

  case PS_HTTPPARA_RESPONSE:
    {
      parseState = PS_DETECT_MSG_TYPE;
      sendGSM("AT+HTTPACTION=0");
     /*  while(GSM.available()) {
    //lastActionTime = now;
    parseATText(GSM.read());
  }*/

    }
    break;

  case PS_DETECT_MSG_TYPE: 
    {
      if ( b == '\n' )
        resetBuffer();
      else {        
        if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) {
          parseState = PS_IGNORING_COMMAND_ECHO;
        }
        else if ( b == ':' ) {
          //Serial.print("Checking message type: ");
          //Serial.println(buffer);

          if ( strcmp(buffer, "+HTTPACTION:") == 0 ) {
            Serial.println("Received HTTPACTION");
            parseState = PS_HTTPACTION_TYPE;
          }
          else if ( strcmp(buffer, "+HTTPREAD:") == 0 ) {
            Serial.println("Received HTTPREAD");            
            parseState = PS_HTTPREAD_LENGTH;
          }
          resetBuffer();
        }
      }
    }
    break;

  case PS_IGNORING_COMMAND_ECHO:
    {
      if ( b == '\n' ) {
        Serial.print("Ignoring echo: ");
        Serial.println(buffer);
        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_TYPE:
    {
      if ( b == ',' ) {
        Serial.print("HTTPACTION type is ");
        Serial.println(buffer);
        parseState = PS_HTTPACTION_RESULT;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_RESULT:
    {
      if ( b == ',' ) {
        Serial.print("HTTPACTION result is ");
        Serial.println(buffer);
        parseState = PS_HTTPACTION_LENGTH;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_LENGTH:
    {
      if ( b == '\n' ) {
        Serial.print("HTTPACTION length is ");
        Serial.println(buffer);

        // now request content
        GSM.print("AT+HTTPREAD=0,");
        GSM.println(buffer);

        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPREAD_LENGTH:
    {
      if ( b == '\n' ) {
        contentLength = atoi(buffer);
        Serial.print("HTTPREAD length is ");
        Serial.println(contentLength);

        Serial.print("HTTPREAD content: ");

        parseState = PS_HTTPREAD_CONTENT;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPREAD_CONTENT:
    {
      // for this demo I'm just showing the content bytes in the serial monitor
      Serial.write(b);

      contentLength--;

      if ( contentLength <= 0 ) {

        // all content bytes have now been read

        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();

        Serial.print("\n\n\n");

        actionState = AS_IDLE;
      }
    }
    break;
  }
}

现在我需要对此进行修改,因为当速度大于0时,随着LED的发光,变量flag(全局声明的int flag=0;)会递增。当速度等于0时,flag设置为0.如果标志值变为2(即两次连续读数时速度大于0),我想发送纬度,经度,日期,时间和在那个瞬间加速到另一个数据库,这也是通过调用URL(url1)来完成的。之后,我想通过调用其URL(url)将其发送到通常的数据库。

我做了如下修改:

if(s>0) // Change led state when speed greater than 0 or less than 0
   {       
      digitalWrite(13, HIGH);
      flag++;
      }          
  else
       {
        digitalWrite(13, LOW);
         flag=0;
          }
 if(flag==2)
    {
      sprintf(url1, "AT+HTTPPARA=\"URL\",\"http://speed.000webhostapp.com/HInsert.php?rno=%s&lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",rno,lati,longi,s,dt,tm );
      sendGSM(url1);
      parseState = PS_HTTPPARA_RESPONSE; // a new state
      actionState = AS_WAITING_FOR_RESPONSE;
     }

这并没有像我想象的那样获得结果。谁能帮我。是否可以在flag中使loop()变量以这种方式工作。我使用flag是否有问题,或者是另一个问题。

1 个答案:

答案 0 :(得分:0)

要对两个URL进行arduino请求有点困难,因为我们必须处理两个单独的请求及其响应,要么两个请求将合并并且不会获得所需的结果,否则代码会变得很大,因为arduino-uno不会能够处理。

所以我找到了一种简单的方法,即从第一个PHP页面(arduino本身请求)请求第二个PHP页面。这两个请求之间的唯一区别是第二个请求需要一个额外的变量。我传递了第一个请求,因此可以从第一页提出请求。

我更改了arduino代码如下:

  1. 首先我修改了进行检查的部分 - 正如我在问题中提到的displayinfo();之后,添加了一个标志位。所以它变成了这样:

    if(s>0) // s is speed
      {
       digitalWrite(13, HIGH); //if speed exceeds limit then LED is set to HIGH
       flag++;
      }
    else
     {
      digitalWrite(13, LOW); 
      flag=0;
     }
    
  2. arduino请求的网址也添加了flag变量。 (对于第二页的请求)。

    sprintf(url, "AT+HTTPPARA=\"URL\",\"http://hinder.000webhostapp.com/HInsert.php?flag=%d&rno=%s&lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",flag,rno,lati,longi,s,dt,tm );
    
  3. 在PHP代码中,我添加了以下行:

    if ( $flag == 2 )
    {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "http://masp203.000webhostapp.com/RTO.php?rno=".$rno."&date=".$date."&time=".$time."&speed=".$speed."&street=".$street."" );
    curl_setopt($ch, CURLOPT_HEADER, 0);
    
    curl_exec($ch);
    
    curl_close($ch);
    }
    

    这就像我希望的那样。

    希望这对某人有所帮助。