Using the Asterisk Database: Custom Incoming CallerID Name Lookup

Asterisk knows the CallerID information of the calling channel and can arbitrarily set this information when a call is moving through the dialplan. In this article we use these factors to our advantage to create a custom database of CallerID text for phone numbers we know. Provides a thorough introduction to working with the Asterisk Database, and creates a foundation for future articles on the topic.

One thing I noticed (more) once I started running Asterisk was how poor most CallerID text is. It will either say “WIRELESS CALLER,” “LOS ANGELES CA” or it will be the name of someone other than who is calling (often this is due to another person owning the phone). Obviously none of these is terribly useful, and the capitals are pretty ugly too.

As you can imagine, Asterisk knows the CallerID information of the calling channel and can arbitrarily set this information when a call is moving through the dialplan. In this article we’ll use these factors to our advantage and create a custom database of CallerID text for phone numbers we know.

Roll up your sleeves! We’ll delve straight into the Asterisk console and dialplan, so you should be somewhat familiar with both. This is a functional example, but it also presents a thorough introduction to using the Asterisk Database, and creates a foundation for further articles in this direction.

Introducing The Asterisk Database

Asterisk comes bundled with a simple built-in database. Since it only stores and retrieves key/value pairs, there is no complex query language to know. The simplicity is perfect for what we want to do here, and also a good fit for most needs in Asterisk development. Even if you’re not familiar with databases, no worries! It’s easy.

First, we pick an arbitrary family name to store our data. You can think of the family name like a folder. In this example, I’ll be using “cidname” to avoid confusion. I recommend using all lowercase letters and numbers without any special characters or spaces. You’ve been warned.

Let’s assume that I’m getting calls from phone number 8005555555. Instead of saying whatever generic thing it says, I want the CallerID to read “Asterisk Caller #1″. To set this custom name for this phone number, we’ll use the Asterisk command “database put”.

To see the format of this command (in the console), ask Asterisk for help:

CLI> help database put
Usage: database put <family> <key> <value>
       Adds or updates an entry in the Asterisk database for
       a given family, key, and value.

Our family name is cidname, the key is the phone number, and the value is the CallerID name we want to see when this number calls. So enter the following command into the console:

CLI> database put cidname 8005555555 "Asterisk Caller #1"
Updated database successfully

Notice that we didn’t have to tell Asterisk anything about the cidname family, it is automatically created when something is stored there. (Actually, it’s there if keys exist, it’s gone if there are no keys.) You can use any family name and store any arbitrary key/value pairs this way, it doesn’t have to be phone numbers.

When you put the value into the database as above, Asterisk responds by telling you that the database was successfully updated. If you want to verify or lookup data in the database, the converse of put is get. The command format is the same but it doesn’t take a key value:

CLI> help database get
Usage: database get <family> <key>
       Retrieves an entry in the Asterisk database for a given family and key.

Retrieve the value for the phone number like this:

CLI> database get cidname 8005555555
Value: Asterisk Caller #1

That mostly covers the Asterisk Database for what we need here. Obviously if we can store and retrieve this data so easily, all we need to do to implement our custom CallerID lookup functionality is to get this logic into the dialplan…

Dialplan Logic

I don’t know your dialplan, so you will need to adapt this section to suit your needs. In the example, we’ll assume that calls are coming through extension “s” which may not be true in your case. You can insert this logic anywhere prior to the Dial application that you want to carry your custom CallerID name.

Conceptually, the flow of the call is like this:

  • Incoming call is received
  • CallerID number is looked up in Asterisk Database
  • If CallerID number is found in database, set CallerID name to database value
  • Dial local extension

To set the name portion of the CallerID, we would normally use this in the dialplan:

exten => s,n,Set(CALLERID(name)=Deep Liquid)

Incidentally, database values can be set from the dialplan using a similar construct:

exten => s,n,Set(DB(cidname/8005555555)=Asterisk Caller #1)

We can also reference values of these special variables within other dialplan arguments:

exten => s,n,Log(NOTICE, "Incoming CallerID Data:   ${CALLERID(all)}")
exten => s,n,Log(NOTICE, "Incoming CallerID Number: ${CALLERID(num)}")
exten => s,n,Log(NOTICE, "Incoming CallerID Name:   ${CALLERID(name)}")

exten => s,n,Log(NOTICE, "A key value:   ${DB(cidname/8005555555)}")
exten => s,n,Log(NOTICE, "CallerID Name: ${DB(cidname/${CALLERID(num)})}") 

So you can see that it’s powerful, and gets messy quick. The matter of trying to implement conditional logic in the dialplan is no less sticky, mostly because of the same syntacitc issues. This is why I recommend you copy the following rule verbatim and only adjust the instances of “cidname” if you used a different family name.

exten => s,n,Set(CALLERID(name)=${IF($["${DB(cidname/${CALLERID(num)})}" = ""]?${CALLERID(name)}:${DB(cidname/${CALLERID(num)})})})

I told you it was ugly. There are other ugly ways you could do this conditional logic, but not in a single dialplan rule. In English, it says: ”Set CallerID name to current value if a lookup on the database key returns an empty string, otherwise set the value returned by the database.” So you see, in this pattern we are actually setting the CALLERID(name) variable no matter what. We either set it to the database value if one exists, or we re-set it’s value to it’s current value.

Paste this rule into your dialplan before the Dial application. Adjust the extension and priority appropriately then reload the dialplan in the console:

CLI> dialplan reload

If Asterisk throws errors when you reload the dialplan or when calls pass through the dialplan priority you just inserted, then you probably did not paste it correctly or had some other transcription error. Check your code! (I copied the above rule directly out of my working dialplan.)

When you’re ready to test, call your phone as you normally would. Whatever CallerID number you are calling from will need to have a database key set as per above instructions. If you didn’t already add a key/value into the database for this phone number, go back and do that now. If all is well, the new custom CallerID name should now be displayed when you call.

Managing Data

It should be noted that there is no significant overhead to using the Asterisk database. In fact, databases of this style are extremely efficient. By allowing you to store data in a family of keys, whole trees of key/value pairs can be retrieved or removed quickly. To see all the commands, ask Asterisk for help:

CLI> help database
     database del       Removes database key/value
     database deltree   Removes database keytree/values
     database get       Gets database value
     database put       Adds/updates database value
     database show      Shows database contents
     database showkey   Shows database contents

The commands we haven’t covered involve retrieving and deleting values by various means. This isn’t entirely necessary for our example (since efficiency is not a prominent issue, we don’t necessarily need to remove keys). However, if you managed to get some garbage into your database you can remove it like this:

CLI> database del cidname 8005555555
Database entry removed.

If you want to remove the entire family of cidname values:

CLI> database deltree cidname
Database entries removed.

Be careful! Working with the Asterisk database is very “on the fly.” There isn’t any way to restore these deleted values and Asterisk won’t ask you for confirmation.

If you have several tables that store data using CallerID numbers as keys, you can look for all the occurances of a particular key in the Asterisk database using “showkey” like this:

CLI> database showkey 8005555555
/blacklist/8005555555                      : yes
/cidname/8005555555                        : Asterisk Caller #1

Finally, if you want to see all the values for a particular family, you can use the command “database show” like this:

CLI> database show cidname
/cidname/8005555555                        : Asterisk Caller #1
/cidname/8005551234                        : Asterisk Caller #2

That pretty much covers all the database commands!

Conclusion

This built-in data storage can greatly simplify some dialplan tasks. The same concept can be extended to many different scenarios where you need to store data and act on the result in the dialplan. The database is limited in the sense that it only works with family/key/value tuples, but you are not limited to using these features for a particular purpose. What the database stores, and what is stored in it, is purely dependant on your particular application.

You could apply the database techniques in this article to a number of scenarios:

  • Create a blacklist of numbers that are sent to a torture script
  • Create conditional dialplan routing based on CallerID number
  • Play a variable status message to callers based on the value of a particular key

What have you used it for? What do you want to use it for? Did you find this article useful? Please post comments below. Thanks for reading!

Tags: , , ,

One Response to “Using the Asterisk Database: Custom Incoming CallerID Name Lookup”

  1. master reseller hostingNo Gravatar wrote:

    Nice blog I really like your writing style,it is really interesting to read your articles.