Как отредактировать библиотеку SIM800l, чтобы убедиться, что вызов установлен
Я использую SIM800l для звонков с помощью Arduino UNO с AT-командами. Используя эту библиотеку, я звоню с gprsTest.callUp(number)
функция. Проблема в том, что он возвращает true
даже номер неправильный или нет кредита.
По этой части кода из библиотеки GPRS_Shield_Arduino.cpp понятно, почему это происходит. Не проверяет возврат 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 если он звонит?
1 ответ
Этот библиотечный код кажется лучше, чем худшее, что я видел на первый взгляд, но у него все еще есть некоторые проблемы. Наиболее серьезной является обработка кода в конечном результате.
sim900_check_with_cmd
Функция концептуально почти там, но только проверка на OK
ни в коем случае не приемлемо. Он должен проверять каждый возможный код окончательного результата, который модем может отправить. Из ваших выходных примеров у вас есть следующие конечные коды результатов
- Хорошо
- ОШИБКА
- НЕТ НОСИТЕЛЯ
- НЕТ ОТВЕТА
но существует и еще несколько. Вы можете посмотреть на код для atinout для примера is_final_result_code
функция (вы также можете сравнить с isFinalResponseError
а также isFinalResponseSuccess
1 в U300 RIL ST-Ericsson).
Безусловный 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;
Совет: Прочитайте всю главу 5 в спецификации V.250, она научит вас почти всему, что вам нужно знать о командных строках, кодах результатов и обработке ответов. Как, например, командная строка также должна заканчиваться \r
только не \r\n
-
1 Обратите внимание, что CONNECT
это не окончательный код результата, это промежуточный код результата, поэтому имя isFinalResponseSuccess, строго говоря, не на 100% правильно.