Friday, April 27, 2018

Asterisk commands

Just a list of some asterisk functions and commands that are popular from real working conditions

This command will cut the channel variable, starting at position 5, and then moving 3 characters over and save it in variable foo

exten => s,n,Set(foo=${CHANNEL:5:3})

Tuesday, April 17, 2018

Asterisk IAX trunk with dynamic IP address

You can run into situations where the IPs change on a PBX.   In this example will imagine we have a demo PBX that sales uses ad different customer sites with different WAN addresses. 
With this example, our main "corporate" pbx that allows external connections will now accept a properly formatted IAX trunk from a connection using a valid user/password.

I like IAX because MOST times it will tunnel straight through without any modifications to firewalls.  I've had it work from an Airplane so its pretty successful.

Build your IAX trunk between your two sites to be as dynamic as possible. This way, especially at the customer demo side, you wont care about what the external IP is.

CORPORATE SIDE make an IAX trunk using these settings!
Create a new IAX TRUNK in FreePBX
SUBMIT and SAVE these changes

Create a new IAX TRUNK in FreePBX

REGISTER STRING= (syntax is   trunkname:password@DESTINATION_IP)

example based on above config examples
demotrunk:blahbahayaddayadda@X.X.X.X (this is your corporate IP HERE)

SUBMIT and APPLY your changes.
This type of IAX trunk should allow the "demo" side of your pbx to register to your corporation and use whatever WAN side IP its detected. This way you dont have to worry about programming the IP in your corporate PBX connection. You can use a mobile hot spot or whatever, the system will register as that IP.

On the corporate PBX create an outbound route that points to the IAX trunk you just created, and in the dial pattern, just put in the “match pattern” of the extensions at the far end. So if your demo PBX uses extension 4455 just put that in the that box and submit/apply the changes. Or you can do “4XXX” if you want to match everything from 4000-49999
On the DEMOPBX side, you can do a similar thing should you want them to make calls back. So if your extensions on the corporate PBX side are 7000-7999 put in 7XXX in the outbound routes of the demopbx, and the phones can call back.

Sunday, April 15, 2018

Play a message to a caller after agent hangs up from queue.

Imagine if you wanted to play a message to a caller, or do something in your code AFTER the agent hangs up, vs the agent needing to xfer them manually.  Here's what you do
(tested in FreePBX Distro)

The ‘small c’ in the queue section of the dialplan will allow the dialplan to continue on when the agent hangs up (vs triggering a hangup of both agent and caller).

Then it will automatically call the script and the caller into your queue will hear it and be able to respond.
We are copying the QUEUE code into the override file. Here is the caveat to this that you will need to remember for this particular code change.
ANY Changes that you need to make to the queues via the GUI will have NO effect on the queue’s behavior. Since we are using the override file. What this means is if you need to make changes to the queue, you will need to perform the steps below for those changes to take effect in your production PBX as well as allow the automatic message to play. Without doing it, you will make changes, but asterisk will continue with the code that is in the override file, ignoring the changes.
Its the price of free.

First create your queue, assuming you have one already, but if not, create the queue you want and make sure it works.
Open up extensions_additional.conf
Go [ext-queues] and copy everything from [ext-queues] all the way to ;–== end of [ext-queues] ==–;
include => ext-queues-custom
exten => 8860,1,Macro(user-callerid,)
exten => 8860,n,Answer
bla bla bla
bla bla bla
exten => 8860,n,Set(VQ_DEST=)
exten => 8860,n,Dial(Local/554@from-internal/n,)
exten => 8860,n(gotodest),GotoIf($["${QDEST}"=""]?app- 

exten => 8860*,1,Macro(agent-add,8860,) 

exten => 8860**,1,Macro(agent-del,8860)

exten => h,1,Macro(hangupcall,)

;--== end of [ext-queues] ==--;
Copy this into “extensions_override_freepbx.conf”
Now you will need to modify two lines in the override file.
1> For the section that reflects your queue (in my example my queue is 8860) that will look basically like this (just remember yours will reflect the number that you have assigned to your queue)
exten => 8860,n(qcall),Queue(8860,${QOPTIONS},,${QAANNOUNCE},${QMAXWAIT},${QAGI},,${QGOSUB},${QRULE},${QPOSITION})
The change you will make is
exten => 8860,n(qcall),Queue(8860,${QOPTIONS}c,,${QAANNOUNCE},${QMAXWAIT},${QAGI},,${QGOSUB},${QRULE},${QPOSITION})
specfically you will add a “c” (lower case) right after QOPTIONS and before the first “,” comma mark
Now, scroll down about 5 or so lines and you’ll see this:
exten => 8860,n,Set(VQ_DEST=)
exten => 8860,n(gotodest),GotoIf($["${QDEST}"=""]?app blackhole,hangup,1:${CUT(QDEST,^,1)},${CUT(QDEST,^,2)},${CUT(QDEST,^,3)})

Now between these lines insert the following line, except modify the XXXX value to be the number you dial to test your script with.
exten => 8860,n,Set(VQ_DEST=)
exten => 8860,n,Dial(Local/XXXX@from-internal/n,)
exten => 8860,n(gotodest),GotoIf($["${QDEST}"=""]?app blackhole,hangup,1:${CUT(QDEST,^,1)},${CUT(QDEST,^,2)},${CUT(QDEST,^,3)})
Now save your changes
from command line type in asterisk -rx 'core reload’
To backout this code if there is a problem that is affecting a production system, it the extensions_override_freepbx.conf file, change the heading [ext-queues] to [ext-queues-bypass]
save that change
then in the cli type in
asterisk -rx 'core reload’
This will revert the pbx back to the original code.
You can then identify the changes, remove the -bypass
save/reload the script and test.

Customer Survey after a queue call.

This code will allow your asterisk server to play a series of questions questions, then record the digits the caller gives for each question, then save it to the CDR table of asterisk. It will/can also send an email to someone with the digits entered.

This survey can be made to automatically run at the end of a queue call when the agent hangs up, or it can be something your agent or employee can transfer a caller to manually.

What this does:
When activated, it will ask a question, then allow the user to place an answer.
This demo asks 2 questions.

Once the caller answers the questions and hangs up, the values entered are written to the “USERFIELD” in the CDR table.

You can go to the CDR module in freepbx and see the values for each caller in this database.
There is a line included that will send an email to someone with the data, however its difficult to make work as SMTP is very organizational specific.

create your ‘questions’ in system recordings. I called mine “question1” and “question2”
Create a thank you message. My file was saved as “thankyouforyourtime”.

open up /etc/asterisk/extensions_custom.conf

Go to the bottom of the file, paste in the following: (noted the portion /custom/questionX the last bit is your file name, so if you saved them differently, you’ll need to update the filename name in the code)

Note the path for the recordings.  It MIGHT be different on your system implementation.  You might need to double check your recording location after you save it and adjust the path below accordingly.
exten => s,1,answer()

;this asks the first question (based on your recording file named as "question1") and stores them in variable
exten => s,n(question1),Read(answer1,/var/lib/asterisk/sounds/custom/question1,1,,1,2)
exten => s,n,GotoIf($[ ${answer1} < 4 ]?question2:question1)

;this asks the second question (based on your recording named 'question2") and stores them in variable
exten => s,n(question2),Read(answer2,/var/lib/asterisk/sounds/custom/question2,1,,1,2)
exten => s,n,GotoIf($[ ${answer2} < 4 ]?finish:question1)

;you can ask more questions by repeating the above code, change the variable "2" and make it "3" then "4" etc.

;this line puts the two answers together and separates them with a | symbol.
exten => s,n(finish),set(answer=${answer1}|${answer2})

;this saves the answers into the CDR field of "userfield"
exten => s,n,Set(CDR(userfield)=${answer})

;This line will send an email with the subject saying "Survey John Smith 555-123-4455 3|2"
exten => s,n,system(mail -s "Survey ${CALLERID(name)} ${CALLERID(number)} ${answer}" EMAIL@ADDRESS.COM < /dev/null)

;play a thankyou message.  you can just remove this line for anyone who doesn't want the thankyou.
exten => s,n,playback(/var/lib/asterisk/sounds/en/custom/thankyouforyourtime)

exten => s,n,hangup() 

SAVE changes

Now create a "Custom Destination" in the PBX GUI.  Set the "destination to be 
and give it a description of "After Call Survey"

Save those changes.

Play automatically after an agent in a queue hangs up:
In the GUI settings for the queue(s), set the "Queue Continue Destination" to be "Custom Destination" then select "after call survey" in the subsequent drop box that will appear.

Have agent/employee transfer manually.
If you want to send callers manually, create a ring group. in the extension list put a dummy extension that does not exist, for example "1". Then set the ringgroup failover destination to be the custom destination "after call survey".  Your employees can transfer to the ring group and it will fail through to the survey.


You should hear your first question. Press “2”
You should now hear your second question, Press “3”

Call will hang up

Go to CDR reports and run a report (usually can just hit SEARCH) and it will show the most recent calls. You should see your call, and in “USERFIELD” you’ll see “2|3”

2 is the first answer, “|” (pipe) is a delimiter, and 3 is the second answer.

Monday, April 2, 2018

Collect a pin number value in asterisk and write it to a file

This dialplan will ask the user to enter in a pin number, and then it will save it to a file.
Tons more you can do with this and tweaks of course, but this is an example of what you can do.

I'm using all the default recordings in asterisk, so they aren't perfect prompts, but good enough for you to test with.

1> Open up /etc/asterisk/extensions_custom.conf

2> Paste the code between the snips into this file.
===== snip ======
exten => s,1,Answer()

;we set a variable to prevent looping over and over in IVR, either by accident or malicious
exten => s,n,Set(Attempts=1)

;throw a entry in the asterisk log that system is requesting a PIN entry
exten => s,n(begin),NooP(&&&&&&& Collecting PIN info for ${CALLERID(all)} attempt ${Attempts} &&&&&)

exten => s,n,Playback(please-enter-your&pin_number)

;system listens for DTMF and records it in variable "pinnumber"
;the syntax at the end= 7=MAX DIGITS, 1=attempts if no data, 10=timeout.   The ",," value i'm not using in this code example)
exten => s,n,Read(pinnumber,then-press-pound,7,,1,10)

;system checks for blank value and asks again
exten => s,n,ExecIf($["${pinnumber}"=""]?goto(macro-pincollection,s,1))

;systems plays back the number they entered in to caller
exten => s,n,Playback(you-entered)
exten => s,n,SayDigits(${pinnumber})

;system asks them to press 1 to accept or 2 to retry
exten => s,n,Playback(if-this-is-correct-press)
exten => s,n,SayDigits(1)
exten => s,n,Playback(otherwise-press)
exten => s,n,SayDigits(2)

;system listens for the value entered
exten => s,n,Read(digi,,1)

;this section we test for invalid entries.  On their 4 try we hangup.  We dont want someone looping over and over again.
exten => s,n,Set(Attempts=${MATH(${Attempts}+1,i)})

;if they reach their 4th attempt, system plays some messages and hangsup.
;Change the "4" to a different value if you want to increase/decrease chances
;Change the "HANGUP to RETURN" if you want the system to go back to a different location as set in the CUSTOM DESTINATIONS section

exten => s,n,ExecIf($["${Attempts}"="4"]?playback(sorry-youre-having-problems))
exten => s,n,ExecIf($["${Attempts}"="4"]?playback(hangup-try-again))
exten => s,n,ExecIf($["${Attempts}"="4"]?HANGUP())

;if user presses 1 to confirm, system sends the clal on
exten => s,n,ExecIf($["${digi}"="1"]?goto(writevalue))

;if callers presses any other digit, system will re-ask them to enter in their number
exten => s,n,goto(macro-pincollection,s,begin)

;If they press "1" as being a valid entry, the entry is written into the file.
;system writes the pin collected to the file 'pincollected.txt'
;saved as "DDMMYYY-HH:MM:SS, CALLERid, UNIQUE NUMBER (to trace call in logs easier if needed), PINNUMBER
exten => s,n(writevalue),system(echo "${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)},${CALLERID(all)},${UNIQUEID},${pinnumber}" >> /tmp/pincollected.txt)

;uncomment next line to attach the pinnumber to the callerid.  IE "john smith" <5551234->
;exten => s,n,set(CALLERID(num)=${CALLERID(num)}-${pinnumber})

;uncomment next line to send the call to a voicemail box after your are done.  this is 900 unavailable message
;exten => s,n,Voicemail(900@default,u)

exten => s,n,Return
===== snip ======

3> Save these changes

4> Open up FreePBX


6> Create a new destination
TARGET = macro-pincollection,s,1
Description= Collect Pin and save
Notes= blank (you can put something in if you want)
Return = YES
(the destination in this case is what you want to have happen when they enter their pin number.  In my example I wanted the code to continue on, but if you say “no” for RETURN then the system will hangup after the call.  if you want the call to hangup, just select return=NO

7> Save changes

8> Open up your IVR and put in an entry in it to go to this custom destination
If they press “2” in your ivr, select “CUSTOM DESTINATION” then select “Collect Pin and save”

9> Save your changes, then submit.

10> TEST!

Dial the number that will trigger this.  In my example I all the IVR then pressed “2”
System will ask you to enter your pin, then will play it back to confirm and then if “YES” is selected, it will save it to /tmp/pincollected.txt **DDMMYY-HHMMSS, CLID info, unique ID, pin#entered**

02042018-11:51:38,John Smith <123-555-1165>,1522680683.98551,123
02042018-11:54:49,Jane Doe <123-555-4455>,1522680864.98560,1234