【问题标题】:SIM900 AT Commands response parsingSIM900 AT 命令响应解析
【发布时间】:2016-04-25 20:03:41
【问题描述】:

我正在使用连接到 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",然后解析剩下的数据。解析的最佳方式是什么?

【问题讨论】:

    标签: arduino sms at-command sim900


    【解决方案1】:

    如何解析我的 AT 命令的响应?

    是的,这是正确的问题。

    发送 AT 命令后,如何删除串口中打印的 1st 行?

    不,这是一个错误的问题,因为如果您关心 echo 是否打开,那么您做错了。

    解析AT命令输出的正确策略如下:

    • 发送 AT 命令行(以"\r" 正确终止)。
    • 读取从调制解调器接收到的一个和一个字符,直到您有一个以"\r\n" 结尾的完整行,然后解析该行。
      • 如果该行等于最终结果代码,则命令行的所有输出都已完成(并且调制解调器已准备好接收新命令)。这一定是您测试的第一件事!
      • 如果运行的 AT 命令对其信息文本响应行有前缀(几乎所有都有),请检查该行是否以该前缀开头,如果是则处理该行,否则忽略它。
      • 如果运行的 AT 命令没有前缀,您可能希望在收到最终结果代码之前打印所有内容。这仅适用于像 ATI 这样的旧命令,并且对于解析这些命令,您可能会理所当然地关心 echo 与否。

    现在对于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”)之前的所有行都属于此。

    请参阅this answer 了解一般代码结构和流程,尽管如上文所述,响应的多行属性需要更多处理。我会使用类似以下的东西(未经测试的代码):

    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))
    

    【讨论】:

    • 哇,这吸收了很多东西,非常感谢您提供这些有用的信息,我只是怀疑我是否有能力完全实现这一点,因为这是我第一次处理 AT 命令和解析,还有一点点对某些部分感到困惑..非常感谢!
    【解决方案2】:

    第一行AT+CMGL="ALL" 似乎是回声。您可以通过在 setup 函数中向您的模块发送 ATE0 来禁用它。

    至于其余的数据,它们都具有相同的格式。您可以使用不同的字符串操作函数轻松编写解析器。

    【讨论】:

    • 非常感谢你!!!几天来我一直在寻找消除这些回声的方法,但我仍然不知道如何解析数据,你能给我一个简单的例子吗?
    • @Ralph 你的意思是像两小时前有人给你的答案on the Arduino site
    • @frarugi87 是的,因为我不知道何时调用该函数以及参数是什么以及为什么它返回一个 int 1,当我尝试将 Serial 存储到一个 char 数组中时,我得到随机字符` if (mySerial.available() > 0) { for (byte i = 0; i
    • @Ralph 什么?那个代码是从哪里来的?这个例子完全不同......
    【解决方案3】:

    如果您使用的是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);
      }
    };
    

    【讨论】:

      猜你喜欢
      • 2019-01-28
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-29
      • 1970-01-01
      相关资源
      最近更新 更多