Follow me

From SoftIVR

Jump to: navigation, search

Routing calls automatically depending on location

This is a simple application to demonstrate dynamic call routing. It's written for my specific requirements, where I've a landline phone at home, a mobile phone, a Mac laptop which I use for everything and static IP addresses on the DSL connections at work and home. What I'd like to do is to have inbound calls routed to my landline when I'm near it, and to my mobile phone whenever I'm not. Before I go on, I have to give credit to Newber, whose large budget to achieve roughly the same ends was the spur to get this done. The story's at iPhone Dev Spends $500k on Development, Still Not Approved by Apple.

The solution has a number of parts, none of which are terribly complex, but all of which are needed to make it work. The first is a little application to work out whether or not my mobile phone is near to my laptop. This is done using Bluetooth, Python and the cross-platform Lightblue library from http://lightblue.sourceforge.net/ - this should help with porting this application to other platforms.

Having installed Lightblue as per the instructions, let's see if it can find my phone. I turned the phone's Bluetooth on, asked Lightblue to enumerate the devices it could see, turned it off and repeated. Here's what I got:

python
Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import lightblue
>>> lightblue.finddevices()
[('00:1C:B3:24:65:61', u"Dave's iPhone", 3146252)]
>>> lightblue.finddevices()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.5/site-packages/lightblue/_lightblue.py", line 51, in finddevices
    inquiry.run(getnames, length)
  File "/Library/Python/2.5/site-packages/lightblue/_lightblue.py", line 370, in run
    "Error during device inquiry")
lightblue._lightbluecommon.BluetoothError: [Errno 188] Error during device inquiry

- so it'll either see my phone or throw an exception. That's fine, although its behaviour in the "phone absent" case leaves a bit to be desired. But no matter; a quick read-up on Python's exception handling and I have:

import sys
import lightblue

while 1:
        found = 0
        try:
                devices = lightblue.finddevices()
                print devices
                for device in devices:
                        print device[1]
                        if device[1] == "Dave's iPhone":
                                found = 1
        except lightblue._lightbluecommon.BluetoothError:
                found = 0
        print "Found: "
        print found

which works just fine, plus or minus a memory leak - I've a patched version of lightblue which fixes the leak and is available to anyone who asks. Now to get this to talk to a web server, so that the web server can track my location.

A quick bit of PHP does the trick:

<?
  mysql_connect("localhost", "root", "");
  mysql_select_db("testcd");
  if ($_GET['found'] == 1) {
    if ($_SERVER['REMOTE_ADDR'] == '78.86.165.234') {
      mysql_query("replace into location (who, location, time) values('dave', 'home', NOW())");
    } 
    if ($_SERVER['REMOTE_ADDR'] == '87.117.74.121') {
      mysql_query("replace into location (who, location, time) values('dave', 'work', NOW())");
    } 
  }
  if ($_GET['wheres'] == 'dave') {
    if ($row = mysql_fetch_assoc(mysql_query("select * from location where who='dave' and time>DATE_SUB(NOW(), INTERVAL 2 MINUTE)"))) {
      echo $row['location'];
    } else {
      echo "unknown";
    }
  }
?>

- this'll keep track of whether I (and my phone and laptop) are at work, at home or unknown.

It needs a database table:

create table location (
  who char(32) not null primary key,
  location char(32) not null,
  time datetime not null
);

I then updated the phone locator to hit this script to update the stored location information:

import lightblue
import urllib

while 1:
        found = 0
        try:
                devices = lightblue.finddevices()
                for device in devices:
                        if device[1] == "Dave's iPhone":
                                found = 1
        except lightblue._lightbluecommon.BluetoothError:
                found = 0
        tmp = urllib.urlopen("http://www.softivr.com/davetracker.php?found=" + str(found))
        tmp.close()

Lastly, we need the call handler, which is a pretty simple SoftIVR service:

where = httpGet("http://www.softivr.com/davetracker.php?wheres=dave");
phone = "+447773800000";
if (where == "home") {
  phone = "+441932100000";
}
if (where == "work") {
  phone = "+442081141000";
}
dial(phone);

For more information, or if you'd like to be able to create cool applications like this, please contact support@softivr.com, and we'll send you an invite for a SoftIVR beta account. Or, to find out more, click here to learn more about SoftIVR.

Personal tools