Как определить, что удаленная сторона отклонила голосовой вызов с помощью AT-команды

Ситуация:

В модеме на базе GSM вы начинаете голосовой вызов с ATDxxxxxxxxx;

Некоторые модемы выдают сообщение «CONNECT», когда удаленная сторона ответила, или другой модем возвращает «^ CONN: 1, 0» на диагностическом порте.

Однако, если удаленная сторона отклоняет вызов, эта обратная связь по соединению все равно отправляется.

AT + CPAS возвращает 4 (вызов выполняется).

AT + CIND (если поддерживается) возвращает, что вызов выполняется, и вызов не звонит.

У некоторых модемов данные не отправляются через порт данных, но у других есть (обычно отправляется тишина или тональный сигнал).

Через долгое время сеть отключает вызов, и модем, наконец, выдает «^ CEND» на диагностическом порте или «HANGUP: 1» на порте приложения.

Я хотел бы как можно скорее определить, когда удаленная сторона отклонила вызов, а не после тайм-аута сети. Как мне это сделать ?

РЕДАКТИРОВАТЬ: Кстати, я не говорю об «автоматическом» автоответчике, а об явном отклонении вызова (чтобы он не перенаправлялся на автоответчик).

Кроме того, я хотел бы избежать «обнаружения мелодии звонка на порте данных», как в решениях, которые могут оказаться сложными и требующими больших затрат ресурсов ЦП.


person xryl669    schedule 09.04.2014    source источник


Ответы (1)


Я отвечаю на свой вопрос, так что он служит другим в том же случае.

Обнаружение зависит от сети. Как правило, у французского оператора Free сеть не отключает вас при отклонении вызова (но позволяет вместо этого слышать мелодию звонка). В Германии это так. Поэтому я считаю, что французская сеть ведет себя неправильно или, по крайней мере, бесполезной.

В стандарте GSM / 3GPP нет ничего особенного для обнаружения мелодии звонка, поэтому единственный способ использовать такую ​​сеть - выполнить обнаружение программным способом. Это можно сделать «просто», проверив временное расстояние между схожими «звуковыми» значениями. Алгоритм примерно такой:

int range = 5, value = 350, periodFound = 0; // Arbitrary
int period[16] = {};
void onDataReceived(int sampleRate, short * data, int len)
{
     for (int i = 0; i < len; i++)
     {
         if (data[i] >= value - range && data[i] <= value + range)
         {
             period[periodFound++] = i;
         }
         if (periodFound == 16) break;
     }
     // Compute distance between periods (if it's the same, it's a ring tone)
     float avg = 0, dev = 0;
     int prev = period[0];
     for (int i = 1; i < periodFound; i++)
     {
         avg += (period[i] - prev);
         prev = period[i];
     }
     avg /= periodFound-1;
     prev = period[0];
     for (int i = 1; i < periodFound; i++)
     {
         dev += (period[i] - prev - avg) * (period[i] - prev - avg);
         prev = period[i]
     }

     // Last test
     if (fabs(avg - expectedPeriod) < range && dev < errorAllowed)
         printf("Ring tone!");
}
person xryl669    schedule 14.04.2014