Voice dial
From SoftIVR
Voice dial
This sample implements a voice-activated dialling application. What makes it a little special is that it gets the contacts to dial from those attached to a GMail account, which makes heavy use of SoftIVR's HTTP functionality and its XML handling capabilities.
The first part of the code logs us in to Google:
// Google credentials gm_user = "softivr.call%40gmail.com"; gm_pass = "REDACTED"; // Do Google login postdata = "accountType=HOSTED_OR_GOOGLE&Email=" + gm_user + "&Passwd=" + gm_pass + "&service=cp&source=SoftIVR-dial-1"; resp = httpPost("https://www.google.com/accounts/ClientLogin", postdata); lines = resp.split(/\r|\n/); auth = ""; for (i = 0; i < lines.length; i++) { if (lines[i].substr(0, 5) == "Auth=") { auth = lines[i].substr(5); } } if (auth.length === 0) { log("Google auth failed - data posted was " + postdata); finish(); }
Provided this has worked, we now go through the entries in the account's contact list, and build up a grammar. For each contact, the grammar consists of the contact's name, plus any combination of on or at, his, hers or their, and mobile, home or work - which elements of this last group being used depending on which numbers are stored for that contact. The grammar has the relevant contact numbers added to it to make the dialling part easy.
The code also builds up a phonebook in an array, which we will use in future to disambiguate ambiguous requests - such as 'Call Mike Smith', where Mike Smith has more than one contact number.
// We have an authentication token..! Fetch address book, 1 entry at a time // This will be s-l-o-w for large address books cnum = 1; pb = -1; phonebook = []; // We build up an ABNF grammar as we go along grammar = ""; grammar = grammar + "#ABNF 1.0 ISO-8859-1;\n"; grammar = grammar + "language en-US;\n"; grammar = grammar + "public $dial = Call ("; while (cnum > 0) { contacts = httpGet("http://www.google.com/m8/feeds/contacts/default/full?max-results=1&start-index=" + cnum, "GData-Version: 2", "Authorization: GoogleLogin Auth=" + auth); parseXML(contacts); if (testXPath("entry")) { cname = getXPath("entry/title"); pn = 0; while (testXPath("entry/gd:phoneNumber[" + pn + "]")) { // The 'type' of the number can be found after the # in the rel link // Assume 'work' if not found ntype = getXPath("entry/gd:phoneNumber[" + pn + "]/rel"); num = getXPath("entry/gd:phoneNumber[" + pn + "]/content"); hp = ntype.indexOf("#"); if (hp > 0) { ntype = ntype.substr(hp + 1); } else { ntype = "work"; } // Add number and type to the phone book if (pn === 0) { // This is the first entry for this contact, so add their name phonebook[cname] = []; grammar = grammar + cname + " { $.who='" + cname + "'; } [[on | at] [his | her | their] ["; } // and add the number and type to the phone book.. phonebook[cname][pn * 2] = num; phonebook[cname][pn * 2 + 1] = ntype; // ...and to the grammar. if (pn > 0) { grammar = grammar + " | "; } grammar = grammar + ntype + " { $.where='" + ntype + "'; $.num='" + num + "'; } "; pn = pn + 1; } if (pn > 0) { grammar = grammar + "]] | "; } cnum++; } else { cnum = 0; } }
Having prepared our grammar, we answer the phone, prompt the user and see who they want to speak to:
// Got the phonebook, so answer the phone answer(); say("Who would you like to call?"); // Strip trailing | from grammar and run ASR grammar = grammar.substr(0, grammar.length - 2) + ");"; call = ASR(grammar); parseXML(call); num = getXPath("interpretation/instance/num"); dial("+44" + num.substr(1));
- and the job's done.