SaffronSuite

Saffron SIP

Asterisk: wake a sleeping iPhone

Two pieces: a PJSIP endpoint the app registers to, and three lines of dialplan that wake the iPhone just before you dial it. Fifteen minutes, most of it copy-paste.

Before you start

  • Asterisk 16 or newer with PJSIP (any current LTS is fine).
  • The relay endpoint and PBX key from the app: Settings → Incoming Calls, then copy both. The key starts with pk_ and belongs to your account, so treat it like a password.
  • curl on the PBX host, and outbound HTTPS allowed (port 443).

1. The endpoint

A wizard block gets you a working extension with the NAT settings a moving iPhone needs. Adjust the extension number and password:

/etc/asterisk/pjsip_wizard.conf
[101]
type = wizard
accepts_registrations = yes
sends_registrations = no
accepts_auth = yes
sends_auth = no
endpoint/context = from-internal
endpoint/allow = !all,opus,g722,ulaw,alaw
endpoint/direct_media = no
endpoint/rtp_symmetric = yes
endpoint/force_rport = yes
endpoint/rewrite_contact = yes
aor/max_contacts = 1
aor/remove_existing = yes
aor/qualify_frequency = 60
inbound_auth/username = 101
inbound_auth/password = YOUR_SIP_PASSWORD

The NAT flags are the part worth understanding:

  • rtp_symmetric and force_rport send media and signalling back to where the phone's packets actually came from, which is what keeps audio working on cellular.
  • rewrite_contact updates the contact with the phone's NAT'd address.
  • max_contacts = 1 with remove_existing means a fresh registration after a wake cleanly replaces the stale one.

In the app: Settings → Account, with username 101, your SIP password, and your PBX's domain and port. Transport lives under Settings → Advanced if your server speaks TCP rather than TLS.

2. The wake dialplan

The whole trick: when a call arrives, tell the relay, give the push a moment to land, then dial the extension as usual.

/etc/asterisk/extensions.conf
[globals]
SAFFRON_KEY=pk_your_key_from_the_app

[from-trunk]
exten => 101,1,NoOp(Waking Saffron SIP for 101)
 same => n,System(curl -s -m 2 https://sipreg.saffronsuite.com/v1/incoming-call -H "Authorization: Bearer ${SAFFRON_KEY}" -H "Content-Type: application/json" -d '{"call_id":"${UNIQUEID}","to":"sip:101@pbx.example.com","from":"${CALLERID(num)}","display_name":"${CALLERID(name)}"}')
 same => n,Wait(1.5)
 same => n,Dial(PJSIP/101,25)
 same => n,VoiceMail(101@default,u)
 same => n,Hangup()

Notes on the three lines:

  • Wait(1.5) is the retain step: it holds the call while Apple's push wakes the phone and the app re-registers. Don't skip it.
  • call_id just needs to be unique per call and stable across retries; ${UNIQUEID} does both. If you want the app to correlate the wake with the exact call, use the SIP Call-ID: ${CHANNEL(pjsip,call-id)}.
  • -m 2 caps the webhook at two seconds so a network blip can't stall your call flow.
  • If your dialplan uses Goto into ring groups or queues, fire the wake at the point where the call is committed to this extension, then route as normal.

3. Prove it works

From the PBX host, fake a call with curl. Your phone should ring within a couple of seconds, even locked in your pocket:

on the PBX host
curl -s https://sipreg.saffronsuite.com/v1/incoming-call \
  -H "Authorization: Bearer pk_your_key_from_the_app" \
  -H "Content-Type: application/json" \
  -d '{"call_id":"test-1","to":"sip:101@pbx.example.com","from":"100","display_name":"Test"}'

A 202 with "devices_woken": 1 means the relay found and woke your phone. Anything else, the troubleshooting page decodes it. Then reload the dialplan (dialplan reload in the Asterisk CLI) and make a real call.