0. About
Bind a key sequence or regular expression to an action to match on incoming DTMF tones.
1. Description
The bind_digit_action
application is very similar to mod_dptools: bind_meta_app
but is better, more flexible, and can be used to replace it in all cases.
Be aware that when using bind_digit_action
you may inadvertently break other apps that rely upon DTMFs. This is because any digits that match a pattern are consumed by bind_digit_action
, and thus will not be sent through.
However, any non-matching digits will be sent through. Therefore you should make sure that you don't have any regular expressions (or regexes) that "grab everything" unless you are equipped to handle that scenario.
bind_digit_action
uses the concept of realms for binding various actions.
- A realm is similar to a dialplan context where the dialed number means something different depending upon which context the call is in.
(Could also be perceived as a state in a finite state machine.) - You may bind one or more digits or a regular expression (also called regex) to an action.
Note that you cannot "capture" digits in bind_digit_action
.
TODO Is this still valid? Section 3.4 Capture dialed digits describes exactly this scenario, and there's even a channel variable for it.
2. Syntax
<action application="bind_digit_action" data="<realm>,<binding>,<command_string>[,<value>][,<dtmf_target_leg>][,<event_target_leg>]"/>
Parameter | Description | Example | ||||||
---|---|---|---|---|---|---|---|---|
<realm> | Somewhat similar to a dialplan context (see XML Dialplan) or a state in a finite state machine. To clear or remove the digit bindings, use To switch between realms, use | get_passcode | ||||||
<binding> | A
TODO Only assuming PCRE-compatibility because other module descriptions mention it, and one of FreeSWITCH dependencies is the PCRE library. |
| ||||||
<command_string> |
|
| ||||||
<value> | OPTIONAL Contains the arguments to the | |||||||
<dtmf_target_leg> | OPTIONAL Possible values:
| peer | ||||||
<event_target_leg> | OPTIONAL See | self |
TODO Write this up properly. The following text is directly from the commit comment.
<binding>
can have a flag, 'P' (for "Priority") to bind_digit_action so that a match is returned as soon as it is found, without waiting for the inter-digit timeout to expire.
This can be very useful where the system needs to be more responsive to the user.
By default, if multiple bindings are enabled and one or more use a regex, switch_ivr_dmachine_check_match waits for the inter-digit timeout to expire before returning a match. This ensures overlapping patterns, such as "^\d{4}$" and "^\12{3}$" can both be reliably matched
When the 'P' flag is specified with bind_digit_action, whose action is exec, a match is returned as soon as the condition is satisfied, regardless of whether or not a longer match may be possible if further digits were entered.
For example:
<action application="bind_digit_action" data="test,~^*\d{2}$, exec[P]:execute_extension,myextn,self,self"/>
<action application="bind_digit_action" data="test,~^#\d{2}$", exec:execute_extension,myotherextn,self,peer"/>
The first example causes a match to be returned immediately after the 2nd digit is received, whereas the second example defaults to waiting for the inter-digit timeout to expire before returning.
In cases where the 'P' flag is used with a regex and string, and both are matched, the more explicit, string match will be returned.
For example:
<action application="bind_digit_action" data="test,~^*\d{2}$, exec[P]:execute_extension,myextn,self,self"/>
<action application="bind_digit_action" data="test,*12, exec[P]:execute_extension,myotherextn,self,self"/>
If "*12" is matched, myotherextn is executed, because "*12" is more explicit/specific than "^*\d{2}$"
If the 'P'(riority) flag is not used, behaviour is unchanged from previous versions. This ensures backward compatibility.
3. Examples
3.0 Usage
<action application="bind_digit_action" data="my_digits,11,exec:execute_extension,att_xfer XML default,both,self"/> <action application="bind_digit_action" data="my_digits,11,api:hupall"/>
3.1 Two-realm example 1
TODO Is this right? "The initial realm is test1
(set by mod_dptools: digit_action_set_realm
), and realm myrealm
is never used, but shows how to use multiple realms."
<action application="bind_digit_action" data="myrealm,500,exec:playback,ivr/ivr-welcome_to_freeswitch.wav"/> <action application="bind_digit_action" data="test1,456,exec:playback,ivr/ivr-welcome_to_freeswitch.wav"/> <action application="bind_digit_action" data="test1,##,exec:execute_extension,mix_welcome_to_freeswitch"/> <action application="digit_action_set_realm" data="test1"/>
3.2 Two-realm example 2
- The initial realm is
cool
(set bymod_dptools: digit_action_set_realm
), - dialling 500 or any number starting with 7 will start playing the
ivr/ivr-welcome_to_freeswitch.wav
file, and - any sequence of numbers that start with the digit 1 will switch between realms (or contexts or states).
<action application="bind_digit_action" data="cool,500,exec:playback,ivr/ivr-welcome_to_freeswitch.wav"/> <action application="bind_digit_action" data="cool,~7\d{3},exec:playback,ivr/ivr-welcome_to_freeswitch.wav"/> <action application="bind_digit_action" data="cool,~1\d+,exec:digit_action_set_realm,rad"/> <action application="bind_digit_action" data="rad,~1\d+,exec:digit_action_set_realm,cool"/> <action application="digit_action_set_realm" data="cool"/>
3.3 Call Recording
TODO From the comment section:
Denis 2016.01.26
Call Recording On/Off Switch - work only with 1 bind, you can not make several binds - after enable|disable record and switch context we got new bindings with new realm.
The following dialplan example demonstrates how to use bind_digit_action
to create an on/off sequence for call recording. We'll use *2
as the key sequence that toggles the record, but you can use whichever key sequence you see fit.
We need three different extensions for this operation:
- The
SETUP_RECORDING
extension - The
START_RECORDING
extension - The
STOP_RECORDING
extension
3.3.1 Extension definitions
<extension name="setup bind_digit_action_recording"> <condition field="destination_number" expression="^SETUP_RECORDING$"> <action application="log" data="INFO Configuring bind_digit_action to do recording on this session..."/> <action application="bind_digit_action" data="start_recording,*2,exec:execute_extension,START_RECORDING XML default"/> <action application="bind_digit_action" data="stop_recording,*2,exec:execute_extension,STOP_RECORDING XML default"/> <action application="digit_action_set_realm" data="start_recording"/> </condition> </extension>
<extension name="bind_digit_action Start Recording"> <condition field="destination_number" expression="^START_RECORDING$"> <action application="log" data="INFO Starting recording..."/> <action application="set" inline="true" data="rec_file=$${base_dir}/recordings/${strftime(%Y-%m-%d-%H-%M-%S)}_${destination_number}_${caller_id_number}.wav" /> <action application="record_session" data="${rec_file}"/> <action application="digit_action_set_realm" data="stop_recording"/> </condition> </extension>
<extension name="bind_digit_action Stop Recording"> <condition field="destination_number" expression="^STOP_RECORDING$"> <action application="log" data="INFO Stop recording [${rec_file}]"/> <action application="stop_record_session" data="${rec_file}"/> <action application="digit_action_set_realm" data="start_recording"/> </condition> </extension>
3.3.2 Application
Now we need to apply this to our inbound and outbound calls.
3.3.2.1 Outbound calls
Outbound calls (A leg) are simple, just add an execute extension:
<!-- ... --> <action application="execute_extension" data="SETUP_RECORDING XML default"/> <action application="bridge" data="<your bridge stuff here>"/> <!-- ... -->
3.3.2.2 Inbound calls
For inbound calls (or the B leg) you need to do a little bit more.
Add this to the Local_Extension after the bind_digit_action
calls:
<!-- ... --> <action application="set" data="bridge_pre_execute_bleg_app=execute_extension"/> <action application="set" data="bridge_pre_execute_bleg_data=SETUP_RECORDING XML default"/> <!-- ... -->
3.4 Capture dialed digits
Sometimes it is useful to know what digit(s) the caller dialed, especially when using a regular expression to capture digits. This is done with a channel variable called last_matching_digits
that is updated with each match.
This dialplan snippet demonstrates how it works:
<extension name="Bind a regex"> <condition field="dialed_number" expression="^(9921)$"> <action application="bind_digit_action" data="my_digits,~^\d+,exec:execute_extension,LOG_DIGITS XML default"/> <action application="digit_action_set_realm" data="my_digits"/> </condition> </extension> <extension name="Display digits dialled"> <condition field="dialled_number" expression="^LOG_DIGITS$"> <action application="log" data="INFO Called dialled ${last_matching_digits}"/> <action application="say" data=" en number iterated ${last_matching_digits}"/> </condition> </extension>
3.5 Lua example
While on a call, you can dial 555, 556, or 557.
Put this in your dialplan extension "Local_Extension":
<action application="lua" data="test.lua"/>
and this in ${scripts_dir}/test.lua file
wav1 = "ivr/ivr-welcome_to_freeswitch.wav" wav2 = "ivr/ivr-you_are_number_one.wav" session:execute("bind_digit_action","myrealm,555,exec:playback," .. wav1); session:execute("set","playback_delimiter=#"); session:execute("set","playback_sleep_val=100"); session:execute("bind_digit_action","myrealm,556,exec:playback," .. wav1 .. "#" .. wav2); session:execute("bind_digit_action","myrealm,557,exec:playback,file_string://" .. wav1 .. "!" .. wav2);
4. Channel Variables
See Channel Variables Catalog to see all channel variables.
Channel variable name | Description |
---|---|
Integer Inter-digit timeout, in milliseconds. This sets the time to wait between individual dialed digits. Default value is 1500 milliseconds. Mostly only useful in conjunction with See section 3.1 in Usage Example <!-- To wait 10 seconds between digits: --> <execute application="set" data="bind_digit_digit_timeout=10000" /> | |
Integer Overall timeout, in milliseconds. This sets the overall time to wait for the entire digit sequence to be entered. Default value is 0 milliseconds. Mostly only useful in conjunction with See section 3.1 in UsageExample <execute application="set" data="bind_digit_input_timeout=10000" /> |
4.1 Example use case: using mod_dptools: play_and_get_digits
and mod_dptools: bind_digit_action
together
TODO Still not sure why one would need to use these two together.
Quoting from [Freeswitch-users] problem with "play_and_get_digits" command (DTMF delay time):
5. Notes
5.1 Using bind_digit_action
with a conference
Be aware that when using bind_digit_action
you may inadvertently break other apps that rely upon DTMFs. This is because any digits that match a pattern are consumed by bind_digit_action
, and thus will not be sent through.
However, any non-matching digits will be sent through. Therefore you should make sure that you don't have any regular expressions (or regexes) that "grab everything" unless you are equipped to handle that scenario.
The bind_digit_action
can definitely be used with conferences, however the above rule about matching digits still applies. Make sure that any keys that you wish to be available to your callers to control the conference (i.e. the conference caller-controls) do not "match" in your bind_digit_action
s. There should be no overlap or overload of defined digits.
If you have a PIN on your conference then you will need to make sure that the PIN code also does not "match" any of your bound digit actions, otherwise bind_digit_action
will consume the digits that the caller dials and will *not* send them on to the conference! This results in a caller not being able to join a conference that is locked with a PIN code.
5.2 Inband vs. 2833 DTMFs
The bind_digit_action
supports both inband and 2833 DTMFs. For an example on how to check the SDP for RFC 2833 and automatically start in-inband dtmf detection look in conf/dialplan/default.xml and locate the "global" extension. The 2833 detection is commented out by default.
TODO RFC 2833 is obsoleted by RFC 4733.
5.3 Setting on the B leg
TODO How does this relate to section 3.3? Didn't touch this section.
Here are several choices:
Set the dtmf target leg to "peer" (see above)
These 2 vars on the A leg using the set app:
<action application="set" data="bridge_pre_execute_bleg_app=bind_digit_action"/> <action application="set" data="bridge_pre_execute_bleg_data=whatever"/>
This var with export app:
<action application="export" data="nolocal:execute_on_answer=bind_digit_action whatever"/>
These vars with export app:
<action application="export" data="nolocal:bridge_pre_execute_app=bind_digit_action"/> <action application="export" data="nolocal:bridge_pre_execute_data=whatever"/>
or one of these vars in the dial string {}:
{bridge_pre_execute_app=bind_digit_action,bridge_pre_execute_data='whatever'} {execute_on_answer='bind_digit_action whatever'}
6. See Also
mod_dptools: digit_action_set_realm
- switch realmsmod_dptools: clear_digit_action
- clear digit bindinglast_matching_digits
channel variable
1 Comment
Denis
Call Recording On/Off Switch - work only with 1 bind, you can not make several binds - after enable|disable record and switch context we got new bindings with new realm.