SaffronSuite

Saffron SIP

FreePBX: push calls to a sleeping iPhone

FreePBX rides on Asterisk, so the shape is the same: an extension for the app, and a small custom context that wakes the phone before the call is delivered. The GUI does most of it.

Before you start

  • FreePBX 15 or newer, extensions on chan_pjsip (the default).
  • The relay endpoint and PBX key from the app: Settings → Incoming Calls. The pk_ key is account-scoped, treat it like a password.
  • Shell access to the PBX for one small config file.

1. The extension

  1. Applications → Extensions → Add Extension → Add New SIP [chan_pjsip] Extension.
  2. Give it a number (say 101), a display name, and note the Secret.
  3. On the Advanced tab set Max Contacts to 1 and leave Remove Existing on yes. A fresh registration after a wake then replaces the stale one instead of fighting it.
  4. FreePBX's chan_pjsip defaults already include the NAT settings a mobile client needs (rtp_symmetric, rewrite_contact, force_rport). Leave them on.
  5. Submit and Apply Config.

In the app: Settings → Account with username 101, the Secret as password, and your PBX's address. If your FreePBX doesn't have TLS set up, choose TCP transport under Settings → Advanced (or follow the TLS guide and keep encryption).

2. The wake hook

FreePBX owns the generated dialplan, so custom logic goes in extensions_custom.conf, which survives upgrades and Apply Config. This context wakes the phone, waits for the push to land, then hands the call to FreePBX's normal extension routing:

/etc/asterisk/extensions_custom.conf
[saffron-wake]
exten => _X.,1,NoOp(Waking Saffron SIP for ${EXTEN})
 same => n,System(curl -s -m 2 https://sipreg.saffronsuite.com/v1/incoming-call -H "Authorization: Bearer pk_your_key_from_the_app" -H "Content-Type: application/json" -d '{"call_id":"${UNIQUEID}","to":"sip:${EXTEN}@pbx.example.com","from":"${CALLERID(num)}","display_name":"${CALLERID(name)}"}')
 same => n,Wait(1.5)
 same => n,Goto(from-did-direct,${EXTEN},1)

Then wire calls through it:

  1. Admin → Custom Destinations → Add. Target saffron-wake,101,1, description "Wake Saffron SIP 101".
  2. Connectivity → Inbound Routes: point the DID that should ring your iPhone at that Custom Destination instead of the extension. The context forwards to the extension itself after the wake.
  3. Apply Config.

Ring groups and queues work the same way: route them at the custom destination, or fire the wake from a queue's pre-dial hook if you're comfortable deeper in the dialplan.

3. Prove it works

Lock your phone, put it in your pocket, and call the DID. You should feel the ring in about two seconds. To test the relay leg alone, run the curl command from the block above directly in a shell; 202 accepted with "devices_woken": 1 means the wake path is healthy end to end.