SIM900 AT命令响应解析
SIM900 AT Commands response parsing
我正在使用连接到 Arduino Uno 的 SIM900 GPS/GPRS 模块扩展板,我将如何解析我的 AT 命令的响应?或者在发送 AT 命令后如何删除串口中打印的 1st 行?
AT+CMGL="ALL"
+CMGL: 1,"REC READ","+XXXXXXXXXX","","16/04/25,15:20:59+32"
Hilp akp si ralphh the pogi one mmalit mi pizza hehehehehe
+CMGL: 2,"REC READ","+XXXXXXXXXX","","16/04/25,21:51:33+32"
Yow!!!
OK
上面输出的例子,我想去掉AT+CMGL="ALL"
然后解析剩下的数据。什么是最好的解析方法?
第一行AT+CMGL="ALL"
好像是回声。您可以通过在 setup
函数中向您的模块发送 ATE0
来禁用它。
至于其余的数据,都是一样的格式。您可以使用不同的字符串操作函数轻松编写解析器。
How will I be able to parse the response of my AT commands?
是的,这是正确的问题。
How will I be able to remove the 1st line printed in the serial after sending an AT command?
不,这个问题问错了,因为如果你关心 echo 是否开启,那你就错了。
解析AT命令输出的正确策略如下:
- 发送 AT 命令行(以
"\r"
正确终止)。
- 读取从调制解调器收到的一个字符,直到你有一个完整的行以
"\r\n"
结束,然后解析该行。
- 如果该行等于最终结果代码,则命令行的所有输出都已完成(调制解调器已准备好接收新命令)。这一定是您测试的第一件事!
- 如果 AT 命令 运行 的信息文本响应行有前缀(几乎所有都有)检查该行是否以此开头,如果是则处理该行,否则忽略它。
- 如果 AT 命令 运行 没有前缀,您可能想要打印所有内容,直到收到最终结果代码。这仅适用于遗留命令,如
ATI
,并且对于解析这些命令,您可能合理地关心是否回显。
现在,AT+CMGL
命令需要多做一些工作,因为响应被分成多行。
首先,最好的信息来源应该是制造商特定的 AT 文档,其次是标准化 AT+CMGL
命令的官方 3GPP 27.005 规范。
文本模式下AT+CMGL的响应指定为
+CMGL: <index>,<stat>,<oa/da>,[<alpha>],[<scts>][,<tooa/toda>,
<length>]<CR><LF><data>[<CR><LF>
+CMGL: <index>,<stat>,<da/oa>,[<alpha>],[<scts>][,<tooa/toda>,
<length>]<CR><LF><data>[...]]
因此,在收到以“+CMGL:”开头的行之后,直到您阅读空白行 (“\r\n”) 之前的所有行都属于此。
请参阅 了解一般代码结构和流程,尽管如上所写,响应的多行 属性 需要更多处理。我会使用类似下面的东西(未经测试的代码):
enum CMGL_state {
CMGL_NONE,
CMGL_PREFIX,
CMGL_DATA
};
// Extra prototype needed because of Arduino's auto-prototype generation which often breaks compilation when enums are used.
enum CMGL_state parse_CMGL(enum CMGL_state state, String line);
enum CMGL_state parse_CMGL(enum CMGL_state state, String line)
{
if (line.equals("\r\n") {
return CMGL_NONE;
}
if (line.startsWith("+CMGL: ") {
return CMGL_PREFIX;
}
if (state == CMGL_PREFIX || state == CMGL_DATA) {
return CMGL_DATA;
}
return CMGL_NONE;
}
...
write_to_modem("AT+CMGL=\"ALL\"\r");
CMGL_state = CMGL_NONE;
goto start;
do {
CMGL_state = parse_CMGL(CMGL_state, line);
switch (CMGL_state) {
case CMGL_PREFIX:
process_prefix(line); // or whatever you want to do with this line
break;
case CMGL_DATA:
process_data(line); // or whatever you want to do with this line
break;
case CMGL_NONE:
default:
break;
}
start:
line = read_line_from_modem();
} while (! is_final_result_code(line))
如果您正在使用 arduino
,我建议您使用一个好的库!你不需要处理这些东西。试试 http://www.gsmlib.org/ 或者你可以找到任何其他你喜欢的。
我将在这里举一个例子。
#include "SIM900.h"
#include <SoftwareSerial.h>
//If not used, is better to exclude the HTTP library,
//for RAM saving.
//If your sketch reboots itself proprably you have finished,
//your memory available.
//#include "inetGSM.h"
//If you want to use the Arduino functions to manage SMS, uncomment the lines below.
#include "sms.h"
SMSGSM sms;
//To change pins for Software Serial, use the two lines in GSM.cpp.
//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.
//Simple sketch to send and receive SMS.
int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
void setup()
{
//Serial connection.
Serial.begin(9600);
Serial.println("GSM Shield testing.");
//Start configuration of shield with baudrate.
//For http uses is raccomanded to use 4800 or slower.
if (gsm.begin(2400)){
Serial.println("\nstatus=READY");
started=true;
}
else Serial.println("\nstatus=IDLE");
if(started){
//Enable this two lines if you want to send an SMS.
//if (sms.SendSMS("3471234567", "Arduino SMS"))
//Serial.println("\nSMS sent OK");
}
};
void loop()
{
if(started){
//Read if there are messages on SIM card and print them.
if(gsm.readSMS(smsbuffer, 160, n, 20))
{
Serial.println(n);
Serial.println(smsbuffer);
}
delay(1000);
}
};
我正在使用连接到 Arduino Uno 的 SIM900 GPS/GPRS 模块扩展板,我将如何解析我的 AT 命令的响应?或者在发送 AT 命令后如何删除串口中打印的 1st 行?
AT+CMGL="ALL"
+CMGL: 1,"REC READ","+XXXXXXXXXX","","16/04/25,15:20:59+32"
Hilp akp si ralphh the pogi one mmalit mi pizza hehehehehe
+CMGL: 2,"REC READ","+XXXXXXXXXX","","16/04/25,21:51:33+32"
Yow!!!
OK
上面输出的例子,我想去掉AT+CMGL="ALL"
然后解析剩下的数据。什么是最好的解析方法?
第一行AT+CMGL="ALL"
好像是回声。您可以通过在 setup
函数中向您的模块发送 ATE0
来禁用它。
至于其余的数据,都是一样的格式。您可以使用不同的字符串操作函数轻松编写解析器。
How will I be able to parse the response of my AT commands?
是的,这是正确的问题。
How will I be able to remove the 1st line printed in the serial after sending an AT command?
不,这个问题问错了,因为如果你关心 echo 是否开启,那你就错了。
解析AT命令输出的正确策略如下:
- 发送 AT 命令行(以
"\r"
正确终止)。 - 读取从调制解调器收到的一个字符,直到你有一个完整的行以
"\r\n"
结束,然后解析该行。- 如果该行等于最终结果代码,则命令行的所有输出都已完成(调制解调器已准备好接收新命令)。这一定是您测试的第一件事!
- 如果 AT 命令 运行 的信息文本响应行有前缀(几乎所有都有)检查该行是否以此开头,如果是则处理该行,否则忽略它。
- 如果 AT 命令 运行 没有前缀,您可能想要打印所有内容,直到收到最终结果代码。这仅适用于遗留命令,如
ATI
,并且对于解析这些命令,您可能合理地关心是否回显。
现在,AT+CMGL
命令需要多做一些工作,因为响应被分成多行。
首先,最好的信息来源应该是制造商特定的 AT 文档,其次是标准化 AT+CMGL
命令的官方 3GPP 27.005 规范。
文本模式下AT+CMGL的响应指定为
+CMGL: <index>,<stat>,<oa/da>,[<alpha>],[<scts>][,<tooa/toda>,
<length>]<CR><LF><data>[<CR><LF>
+CMGL: <index>,<stat>,<da/oa>,[<alpha>],[<scts>][,<tooa/toda>,
<length>]<CR><LF><data>[...]]
因此,在收到以“+CMGL:”开头的行之后,直到您阅读空白行 (“\r\n”) 之前的所有行都属于此。
请参阅
enum CMGL_state {
CMGL_NONE,
CMGL_PREFIX,
CMGL_DATA
};
// Extra prototype needed because of Arduino's auto-prototype generation which often breaks compilation when enums are used.
enum CMGL_state parse_CMGL(enum CMGL_state state, String line);
enum CMGL_state parse_CMGL(enum CMGL_state state, String line)
{
if (line.equals("\r\n") {
return CMGL_NONE;
}
if (line.startsWith("+CMGL: ") {
return CMGL_PREFIX;
}
if (state == CMGL_PREFIX || state == CMGL_DATA) {
return CMGL_DATA;
}
return CMGL_NONE;
}
...
write_to_modem("AT+CMGL=\"ALL\"\r");
CMGL_state = CMGL_NONE;
goto start;
do {
CMGL_state = parse_CMGL(CMGL_state, line);
switch (CMGL_state) {
case CMGL_PREFIX:
process_prefix(line); // or whatever you want to do with this line
break;
case CMGL_DATA:
process_data(line); // or whatever you want to do with this line
break;
case CMGL_NONE:
default:
break;
}
start:
line = read_line_from_modem();
} while (! is_final_result_code(line))
如果您正在使用 arduino
,我建议您使用一个好的库!你不需要处理这些东西。试试 http://www.gsmlib.org/ 或者你可以找到任何其他你喜欢的。
我将在这里举一个例子。
#include "SIM900.h"
#include <SoftwareSerial.h>
//If not used, is better to exclude the HTTP library,
//for RAM saving.
//If your sketch reboots itself proprably you have finished,
//your memory available.
//#include "inetGSM.h"
//If you want to use the Arduino functions to manage SMS, uncomment the lines below.
#include "sms.h"
SMSGSM sms;
//To change pins for Software Serial, use the two lines in GSM.cpp.
//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.
//Simple sketch to send and receive SMS.
int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
void setup()
{
//Serial connection.
Serial.begin(9600);
Serial.println("GSM Shield testing.");
//Start configuration of shield with baudrate.
//For http uses is raccomanded to use 4800 or slower.
if (gsm.begin(2400)){
Serial.println("\nstatus=READY");
started=true;
}
else Serial.println("\nstatus=IDLE");
if(started){
//Enable this two lines if you want to send an SMS.
//if (sms.SendSMS("3471234567", "Arduino SMS"))
//Serial.println("\nSMS sent OK");
}
};
void loop()
{
if(started){
//Read if there are messages on SIM card and print them.
if(gsm.readSMS(smsbuffer, 160, n, 20))
{
Serial.println(n);
Serial.println(smsbuffer);
}
delay(1000);
}
};