Как отредактировать библиотеку 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 а также isFinalResponseSuccess1 в 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% правильно.

Другие вопросы по тегам