Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Does anyone have experience driving a modem with perl?

I have recently been asked if I can write a program that will dial a number and then emmit a series of tones (simulate touchtone keypad) then hang up and go to the next one.

Your input is extremely appreciated.

Replies are listed 'Best First'.
Re: perl + modem
by KM (Priest) on Aug 21, 2000 at 23:58 UTC
    On Win32, look at Win32::SerialPort, on *nix look at Device::SerialPort, and see if those help you.

    Cheers,
    KM

      after that handy help, it's a question of modem command syntax.
      e.g.
      for 'AT' syntax: atd1234
      will 'typically' dial 1234 using tones.
      if you send any character during dialing or just after dialing ,during modem handshaking, then the modem will hang up!
      so be wary of terminal settings if you send something like:
      print <modem_fh> "atdt1234\r\n";
      the \r 'might' not be neccesary, and you will be driven up the wall if it isn't, not that this has happpend to me! ;)
      the second 't' in that example should 'force' the modem to use tones, even if its configured to do pulses by default.
      Regards,
      Wayne
        Here's a list of commands, as best as I can remember without digging out the docs (which are at home).
        • ATDT<phone number> will dial the phone number. The modem will attempt to negotiate with the far-end answering device.
        • ATDT<phone number>; will dial the number will dial the number and return to command state. At this point, no negotiation will be attempted. You can either wait programatically a given amount of time, or, add commas to the end of the phone number. Each comma will provide aproximately 2 seconds of delay. You can use other dial modifiers here, such as 'W' to wait for a secondary dial tone (PBX systems), '!' to flash the switchhook, and a few others.
        • If you wish to send additional touch tones after the far end has answered (but not negotiated), you can use 'ATDT<numbers>;'.
        • ATO - This will go 'online'. I can't remember if this will negotiate a connection or not if an existing connection is not present. I think it will.
        • ATH - This will hang up the modem. ATH0 is the default, which hangs it up. ATH1 will take the modem off hook, without dialing.
        • ATR - Renegotiate, and resume connection.
        • ATE - 0 will turn command echo off (desirable in a script), 1 will enable command echo (better in a terminal program)
        • ATV - 0 will turn off verbose result codes (numbers as responses), 1 will enable (text strings as a responses). ATV0 is common for scripts, ATV1 for terminal programs.
        • ATX - Extended result codes. There are a handful of different values, but ATX4 is most commonly used.
        • ATZ - Reset the modem (handy after you've dorked all the settings up.
        • A/ - Repeat last command. Handy when dialing and the number is busy.
        Any character sent to the modem while it is dialing or negotiating will result in the connection being dropped and the modem going on-hook. Commands can be terminated by a CR, or LF, but not both.

        I'm doing this from memory. I have the complete specs at home (somewhere) from when I worked at Hayes. If you need more details, feel free to contact me at the e-mail address below.

        --Chris

        e-mail jcwren
      IMHO, Device::SerialPort is something that could stand to be rewritten from scratch.

      If you read the docs in the modules you'll see that the unix module is actually a port of the Win32 module (personally I'd feel better if it was the other way around). There are many functions that don't quite work right in Unix but are functional in the Win32 environment.

      I actually had to write a wrapper for Device::SerialPort to make it somewhat more usable (i was doing automated installation/configuration through a serial cable), and would be glad to post it up, although I'm not sure it would help you with dialing stuff...

      BlueLines

      Disclaimer: This post may contain inaccurate information, be habit forming, cause atomic warfare between peaceful countries, speed up male pattern baldness, interfere with your cable reception, exile you from certain third world countries, ruin your marriage, and generally spoil your day. No batteries included, no strings attached, your mileage may vary.
        Yes the man sucks.

        I have been trying to dial a phone number for almost 3 hours now and have got nowhere. I know my modem works because I can dial using minicom. But getting this dang Device::SerialPort to actually do something is yet to be seen. Hey I might as well post the code in case someone else can spot the obvious.
        #!/usr/bin/perl
        use Device::SerialPort qw( :PARAM :STAT 0.07 );

        $PortName = '/dev/ttyS1';
        $Configuration_File_Name = 'phone.conf';

        $PortObj = new Device::SerialPort ($PortName) || die "Can't open $PortName: $!\n";
        $PortObj->user_msg(ON);
        $PortObj->databits(8);
        $PortObj->baudrate(9600);
        $PortObj->parity("none");
        $PortObj->stopbits(1);
        $PortObj->handshake("rts");
        $PortObj->write_settings || undef $PortObj;
        $PortObj->save($Configuration_File_Name);


        $PortObj->write("ATDT5010005");
        $PortObj->close || die "failed to close";
        undef $PortObj; # frees memory back to perl

        print "help\n";

        __END__
        I've actually been using Device::Modem to do my dialing (which in turn imports Device::SerialPort). However, once I make a connection to the other end it doesn't recognise the 'CONNECT' and waits for the timeout before returning control. I don't know if that helps. Using Device::Modem to dial and check modem was really simple. Just having other issues communicating through the modem to the other side. If anyone wants to offer up any expertise that'd be great. I'll post if I have anything.