取得訊息範例
2407.565181,N,12041.025767,E,170526,231638.0,44.4,11.6,266.2
#define iModemRx 26
#define iModemTx 27
#define iCharArrayMax 1024
#define iLed 12
#include <ctype.h>
HardwareSerial SerialAT(1);
char caATCmd[]="AT+CGPSINFO";
char caATKeyword[]="+CGPSINFO:";
char caPhp[]="cgpsinfo.php";
int iLedVal=0;
void qa(const char caQuestion[], char caAnswer[])
{
caAnswer[0]='\0';
while(SerialAT.available()) { SerialAT.read(); } // clear leftover data
SerialAT.write(caQuestion);
SerialAT.write("\r\n");
delay(50);
int iLen=0;
unsigned long ulLast=millis();
int iMaxMilliSecond=10000;
// maybe multi lines
while((millis()-ulLast)<iMaxMilliSecond)
{
while(SerialAT.available())
{
char c1=SerialAT.read();
ulLast=millis();
if(iLen<(iCharArrayMax-1))
{
caAnswer[iLen]=c1;
iLen++;
caAnswer[iLen]='\0';
}
}
if(strstr(caAnswer, "\r\nOK\r\n") || strstr(caAnswer, "\r\nERROR\r\n")) { iMaxMilliSecond=300; }
delay(1);
}
}
bool getBooQA(const char caQuestion[], const char caKeyword[])
{
static char caAnswerBuffer[iCharArrayMax];
qa(caQuestion, caAnswerBuffer);
if(strstr(caAnswerBuffer, caKeyword)!=NULL) { return true; }
return false;
}
void setup()
{
static char caAnswer[iCharArrayMax];
pinMode(iLed, OUTPUT);
digitalWrite(iLed, 1);
Serial.begin(115200); // esp32
SerialAT.begin(115200, SERIAL_8N1, iModemRx, iModemTx); // sim7600g-h
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
delay(3000);
while(SerialAT.available()) SerialAT.read();
while(getBooQA("AT", "OK")==false) { delay(1000); } // wait until AT is OK
// enable GPS via AT+CGPS=1
qa("AT+CGPS=0", caAnswer);
delay(3000);
qa("AT+CGPS=1", caAnswer);
// network registration
int iRetry=0;
while(getBooQA("AT+CGDCONT=1,\"IP\",\"internet\"", "\r\nOK\r\n")==false)
{
delay(1000);
iRetry++;
if(iRetry>10) { break; }
}
if(iRetry>10)
{
digitalWrite(4, LOW);
delay(500);
digitalWrite(4, HIGH);
delay(8000);
ESP.restart();
}
digitalWrite(iLed, 0);
}
bool getBooExtractGPSDataOk(char caInput[], char caOutput[], int iOutputMax, const char caKeyword[])
{
int iIdxInput=0;
int iIdxOutput=0;
bool booFound=false;
caOutput[0]='\0';
while(true)
{
if(caInput[iIdxInput]=='\0') { break; }
if(strncmp(&caInput[iIdxInput], caKeyword, strlen(caKeyword))==0)
{
booFound=true;
iIdxInput+=strlen(caKeyword);
while(caInput[iIdxInput]==' ') { iIdxInput++; } // remove spaces
break;
}
iIdxInput++;
if(iIdxInput>=(iCharArrayMax-1)) { return false; }
}
if(booFound==false) { return false; }
while(true)
{
if(caInput[iIdxInput]=='\0') { break; }
if(caInput[iIdxInput]=='\r' || caInput[iIdxInput]=='\n') { break; }
if(iIdxOutput<(iOutputMax-1))
{
caOutput[iIdxOutput]=caInput[iIdxInput];
iIdxOutput++;
}
else
{
break;
}
iIdxInput++;
if(iIdxInput>=iCharArrayMax) { break; }
}
caOutput[iIdxOutput]='\0';
if(iIdxOutput<=28) { return false; }
if(caOutput[11]!=',' || caOutput[13]!=',' || caOutput[26]!=',' || caOutput[28]!=',') { return false; }
return true;
}
bool getBooSafeChar(char c1)
{
if ((c1 >= 'a' && c1 <= 'z') ||
(c1 >= 'A' && c1 <= 'Z') ||
(c1 >= '0' && c1 <= '9'))
{
return true;
}
if (c1 == '-' ||
c1 == '_' ||
c1 == '.' ||
c1 == '~')
{
return true;
}
return false;
}
void encodeURIComponent(const char caInput[], char caOutput[], int iOutputMax)
{
static const char caHex[] = "0123456789ABCDEF";
int iIdxInput=0;
int iIdxOutput=0;
while(caInput[iIdxInput]!='\0' && iIdxOutput<(iOutputMax-1))
{
char c1=caInput[iIdxInput];
if(c1=='\r' || c1=='\n')
{
}
else if(getBooSafeChar(c1)==true)
{
caOutput[iIdxOutput]=c1;
iIdxOutput++;
}
else
{
if((iIdxOutput+3)>=iOutputMax) { break; }
caOutput[iIdxOutput+0] = '%';
caOutput[iIdxOutput+1] = caHex[(c1 >> 4) & 0xF];
caOutput[iIdxOutput+2] = caHex[c1 & 0xF];
iIdxOutput+=3;
}
iIdxInput++;
if(iIdxInput>=iCharArrayMax) { break; }
}
caOutput[iIdxOutput]='\0';
}
void sendGpsData(const char caPhp[], const char caGpsData[])
{
static char caEncodedGpsData[iCharArrayMax];
static char caCommand[1024];
caEncodedGpsData[0]='\0';
caCommand[0]='\0';
while(true)
{
if(getBooQA("AT+CPIN?", "+CPIN: READY")==false) { break; }
if(getBooQA("AT+CGATT=1", "\r\nOK\r\n")==false) { break; }
if(getBooQA("AT+CGATT?", "+CGATT: 1")==false) { break; }
if(getBooQA("AT+HTTPINIT", "\r\nOK\r\n")==false) { break; }
// parameters
encodeURIComponent(caGpsData, caEncodedGpsData, iCharArrayMax);
snprintf(
caCommand,
sizeof(caCommand),
"AT+HTTPPARA=\"URL\",\"http://liujiaje.com/resources/20260513_lilygo_t_sim7600g_h/%s?id=%s&data=%s\"",
caPhp, "lilygo1", caEncodedGpsData);
if(getBooQA(caCommand, "\r\nOK\r\n")==false) { break; }
if(getBooQA("AT+HTTPACTION=0", "+HTTPACTION:")==true)
{
delay(50);
getBooQA("AT+HTTPREAD=0,200", "+HTTPREAD:"); // read 200 bytes
delay(50);
}
int iRetry=0;
while(getBooQA("AT+HTTPTERM", "\r\nOK\r\n")==false)
{
delay(1000);
iRetry++;
if(iRetry>30)
{
// modem might be stuck
digitalWrite(4, LOW);
delay(500);
digitalWrite(4, HIGH);
delay(8000);
break;
}
}
break;
}
}
void loop()
{
char caAnswer[iCharArrayMax];
char caGpsData[iCharArrayMax];
iLedVal=(iLedVal+1) % 2;
digitalWrite(iLed, iLedVal);
while(true)
{
if(getBooQA("AT+CGPS?", "+CGPS: 1,1")==false) { break; }
delay(10);
qa(caATCmd, caAnswer);
caAnswer[iCharArrayMax-1]='\0';
if(getBooExtractGPSDataOk(caAnswer, caGpsData, sizeof(caGpsData), caATKeyword)==false) { break; }
if(strlen(caGpsData)<=14) { break; }
sendGpsData(caPhp, caGpsData);
break;
}
delay(1000);
/*
while (Serial.available()) { SerialAT.write(Serial.read()); }
while (SerialAT.available()) { Serial.write(SerialAT.read()); }
*/
}