如何编辑SIM800l库保证通话建立

How to edit SIM800l library to ensure that a call is established

我使用 SIM800l 通过 AT commands. By using this library 通过 arduino UNO 拨打电话 我通过 gprsTest.callUp(number) 功能拨打电话。问题是returns true连号都错了或者没有积分。

GPRS_Shield_Arduino.cpp library 的这部分代码中可以清楚地看出为什么会这样。它不检查 ATDnumberhere;

的 return
bool GPRS::callUp(char *number)
{
    //char cmd[24];
    if(!sim900_check_with_cmd("AT+COLP=1\r\n","OK\r\n",CMD)) {
        return false;
    }
    delay(1000);
    //HACERR quitar SPRINTF para ahorar memoria ???
    //sprintf(cmd,"ATD%s;\r\n", number);
    //sim900_send_cmd(cmd);
    sim900_send_cmd("ATD");
    sim900_send_cmd(number);
    sim900_send_cmd(";\r\n");
    return true;
}

软件串口通讯ATDnumberhere;的return为:

如果号码有误 ERROR

如果没有积分

 `MO CONNECTED  //instant response

  +COLP: "003069XXXXXXXX",129,"",0,"" // after 3 sec

  OK`

如果正在呼叫但无人接听

MO RING //instant response, it is ringing

NO ANSWER // after some sec

如果是来电挂断

MO RING //instant response

NO CARRIER // after some sec

如果接收方没有载波

ATD6985952400;

NO CARRIER

如果是来电,接听并挂断

MO RING

MO CONNECTED

+COLP: "69XXXXXXXX",129,"",0,""

OK

NO CARRIER

问题是如何通过此函数 gprsTest.callUp(number) 为每种情况使用不同的 return,或者至少如何 return如果响铃是真的吗?

这个库代码乍一看似乎比我见过的最差的要好,但它仍然存在一些问题。最严重的是它的最终结果代码处理。

sim900_check_with_cmd 函数在概念上已经差不多了,但是只检查 OK 是绝对不能接受的。它应该检查调制解调器可能发送的 每一个可能的 最终结果代码。 从您的输出示例中,您有以下最终结果代码

  • 好的
  • 错误
  • 无承运人
  • 没有回答

但还有更多。您可以查看 atinout for an example of a is_final_result_code function (you can also compare to isFinalResponseError and isFinalResponseSuccess1 in ST-Ericsson's U300 RIL).

的代码

GPRS::callUp 末尾的无条件 return true; 是一个错误,但这可能是故意的,因为缺乏实现更好的 API 的想法,以便调用客户端可以检查中间结果代码。但这是一种错误的做法。 该库确实应该无一例外地执行所有有状态的命令行调用和最终结果代码解析。只在库中完成其中的一部分并将其中的一部分留给客户是糟糕的设计。

当客户端想要检查或操作命令行和最终结果代码之间的中间结果代码或信息文本时,正确的方法是让库 "deframe" 它收到的所有内容从调制解调器到单独的完整线路,对于不是最终结果代码的所有内容,通过回调函数将其提供给客户端。

以下是我的 atinout 程序未完成的更新:

bool send_commandline(
        const char *cmdline,
        const char *prefix,
        void (*handler)(const char *response_line, void *ptr),
        void *ptr,
        FILE *modem)
{
        int res;
        char response_line[1024];

        DEBUG(DEBUG_MODEM_WRITE, ">%s\n", cmdline);
        res = fputs(cmdline, modem);
        if (res < 0) {
                error(ERR "failed to send '%s' to modem (res = %d)", cmdline, res);
                return false;
        }

        /*
         * Adding a tiny delay here to avoid losing input data which
         * sometimes happens when immediately jumping into reading
         * responses from the modem.
         */
        sleep_milliseconds(200);

        do {
                const char *line;
                line = fgets(response_line, (int)sizeof(response_line), modem);
                if (line == NULL) {
                        error(ERR "EOF from modem");
                        return false;
                }
                DEBUG(DEBUG_MODEM_READ, "<%s\n", line);
                if (prefix[0] == '[=10=]') {
                        handler(response_line, ptr);
                } else if (STARTS_WITH(response_line, prefix)) {
                        handler(response_line + strlen(prefix) + strlen(" "), ptr);
                }
        } while (! is_final_result(response_line));

        return strcmp(response_line, "OK\r\n") == 0;
}

您可以将其作为实施正确处理的基础。如果你想 从函数中获取错误响应,添加一个额外的回调参数并更改为

        success = strcmp(response_line, "OK\r\n") == 0;
        if (!success) {
                error_handler(response_line, ptr);
        }
        return success;

提示:请阅读 V.250 specification, it will teach you almost everything you need to know about command lines, result codes and response handling. Like for instance that a command line should also be terminated with \r only 中的第 5 章全部内容,而不是 \r\n-


1注意CONNECT不是最终结果码,是中间结果码,所以名字isFinalResponseSuccess严格来说不是100%正确。