Monday, September 30, 2013

Custom Caller ID Names with Google Voice, OBi202, OpenCNAM and YATE (part 3 of 3)

In this series: Part 1 | Part 2 | Part 3

If you are not already aware, Google will be making changes in May, 2014 that will break compatibility with Obi devices and Google Voice. Some or all of this document may not be applicable after that time. (http://blog.obihai.com/2013/10/important-message-about-google-voice.html)


Update 9/11/2014 - Obi + Google Voice now supported again!

In Part 1 of this series, we configured a YATE server. In Part 2, we configured the OBi202 to forward Google Voice calls to the YATE server. If you've followed these instructions and tested at each point along the way, your system is now set up so that when someone calls your Google Voice number, the call goes from Google Chat to OBi202 to YATE to OBi202 to the corded or cordless phone(s) attached to the OBi202. However, there still is no caller ID name information.

In this third and final part in the series, we will use a script on the YATE server to add caller ID name information to Google Voice calls that go through YATE. The final script that I provided implements the following features:


  • First, check a custom telephone directory (which I have implemented as a simple text file). This allows you to define well-known numbers and associate a name of your choice with them. The text you display for these incoming calls is limited only by your creativity -- and of course, the 15 character limit for CNAM.
  • Second, check a local "cache" of already looked-up numbers, so as to avoid looking up numbers that have been looked up before. The script logs these numbers to a separate file, which you may wish to add to your custom telephone directory if they're frequent callers.
  • Third, use OpenCNAM to look up the name. OpenCNAM is a simple, HTTPS+REST API to look up names associated with numbers.
  • Fourth, if all of the above have failed, display a string of your choice, e.g. "Unknown Caller."
  • Finally, this can be configured to direct calls to different phones -- for example, Google Voice number 1 will ring phone 1, and Google Voice number 2 will ring phone 2.
The provided script is in Perl, and I've written it in such a way that it's pretty extensible without knowing anything about YATE, so you can add your own logic. I've listed some additional ideas (without implementation) later in the post.

Important Note

Once again, it bears repeating that the procedures in this section will manipulate the caller ID names that are shown on the telephones attached to your OBi202 -- NOT over any public telephone lines. Custom caller ID data is a common feature of just about any PBX system, and that's not hacking, cracking, or spoofing.

If you want to change how your caller ID name displays to others when you call them, contact your telephone service provider.

Prerequisites

Before you get started here, you should have tested that calls to your Google Voice number are forwarded to YATE, back to your OBi202, and ultimately ringing the phones connected to your OBi202. This test is described in Part 2 of this series.

Install the YATE script libraries

On Ubuntu, I installed the yate-scripts deb as follows:

$ sudo apt-get update
$ sudo apt-get install yate-scripts

(Note that I had already set up my system to use the wildfire PPA in Part 1, so it found package matching my YATE installation.)

The yate-scripts package deposited several files into the /usr/share/yate/scripts directory, including the Perl module, Yate.pm, which will be used later. There are libraries there for PHP and python as well.

If your Linux distribution doesn't provide this, or if you compiled YATE yourself from source, you'll find Yate.pm and the other libraries in the share/scripts directory of the distribution. From the current trunk: http://voip.null.ro/svn/yate/trunk/share/scripts/Yate.pm.

It's probably best to install the YATE script libraries that exactly correspond to the version of YATE that you are running (although I would not be at all surprised if it was OK to have mismatched versions so long as the versions of YATE were similar enough to be using roughly the same API).

Verify perl dependencies

Your installed perl version needs to support the following modules/libraries:
  • LWP::UserAgent (including SSL support)
  • JSON
Ubuntu already has LWP::UserAgent with SSL support "out of the box." To install JSON support:

$ sudo apt-get install libjson-perl libjson-xs-perl

Install custom caller ID script

Instead of putting my script in /usr/local/bin or similar, I suggest that you have a directory on your YATE server that is used only for YATE scripts (you'll see why below). On my system I chose to put this in /etc/yate/scripts so these instructions will reflect that.

$ sudo mkdir /etc/yate/scripts
$ cd /etc/yate/scripts
$ sudo wget -O caller-id.pl https://github.com/kpaulisse/yate-caller-id/yate-caller-id/caller-id.pl
$ sudo chmod 755 caller-id.pl

You can find the caller ID script in my github repository:

https://github.com/kpaulisse/yate-caller-id

If your Yate.pm module is in /usr/share/yate/scripts, you're all set. Otherwise, copy Yate.pm into the same directory where you put caller-id.pl.

Configure custom caller ID script

The caller ID script is entirely configured using a single configuration file. I named mine /etc/yate/caller-id.cfg. For now, just paste in this content -- I will describe these settings later.

OPENCNAM_URL = https://api.opencnam.com/v2/phone/%s?format=json
#OPENCNAM_ACCOUNT_SID = YourAccountSIDGoesHere
#OPENCNAM_AUTH_TOKEN = YourAuthTokenGoesHere
CUSTOM_MAP = /etc/yate/caller-id.map
LOGFILE = /var/yate/caller-id.log
UNKNOWN_CALLER_NAME = Unknown Caller
HINTFILE = /var/yate/caller-id-hint.txt
CNAM_CACHE_TTL = 15552000
PREFIX_STR = ""

(Note: this assumes the existence of /var/yate which was created in Part 1 of this series.)

Create local caller ID map file

This is the file where you get to have all the fun -- associating your own custom "names" with certain incoming numbers. For now you can start with just your own cell phone number. ("1" followed by ten digits, with no punctuation -- then one or more whitespace characters -- and then "your name.")

$ sudo vi /etc/yate/caller-id.map
12025551212     My Cell Phone

Configure YATE to use your script

Edit the /etc/yate/extmodule.conf file to add the following entries to the indicated sections.

[general]
scripts_dir=/etc/yate/scripts

[scripts]
caller-id.pl=/etc/yate/caller-id.cfg

Now you need to restart YATE. Make sure you're not in the middle of a phone call that's being routed through it (because this will kill that call) and then execute the appropriate restart command for your OS. For Ubuntu this is:

$ sudo service yate restart

Look at the process list and you should see the caller ID script running too.

$ ps -ef | grep yate
yate     20937     1  0 Sep14 ?        00:00:22 /usr/bin/yate -p /var/yate/yate.pid -d -rs -l /var/yate/yate.log -Dfu -v
yate     20938 20937  7 Sep14 ?        02:31:14 /usr/bin/yate -p /var/yate/yate.pid -d -rs -l /var/yate/yate.log -Dfu -v
yate     20943 20938  0 Sep14 ?        00:00:00 /usr/bin/perl /etc/yate/scripts/caller-id.pl /etc/yate/caller-id.cfg

If you see that, great! If not, take a look at /var/yate/yate.log to see if there are any obvious errors.

Testing caller ID integration

Now, give yourself a call from your cell phone (which you put into the caller ID map file) and see if your custom name is displayed. You can look in /var/yate/caller-id.log for more details from the caller ID script.

Note that on your caller ID, the number you're calling from should look like '1112025551212' -- the prefix "11" will be on the number. At this point, your call should also ring phones connected to Phone #1 and Phone #2. We will remove the prefix and route the calls correctly in a little bit.

Testing OpenCNAM integration

If a phone number is not found in your map file, the caller ID script will query OpenCNAM. The free "hobbyist" usage tier has limited results, and I did not find that it knew my cell phone number or home phone number. Your mileage may vary.

To test, edit your map file and remove (or comment out) the line with your cell phone number, and then call again. (No need to restart YATE or the script -- it re-reads the map file with each call.) You can look at /var/yate/caller-id.log for details. Unless you're lucky, you probably got Unknown Caller for this.

Setting up OpenCNAM professional tier

If you have decided that you want reliable caller ID name data for your setup, you can sign up for the OpenCNAM professional tier, which costs 0.4 cents per successful lookup (as of September, 2013). For your initial $10 deposit you get 2500 lookups, which should hopefully last you for a good while!

Here's how to configure that:
  1. Go to http://www.opencnam.com and sign up.
  2. Deposit $10.00 into your account with a credit card or other accepted payment method.
  3. At the top of your dashboard, you will see your Account SID. There is also a padlock next to your Auth Token. Click the padlock to expand your auth token.
  4. Edit /etc/yate/caller-id.cfg and uncomment the OPENCNAM_ACCOUNT_SID and OPENCNAM_AUTH_TOKEN lines. Fill in your own account SID and auth token.
  5. Restart YATE to apply this configuration change.
Now make another call from your cell phone to your Google Voice number. This time, OpenCNAM should pull the correct publicly available caller ID data. You can see /var/yate/caller-id.log for details.

Finally, make yet another call from your cell phone to your Google Voice number. This time you should see the same caller ID data, but if you look in /var/yate/caller-id.log you should see that it pulled this data from the cache. In other words, you weren't charged for this lookup, because the script did not hit OpenCNAM again. The default cache TTL of 15552000 seconds is 180 days.

Advanced Topic: Multiple Google Voice numbers

In my setup, there are two Google Voice numbers handled by my OBi202, and I want things configured such that calls to one of those numbers will ring phones connected to "Phone 1" and calls to the other number will ring phones connected to "Phone 2." To achieve this, I will assign prefix '11' to those Google Voice numbers I want to ring phone #1, and '12' to those numbers I want to ring phone #2.

To be perfectly clear, you should continue with this section only if ALL of the following are true... otherwise you're just making extra work for yourself:

  • You have two or more Google Voice numbers being routed into your OBi and through YATE
  • You want one of your numbers to ring Phone #1 and the other to ring Phone #2

1. Create the Google Voice numbers prefix mapping file. In this file, list out all of your Google Voice numbers (ten digit number -- no leading '1' and no punctuation). Assign each number either "11" (ring phone #1) or "12" (ring phone #2). Here's an example where 202-555-1212 will ring phone #1 and 312-555-1212 will ring phone #2.

$ sudo vi /etc/yate/google-numbers.map
2025551212 = 11
3125551212 = 12

2. Edit the configuration file (/etc/yate/caller-id.cfg if you followed my examples) and modify or add the 'PREFIX_STR' and 'PREFIX_MAP' lines as follows:

$ sudo vi /etc/yate/caller-id.cfg
(existing data is here)
PREFIX_STR = "00"
PREFIX_MAP = "/etc/yate/google-numbers.map"

3. Restart YATE.

$ sudo service yate restart

4. Place a call to each of your Google Voice numbers. You should notice the caller ID number will include the prefix (it'll look strange). This is expected for now, but make sure this is happening before you continue.

5. Now log in to the administration of your OBi202. In Part 2 you configured a service provider that logs in to your YATE server (see "Voice Services Configuration for Yate" section). If you followed my example, this is SP4.

6. In the web administration interface, open "Voice Services" and then the SP# mentioned above (for me, SP4).

7. Next to "X_InboundCallRoute" uncheck the default box. Then type the following into the Value box. (Copy and paste this directly unless you know exactly what you're doing!)

{(<11:>x.):ph}, {(<12:>x.):ph2}

8. Scroll to the bottom and Submit the changes. Then reboot the OBi.

9. Now repeat your tests -- the caller ID phone numbers should look "normal" and either Phone #1 or Phone #2 should ring based on the prefix. 

Maintaining your system

You can make changes to your custom map file (/etc/yate/caller-id.map) whenever you want. You do not need to restart the YATE server when you do. This allows you to map phone numbers to your own custom names. Have fun!

You may wish to check /var/yate/caller-id-hint.txt from time to time. This has the cache for the OpenCNAM lookups. If you have frequent callers, especially whose names you wish to customize, you can add these to your custom map file.

Ideas

Here are some (currently) unimplemented ideas for extending the caller ID functionality:
  • Create, obtain, or access a lookup table that maps area code + exchange (XXX-XXX-xxxx) to a particular city and state. For example, 608-220 numbers are the Madison, WI area. If nothing is found in OpenCNAM for the number, display city and state instead of Unknown Caller.
  • Query the phone number against your Google, LinkedIn, and/or Facebook contacts before querying OpenCNAM. For efficiency, this would be best implemented as a periodic download that populates the custom map file from the data source(s), rather than a real-time lookup.
  • Implement the custom map as something other than a text file, and perhaps something with a web front end or other GUI for manipulating entries. You could almost certainly increase the WAF of your solution by providing a means other than "vi" to add custom names.
  • This script is not designed to scale massively (e.g. cache is kept in memory and caller ID map is read with each incoming call).  Then again, it's only intended for the home user to add caller ID data for a single Google Voice number, and it works perfectly well for that.

Caveats

  • I discovered that if you use $_ in your own Perl script that uses Yate.pm, the next time a call comes in, the script will crash. This is because Yate.pm uses $_ explicitly as an object but does not localize it. This can lead to errors such as 'Cannot use "12025551212 My Cell Phone" as object reference...' errors, for example. I've placed a patch in my github repo for this issue, although my script does not trigger the error.

Summary

Congratulations - you now have complete control over how caller ID names are displayed on your telephones. I hope this was useful and will enhance your experience with Google Voice and the OBi202.

No comments:

Post a Comment