Announcement

Collapse
No announcement yet.

phone dialing

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • phone dialing

    I know that a phone dialing program is very simple to all of you
    programmers that are writing complex communication programs, but
    I have been fighting this problem off and on for a couple of months
    now. The problem is being able to tell what kind of response there
    is from the dialing... whether the phone number that I'm calling
    is busy, or is ringing. The executable program below shows the
    coding I am currently using, but I know that it could be improved.

    It basically depends on a 10 sec delay without getting the "no dialtone"
    message to designate the time to pick up the phone and break the
    modem connection. If I disconnect the modem from the line, I do get
    a "no dialtone" message. It would be nice if there was a positive way of
    sensing that the phone was ringing, because that is the time to pick up
    the phone and break the modem connection.

    Any suggestions would be greatly appreciated.

    Code:
    'Phone dialing example
    
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "win32api.inc"
    GLOBAL hWin AS LONG
    %MyCommPort = 4
    $defPhoneNo = "892-4706"
    
    SUB endComm(hComm AS LONG)
       LOCAL s AS STRING
       COMM PRINT #hComm, "ATZH"
       IF COMM(#hComm, RXQUE) THEN
          COMM RECV #hComm, COMM(#hComm, RXQUE), s
       END IF
       COMM RESET #hComm, FLOW
       COMM CLOSE #hComm
    END SUB
    
    CALLBACK FUNCTION winProc
       LOCAL commPort AS STRING, fromModem AS STRING
       LOCAL dialNo AS STRING, statusMsg AS STRING
       LOCAL hComm AS LONG, n AS LONG, connected AS INTEGER
       LOCAL start AS SINGLE, s AS STRING
       SELECT CASE CBMSG
       CASE %WM_COMMAND
          IF CBCTL = 102 THEN 'quit program
             DIALOG END hWin
          ELSEIF CBCTL = 101 THEN 'dial phone
             CONTROL GET TEXT hWin, 100 TO dialNo
             IF LEN(dialNo) < 8 THEN
                 CONTROL SET FOCUS hWin, 100
                 EXIT FUNCTION
             END IF
             hComm = FREEFILE
             commPort = "COM" + TRIM$(STR$(%MyCommPort))
             COMM OPEN commPort AS #hComm
             COMM SET #hComm, BAUD = 9600
             COMM SET #hComm, BYTE = 8
             COMM SET #hComm, PARITY = %FALSE
             COMM SET #hComm, STOP = 0
             COMM SET #hComm, RXBUFFER = 1024
             COMM SET #hComm, TXBUFFER = 1024
             'check modem connection --------------------------------------------
             s = ""
             COMM SEND #hComm, "ATZ" + $CRLF
             start = TIMER
             DO
                n = COMM(#hComm, RXQUE)
                COMM RECV #hComm, n, fromModem
                s = s + LCASE$(fromModem)
                IF INSTR(s, "ok") > 0 THEN EXIT DO
                IF TIMER - start > 5 THEN
                   s = "Modem not responding on commPort" + STR$(%myCommPort)
                   MSGBOX s, %MB_ICONWARNING, "Modem Connection"
                   endComm(hComm): EXIT FUNCTION
                END IF
             LOOP
             'check for dial tone and dial phone --------------------------------
             COMM SEND #hComm, "ATDT" + dialNo + $CRLF
             s = "Dialing " + dialNo
             CONTROL SET TEXT hWin, 103, s
             s = ""
             start = TIMER
             DO
                n = COMM(#hComm, RXQUE)
                COMM RECV #hComm, n, fromModem
                s = s + LCASE$(fromModem)
                IF INSTR(s, "no dialtone") THEN
                   statusMsg = "No dial tone": connected = -1
                ELSEIF TIMER - start > 10 THEN
                   statusMsg = "Connected..": connected = 1
                END IF
                IF connected THEN EXIT DO
             LOOP
             CONTROL SET TEXT hWin, 103, statusMsg
             IF connected > 0 THEN
                BEEP: s = "Connected ... Pick up the phone and click Ok"
                MSGBOX s, %MB_ICONINFORMATION, "Dialing " + dialNo
             END IF
             'hang up modem -----------------------------------------------------
             endComm(hComm)
          END IF
       END SELECT
    END FUNCTION
    
    FUNCTION PBMAIN()AS LONG
       LOCAL title AS STRING, style AS LONG
       title = "Phone Dialing Example"
       style=%WS_SYSMENU + %WS_MINIMIZEBOX
       DIALOG NEW 0,title,,,190,120,style TO hWin
       CONTROL ADD LABEL, hWin, -1, "Phone number to dial: ", 10, 20, 70, 12
       CONTROL ADD TEXTBOX, hWin, 100, $defPhoneNo, 85, 20, 70, 12
       CONTROL ADD BUTTON, hWin, 101, "&Dial", 30, 50, 50, 25
       CONTROL ADD BUTTON, hWin, 102, "&Quit", 100, 50, 50, 25
       CONTROL ADD LABEL, hWin, -1, "Status: ", 10, 90, 30, 10
       CONTROL ADD LABEL, hWin, 103, "", 40, 90, 100, 10
       DIALOG SHOW MODAL hWin& CALL winProc
    END FUNCTION

  • #2
    Your code:
    Code:
    ...
    COMM SEND #hComm, "ATDT" + dialNo + $CRLF
    ...
    Puts the modem into "data mode" so when the other end is answered the modem will be expecting to try to connect - if a modem does answer then your phone-dialer just became a terminal application! Obviously this may not be what you want to have happen.

    The best method for a "dialer" app is to add a semi-colon to the end of the dialing string, ie, "ATDT555-4321;". This semi-colon tells Hayes-compatible modems (most of 'em, anyway!) to remain in "command mode", and not to try to actually connect to a remote modem.

    Beyond that, there is nothing else you app can do except wait for the modem's timeout to occur - NO ANSWER or ERROR, or whatever your modem is capable of. These types of settings are usually determined by the modem's "S-registers" whoch ate programmed via "AT" commands. Some modems are very programmable others are not.

    For example, my (DOS-based) PBFax software waits for one of the following responses from the modem, or 1 minutes elapses - which ever comes first:
    Code:
    loop until instr(Response$, "OK")   or _
        instr Response$, "CONNECT")     or _
        instr(Response$, "RING")        or _
        instr(Response$, "NO CARRIER")  or _
        instr(Response$, "ERROR")       or _
        instr(Response$, "NO DIALTONE") or _
        instr(Response$, "BUSY")        or _
        instr(Response$, "NO ANSWER")   or _
        timer - t& > TimeOut&
    Of course, my fax program is entering data-mode, so the normal modem response is "CONNECT", but this should give you the idea. Also, this is from a DOS app, but luckily modem control itself is largely compiler independent is long as your modem is set to use verbose response messages.

    I've had no reports of any problems with the above strategy and PBFax has been downloaded several thousand times and is in use all over the world.

    I hope this helps.

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      If you only need to dial why not use build in window Tapi

      DECLARE FUNCTION tapiRequestMakeCall LIB "TAPI32.DLL" ALIAS "tapiRequestMakeCall" (BYVAL DestAddress$, BYVAL AppName$, BYVAL CalledParty$, BYVAL Comment$) AS LONG



      ------------------

      Comment


      • #4
        Gafny, Thanks for your suggestion. I wasn't aware of that API.
        I only found it with my MS Visual C++ compiler... nothing in the
        PB API's found in the supplied INC files. I tried it and am
        still debating whether to use it.

        Lance, Thanks for your help too. Sensing a 'RING' from the phone
        being dialed would do perfectly, but my modem doesn't seem to be
        able to sense that response. It can, however, sense 'BUSY' and
        'NO DIALTONE'. I wasn't sure what you meant about adding the ';'
        after the phone number. Without the $CRLF, the modem does not dial
        at all.


        ------------------

        Comment


        • #5
          > I wasn't sure what you meant about adding the ';'
          > after the phone number. Without the $CRLF, the
          > modem does not dial at all.

          Like this...

          Code:
          COMM SEND #hComm, "ATDT" + dialNo + ";" + $CR
          (I'd recommend using $CR instead of $CRLF.)

          The semicolon tells the modem "dial this number and then, instead of trying to establish a connection to another modem, return to the command state and wait for more AT commands." One warning... Most modems will respond properly to the semicolon, but a very small number will lock up after a semicolon has been used.

          -- Eric


          ------------------
          Perfect Sync: Perfect Sync Development Tools
          Email: mailto:[email protected][email protected]</A>

          "Not my circus, not my monkeys."

          Comment


          • #6
            Also, in my experience, RING is never reported when the modem dials the phone and is "listening" for a busy signal or a modem connect-tone. RING is only reported when the modem is on-hook, usually waiting for an incoming call.

            (To explain the terminology, when a modem "picks up the line" it is said to be "off hook". When a modem hangs up the phone line, it is said to be "on hook". These are very old terms that refer to the process of physically placing a telephone handset on a hook in order to hang up after a call.)

            -- Eric

            ------------------
            Perfect Sync: Perfect Sync Development Tools
            Email: mailto:[email protected][email protected]</A>



            [This message has been edited by Eric Pearson (edited March 14, 2000).]
            "Not my circus, not my monkeys."

            Comment


            • #7
              Thanks Eric,

              My problem is that the correct time to hang up the modem depends on time.
              If the user is allowed to hang up the modem before the dialing is completed,
              the call is stopped. The only way that the user has of knowing if the modem
              is still dialing is the audible noise from the modem. But if the user has
              muted the modem sound in control panel, then the user has no idea when the
              modem is finished dialing.

              Timing is a poor solution because the length of time for the modem to dial
              the number depends on the length of the number, and with area code and a
              dialing prefix (say 1010297), that time can change significantly.

              What is needed is some kind of response from the modem that it has quit
              dialing. I'm grateful for your knowledge that I can't depend on 'RING'.
              That will save me a lot of trial and error. Can you think of anything
              else that might help? If not, I'll just have to go with what I have.

              Thanks again.

              ------------------

              Comment


              • #8
                > Timing is a poor solution because...

                You can use the S11= switch to control how fast the modem dials. After the equal sign, put the number of milliseconds for each digit, for example S11=100 would produce a delay of 1/10 of a second per digit. There's a little more to it than that... there's an initial delay, and a slight pause between the digits... but what I'm getting at is that you can reliably multiply the number of digits in the phone number (from the LEN function) times the S11 setting, fudge the number a little bit, and get the time that it will take the modem to dial any given number. Like this...

                Code:
                AT S11=100 DT 5551212
                The modem will generally time-out after a couple of seconds if there is no dial tone, and it will generally detect a busy signal within two tone-cycles (buzz...buzz...), but remember that busy signals do not always start right away, especially on long-distance calls.

                One other little "gotcha"... Many modems are not good at telling the difference between a busy signal and other sounds. For example, most modems will return "busy" when they hear a recording say "The number you have dialed... (is not in service, or has been changed, etc.)"

                > What is needed is some kind of response from
                > the modem that it has quit dialing.

                When I send ATDT5551212; my modem responds OK right after it finishes dialing the last digit. Doesn't yours?

                If you can describe in detail what you need to do, maybe I can suggest something else. Is this just a "convenience" dialer where you select a number and the program dials it for you? Or are you trying to call a numeric pager, or some other kind of tone-driven service, or...?

                -- Eric

                ------------------
                Perfect Sync: Perfect Sync Development Tools
                Email: mailto:[email protected][email protected]</A>

                "Not my circus, not my monkeys."

                Comment


                • #9
                  Eric,

                  You fixed it. I wasn't getting the 'OK' until I added the ';' per your
                  instructions. My project is just a simple dialing convenience, not needing
                  to connect to another modem or anything complicated. All of my efforts
                  without the semicolen were generating the 'BUSY' and 'NO DIALTONE' responses,
                  but not the 'OK', which I was checking for in my actual application code
                  (not the sample included above).

                  I can't thank you enough, Eric. This forum sure is helpful.


                  ------------------

                  Comment


                  • #10
                    You're welcome, but giving credit where credit is due... Lance suggested using the semicolon.

                    Glad it's working for you now.

                    -- Eric

                    ------------------
                    Perfect Sync: Perfect Sync Development Tools
                    Email: mailto:[email protected][email protected]</A>

                    "Not my circus, not my monkeys."

                    Comment


                    • #11
                      To clarify one point about the "RING" response...

                      In normal circumstances you wont get a RING response when originating calls... or so I thought until I put PBFAX into a real-life production environment... I found that sometimes someone rang in at the moment PBFax opened the modem port... by the time PBFax issued commands to the modem to pick up the line and then listened for modem responses, PBFax found a "RING" response in the input buffer ahead of the expected "OK" response !!!

                      Out of interest, I found ATS11=55 to be the best S11 value, at least for dialing in New Zealand. I have come across one modem that would ignore S11 values less than 100ms (or thereabouts).

                      Finally, one last comment about modem that dial internationally are very likely to encounter tone responses that the modem does not recognize, and applications that are likely to be run on a laptop may encounter different dial-tone sounds that result in a "No Dialtone" response - the X register (?) is a useful option to overcome this problem and all good dialing apps should provide an "advanced options" setup to allow for custom init strings or check-box options to adjust modem behavior.

                      These are some of the hard lessons I learnt the hard way. I guess my point is that you must always expect the unexpected! I've never seen anything that documents most of my "unusual" experiences but ended up learning about it the hard way! I used to get phone calls at 4am from a guy in Greece who helped me identify some of these situations!

                      ------------------
                      Lance
                      PowerBASIC Support
                      mailto:[email protected][email protected]</A>
                      Lance
                      mailto:[email protected]

                      Comment


                      • #12
                        > I found that sometimes someone rang in at the
                        > moment PBFax opened the modem port..

                        That might not have been as big a coincidence as you think... I've run across at least one modem that "saved" its responses until my program opened the port. For example, my program has the option of resetting the modem (with ATZ or AT&F) whenever the program is closed, and when the program was re-started and began to make its first call, the "OK" from the previous reset would always mysteriously appear. It took me a long time to figure that one out! So the phone could have rung several hours before your fax program opened the port. (Now my program always checks for an incoming string before it sends its first AT command. Live and learn.)

                        Don't you just love working with modems!

                        > I found ATS11=55 to be the best S11 value

                        Me too, as long as the modem is connected directly to the phone line. But some of my customers own phone systems that don't like it when you dial that fast, and digits get dropped. I found that out -- the hard way -- when my program (at a customer site) called 911 once an hour, on the hour, over a 3-day weekend. The customer was not amused, nor were the police. And if you're using the modem to send messages to a numeric pager, many (most?) pager companies require slower dialing when you enter the number that will be displayed on the beeper. (Don't get me started about calling pagers...)

                        Another amusing story, if I may digress for a moment... When I was in the early stages of writing my primary comm program, I set it up to perform some automated "stress" testing over a weekend. Auto-dialing out to several different modems several times per hour, things like that, so I could check the reliability. When I came in on Monday morning I heard the modem dialing and was relieved that the program was still running smoothly... until I heard an angry voice from the modem speaker. "Who the &$%#& is this? What the $%#@ do you want?" From then on I was much more careful when typing in modem phone numbers...

                        > all good dialing apps should provide an "advanced
                        > options" setup to allow for custom init strings or
                        > check-box options to adjust modem behavior.

                        I agree 100%! And I'd strongly recommend using "two stage dialing", i.e. have your program send the modem init string and wait for an "OK", then send the ATDT dialing string.

                        > I've never seen anything that documents most of my
                        > "unusual" experiences

                        Nor have I. Maybe this thread will become a list of hard-learned lessons that other people can benefit from.

                        -- Eric


                        ------------------
                        Perfect Sync: Perfect Sync Development Tools
                        Email: mailto:[email protected][email protected]</A>

                        "Not my circus, not my monkeys."

                        Comment


                        • #13
                          If you're using a reasonably recent modem (not, say, a 2400-bps model), you may wish to look into the X command, particularly if you're dialing within the U.S.A. The X command enables a given level of modem result codes. With ATX5, for example, the modem will be more clever about detecting (and returning information about) whether the line is busy, whether a voice is detected, and so forth. However, the modem can get confused by the great variety of different phone "ringing" tones, et al, employed internationally-- so it may be best to stay with lower X levels in such situations.

                          ------------------

                          Comment

                          Working...
                          X