Situation:

On a GSM based modem, you start a voice call with ATDxxxxxxxxx;

Some modem issue a "CONNECT" when the remote side has answered, or other modem returns "^CONN: 1, 0" on the diagnostic port.

However, if the remote side rejects the call, this connection feedback is still sent.

AT+CPAS returns 4 (call in progress).

AT+CIND (when supported) returns that a call is running, and the call is not ringing.

Some modem do not have data sent on the data port, but other does (typically silence is sent, or a tone).

After a long time, the network disconnect the call and the modem then finally issue a "^CEND" on diagnostic port, or "HANGUP: 1" on the application port.

I would like to detect when the remote side has rejected the call as soon as possible, not after the network timeout. How do I do that ?

EDIT: BTW, I'm not speaking about the "automatic" answering machine, but a clear reject for the call (so it does not get redirected to the answering machine).

Also, I would like to avoid "detecting a ring-tone on the data port" like solutions which would prove tricky and CPU intensive to get right.

有帮助吗?

解决方案

I answer my own question, so it serves other in the same case.

The detection depends on the network. Typically, in French's operator Free, the network does not disconnect you on call rejection (but let you hear a ring tone instead). In Germany, it does. So I think the behaviour of the French network is wrong, or at least not helpful.

There is nothing specific in GSM/3GPP standard for detecting a ring tone, so the only way to go for such network is to perform detection programmatically. It can be done "simply" by checking the time distance between similar "sound" value. The algorithm is something like this:

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!");
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top