Tag Archives: analog

Update on rotary phone refurbishment

In my last post, I suspected problems with the rotary dial on the Automatic Electric Monophone model 40, and a wiring problem on the Northern Electric 302, both of which kept me from being able to successfully pulse-dial through the HandyTone 502 analog adapter.

After a quick wiring check on the 302 and a lot of tweaking and oiling of both dials, I have to throw in the towel on getting these two to pulse-dial. Both need to have their centrifugal governors (the part that regulates the dial’s return speed) adjusted: the 302 pulses too slowly and with some irregularity, and the Monophone 40 pulses too quickly. I have read that telephone technicians of the past had to practice dial repair for a week under supervision before becoming competent at it. That is to say, the final touches are definitely beyond my skill level, and with a voice-driven workaround available, I’ve decided to call these phones “complete”–for now. I’m a tinkerer and may get adventurous some day and rip the phones apart once again.

A brief review of the Grandstream HT-502 ATA

The used HT-502 2-FXS analog telephony adapter I bought from eBay arrived earlier this week, and I hoped that by this time I could write about two functional rotary dial phones happily dialing out through this device.

No such luck, but the HT-502 is not to blame. The Northern Electric 302 seems to be mis-wired, because the ATA isn’t detecting the pulse dialing at all. I’ll have to open it up and dig in this weekend. The Automatic Electric Monophone 40, on the other hand, is wired correctly but needs some adjustment: the upper digits (7 through 0) sometimes miss a click, resulting in mis-dialing.

Image from Grandstream.comThat said, I’m already prepared to give the Grandstream HT-502 ATA very positive reviews. In fact, I might like it even better than my trusty Cisco-Linksys-Sipura SPA3102.

You can read about the device on Grandstream’s web site. Here are the unmentioned features that I really like:

  • It accepts rotary/pulse dialing, without any special configuration or modification. This was the reason I bought it, and indeed, it works. The HT-503 (1 FXS and 1 FXO port) can accept pulse dialing on its FXS port, also.
  • On an active call, it accepts rotary-dialed input and converts to SIP DTMF codes. Thus you can navigate a menu tree with your rotary phone, as long as you don’t need “*” or “#”.
  • You can configure the device with a touch-tone phone (real touch-tone; “*” required), web browser, or telnet. You can also provision the device using TFTP like the “big guys” do.
  • It has an excellent debugger. In the Advanced menu, enter the IP address of your syslog server (prerequisite: set up a syslog server), and set the verbosity to DEBUG. The floodgates will open and you will be able to see every action the device performs or receives, including dialed digits from the analog ports. This is how I was able to see where my rotary dial was sticking.
  • The device can pull its own firmware upgrades over the Internet. Nice if used carefully.
  • It’s super easy to configure. I followed documentation to factory-reset the device, hooked up a laptop to the LAN port, and reconfigured it for my own network in about 5-10 minutes. 
  • Lastly–and this is a rather obscure bonus–it uses the same power supply specifications as the Cisco-Linksys SPA devices. This hardly matters except that I have one of these–a wireless bridge for Cisco SPA devices with pass-through power. I’m planning to make the HT-502 WiFi.

The HandyTone 502 has made a good first impression and I’m looking forward to getting my rotary phones fully working on it.

A new old phone and rotary dialing, revisited

During the holidays I received and lightly restored another beautiful telephone from the 1940s, this Automatic Electric Monophone model 40:

ae40.jpgAutomatic Electric was an independent supplier of telephone equipment throughout the 20th century, eventually being purchased by GTE, and in direct competition with the Bell empire (or Western Electric, Bell’s equipment division) throughout its existence. The community-written Wikipedia article tells more of the story.

Some details about this Monophone:

  • Manufactured from 1939 to the mid-fifties, but I can’t find a stamp on the inside or outside to date it.
  • The coiled handset cable would typically indicate a later model, but the nicked-up brass screws inside the handset where the cable is connected suggest that the coiled cable was an upgrade or repair at some point in this phone’s lifetime. So it may be an old phone body with a newer cable, or it may be a later model, all-original.
  • The dial plate seems to be uncommon. Browsing many pictures of AE model 40s on the web, I haven’t seen any others with white-numbered, black dial plates. Also, it has no alphabet markings, only digits.
  • It’s all Bakelite, and heavy. The Northern Electric 302, with a thermoplastic shell, is almost a full pound lighter. External data: someone weighed their own collection of phones.

The Northern Electric 302 and the Automatic Electric Monophone 40 ready to duel:
ne320-ae40.jpgThe AE40 works fine and will be a new addition to the analog remix, but I decided to do one more search for VoIP analog telephony adapters (ATAs) that will accept rotary/pulse dialing. Recently, a commenter suggested UTStarcom adapters, but others report of an ATA that is still in service and accepts rotary dialing: the Grandstream HT-502/503. I have a 502 coming from an eBay auction and will report back on how it works out.

Appendix: analog remix debugging and notes

Part 1: Intro, Part 2: Tropo/PHP, Part 3: Asterisk Manager/Perl

These notes are from a weekend of hacking and debugging with Michigan Telephone, the first guinea pig to try out the “analog remix” scripts. Thanks for the extra challenges. 🙂

Asterisk 1.4, 1.8 and the Asterisk Manager Interface

  • Asterisk 1.4’s Manager calls the channel that is bridged to the current channel “Link.” Newer versions, more sensibly, call it “BridgedChannel.” I updated the Perl CGI to use whichever is defined, so now the CGI will work with newer versions of Asterisk, and not just 1.4.
  • A bug exists on specific versions of Asterisk 1.4, 1.6 and 1.8 that breaks call transfer from the Manager (as well as SIP blind transfers). The current -rc1 versions, as of this writing, have the fix: 1.4.39-rc1, 1.6.2.16-rc1, and 1.8.2-rc1. This bug has been in 1.4 since 1.4.38-rc1; in 1.6 since 1.6.2.15-rc1; and in 1.8 since 1.8.0-rc4. If you’re on a buggy version, the transfer will just hang up the channel.
  • How to set up the Manager user may not be obvious. Just make a new user block in manager.conf or manager_custom.conf (FreePBX) with the following permissions:

    [tropousername]
    secret = tropopassword
    deny=0.0.0.0/0.0.0.0
    permit=127.0.0.1/255.255.255.0
    read = call
    write = call

    Set the username and password to whatever you want, and then use these in the Perl CGI in the AMI::Common::new() function. Your manager user needs only “call” permissions to perform the actions in the CGI.

Perl

  • MT notes that you may have to install the AnyEvent and parent Perl modules before Asterisk::AMI. Use CPAN’s installer if you can: perl -MCPAN -e shell and install parent, AnyEvent, and Asterisk::AMI
  • The Data::Dumper module can be really helpful if you find that things aren’t going well with your CGI. Just use Data::Dumper at the top of the CGI, then print STDERR Dumper($variablename) wherever you need it. Try this on a hash, such as $currchan, and you’ll get a dump of the whole thing.

Firewall/ACL

You may want to set up a separate Apache VirtualHost with access controls (username/password and/or IP access list) for your Tropo CGI. Or, if your web server is firewalled, you’ll need to let Tropo in to make the request. Tropo’s support team indicated that requests will come from 66.193.54.21, so this IP can be allowed through your firewall. They will announce any changes to this on changes.tropo.com.

Analog remix part 3: some Perl CGI to route the call

Part 3 of the analog remix ties it all together. We need a way for Tropo to tell Asterisk to transfer the call, since we’re not going to use SIP REFER. A simple Perl CGI that connects to Asterisk Manager Interface (AMI) will do the trick.

I’m sticking with old-school Perl for this one because I really like Ryan Bullock’s Asterisk::AMI modules. His code is easy to use and he keeps it up to date.

Referring back to part 2, you can see where the curl function calls tropo.cgi (the Perl script below) with parameters f=xfer (the only function for now), callid=the SIP Call-ID, and dest=the number the caller requested. The Perl script finds the Call-ID by iterating through the channel list, finding one that’s connected to Tropo, and then checking the Call-ID to make sure it’s the exact one. (You could have more than one channel open to Tropo.) Once it finds that, it transfers the second leg of that call, which is the caller. Output is to STDERR so that I can review the transaction in the Apache error log.

Updated 12/19/2010: This line

my $link = $currchan->{'Link'} || $currchan->{'BridgedChannel'};

is updated to use either the key returned by Asterisk 1.4 (“Link”) or by later versions (“BridgedChannel”) in the channel listing.

The code:

#!/usr/bin/perl

use strict;
use Asterisk::AMI::Common;
use CGI;
use URI::Escape;

select(STDERR);
local $| = 1;
select(STDOUT);
local $| = 1;

my $cgi = CGI->new;
my $func = $cgi->param('f');
my $callid = uri_unescape($cgi->param('callid'));
my $dest = $cgi->param('dest');

print $cgi->header("text/plain");

if(defined $func) {
  if($func eq "xfer") {
    if(defined $dest && $dest ne "") {
      my $ami = Asterisk::AMI::Common->new (PeerAddr => 'localhost',
                                    PeerPort => '5038',
                                    Username => 'USERNAME',
                                    Secret => 'PASSWORD',
                                    Events => 'off',
                                    on_error => &errorHandler
                                   )
      or die "Unable to connect to Asterisk Manager.n";

      my $channels = $ami->channels;
      if (defined($channels)) {
        foreach my $channel (keys %{$channels}) {
          my $currchan = %{$channels}->{"$channel"};
          if ($channel =~ m/tropo.com/) { # find channels connected to Tropo
            my $currchan_callid = $ami->get_var($channel, "SIPCALLID");
            if ($currchan_callid == $callid) { # make sure it's the right call,
              print STDERR "Channel $channel"; # identified by Call-ID
              print STDERR "Callid $callid";

              my $link = $currchan->{'Link'} || $currchan->{'BridgedChannel'};
              if (defined($link)) { # this is the initiating leg of the call
                my $transfer = $ami->transfer($link, $dest, "from-internal");
                if (defined($transfer)) {
                  if ($transfer == 1) {
                    print STDERR "Tropo successfully transferred $link to $dest.";
                  } else {
                    print STDERR "Tropo FAILED to transfer $link to $dest.";
                  }
                } else {
                  print STDERR "System error performing transfer.";
                }
              } else {
                print STDERR "Local channel leg not found.";
              }
            }
          }
        }
      } else {
        print STDERR "Could not get channel list from Asterisk manager.";
      }
      $ami->disconnect; # close Manager connection
    } else {
      print STDERR "xfer requested but no dest specified.";
    }
  } else {
    print STDERR "Invalid function sent in CGI.";
  }
} else {
  print STDERR "No function sent in CGI.";
}

print "Done.n";
exit;

#### Functions ####

sub errorHandler {  # A fatal error occurred
  my ($amiobj, $errmsg) = @_;
  print STDERR "AMI Fatal error: $errmsgn";
  exit 1;
}

Summary

Starting with part 1, configure a hot line or warm line for your old analog device to automatically ring an extension on your system. You’ll define that extension as the SIP URI to the Tropo application you made in part 2. The Tropo application, in turn, will connect back to your Asterisk server running web services (Apache) with a CGI that can take the input and connect to the Asterisk Manager Interface and transfer your call. Simple! 🙂

Analog remix part 2: Tropo

Tropo, a project of Voxeo Corporation, adds voice and short-message-communications functions to PHP, JavaScript, Ruby, Python, and Groovy through a set of classes. They host the platform and your scripts, which are then triggered through the web or by PSTN/SIP, SMS, Twitter, or chat events. You can use the system as long as you want for free for development, or pay reasonable hosting rates to go production. Oh, and their support team is terrific, even for developers who haven’t yet paid them a dime.
So what can you do with it?
  • Interactive voice-response (IVR) systems
  • Chat or Twitter robot
  • Dialer
  • Call routing based on logic in the script
  • Text-to-speech
  • Speech-to-text
  • Audio recording
  • Whatever you can normally do with the aforementioned scripting languages, but note that the stdout will be a communications outlet such as a SIP channel, a Twitter feed or conversation, a chat, or an SMS–not a web page
My first Tropo application, the “local operator,” is the topic of part two of the analog remix. The platform has so many features, though, that I look forward to spending more time developing in it.
I chose to use PHP because it’s the language with which I am most familiar and also has Curl libraries built in, which I am using to make a CGI callback to my own Asterisk server. The purpose should become clear when you read the code, but you may ask, “why not just send a SIP REFER to do the call transfer?” The answer is that you can’t with the Tropo platform. All transfers go through Tropo; there’s no option for a REFER. So if you want to use your own dialplan and not have your call going out to Tropo and back to use local resources, you have to do the transfer through the Asterisk Manager, thus the CGI call.
Number, Please?
The script answers the call (which will come in by SIP URI), asks, “Number, please?”, validates and confirms the spoken number with the caller, then uses the Curl functions to go back to the calling Asterisk server (running a web server) and transfer the call.
Getting There From Asterisk
Once you’ve written a script and uploaded it to  Tropo (or typed it directly into Tropo’s file-editing interface), you go to the Applications section and choose your script as the source. Once you’ve submitted it, you’ll be given a SIP URI (amongst other methods) by which to access the application. So as part of a FreePBX Custom Extension or in your extensions.conf file, you can make an extension for your new application by referencing SIP/somenumber@sip.tropo.com. I set mine up as extension 1100, which I mentioned in the previous post.
Now, if I go off hook from one of my internal extensions and dial 1100, or simply pick up the analog extension on which I configured the Warm Line/Hot Line, I’ve got the operator ready to take my number and transfer my call. Only one piece left after this: the Asterisk Manager CGI script.

Appendix: the PHP code (Number, Please?)

<?php

// Main

// SSML tags needed for advanced text-to-speech manipulation
$ssml_start = "<?xml version='1.0'?><speak>";
$sayas_end="</say-as>";
$sayas_digits ="<say-as interpret-as='vxml:digits'>";
$ssml_end = "</speak>";

answer();

// These IDs are used to identify the caller and the Asterisk box
$callid = $currentCall->getHeader('x-sbc-call-id');
$hostid = trim((strstr($callid, '@')),'@');

_log("Call-ID is $callid");
_log("Host is $hostid");

wait(1000);

$haveNumber = false;

while (!$haveNumber) {
$number = ask($ssml_start . "Number <emphasis level='reduced'>please?</emphasis>" .
$ssml_end,
array(voice => "allison",
attempts => 3,
bargein => false,
choices => "[4-16 DIGITS]",
minConfidence => 0.4,
timeout => 8,
onBadChoice => "handlerBadChoice",
onError => "handlerError",
onHangup => "handlerHangup",
onTimeout => "handlerTimeout"
));

// Confirm the number with the caller
// 1 and 0 are options for testing with DTMF
$yesno = ask($ssml_start . $sayas_digits . $number->value . $sayas_end .
", is this correct?" . $ssml_end,
array(voice => "allison",
attempts => 2,
bargein => false,
choices => "yes, no, 1, 0",
minConfidence => 0.5,
timeout => 3,
onBadChoice => "handlerBadChoice",
onError => "handlerError",
onHangup => "handlerHangup",
onTimeout => "handlerTimeout"
));

_log("Caller said $yesno->value.");

if ($yesno->value == "yes" || $yesno->value == "1") {
$haveNumber = true;
} else {
say("OK, let's try again.");
}
}

// The CGI callback. Refer to a future posting for the design
// Customize for your server. Use SSL for security if you can.
$url = "http://$hostid/tropo.cgi?f=xfer&callid=" . urlencode($callid) .
"&dest=" . $number->value;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "USERNAME:PASSWORD");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

_log("Received from CGI: " . $result = curl_exec($ch));

if (!$result) {
_log(curl_error($ch));
}
curl_close($ch);

// If the transfer didn't happen, the caller is still here...

if ($currentCall->isActive()) {
_log("Transfer failed and caller still on the line.");
say("I'm sorry, something went wrong. Please try again later.");
hangup();
}

return;
// END OF MAIN

// Function definitions

function handlerBadChoice($event) {
say("I'm sorry, I didn't understand you.");
if($event->attempt >= 3) {
say("Goodbye.");
hangup();
}
return;
}

function handlerError($event) {
_log("Error occurred: $event->value");
say("I'm sorry, an error occurred. Goodbye");
hangup();
return;
}

function handlerHangup($event) {
_log("Caller hung up.");
exit;
}

function handlerTimeout($event) {
say("I'm sorry, I didn't hear you.");
if($event->attempt >= 3) {
say("Goodbye.");
hangup();
}
return;
}

?>

Analog remix part 1: a VoIP manual service exchange

Recently, I decided to revisit the analog side of my home Asterisk VoIP system, specifically, the Northern Electric 302 that I keep hooked up and on display. It’s a conversation piece, for when folks spot the rotary-dial phone, they ask, “Does that thing work?” At that point I explain that I can answer calls on it, but because of the rotary dial (and because I haven’t fashioned or purchased a rotary-to-DTMF converter) I can’t place a call from it.

Until now. With a little tweaking of the analog adapter, a fresh rediscovery of VoiceXML through the Tropo application platform, and some straightforward CGI programming, I have a robotic operator ready to connect me to whatever number I tell her. No dialing necessary!
Speech recognition is not new technology, but I think that using it here is a clever way to get around the limitations of my old technology (the rotary dial) by using the computerized equivalent of even-older “technology” (the human operator). So this discussion on implementing a manual service exchange in VoIP is dedicated to Almon Strowger, inventor of the automatic telephone switch.
There are three components to this:
  • configuring the analog adapter as an automatic ringdown (hot-line) or warm-line
  • programming the speech-to-text “operator” service on Tropo
  • programming the call-back CGI on a web server that can connect to the Asterisk Manager and perform call-handling functions
listed in order of difficulty.
Part 1: the automatic ringdown
Most VoIP-analog adapters (and probably most IP phones for that matter) have the ability to act as a hot-line, which rings a set destination when the phone goes off-hook, or a warm-line, which does the same after a timeout period (for example, six seconds without any digits entered). If you’ve got your vintage analog gear on a dedicated ATA, go for the hot-line, because you’ll never actually be “dialing” anything. As for me, I’ve got my 302 bridged with a Panasonic cordless system, so I need to maintain the ability to dial. But after six seconds of no dialing, the ATA assumes I want the operator and connects the call appropriately.
The hot-line/warm-line is configured in the endpoint’s dial plan. Refer to your device’s manual. The common Cisco/Linksys/Sipura SPA adapters all seem to have the same dial plan syntax, documented here. Here are the key items from that document:

The following implements a Hot Line phone, which automatically calls 1 212 5551234.

The following provides a Warm Line to a local office operator (1000) after five seconds, unless a four-digit extension is dialed by the user.

In my case, my “operator” extension is going to be 1100, so part of my dial plan will contain | P6 <:1100> |, which tells the ATA to automatically connect the call to extension 1100 after six seconds of no input.
Now that the need to dial has been eliminated, we’ll need something useful at extension 1100, which will be the Tropo-powered speech synthesis and recognition system, discussed in a future post.

For reliable telephone service, you need batteries, somewhere

In a recent post at mgraves.org, Michael Graves observed that today’s POTS [plain old telephone service] analog equipment seldom runs just off the phone line power, as it used to. It needs “wall power.” And folks who claim that POTS is more reliable than VoIP because the power comes over the phone line are likely forgetting this, or remembering their Trimline from thirty years ago that did indeed run solely on phone line power and worked during an electricity outage.

The telco knew the importance of reliable phone service and set up large banks of batteries at the central office that would power the lines at all times. If the electricity is out, the phone is still up, because the wall or desk phone they leased you (or later, that you bought yourself) ran off that line power. When cordless phones, FAX machines, and other more advanced analog sets came out, many did not or could not run off of phone line power and now required AC electric power. This new requirement undermined the reliability that the telco had put in place long ago.

To keep your advanced analog equipment online during a power outage, now you’d need the telco’s batteries as well as local batteries–an uninterruptible power supply, or UPS. This is what we have in place for PSU VoIP.

Our “central office”–actually, the data centers where the VoIP servers, gateways and other core devices reside–are covered by large UPSes and diesel generators. Anything between the core and the endpoint (your phone) that requires electricity is also on a UPS, including the PoE switch to which your phone is connected. Thus, if the electricity goes out, your VoIP phone will still be online.

Whether you go with POTS or VoIP, you need batteries, somewhere, to keep your phone service alive.

New phone guy meets Old Phone Guy

At a flea market earlier in the year, my mother picked up a Northern Electric (Western Electric’s Canadian counterpart) 302 telephone, manufactured in August 1948, for $20. She gave it to me during a recent visit and I set out to make it work on my home Asterisk setup.

The short of it is, it’s functional. I needed to replace the line and handset cords and give the thing a thorough cleaning, but it works. That is to say, it gets a dial tone from my analog telephone adapter and I can answer calls on it. The ringer is extremely weak as I think my ATA only supports about 2, maybe 2.5 REN and the 302 probably needs about that much current to ring the bells. I had thought that a 302 would be 1 REN but maybe this wasn’t standardized until the 500 set.

What to do about the rotary dial? I’ll buy a pulse-to-tone converter or wire up an inline keypad if I want to get creative–or find a Digium IAXy ATA, now discontinued–but until then, I have a workaround. Some time ago, a friend gave me an old Sharp organizer, the kind that stores a couple hundred names and phone numbers and plays touch tones into your handset for “speed dialing.” He found it in a drawer and gave it to me as a joke. Switch it to manual mode and I now have a dialer for my antique phone.

There are lots of resources on the web for people who want to fix up antique phones. I’m not an antiques person but I’m having fun with this little project and will keep my eyes open for more analog goodness in the future. Oldphoneguy is a great resource for restoring and wiring up old phones to work on modern lines. And Bell System Memorial, which I mentioned in an earlier blog post, has some great historical information.