我使用SIM800l与AT commands的arduino UNO拨打电话。通过使用此library,我使用gprsTest.callUp(number)
函数进行调用。问题是,即使数字错误或没有信用,它也会返回true
。
这部分代码很清楚GPRS_Shield_Arduino.cpp library为什么会发生这种情况。它没有检查ATDnumberhere;
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;
在软件串行通信上的返回是:
如果数字错误
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)
为每种情况使用不同的返回值,或者至少如果响铃则如何返回true?
答案 0 :(得分:1)
这个库代码似乎比我第一眼看到的最差,但它仍然有一些问题。最严重的是它的最终结果代码处理。
sim900_check_with_cmd
函数在概念上几乎就在那里,但只检查OK
是不可接受的。它应该检查调制解调器可能发送的每个可能的最终结果代码。
从输出示例中,您可以获得以下最终结果代码
但也存在一些。您可以查看atinout的代码,了解is_final_result_code
函数的示例(您还可以与isFinalResponseError
和isFinalResponseSuccess
1 进行比较{ {3}})。
return true;
末尾的无条件GPRS::callUp
是一个错误,但由于缺乏实施更好的API的想法而可能是故意的,因此调用客户端可以检查中间结果代码。但这是一种错误的做法。
该库实际上应该完成所有有状态命令行调用和最终结果代码解析,没有异常。只是在库中执行部分操作并将其中的一部分留给客户端只是糟糕的设计。
当客户想要检查或处理命令行和最终结果代码之间的中间结果代码或信息文本时,正确的方法是让库“解冻”从调制解调器接收的所有内容个别完整的行,并且对于不是最终结果代码的所有内容,通过回调函数将其提供给客户端。
以下是对我的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] == '\0') {
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;
提示:阅读ST-Ericsson's U300 RIL规范中第5章的全部内容,它将教您几乎所有关于命令行,结果代码和响应处理的知识。例如,命令行也应该以{{1}} V.250终止,而不是\r
-
1 请注意,\r\n
不是最终结果代码,它是中间结果代码,因此名称isFinalResponseSuccess严格来说不是100%正确。