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!

1 Answer 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, "PJ init error", status);

    status = pjsua_create();
    if (status != PJ_SUCCESS) {
        pjsua_perror(THIS_FILE, "PJSUA create error", status);

    cfg.cb.on_incoming_call = &on_incoming_call;
    cfg.cb.on_dtmf_digit = &on_dtmf_digit;
    cfg.user_agent = pj_str("SIPDTMF 1.0");

    log_cfg.console_level = 1;

    status = pjsua_init(&cfg, &log_cfg, &media_cfg);
    if (status != PJ_SUCCESS) {
        pjsua_perror(THIS_FILE, "PJSUA init error", status);

    transport_cfg.port = 5060;
    status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &transport_cfg, &transport_id);
    if (status != PJ_SUCCESS) {
        pjsua_perror(THIS_FILE, "Transport error", status);

    status = pjsua_start();
    if (status != PJ_SUCCESS) {
        pjsua_perror(THIS_FILE, "PJSUA start error", status);

    status = pjsua_acc_add_local(transport_id, PJ_TRUE, &acc_id);
    if (status != PJ_SUCCESS) {
        pjsua_perror(THIS_FILE, "Account error", status);

int main (int argc, char *argv[]) {
    char c;
    cout << "SIPDTMF ready. Type Q to stop." << endl;
    while (cin >> c) {
        if (c == 'Q' || c == 'q') {
    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.

  • This all sounds fascinating... in particular the idea of "instant messaging" that could be transported without paying tolls to the telecom giants. Are there any SIP-based apps you could recommend that run on RPi today that do anything like "instant messaging"?
    – Seamus
    Mar 19, 2021 at 20:25
  • 1
    @Seamus I dont know any existing apps, but instant messaging is also easy to implement with PJSUA. I have video doorphone with such feature, based on PJSUA, running on RPi. I can call my RPi, send some DTMF code, and in response I get instant message with current outside temperature, pressure, humidity and other params from platform like cpu/gpu temp. If you'll be implementing similar functionality, and you'll be having some question, give a link and I'll try to help you.
    – DaszuOne
    Mar 23, 2021 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.