Skip to content
Lorne Gaetz edited this page Feb 17, 2014 · 4 revisions


This FreePBX module allows you to create short custom dial plan fragments. While such fragments can also be added to extensions-custom.conf, the advantage of creating them in this module is that the resulting dial plan fragment can be directly selected as a destination in modules that use destinations. Optionally, the dial plan fragment can also be accessed directly by calling an extension number. Just about anything that could be put into extensions_custom.conf can be placed in a Dialplan Injection.

Version history

Version 0.0.1: Initial version

Version 0.0.2: Fixed extension bug Allowed patterns in extension (allows a Dialplan Injection to be accessed by a group of extensions defined by a pattern) Commands are one big text area now

Version 0.0.3: Added ability to add line labels. Labels also become available as destinations for other modules. Each direct dial injection is now in its own context to allow individual inclusion in other contexts. Version now display correctly on screen.

Version 0.1.0: Removed unique constraint on direct dial extension. Added templates for most dialplan apps.

Version 0.1.1: Fixed a few templates and version display bug.

Version 0.1.1m: Fork by to fix major issues with later versions of FreePBX.


Download the latest version from here: In module admin, select upload modules and browse to the downloaded file. Click upload then browse to FreePBX, Tools | Module Administration. You should see an entry for Dialplan Injection. Click on it, click install, then click process and the red bar as usual.

Usage Instructions

To create a Dialplan Injection, click on Dialplan Injection and then on "Add Injection" (if you are not already on that page).

Enter a short description for your Injection - this should contain letters and numbers only.

Optionally, you may enter an extension number for direct access, which will allow dialing this injection directly. You may leave the extension field blank if you only plan to access the injection indirectly (such as from an IVR menu choice) OR if you plan to use Misc. Applications to create one or more extensions (or feature codes) for entry point(s). The extension may be a pattern (such as would be allowed in a route dial plan) to match (for example) a range of extensions. Also, you may use a pipe | to strip the preceding digits, as would be allowed in a route dial plan pattern.

Under Destination, choose a destination for use when all the lines in your Dialplan Injection have executed. For example, you could select Core: Hangup if you simply plan to play a message to the caller and disconnect. Or, you could send a caller to an IVR to make another selection.

Click on "Submit" to create the Dialplan Injection. Do not click the Red Bar yet.

Now select the Injection you just created from the list of Injections at the right. When you bring it up, you should see a text box where you can enter the actual lines of your injection. Remember, at this point you are playing the role of computer programmer and if you write bad code, your Injection wont work as you intend. Garbage in, garbage out. So check what you write very carefully.

As with code you might write in an actual context, you can use line labels to allow for conditional or unconditional jumps, or to permit multiple entry points to your code (for example, you might write a routine that returns certain information about an extension - if entered at one point, it might give the information about the extension the user is calling from, whereas if entered at a different point, it might prompt the caller to enter an extension and then give the report about that extension). To use a label, simply enclose it in parenthesis and put a comma between it and the statement, like this:

(label1),NoOp(This is a line with a label)



Each label you use can be selected as an entry point from other applications (for example, in Misc. Applications you will see a radio button and dropdown for Dialplan Injections, and in that dropdown you'll be able to select any labeled statement as an entry point, in addition to the normal entry at the top of the code). For example, if your Dialplan Injection was named My Injection and contained the above code fragment, you'd be able to use "My Injection" as a destination, and also "My Injection-label1".

There's also a "New Command" box that contains some commonly used commands, in order to help you recall the syntax of these commands. You don't have to select anything here but if you do, whatever you select will be pasted into your code.

Remember to put Ringing on a line by itself (usually as the first line of the code) if you want your caller to hear a Ringing signal until the call is answered. Also, you need to use Answer on a line by itself before playing any significant information to the caller (any message not having to do with call progress) in order to comply with legal requirements and to make sure that billing commences at the proper point. Obviously this does not apply for injections that can only be reached by internal callers, or can only be reached after the call has already been answered (by an IVR, for example).

When you are finished writing your code, click on "Submit", and only now should you click the Red Bar to enable use of your Dialplan Injection.

There is one other point that needs to be mentioned: If you have also installed the Custom Contexts module, you can individually allow or deny each Dialplan Injection. Here is how to do that (please note that nothing in the next three paragraphs will make sense to you if you have never used the Custom Contexts module):

Click on the Tools tab, Custom Contexts Admin, and Add context. Put ext-injections in the Context field (this must be entered exactly as shown), and give it a description (e.g. "Dialplan Injections"). Submit the page and click on the Red Bar.

(Optional but recommended): Go back to Tools, Custom Contexts Admin, and click on the description you just created (e.g. "Dialplan Injections"). When the page comes up, give each of the injections a meaningful name, rather than the default ext-injection-number. Note that the numbers at the end of each default injection name match the numbers in angle brackets following each injection name on the Dialplan Injections page. At present the Custom Contexts Admin tool doesn't seem to pick up the "friendly" name of the Dialplan Injections automatically.

After doing the above, you can go to the Setup tab, Custom Contexts, and edit your contexts (this assumes you've already created some custom contexts) as follows: Deny ext-injections, which should now be in red text, unless you want the context to allow ALL Dialplan Injections. Then, allow only those injections you wish to allow in each custom context.


Here are some actual Dialplan Injections to give you an idea of how simple a Dialplan Injection can be:

Play Music On Hold from the default context to the caller for up to 9999 seconds:


Inform a caller that no 911 service is available on the line by playing an appropriate recording three times, separated by one second of silence (note this should never actually be used as a substitute for 911 service, it's just an example): Playback(no-911-2&silence/1&no-911-2&silence/1&no-911-2,noanswer)

The ,noanswer means that if the call has not already been answered it will not be, since this is considered a call progress message (Playback, unlike some other methods of playing audio, defaults to answering the line and requires the ,noanswer appendage if you don't want the call answered).

In both of the above examples, you would probably use Core: Hangup as the Final Destination.

Before ringing a particular line, play a recording to the caller containing some sort of notice. Here we'll play one second of silence (optional, but useful if some of your callers are calling from a phone with a dial in the handset - it gives them time to get the phone to their ear), then the system recording that says "This call may be monitored or recorded":

Playback(silence/1&this-call-may-be-monitored-or-recorded) Ringing Then use Core: and the desired extension (or, if you prefer, a ring group) as the final destination. You can then use this Injection as a selection from your main IVR menu, so that callers that select this extension or department hear the recording first.

In a way this is a trivial example, because when creating a Ring Group you can specify an announcement to be played before ringing commences, and System Recordings lets you concatenate multiple recordings into one (so you don't really need to use a Dialplan Injection if that is all you want to do). BUT, suppose you want to play some audio that is dynamically generated by an AGI script, rather than system recordings? For example, you could call an AGI script that plays some information about current conditions (e.g. system status, the weather, or whatever you might be monitoring), then returns to an IVR as a final destination.

Inform caller that parking lot slot is empty (example pattern usage) - Let's say you have a parking lot for parked calls with eight slots, which can be numbered 901-908. If a caller tries to pick up a parked call and it's no longer there, you want to inform them of that fact. So, you would create a Dialplan Injection and use a pattern for the extension:


(Note: the underscore as the first character of a pattern is not required, as the module will insert it in the dialplan if it detects a pattern).

Then for the actual injection, simply play one second of silence, followed by an appropriate system recording:


If there is a parked call, it takes precedence when someone dials the appropriate parking lot extension, otherwise the Dialplan Injection kicks in and plays the message to the caller.

Modified Speaking Clock routine with labels and multiple entry points - Finally, here's a more complex example - a modified Speaking Clock routine, that can give the time in either of two time zones (in this example, U.S. Eastern and U.S. Central time, but you can change these to any standard Unix time zones). This example uses labels, AND has two entry points (you can add more). We'll show the complete instructions to implement this:

  1. Go to Dialplan Injections, Add Injection. Give it a description (e.g. "Speaking Clock") but do NOT give it an extension (with the code as shown you actually could add the extension for the Eastern Time Zone entry point, but for demonstration purposes we won't give it an extension here). Make the Destination Core: Hangup. Click Submit.

  2. Re-Enter your new Injection, and paste the following code into the "Command" textbox:

(est),NoOp(Speaking Clock for Eastern Time Zone)
(cst),NoOp(Speaking Clock for Central Time Zone)
Set(FutureTime=$[${EPOCH} + 8])
Set(FutureTimeMod=$[${FutureTime} % 10])
Set(FutureTime=$[${FutureTime} - ${FutureTimeMod}])
Set(MaxConnectTime=$[${FutureTime} + 180])
(scringsomemore),Set(FutureTimeMod=$[${FutureTime} - ${EPOCH}])
GotoIf($["${FutureTimeMod}" < "0"]?scanswer:scwaitasec)
(scplayagain),Set(FutureTime=$[${FutureTime} + 10])
Set(FutureTimeMod=$[${FutureTime} % 60])
GotoIf($["${FutureTimeMod}" = "0"]?scexactmin:scsaysecs)
(scwaittobeep),Set(FutureTimeMod=$[${FutureTime} - ${EPOCH}])
GotoIf($["${FutureTimeMod}" < "1"]?scplaybeep:scwaitsectobeep)
Set(FutureTimeMod=$[${MaxConnectTime} - ${EPOCH}])
GotoIf($["${FutureTimeMod}" < "1"]?scthatsall:scplayagain)
(scthatsall),GotoIf($["x${IVR_CONTEXT}" = "x"]?app-blackhole,hangup,1:${IVR_CONTEXT},return,1)
  1. Click Submit after entering the above.

  2. Now, because we want multiple entry points, go to Misc. Applications, Add Misc. Application. Give it a description (such as "Speaking Clock-Eastern") and a feature code number (an unused one, or you can use *60 if you have disabled FreePBX's default speaking clock under Feature Codes). For the Destination, select Dialplan Injection and in the dropdown select "Speaking Clock-est". Submit.

  3. Repeat step 4, except make the description different (e.g. "Speaking Clock-Central" and assign a different feature code. In the dropdown, select "Speaking Clock-cst". Submit.

  4. Click the red bar. Now you can use one extension or feature code to get the time in one time zone, and the other extension or feature code to get the time in the other.

Alternately, if you have also installed the Custom Contexts module, you could use the same feature code number in steps 4 and 5, but then set up custom contexts in such a way that any particular extension only gets access to one time zone or the other.

Module Author: naftali5

Clone this wiki locally
You can’t perform that action at this time.