How to send various types of notifications on an incoming call in FreePBX

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

PLEASE NOTE: When you look at examples in this article, be aware that WordPress has a nasty habit of changing quotation marks to “prettified” quotes, which WILL NOT WORK. So, unfortunately, if you copy an example line or code block, you may need to go through and change the quotation marks back to the “real” quotes that most software understands. I get SO sick and tired of WordPress changing my articles on me!

Every so often I’ve had someone ask if they could be sent some sort of notification whenever they get an incoming call. It is, although it will send a notification on any incoming call, not just a missed one (if you only want notifications of missed calls, look toward the bottom of this article). The basic technique is as follows:

First, create or edit a Follow-Me for the user’s extension. Let’s say the extension number is 1122. In the Follow-Me, add a line that looks like this:

****1122#

Note you can use about anything in place **** followed by the extension number and # sign — only the trailing # must be there — but I do it that way so I can keep track of what’s going on.  If you are creating the Follow-Me for the first time, be sure to also put your actual extension number in the Follow-Me list (with NO trailing # sign), and check the other Follow-Me options to make sure that they are what you want (for example, that the “Destination if no answer” is your voicemail, if that’s what you want).

Next, in /etc/asterisk/extensions_custom.conf, find the [from-internal-custom] context (it’s right at the top of the file) and add lines similar to the ones shown below to the bottom of that context. Again, we are using 1122 as the extension, but replace it with the actual extension number:

Note that some of these examples depend on certain other software being present. Also, the FIRST line in each sequence must have the line number 1, but if you use more than one of these for an extension, replace the 1 with n in subsequent lines.

To send an e-mail or SMS message (the mail command must function properly from the Linux command prompt for this to work):

exten => ****1122,1,TrySystem(echo "Call from ${CALLERID(name)} at ${CALLERID(number)} received ${STRFTIME(${EPOCH},,%l:%M:%S %p %Z on %A %B %e)}" | mail 9995559999@yourcarrier.com)

Replace 9995559999@yourcarrier.com with the e-mail address (which could be an e-mail to SMS gateway – most wireless carriers have one. Just search for “Email to SMS Gateway” and add your carrier’s name to the search, and you should find the format to use).  You can use “System” or “TrySystem” in the line above, the difference being that TrySystem is non-blocking, so the call should not be delayed if the process of sending the e-mail bogs things down.

To send an instant message using the XMPP/Jabber protocol — for this to work /etc/asterisk/xmpp_custom.conf (/etc/asterisk/jabber.conf in older versions of FreePBX) must be configured correctly, and there must NOT be a noload => res_jabber.so statement in modules.conf:

exten => ****1122,1,JabberSend(asterisk,username@gmail.com,Call from ${CALLERID(name)} at ${CALLERID(number)} received ${STRFTIME(${EPOCH},,%l:%M:%S %p %Z on %A %B %e)})

In the above, asterisk is the account context in xmpp_custom.conf or jabber.conf, and username@gmail.com is the address of the XMPP/Jabber user you want to send the IM to (in this case we assume you and the user are on Google Chat, but you could use any other XMPP/Jabber-based IM service, including a local XMPP/Jabber server set up with Prosody or Openfire or similar software. EDIT: If you are running FreePBX on a Raspberry Pi, see this article and this thread for information on setting up a Prosody server).

If you have Kodi (formerly XBMC) running on a system on your local network, you could use a line such as this to send notifications to it (EDITED to include Kodi Leia, Matrix, and Nexus):

In Eden and other Pre-Frodo versions:

exten => ****1122,1,TrySystem(wget -b -O /dev/null -o /dev/null "http://192.168.0.234:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn&parameter=XBMC.Notification(Call%20from%20%22${URIENCODE(${CALLERID(name)})}%22%2C${CALLERID(number)}%20calling%20extension%2C15000%2C%2Fhome%2Fusername%2Fphone.png)")

In Frodo through Krypton:

exten => ****1122,1,TrySystem(wget -b -O /dev/null -o /dev/null "http://192.168.0.234:8080/jsonrpc?request={%22jsonrpc%22:%222.0%22,%22method%22:%22GUI.ShowNotification%22,%22params%22:{%22title%22:%22Call%20from%20${URIENCODE(${CALLERID(name)})}%22,%22message%22:%22${CALLERID(number)}%20calling%20extension%22,%22displaytime%22:15000,%22image%22:%22%2Fhome%2Fusername%2Fphone.png%22},%22id%22:1}")

In Leia, Matrix, Nexus and probably later versions, until they decide to change it again:

exten => ****1122,1,TrySystem(curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"GUI.ShowNotification","params":{"title":"Call from ${CALLERID(name)}","message":"${CALLERID(number)} calling extension","displaytime":15000,"image":"/home/username/phone.png"},"id":0}' http://192.168.0.234:8080/jsonrpc)

Note: If you set Kodi to require authentication, then in place of the example http://192.168.0.234:8080/jsonrpc instead use the format http://kodiusername:password@ip-address:port/jsonrpc where kodiusername, password and port are the same values you used when setting up your Settings | Service | Control | Web Server settings in Kodi. Note that “kodiusername” is the user name set up in Kodi’s web server settings, and is probably not the same as “username” in the phone.png icon path (which in that case is the name of the user’s home directory).

Note that each of the above is a single long line, and to see any of those lines in its entirety you will need to copy and paste it to a text editor. The above examples assume that Kodi is configured to allow control via a Web interface, at a fixed IP address and port (192.168.0.234 port 8080 in this example). Phone icon - right click and copy imageIf you happen to still have a Linux version of Boxee, the Eden version line might also work with it, perhaps with a bit of tweaking.  I have no idea if it would work (with appropriate modification) with any other standalone home theater PC equipment.  You will likely need to replace username with the user’s name, extension with the called extension’s number, and change the icon path to wherever you put the phone.png file (which is an icon you need to supply, such as the one at the right). Note that the icon path requires %2F in place of forward slashes in pre-Leia versions (therefore %2Fhome%2Fusername%2Fphone.png really means /home/username/phone.png) and this refers to the icon directory and filename — if you choose not to use an icon then leave out this part, depending on your Kodi version:

Eden and prior: %2C%2Fhome%2Fusername%2Fphone.png
Frodo through Krypton: ,%22image%22:%22%2Fhome%2Fusername%2Fphone.png%22
Leia through Nexus (and beyond?): ,"image":"/home/username/phone.png"

Note the comma at the start; it must be included in the deleted section).  By the way, if you are wondering why it had to be changed again for Kodi Leia, see this thread in the Kodi forum.

If you want to receive Caller ID popup notifications on your computer, see A Perl script to send Caller ID popups from Asterisk to computers running Notify OSD (such as Ubuntu Linux) or any command-line invoked notification system and/or A Perl script to send Caller ID popups from Asterisk to computers running Growl under OS X on a Mac or Growl for Windows.  These articles are a bit dated and may not be compatible with some of the newer notification methods in use (such as the Notification Center used in MacOS that was introduced in OS X 10.8); in such cases it may be easier to just send instant messages to the computer as described above, although it may be possible to ssh into the computer and send a notification from the command line – this article describes how to send a notification from the command line in MacOS.

After using the any of above lines (and, again, remember to change the line number from 1 to n on any lines after the first), you may want to include a statement like this:

exten => ****1122,n,NoCDR()

That should prevent Asterisk from creating a separate, usually unwanted CDR entry for the ****(extension number) call.  There will still be a CDR record created for the actual call. EDIT: Actually, if you are going to use this, you probably should make it line 1, and move it above the other ****(extension number) lines, so that the CDR record is not saved even if the call gets disconnected in the middle of sending the notification. EDIT 2: In recent Asterisk versions NoCDR() has been deprecated and replaced by CDR_PROP(disable) so be sure to make that change if you are getting BUSY lines in the CDR when this runs.

Finally, to end this part of the context, you need to include a statement that ends the call in a “not completed” state, so that any other extensions in the Follow-Me will be called.  A couple of possibilities are:

exten => ****1122,n,Congestion
exten => ****1122,n,Busy

Use one and if it doesn’t work as expected, try the other. On my system it appears either will work. Remember that you must do a configuration reload in FreePBX before any of your changes to extensions_custom.conf will take effect!

One reason you may want to do instant message or SMS notifications is if you are forwarding calls via a trunk that does not preserve the original caller’s Caller ID.  If you were forwarding the call to a smart phone (perhaps one that also has a Jabber client running), you could deliver the original caller’s name and number to the phone via instant message or SMS.  It may or may not arrive in time for you to make a decision on whether to answer the call, but if you chose not to answer you’d at least know within a few seconds to a few minutes who the call was from, and you could decide whether to call them back.

If you have figured out any neat tricks to do other types of notifications, or if you know of a way to send a notification only when a call was not answered, feel free to leave a comment.

EDIT: At one time this page showed a method for sending SMS notifications using Google Voice rather than an e-mail to SMS gateway. Unfortunately it appears that the unofficial API that was used by such applications is no longer functional. If you know of a way to send a SMS message from a Linux command prompt using Google Voice that is currently working, please leave a message in the comments!

EDIT: I did think of a couple of techniques that might work for sending a notification only if the call is “missed” — the first is a bit of a hack, and has a serious limitation in that if the caller hangs up prior to the call going to voicemail, no notification would be sent (which might or might not be what you want). Basically, you would create (or modify) a Follow-Me as described above, but don’t put the ****extension# line in it. Instead of making the “Destination if no answer” your voicemail (for example), you would point it to a Ring Group that you have created, and in that Ring Group you would place the ****extension# line, and make the “Destination if no answer” of the ring group your voicemail. So the Follow-Me would ring your extension(s) for the number of seconds in the “Ring Time” setting, but if that time expires and no one answers, the call would be sent to the Ring Group where the only “extensions” would be your ****, which would do their thing and immediately return a “busy” or “congestion”. Since there are no other extensions to try, the Ring Group should immediately pass the call on to its “Destination if no answer”, which would most likely be your voicemail.

I haven’t tested this but I see no reason why it would not work, and in that case the notification would be sent just as the caller is being transferred to voicemail. If the caller doesn’t stick around that long you don’t get a notification, however, the fact that you do get a notification doesn’t necessarily mean that the caller actually left a voicemail — if they hang up during the voicemail greeting, a notification would still have already been sent.

EDIT: Here is a different technique for sending notifications on ONLY missed calls, and with this one the notification is sent whether the caller sticks around to leave a voicemail or not. You do NOT add anything to your Follow Me list when using this technique, nor do you modify extensions_custom.conf.

Note that this technique probably will not work on extensions that are part of a Ring Group or Follow Me where more than one extension is rung simultaneously (at least not without some modification — it should work if you use a ring strategy that only rings one phone at a time, though, such as firstnotonphone or firstavailable) (2017 EDIT: Some users have reported those two ring strategies are broken in FreePBX 13 and 14). Be aware that this one is a bit riskier since you will need to re-do the first part of the following procedure after any FreePBX upgrade, otherwise things may break!

  • Load the /etc/asterisk/extensions.conf file into a text editor such as nano
  • Search (Control-W in nano) for the string [from-internal] (including the brackets)
  • Copy the entire context (you can omit the comments) to a new open page in a text editor on your local computer
  • Next, search for the string [from-did-direct] (including the brackets)
  • Also copy that entire context (without the comments) to the same open page in your text editor
  • You MAY also need to copy the context [macro-hangupcall] which is found in /etc/asterisk/extensions_additional.conf. You would do that the same way as the previous two. I don’t show it in the examples below, but further down I’ll explain why you might need to do that one.

At this point the open page in your text editor will look something like this, although this may vary depending on your version of FreePBX. It is important that you copy these contexts from YOUR system, and repeat the procedure every time you upgrade FreePBX to a newer version:

[from-internal] include => from-internal-noxfer
include => from-internal-xfer
include => bad-number ; auto-generated

[from-did-direct] include => ext-findmefollow
include => ext-local

Now add these two lines to the bottom of EACH of the above two contexts (or all three if you also added [macro-hangupcall]):

exten => h,1,Macro(missed-call)
exten => h,n,hangup

The above is the part you will need to redo if you upgrade FreePBX. Next, add a new macro that looks something like this (this is just an example, don’t copy it verbatim!):

[macro-missed-call]
exten => s,1,NoOp(Checking to see if we need to send a missed call notification)
exten => s,n,GotoIf($["${CT_EXTEN}" > "1121" & "${CT_EXTEN}" < "1125" & "${CT_EXTEN}" != "" & "${ANSWEREDTIME}" = ""]?notify1)
exten => s,n,MacroExit()
exten => s,n(notify1),NoOp(Sending notification of missed call on extension ${CT_EXTEN})
exten => s,n,ExecIf($["${CALLERID(num)}" > "1121" & "${CALLERID(num)}" < "1125"]?MacroExit())
exten => s,n,ExecIf($["${CALLERID(num)}" = "8005551212"]?MacroExit())
exten => s,n,JabberSend(asterisk,username@gmail.com,Missed call from ${CALLERID(name)} at ${CALLERID(num)} for extension ${CT_EXTEN} received ${STRFTIME(${EPOCH},,%l:%M:%S %p %Z on %A %B %e)})
exten => s,n,MacroExit()

Here’s an explanation of what’s happening in the above Macro, so you can modify it for your specific needs:

  • Line 1 is just a NoOp that tells what the macro is doing.
  • Line 2 says that if the call was for extensions 1122 through 1124 (greater than 1121 and less than 1125), that we didn’t get a null value for the extension, and the call was not answered, go to the label notify1. If we only wanted to test for a single extension such as 1122, instead of “${CT_EXTEN}” > “1121” & “${CT_EXTEN}” < “1125” just use “${CT_EXTEN}” = “1122”. You can add as many lines as you need for various extensions, just be sure to jump to different labels.
  • Line 3 says that if none of the above conditions match, exit the macro.
  • Line 4 is just a NoOp that serves as a placeholder for the label and prepares to send the notification.
  • Line 5 is optional and shows how to exclude notifications for calls if the calling number is within a range, in this case 1122-1124 (so, in this example no notifications would be made on calls from one of your own extensions to another in the 1122-1124 range). You can use as many of these lines as you need to exclude more ranges, or none at all if you don’t want to exclude any ranges. Make sure you get the quotation marks right (and again, if you copy lines from this blog, beware of the quotation marks that WordPress has “prettified” – you’ll need to fix them before the lines will work!).
  • Line 6 is optional and shows how to exclude a specific number from triggering the notification. In this case, if the call comes from 8005551212, no notification would be sent. Note that you could use the ${CALLERID(name) variable as a trigger also, and exclude calls from certain names from triggering a notification. Note you can place multiple tests in the same expression by using the bar character (logical OR in Asterisk) to connect them, for example, “${CALLERID(num)}” = “8005551212” | “${CALLERID(name)}” = “INFORMATION” would match if either condition were true. This line can be omitted completely if you don’t want to exclude calls from any specific numbers.
  • Line 7 is where we actually send the notification. Basically any of the methods mentioned in the previous part of this article can be used here, just replace ****1122,1, in the example lines with s,n,
  • Line 8 is where we gracefully exit the macro. Of course, you can repeat lines 4-7 as many times as needed if you are doing notifications for more than one extension.

Now that you have the three (or four) macros in your text file and edited as they should be, copy the whole mess and paste it into the existing file /etc/asterisk/extensions_override_freepbx.conf — do not just overwrite the existing file! Instead, open it with nano or another text editor and paste in the lines you’ve been working on. Also, do a quick scan to make sure you haven’t duplicated a context that’s already in there (the likelihood of that is pretty remote unless you have done something like this in the past). Note that after you do a FreePBX reload, the contexts in this file will replace the equivalents in the files generated by FreePBX, so that’s why you have to check that the originals haven’t changed each time you upgrade FreePBX.

If you want to know what variables are available for you to trigger on, instead of a line sending a notification you can use a line like this:

exten => s,n,DumpChan

This will show you a lot of information, including how several of the channel variables are set.

One final note, the added macro call under [from-internal] is the one that would be taken after a failed call from another extension, while the one under [from-did-direct] is the one used by failed calls coming in from outside the system. Note that most answered calls (not including ones that go to voicemail) will wind up in [macro-hangupcall] and not go through either of those, BUT in certain circumstances unanswered calls might also end via [macro-hangupcall], such as if they go through a ring group. That is why I mentioned above that you might need to include [macro-hangupcall] along with the other contexts copied into /etc/asterisk/extensions_override_freepbx.conf. However, I have not tested every possible condition, and I do know that some things won’t work — such as if multiple extensions are rung simultaneously, no extension number shows up in the ${CT_EXTEN} variable, so those tests in [macro-missed-call] that depend on that variable being set will fail. You may be able to modify the macro so that it will work in such circumstances by using one or more variables you can find by using DumpChan, but that’s a piece of dialplan I’m not prepared to write, since I personally have no need for it (and have already spent way too much time on this)!

I probably should also include this note about the use of extensions_override_freepbx.conf as taken from this page:

If extensions.conf (or extensions_additional.conf) has a context or macro that you NEED to modify, you place that code here as asterisk will only execute the first occurrences of that code and ignores other occurrences. This file will not be overwritten. Be very careful as replacing an existing piece of code this way is the fastest possible way to break your system. If you are doing this you should probably think about filing for a feature request or bug fix to get it addressed properly.

Of course, my experience is that filing a feature request with FreePBX is a great way to either be ignored, or lectured by some a**h*le on why you don’t need that feature, so I wouldn’t bother. Just be sure that if you upgrade FreePBX, or even just the Core or Framework modules, you check to make sure that the contexts you’ve copied into extensions_override_freepbx.conf haven’t been changed (or if they have, make sure you copy over the changes).

Using YATE to overcome Google Voice issues in FreeSWITCH and Asterisk

 

Notice
(May, 2018): FreePBX and Asterisk users that wish to continue using Google Voice after Google drops XMPP support should go here: How to use Google Voice with FreePBX and Asterisk without using XMPP or buying new hardware. The information in this article is VERY outdated and probably will not work.

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

If you have been less than thrilled with the Google Voice support in another software PBX, such as Asterisk or FreeSWITCH, you could try using YATE as a Google Voice Gateway.  It can be installed on either a separate server, or on the same server as your FreeSWITCH or Asterisk installation, however if you are running virtual machines then I recommend the separate server approach.  In fact, that may be the only way to do it with FreeSWITCH if you installed FreeSWITCH under Debian or Ubuntu, since the YATE install requires CentOS.  If you are a Linux expert you may be able to get around this, but don’t ask me how.

To install YATE, see this article from Nerd Vittles:

YATE in a Flash: Rolling Your Own SIP to Google Voice Gateway for Asterisk

EDIT: You may want to upgrade YATE to the latest version.

Just follow the instructions there, and the ones that you see after running the script to add a Google Voice user, and you should be fine, if you are using Asterisk.  The only things I would suggest that are not shown in those instructions are that you set your Trunk “Maximum Channels” to 2, because a Google Voice account will only permit two simultaneous channels of usage maximum, and that if YATE is on a separate server with a static IP address then I’d suggest adding permit/deny lines to the Asterisk Trunk PEER details to enhance security, like so:

permit=xx.xx.xx.xx/255.255.255.255
deny=0.0.0.0/0.0.0.0

Make sure the lines appear in that order, and replace xx.xx.xx.xx with the static IP address of the YATE server.  This may not help much because Asterisk is registering with the YATE server, but it can’t hurt either.

Also, you might want to consider changing the context statement to

context=from-pstn-e164-us

to remove the +1 from the start of the Caller ID number on incoming calls.

The instructions don’t tell you to add a Dialed Number Manipulation Rule to your trunk configuration, but if you want to allow ten digit calls from any of your endpoints then you should add one rule that prepends 1 to 10 digit calls:

1+NXXNXXXXXX (The 1 goes in the first field, the NXXNXXXXXX in the third field)

If you are using the CallerID Superfecta module, and you use “Trunk Provided” as one of your data source, then after adding a Google Voice account to YATE I suggest editing /usr/local/etc/yate/regexroute.conf on the YATE server. You may need to install an editor first. For example, to install nano and then edit the file:

yum install nano
nano /usr/local/etc/yate/regexroute.conf

Look for the [contexts] section and there you will see a line for each of your Google Voice accounts that looks like this:

${in_line}GV1234567890=;called=GV1234567890;jingle_version=0;jingle_flags=noping;dtmfmethod=rfc2833

Just add ;callername to the end of each such line:

${in_line}GV1234567890=;called=GV1234567890;jingle_version=0;jingle_flags=noping;dtmfmethod=rfc2833;callername

This will make sure that nothing is sent for a Caller ID name, so that Caller ID Superfecta will recognize that there is no “Trunk Provided” name and attempt to do a name lookup (note that you could also use ;callername=something to set the Caller ID name to a specific value). If you want to have ;callername
automatically appended whenever you create a new account, just use an editor to edit the script you use to add users, and find the line that looks like this (it should be near the bottom of the script):

${in_line}GV’$acctphone’=;called=GV’$acctphone’;jingle_version=0;jingle_flags=noping;dtmfmethod=rfc2833

Add ;callername to the end of the line, like so:

${in_line}GV’$acctphone’=;called=GV’$acctphone’;jingle_version=0;jingle_flags=noping;dtmfmethod=rfc2833;callername

Save the modified file, and any time you add a new user it will automatically write that line with ;callername appended.

Thanks to Bill Simon for telling me about this method of sending the blank Caller ID name. Alternately, if you don’t want to mess with the YATE configuration, you could add a new Caller ID Scheme in Caller ID Superfecta that is only used with your Google Voice DID’s and that doesn’t include “Trunk Provided” as a data source.

Whether you are connecting from Asterisk or FreeSWITCH, if YATE is running on a separate server and the other system can’t register with YATE, it may be a firewall issue on the YATE server.  After I did the install I found that iptables was configured to only allow incoming ssh connections.  I modified that rule to only allow incoming ssh from a particular IP address (the one I’d be coming in from) and then added rules to permit traffic from the two servers allowed to talk to that YATE server.

EDIT: Hopefully this will not affect you if you have upgraded YATE to the latest version, but if you have a moderate number of Google Voice accounts, you may experience another issue.  If you start seeing messages like this when you telnet to YATE and then use debug on to see what is happening:

<sip:MILD> Flood detected: 20 handled events

And if every so often, the server appears to go into a semi-catatonic state, where calls come in but they don’t go out (this happened to me at least twice before I figured out what was happening), then you may have this issue.  It occurs when you have the same Asterisk server using multiple trunks to connect to YATE.  It turns out that whenever you reload Asterisk (as you might after making a configuration change, for example the “orange bar reload” in one particular GUI), it resends all of the registrations at once, and gives them all a default timeout of 120 seconds, so they all attempt to re-register at the exact same intervals.  And if you have several trunks, there are a LOT of SIP packets sent.  Plus, with qualifyfreq value set to 240, that means that every other time the registrations are taking place, qualifies are also taking place at the same time.  It appears that this is sufficient to cause that warning to appear once in a while.

The method I found that seems to fix this may not be the best way (feel free to comment if you know a better way), but it’s one way to deal with it.  What you need to do is change the registration expiration on each individual trunk so they are not all the same.  In Asterisk this can be accomplished by adding both of these settings to the trunk configuration (susbtitute nn with some random number of seconds, say between 90 and 120, and make it the same for both settings in each trunk, but different for different trunks)

In the trunk PEER details, add:

defaultexpiry=nn

In the Register String, add  ~nn  to the end of the line, replacing nn with the same value used in the defaultexpiry setting, like so:
GV1234567890:password@exampleaddress.com:5060/1234567890~nn

You might also need to vary the qualifyfreq value a bit in each trunk, so that it’s a bit under the specified 240 seconds and different for each trunk.  If doing those things doesn’t fix the issue, and you still get the <sip:MILD> Flood detected: 20 handled events message frequently, that could mean you are being subjected to an actual SIP attack.  The YATE installation includes a script with the filename /usr/src/yate/share/scripts/banbrutes.php that can be used to deal with that issue, but it’s not enabled by default.  View the banbrutes.php script in a text editor, and you’ll find instructions at the beginning of the script.  Or, you could tighten up the iptables firewall to only allow traffic from systems that are supposed to be talking to your YATE server.

END OF EDIT.

As for FusionPBX, when you create a new Google Voice account on the YATE server using the provided add-yate-user script, at the end it will give you a bunch of configuration information for Asterisk.  These translate to FusionPBX Gateway settings as follows (showing what the script prints and the equivalent FusionPBX Gateway settings):

Trunk Name: YIAF1 ; or increment 1 if more than one (in FusionPBX I suggest you don’t use this; instead use the same setting as the Username for the Gateway name, particularly if you plan on having more than one Google Voice account)

host=x.x.x.x (Proxy in FusionPBX)
username=GV1234567890 (Username in FusionPBX)
secret=password (Password in FusionPBX)
type=peer (Not needed in FusionPBX)
port=5060 (Not needed in FusionPBX)
qualify=yes (Not needed in FusionPBX)
qualifyfreq=240 (Not needed in FusionPBX)
insecure=port,invite (Not needed in FusionPBX)
context=from-trunk (Not needed in FusionPBX)

Register String: … (Not needed in FusionPBX)

In FusionPBX, set Register to True and Enabled to True, and leave other Gateway settings at the defaults (EDIT: however, if you have several gateways to YATE, you might want to use the Expire seconds setting in FusionPBX to vary the registration timeouts a bit so that all your accounts aren’t trying to re-register at exactly the same time — see the longer EDIT section above for details).  Note that after you save the settings, it may take a few seconds for the state to change to REGED, so refresh the Gateways page after a bit and it should be okay if everything is configured properly and there are no firewall issues.

For your Inbound Route in FusionPBX, just use the Trunk Name/Username as the Destination Number (including the leading “GV“, which you can also use it in the Inbound Route name field if you like) and then choose the appropriate Action. When you first create the Inbound Route it will complain if you try to save a Destination Number that is not completely numeric, so just use any number and save the settings, then go back and edit the Destination Number field and also the Data field for the destination_number condition (which should be something like ^GV1234567890$, substituting your Google Voice number for the digits, of course).

For your Outbound Route, select your Google Voice trunk as the Gateway, and then select “11 digits long distance” from the dropdown in the “Dialplan Expression” setting. Save that, and if you only have one Google Voice trunk for all users on the system, that is all you need to do.  However, if you want to have multiple Google Voice trunks and have certain extensions only have access to certain trunks, the edit the Outbound Route you just created, and in the “Conditions and Actions” section at the bottom of the page, edit the last action on the page (the “bridge” action).  You want to change the Data field – it will contain something like sofia/gateway/GV1234567890/$1 and you want to change that to sofia/gateway/${accountcode}/$1 — save that change, and then when the Outbound Route page reappears, you may want to change the name to ${accountcode}.11d and add a Description like “Google Voice: Extension Account Code = Gateway Name” so you understand what the route is doing.  This single Outbound Route will handle all your Google Voice calls from all your extensions, if the Account Code setting for each Extension is set to the name of the Gateway for the Google Voice account you want that extension to use.

Note that if you are running PBX in a Flash, you can use the “Caller ID Superfecta” module to try to get a Caller ID name.  IF YATE itself has any ability to do Caller ID name lookups, someone will have to tell me how to enable and configure it, because at this point I would have no clue.  If you know, please leave a comment!

EDIT: To keep the YATE log file from growing too large over time, copy the file /usr/src/yate/packing/yate.logrotate into /etc/logrotate.d as “yate” (get rid of the .logrotate extension).  That file instructs the system logrotate job to roll the yate log file when it gets to 100 MB.  Thanks to Bill Simon for that tip!

EDIT 2: If you have ignored the advice given almost everywhere to create a new, separate Gmail account, and then use that account when you create your Google Voice account, then you have probably run into the issue of not receiving your incoming calls when you are logged into that Google account and for some time thereafter.  That problem, and one possible fix (along with the drawbacks) were discussed in a post in the thread “YATE in a Flash 1.2 Ready” on the PBX in a Flash Forum, which unfortunately disappeared from that site due to a server crash.  The post, originally by user Marian on Aug 6, 2012, read as follows:

Gmail sets a greater resource priority when you connect and don’t advertise unavailable for a while after you disconnect.
So, if you connect to GMail using the same account as yate the calls will be sent there until GMail advertise resource unavailable.
You can set priority=10 in accfile.conf, gmail account section.
But, if you do that you might not see your chat in GMail or another jabber client connected to GMail for the same account (like GTalk or Yate Client).
Unfortunately, the jabber protocol don’t allow setting different priorities for the same resource for different services (e.g. you can’t set a priority for chat and another one for another capatibility, like jingle calls).
I didn’t found a workaround for this situation: having, for the same account, a resource for chat and another one for jingle calls.
This would require a custom jabber client or a custom jabber server.

That, coupled with information from other posts around the web, means the best advice is to add a line of the form:

priority=127

in each of your Google Voice accounts in the file accfile.conf (in the /usr/local/etc/yate directory).

If you want that line to be added by default when you add a new Google Voice account to your YATE server, open the add-yate-user script (which is probably in your /root directory) in a text editor such as nano, and find this line:

echo “options=allowplainauth” >> accfile.conf

and underneath it add this:

echo “priority=127″ >> accfile.conf

Then save the edited file.  I make no guarantees that this will actually work, but it’s worth a try. NOTE: The thread mentioned above suggested setting the priority to 10, however, the Asterisk developers are now using 25. As this wiki page explains:

More about Priorities

As many different connections to Google are possible simultaneously via different client mechanisms, it is important to understand the role of priorities in the routing of inbound calls. Proper usage of the priority setting can allow use of a Google account that is not otherwise entirely dedicated to voice services.

With priorities, the higher the setting value, the more any client using that value is preferred as a destination for inbound calls, in deference to any other client with a lower priority value. Known values of commonly used clients include the Gmail chat client, which maintains a priority of 20, and the Windows GTalk client, which uses a priority of 24. The maximum allowable value is 127. Thus, setting one’s priority option for the XMPP peer in res_xmpp.conf to a value higher than 24 will cause inbound calls to flow to Asterisk, even while one is logged into either Gmail or the Windows GTalk client.

Outbound calls are unaffected by the priority setting.

This would be true in Asterisk OR YATE, therefore the recommendation is to now use at least 25 as the priority value, up to the maximum of 127 as suggested above.

Asterisk hiding a useful feature in plain sight by giving it a "cute" name

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.
easter eggs in the stage of painting
Easter Eggs (Image via Wikipedia)

Somewhere in FreePBX 2.7 or thereabouts, it became know that there was a feature of FreePBX Outbound Route dial patterns, were you could use a /CallerID extension. This (among other things) basically lets you limit the use of an Outbound Route to a particular extension or group of extensions.  It’s a very useful feature, but wasn’t widely announced or promoted at the time.  I finally figured out why.

Thing is, it’s NOT a FreePBX feature, it’s a feature of Asterisk.  Anywhere in an Asterisk dial plan where you have a line that starts with

exten => _somepattern,…

you can use the Caller ID modifier, like this:

exten => _somepattern/callerid,…

In which case the pattern won’t be matched unless the current Caller ID number (which on an internal call is the number of the calling extension) matches whatever you’ve replaced callerid with.  Callerid can itself be a number or a pattern.

The real kick in the head is that it appears this feature has been around for a LONG time.  It was definitely in Asterisk 1.4.  Yet virtually none of the documentation you see on Asterisk even mentions this feature.  It might as well have been an “Easter Egg” hidden in the software, for all anyone knew of it.  Well, I finally figured out why — the Asterisk folks hung a “cute” name on it, and it stuck.

They called it ex-girlfriend logic.  The idea is that you can use it to stop an ex-girlfriend from bothering a particular user on your system (at least in raw Asterisk, though I don’t think that’s directly supported in FreePBX).  Besides being a bit sexist, it’s also about the last terminology anyone would think to Google on if they were trying to find out about this feature.  So while people were writing third-party modules like Custom Contexts and Outbound Route Permissions in FreePBX, it now turns out that essentially the same basic functionality was there all along, but hardly anyone (at least in the FreePBX world) knew about it until around about the time of FreePBX 2.7 or so.  If you can find anything at all about this feature in “official” Asterisk documentation (that doesn’t include third-party sites!), you’re a better searcher than I.

Makes you wonder if there are any OTHER cool features in Asterisk that are hidden in plain sight, under unfortunate descriptive names that no one would ever think to use when searching for such a feature!

 

A Perl script to send Caller ID popups from Asterisk to computers running Notify OSD (such as Ubuntu Linux) or any command-line invoked notification system

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

This is basically an update to my article, A Perl script to send Caller ID popups from Asterisk to computers running Growl under OS X on a Mac or Growl for Windows, and you should still use that article if you are sending notifications to a computer on your local network that runs Growl or Growl for Windows as the notification system.

I wanted to find a way to send Caller ID popups to a Ubuntu Linux box, and in the process I discovered a different method of sending such notifications.  There are pros and cons to using the new method, so let me explain those first:

Pros:

  • Can send notifications to any computer that supports command line generated notifications (so it could also be used with Growl, if you can use growlnotify from a command prompt to generate a notification).
  • Can send notifications to any computer that you can SSH into, provided you have it set up to use public/private key authentication rather than password authentication.

Cons:

  • Notifications typically display a couple of seconds later than under the previous method.  I suspect this is due to the SSH authentication taking a second or two.
  • It’s a little bit more complicated to set this up, though not horribly so.
  • Because this uses SSH and requires that Asterisk be granted permission to establish an SSH connection as the super user (by using sudo), there may be unforeseen security risks.

Read that last point again, and please understand that as with all projects on this site, I offer this for experimental purposes only.  I explicitly do not warrant this method as being 100% secure, nor will I tell you that it could not be exploited to do bad things on your system.  I don’t think it can (and feel free to leave a comment if you think I’m wrong), but I just don’t know that for sure.  So, if you decide to use anything in this article, you agree to assume all risks. If you’re the type that likes to sue other people when something goes wrong, then you do not have permission to use this code.  We’re all experimenters here, so no guarantees!

As with the previous method, you must have the Perl language installed on your Asterisk server, and you must have the Asterisk::AGI module installed (I’m going to assume you know how to install a Perl module from the CPAN repository – if you have Webmin installed, it can be done from within Webmin). Chances are you already have Asterisk::AGI installed, unless you built your Asterisk server “from scratch” and never installed it.

There’s one additional thing you must do on the Asterisk server before this will run, and that’s allow Asterisk to run the ssh command as root. So, add this to your /etc/sudoers file (probably at the very end, but in any case it should be obvious where to add this because it will be in a section where Asterisk is granted similar privileges with regard to other programs):

asterisk ALL = NOPASSWD: /usr/bin/ssh

Next you want to copy and paste the following Perl script to the filename /var/lib/asterisk/agi-bin/notifysend.agi on your Asterisk server (to create a non-existent file, you can use the touch command, and after that you can edit it in Midnight Commander or by using the text editor of your choice). If this code looks somewhat familiar, it’s because it’s adapted from some code that originally appeared in a FreePBX How-To, which I have modified.

#!/usr/bin/perl
use strict;
use warnings;
use Asterisk::AGI;
my $agi = new Asterisk::AGI;
my %input = $agi->ReadParse();

# Next two lines fork the process so Asterisk can get on with handling the call
open STDOUT, '>/dev/null';
fork and exit;

my $num = $input{'callerid'};
my $name = $input{'calleridname'};
my $ext = $input{'extension'};
my $user = $ARGV[0];
my $ip = $ARGV[1];

if ( $ip =~ /^([0-9a-f]{2}(:|$)){6}$/i ) {
    $ip = $agi->database_get('growlsend',uc($ip));
}

# OMIT this section if you don't want IP address
# checking (e.g. you want to use foo.bar.com)
unless ( $ip =~ /^(d+).(d+).(d+).(d+)$/ ) {
    exit;
}

if ( $ARGV[2] ne "" ) {
 $ext = $ARGV[2];
}

my @months = (
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
);
my @weekdays = (
    "Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"
);
my (
    $sec,  $min,  $hour, $mday, $mon,
    $year, $wday, $yday, $isdst
) = localtime(time);
my $ampm = "AM";
if ( $hour > 12 ) {
    $ampm = "PM";
    $hour = ( $hour - 12 );
}
elsif ( $hour eq 12 ) { $ampm = "PM"; }
elsif ( $hour eq 0 )  { $hour = "12"; }
if ( $min < 10 ) { $min = "0" . $min; }
$year += 1900;
my $fulldate =
"$hour:$min $ampm on $weekdays[$wday], $months[$mon] $mday, $year";

# Next two lines normalize NANP numbers, probably not wanted outside of U.S.A./Canada/other NANP places
$num =~ s/^([2-9])(d{2})([2-9])(d{2})(d{4})$/$1$2-$3$4-$5/;
$num =~ s/^(1)([2-9])(d{2})([2-9])(d{2})(d{4})$/$1-$2$3-$4$5-$6/;

my $cmd = qq(./remotenotify.sh "$name" "$num calling $ext at $fulldate");
$cmd = "sudo ssh $user@$ip '$cmd'";
exec "$cmd";

Also, if you want to be able to specify computers that you wish to send notifications to using MAC addresses rather than IP addresses (in case computers on your network get their addresses via DHCP, and therefore the IP address of the target computer can change from time to time), then you must in addition install the following Perl script (if you have not already done so when using the previous method). Note that if you have a mix of computers on your network and you are using both the new and old methods, you only need to do this once — it works with both methods (hence the reference to “growlsend” in the database and “gshelper” as the name of this script). Call it /var/lib/asterisk/agi-bin/gshelper.agi and note that there is a line within it that you may need to change to reflect the scope of your local network:

#!/usr/bin/perl
use strict;
use warnings;
my ($prev, @mac, @ip);
# Change the 192.168.0.0/24 in the following line to reflect the scope of your local network, if necessary
my @nmap = `nmap -sP 192.168.0.0/24|grep -B 1 MAC`;
foreach (@nmap) {
    if (index($_, "MAC Address:") >= 0) {
        @mac = split(" ");
        @ip = split(" ",$prev);
        `/usr/sbin/asterisk -rx "database put growlsend $mac[2] $ip[1]"`;
    }
    $prev=$_;
}

Make sure to modify the permissions on both scripts to make them the same as other scripts in that directory (owner and group should be asterisk, and the file should be executable), and if you use the gshelper script, make sure to set up a cron job to run it every so often (I would suggest once per hour, but it’s up to you).

Now go to this page and search for the paragraph starting with, “After you have created that file, check the ownership and permissions” (it’s right under a code block, just a bit more than halfway down the page) and if you are using FreePBX follow the instructions from there on out (if you are not using FreePBX then just read that section of the page so you understand how this works, and in any case ignore the top half of the page, it’s talking about a different notification system entirely). However, note that the syntax used in extensions_custom.conf differs from what is shown there, depending on whether you are specifying an IP address or a MAC address to identify the target computer.

First, if you are specifying the IP address of the target computer, then instead of using this syntax:

exten => ****525,1,AGI(growlsend.agi,192.168.0.123,GrowlPassWord,525)

You will need to use this:

exten => ****525,1,AGI(notifysend.agi,username,192.168.0.123,525)

Note that username is the account name you use when doing an ssh login into the destination system, and it should also be the desktop user on the system (not root!). Let’s say that the system is currently at IP address 192.168.0.123. In order for this to work, you need to be able to ssh into your Ubuntu box from your Asterisk server, using the following command from the Asterisk server’s command line:

ssh username@192.168.0.123

If it asks for a password, then you need to follow the instructions at Stop entering passwords: How to set up ssh public/private key authentication for connections to a remote server, and get it set up so that it will not ask for a password (if you don’t like my article, maybe this one will make it clearer).

It’s probably easiest to configure each computer that is to receive notifications to use a static IP address. But note that if you use the above code and have the gshelper.agi program running as a cron job, then after the first time it has run while the computer to receive the notifications is online you should be able to use a computer’s MAC address instead of the IP address. This only works if you’ve used the modified script on this page, not the one shown in the FreePBX How-To. As an example, instead of

exten => ****525,1,AGI(growlsend.agi,192.168.0.123,GrowlPassWord,525)

as shown in the example there, you could use

exten => ****525,1,AGI(notifysend.agi,username,01:23:45:AB:CD:EF,525)

(the above is all one line) where 01:23:45:AB:CD:EF is the MAC address of the computer you want to send the notification to. Once again, just in case you missed it the first time I said it, this won’t work until the gshelper.agi script has been run at least once while the computer to receive the notifications was online. If for some reason it still doesn’t appear to work, run the nmap command (from gshelper.agi) including everything between the two backticks (`) directly from a Linux command prompt and see if it’s finding the computer (depending on the size of your network, it might be several seconds before you see any output, which is why I don’t try to run this in real time while a call is coming in).

If you are NOT running FreePBX, but instead writing your Asterisk dial plans by hand, then you will have to insert a line similar to one of the above examples into your dial plan, except that you don’t need the four asterisks (****) in front of the extension number, and if it’s not the first line in the context, you’ll probably want to use n rather than 1 for the line designator (and, you won’t be putting the line into extensions_custom.conf because you probably don’t have such a file; instead you’ll just put it right in the appropriate section of your dial plan). In other words, something like this (using extension 525 as an example):

exten => 525,n,AGI(notifysend.agi,username,192.168.0.123,525)

This line should go before the line that actually connects the call through to extension 525. I do not write Asterisk dial plans by hand, so that’s about all the help I can give you. And if you don’t write your dial plans by hand, but you aren’t using FreePBX, then I’m afraid you’ll have to ask for help in whatever forum you use for advice on the particular software that you do use to generate dial plans, because I can’t tell you how to insert the above line (or something like it) into your dial plan.

Now is where it gets just a bit more complicated than in the original method. If you have followed the above instructions, you’ll be able to send the notifications to the remote system using SSH, but there will be nothing there to receive them. So we have to create a small script on the receiving system to do something with the received notifications. That script will vary depending on the receiving system, but it must be named remotenotify.sh and it must be placed in the destination user’s home directory, and don’t forget to make it executable! Here’s one that will work in most Ubuntu installations that have Notify OSD installed:

export DISPLAY=:0
notify-send --urgency="critical" --icon="phone" "$1" "$2"

Those two lines are all you need. On a different type of system (or if you have multiple displays) you may need to or wish to do something different. For example, as I mentioned above, if the destination system is running Growl then your remotenotify.sh script will need to call growlnotify, but beyond that I wouldn’t know what to use there (EDIT: But if the target system is a Mac that is running OS X, a pretty good guess would probably be that you’d only need one line, something like this:

growlnotify -s -p 1 -a Telephone -m "$2" $1

In this case it should make the notification sticky until dismissed by the user, give it a priority of 1 — the default is 0 — and use the application icon from the “Telephone” application if you have it installed. Instead of -a to specify an application’s icon you could use -I followed by a path to an .icns file that contains an icon you want to use.  Type growlnotify –help to see all the growlnotify options.  Oh, and before you can make an SSH connection to a Mac you have to go into System Preferences | Sharing and turn on Remote Login).

The beauty of this approach is that you can make the remotenotify.sh script as simple or as complicated as you need — you could even make it forward a notification to other devices if you wish, but figuring out how to do that is up to you (if you come up with something good, please leave a comment and tell us about it!).

If you’re running Ubuntu on the target system, here’s a few articles you may wish to use to help you get your notifications to look the way you want them to appear:

Tweak The NotifyOSD Notifications In Ubuntu 10.10 Maverick Meerkat [Patched NotifyOSD PPA Updated]
Get Notifications With A Close Button In Ubuntu
Configurable NotifyOSD Bubbles For Ubuntu 11.04: Move, Close On Click, Change Colors And More

If you want to be able to review missed notifications, you may be able to use this (as a side note, why don’t they have something like this for Growl?):

Never Miss A NotifyOSD Notification With “Recent Notifications” GNOME Applet

The idea behind the shell script that runs on the target system was found in a comment on the following article, which may be of special interest to MythTV users:

Send OSD notification messages to all systems on a network

There are links to other original sources throughout the article, so feel free to follow those if you want more in-depth commentary.