Fonolo Widget – Deep Dialing For Your Business
Fonolo for business lets you embed your companies phone menu (IVR system) right on your website, or in your mobile applications, with just a few simple lines of HTML code.
Fonolo automatically maps out your phone system (and stays up-to-date with any changes you make)- You will get happier customers, fewer misdirected calls, and better feedback from your callers. Best of all, you do not have to change anything in your existing phone system.
Here's a really simple example for our fake "Fonolo Airlines" company:
More details about Fonolo for business can be found here. We're running several live trial runs with a handful of companies- if you're interested in getting access to the Fonolo widget, contact us.
All new Fonolo interface launched!
I'm very excited to announce the release of the new Fonolo consumer web interface. This new web interface not only has a new look and feel, but has improved usability, and many new features and enhancements.
Some of the enhancements to the web portal include:
Anonymous Deep Dialing
Anonymous, in the sense that you do NOT have to sign-up for an account with Fonolo, to try the service out. Search for the company you want from the list of over 500 companies in our database, right from the main page of our website, and click to start your call- no sign-up required. no special software. no special phone- all for FREE.


QuickTones
Ever been on a phone call, and they ask you for your account number? or if you have a Frequent Flyer number, but you can't remember it, and the piece of paper you have it written down on is long since gone?
Store frequently used account numbers, frequent flyer numbers, PINs, etc, in the Fonolo system, for one-click access while on a call. Simply select the tones from your list, and Fonolo will send the tones on your call, as if you had pressed the buttons yourself.
Heads-Up Display for your calls
While a call is active, you'll have full control over adding notes or recordings, with our new "Heads-Up Display" at the top of your screen. This control panel remains active during the life of your call, even if you navigate to other sections of the site.

Improved Call Recordings and Notes
When you make recordings during a call, Fonolo will organize them on a master timeline for that call, along with any notes that you added. Now you can flag the important parts and easily find them later.

Try the new Fonolo website today! it's completely free, and easy to use.
Handling SIP URI Dialing in Asterisk
Asterisk, by design, is very "extension" orientated- that is, if you want to dial an end-point, it requires an extension to route the call to. These extensions (defined in the asterisk extensions.conf file), can be extensions registered to phones, DIDs (XXXYYYZZZZ), or simply usernames assigned to users by the network administrator. Extensions are used for both incoming, and outgoing phone calls.
For example, if I place a call through my SIP phone to 1-444-555-1212, then asterisk will look up the "extension" 14445551212 in the extensions.conf file, to determine how to route the call.
Similarly to how e-mail works, an artifact of these extensions is a direct SIP address, which is basically your SIP extension @ your SIP server- so, if my phone was extension 555, and my SIP server had the IP address 192.168.1.1, then my SIP address would be: sip:555@192.168.1.1, and (if it's not implictely blocked), I can be dialed directly using that SIP address.
But, because Asterisk is so extension orientated, it doesn't easily allow for outbound dialing, using remote SIP addresses; If I try to dial the address sip:444@somedomain.com, Asterisk will immediately strip off the host portion (@somedomain.com), and try to route the call based simply on the extension "444"- which, since it's an extension on a remote server (@somedomain.com), it won't be able to route it locally, and will fail.
The solution? Well, it's not ideal, but Asterisk provides the ability to use wild cards in the extensions.conf file (it refers to them as "patterns") when doing extension look ups; this is handy when you have blocks of extension or DID's- you can use the wildcard to map like extensions to the same config, keeping your config file small.
The issue, is that the wild card only compares against the local part of the SIP URI, which can look like almost anything, including other phone numbers.
First, define some general config
[general] ; ; Your termination provider (defined in sip.conf) ; TERM_PROVIDER = SIP/company_peer ; ; The IP address of this asterisk server ; ASTERISK_IP = 192.168.1.1
The "ASTERISK_IP" address is important later, as we'll use it to validate outgoing SIP addresses.
Then in your default config, you should have something like this configured already- handling NANPA style dialing, and international dialing
[default]
;
; Dial NANPA style phone numbers directly
;
exten => _1NXXNXXXXXX,n,Dial(${TERM_PROVIDER}/${EXTEN},60)
exten => _1NXXNXXXXXX,n,HangUp()
;
; Dial international numbers directly
;
exten => _011.,n,Dial(${TERM_PROVIDER}/${EXTEN}, 60)
exten => _011.,n,HangUp()
After all the specific matches are done, then add:
;
; very last, assume anything else is a SIP URI
;
exten => _.,n,GotoIf($[${SIPDOMAIN} = ${ASTERISK_IP}]?unhandled)
exten => _.,n,GotoIf($[${SIPDOMAIN} = ${ASTERISK_IP}:5060]?unhandled)
exten => _.,n,Macro(uri-dial,${EXTEN}@${SIPDOMAIN})
exten => _.,n,HangUp()
;
; if the call doesn't match anything
;
[unhandled]
exten => s,n,Congestion()
The reason this has to be last, is because matching the extension "_." will match *anything*- basically it's a catch-all. You're saying that if it doesn't match anything else before this, then assume it must be a SIP URI.
This section also compares the ${SIPDOMAIN} variable to your ASTERISK_IP address; this ensures that only SIP URI's with remote hosts are processed as SIP URI's. If the host matches our ASTERISK_IP address value (ie- it's a local extension), then it should have already matched something above this catch-all config.
Pass any SIP URI dials to the uri-dial MACRO, merging back together the extension and the SIP domain value.
;
; handle dialing SIP uri's directly
;
[macro-uri-dial]
exten => s,n,NoOp(Calling as SIP address: ${ARG1})
exten => s,n,Dial(SIP/${ARG1},60)
This solution works, but isn't ideal, as it will match anything that didn't already match; a better solution would be for it to NOT strip off the SIP domain, and allow for using a regular expression of some kind to check the extension, but there is currently no better way of handling this in Asterisk.
Memcache Access From PostgreSQL
A big part of my job is to spend time figuring out how new technologies work, build on it, and then figure out new and inventive ways of merging it into new and existing systems- so I spent a lot of time "playing" around with stuff.
One thing I recently threw together, was some simple stored procedures for PostgreSQL, to give us built-in access to our memcached cluster, using the PL/PERL procedural language, and the Cache::Memcached module. None of this is rocket science, but might be useful for somebody out there that is looking to implement something similar.
First off, you need to build PostgreSQL with PERL support, and create the plperlu (un-trusted) language in our database; you need to use the "un-trusted" language, as we need to "use" the Cache::Memcached module;
postgres=# create language plperlu ; CREATE LANGUAGE
Then you need to install the Cache::Memcached PERL module; I'll assume you know how to do that; you can either install it through CPAN, or get it from the cpan.org site.
You also need at least one instance of memcached running somewhere; it doesn't have to be on your local network, it just needs to be accessible by your database.
Then create the following procedures; I've only listed the "set" and "get" procedures, but you could easily follow the Cache::Memcached module man page, and create a "replace" and "delete" (and any other) procedures you needed.
So first the "set" procedure:
create or replace function memcache_set(_key text, _value bytea) returns int as $$
use Cache::Memcached;
my ($_key, $_value) = @_;
$m = new Cache::Memcached {
'debug' => 0
};
my @list = ("127.0.0.1:9996", "127.0.0.1:9997");
my $servers = \@list;
$m->set_servers($servers);
$m->enable_compress(0);
if ($m->set($_key, $_value))
{
return 0;
} else
{
return 1;
}
$$ language plperlu;
And then a "get" procedure:
create or replace function memcache_get(_key text) returns bytea as $$
use Cache::Memcached;
my ($_key) = @_;
$m = new Cache::Memcached {
'debug' => 0
};
my @list = ("127.0.0.1:9996", "127.0.0.1:9997");
my $servers = \@list;
$m->set_servers($servers);
$m->enable_compress(0);
my $val = $m->get($_key);
if (defined($val))
{
return $val;
} else
{
return undef;
}
$$ language plperlu;
Now, in this case, I used a list of two different servers, both running on localhost, one on port 9996 and the other on port 9997; these servers could be anywhere, and you could only list one- but a really important thing to remember: if you do list more than one server, make sure you always list it in the same order, between all your procedures and all applications that may use this same data.
memcached calculates which server to store the data on, based on the order of this list; so you'll get un-expected results if you list these servers differently between your applications.
A Simple Test
Now that you have the functions defined, you can use them to do some really interesting caching, directly from your database. Starting off with a simple test:
postgres=# select memcache_set('foo', 'bar');
memcache_set
---------------
0
(1 row)
Then do a "get" to retrieve the data
postgres=# select memcache_get('foo');
memcache_get
---------------
bar
(1 row)
Database Session Handler
Now, lets say you had a database-backed session handler for your website; say maybe a PHP site, using something like this, which simply uses the PHP session_set_save_handler() method. Assume a simple session table like this:
create table sessions ( session_id char(32) not null, data bytea not null default '' );
"session_id" is the PHP session id (an MD5 string in this case), and "data" is the serialized contents of the PHP session.
Then add two rules- one for insert and one for update; this triggers the new memcache_set() procedure, so that new session data is always pushed out to your memcached servers
create rule session_insert_rule as on insert to sessions do also select memcache_set(NEW.session_id::text, NEW.data); create rule session_update_rule as on update to sessions do also select memcache_set(NEW.session_id::text, NEW.data);
Testing this is simple:
postgres=# insert into sessions values ('5cc27b0285c9d2e6dc4125456d308548',
'This would be the session data');
INSERT 0 1
postgres=# select memcache_get('5cc27b0285c9d2e6dc4125456d308548');
memcache_get
--------------------------------
This would be the session data
(1 row)
And then subsequent updates
postgres=# update sessions set data = 'This is the new data' where
session_id = '5cc27b0285c9d2e6dc4125456d308548';
UPDATE 1
postgres=# select memcache_get('5cc27b0285c9d2e6dc4125456d308548');
memcache_get
-------------------
This is the new data
(1 row)
Now just make your PHP session handler (or whatever) checks memcached first, before selecting from the sessions table; if you build it right, and set your expiration times correctly, you should be able to build a system that (almost) *never* reads this data from the database, as the data is always available from memcached.
VoicePHP by TringMe
TringMe, an Indian start-up just released its new VoicePHP service, which allows you to develop voice applications using PHP.
This is definitely cool stuff, though I see quite a few issues with implementation. HTTP, is, by design, a non-persistent transaction, and a phone call requires persistency while the call is in progress; therefore, there is no way for PHP alone, to handle "Voice" requests.
The only way to really make this work, is to have an external server (effectively a PBX of some kind) that handles the call traffic, that is simply polled (in some fashion) by PHP on a per request basis. Those requests could be polled via Ajax, or even a comet-like system, but it's still not handled directly via PHP. I assume this is where their VoicePHP "Server" comes in.

So, in this sense, it sounds simply like a PHP wrapper around the TringMe REST API, which is something that can already be done in other ways, like accessing the Asterisk Manager interface via PHP using asterisk-php-api, but with one interesting twist-
It looks like (according to their FAQ) you can access the audio streams directly from PHP- which is pretty interesting, depending on how they've implemented it. Given the (generally) short transaction lengths of an HTTP request, I'm not sure how you would realistically pull audio from a real-time source (like a phone call), or play-back an audio clip on to a call, unless you used some sort of scheduling system.
ie- use PHP to decode and audio file (say .wav or .mp3), and then send the file to the VoicePHP server, which schedules the audio clip for playback, and returned immediately. It's then played over the call in "real-time". PHP could then poll the VoicePHP server to get status about the playback.
I've signed up for a beta account to play around with it, hopefully I'll see something from them soon.