2

I'm looking for a SIP client for my Raspberry Pi (commandline). I want to be able to call my Raspberry Pi, and based on what buttons I press on the phone (resulting in DTMF tones), run the correct python-script.

I've tried the following options:

  • Twinkle https://pypi.org/project/pytwinkle/ Twinkle is not able to run scripts based on DTMF tones. You can run scripts on certain events, for example when a call is incoming, or when an incoming call is answered. But not based on DTMF tones.

  • PJSIP https://www.pjsip.org/ I'm trying to compile and install PJSIP but I cannot get it to work. During the installation process it says it cannot find required modules, and I can't get past that point.

  • Linphone https://www.linphone.org/technical-corner/linphone I haven't been able to find a way to run scripts with Linphone. I'm not sure it's possible.

Does anyone have experience with this? Can you point me in the right direction?

Any tips will be greatly appreciated!

Albrecht
  • 21
  • 1
  • 2

1 Answers1

1

PJSIP is definitely what you need. Tell something more about what exactly your problem is.

Example below shows simple application based on PJSUA (high level API of PJSIP).

#include <pjsua-lib/pjsua.h>
#include <iostream>
#define THIS_FILE "sipdtmf.cpp"

using namespace std;

void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) { PJ_LOG(1, (THIS_FILE, "Incoming call!")); pjsua_call_answer(call_id, PJSIP_SC_OK, nullptr, nullptr); }

void on_dtmf_digit(pjsua_call_id call_id, int digit) { PJ_LOG(1, (THIS_FILE, "Got DTMF %c", char(digit))); }

void init_pjsua() { pjsua_config cfg; pjsua_logging_config log_cfg; pjsua_transport_config transport_cfg; pjsua_acc_id acc_id; pjsua_transport_id transport_id; pjsua_media_config media_cfg; pj_status_t status;

status = pj_init();
if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, &quot;PJ init error&quot;, status);
    exit(1);
}

status = pjsua_create();
if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, &quot;PJSUA create error&quot;, status);
    exit(1);
}

pjsua_config_default(&amp;cfg);
cfg.cb.on_incoming_call = &amp;on_incoming_call;
cfg.cb.on_dtmf_digit = &amp;on_dtmf_digit;
cfg.user_agent = pj_str(&quot;SIPDTMF 1.0&quot;);

pjsua_media_config_default(&amp;media_cfg);
pjsua_logging_config_default(&amp;log_cfg);
log_cfg.console_level = 1;

status = pjsua_init(&amp;cfg, &amp;log_cfg, &amp;media_cfg);
if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, &quot;PJSUA init error&quot;, status);
    exit(1);
}

pjsua_transport_config_default(&amp;transport_cfg);
transport_cfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &amp;transport_cfg, &amp;transport_id);
if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, &quot;Transport error&quot;, status);
    pjsua_destroy();
    exit(1);
}

status = pjsua_start();
if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, &quot;PJSUA start error&quot;, status);
    pjsua_destroy();
    exit(1);
}

status = pjsua_acc_add_local(transport_id, PJ_TRUE, &amp;acc_id);
if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, &quot;Account error&quot;, status);
    pjsua_destroy();
    exit(1);
}

}

int main (int argc, char *argv[]) { char c; init_pjsua(); cout << "SIPDTMF ready. Type Q to stop." << endl; while (cin >> c) { if (c == 'Q' || c == 'q') { pjsua_call_hangup_all(); pjsua_destroy(); break; } } return 0; }

void on_dtmf_digit(...) is callback where you can do something on incoming DTMF (eg. call some system command).

This example use local account. It's mean any SIP call to device which running above application will be handled.

DaszuOne
  • 126
  • 4