From telecom@eecs.nwu.edu Tue Aug 20 23:17:45 1991 Received: from delta.eecs.nwu.edu by gaak.LCS.MIT.EDU via TCP with SMTP id AA21147; Tue, 20 Aug 91 23:17:39 EDT Resent-Message-Id: <9108210317.AA21147@gaak.LCS.MIT.EDU> Received: from NRI.RESTON.VA.US by delta.eecs.nwu.edu id aa09803; 20 Aug 91 16:08 CDT Received: from mcimail.com by NRI.NRI.Reston.VA.US id bo17715; 20 Aug 91 16:49 EDT Date: Tue, 20 Aug 91 20:40 GMT From: "J. Brad Hicks" <0004073044@mcimail.com> To: Pat Townson Subject: IXO.example Message-Id: <23910820204032/0004073044NC5EM@mcimail.com> Resent-Date: Tue, 20 Aug 91 22:21:01 CDT Resent-From: telecom@eecs.nwu.edu Resent-To: ptownson@gaak.LCS.MIT.EDU Status: RO IXO PROTOCOL EXAMPLE Author: J. Brad Hicks Language: HyperTalk Rev. Date: 20 Aug 91 The following two HyperTalk functions implement the IXO/TAP protocol sufficiently to handle numeric paging. To use these scripts in HyperCard or SyperCard, place them in the stack/project script, then call them using: DialPager param1,param2,param3 where param1 is the modem phone number of the local paging company, param2 is the phone number for the pager you want to beep, and param3 is the message to appear on the pager. For debugging purposes, everything sent back from the modem is stored in global variable SaveBuffer. CONSTRAINTS: In the above example, param2 MUST be an eight-digit number with no punctuation, zero-padded on the left ... or so I was told by the tech support gurus at CyberTel Paging. If you are paging a numeric pager, param3 must be 1 to 12 bytes, and can contain any digit, a dash, or a space. The gurus at CyberTel told me that it can contain asterisks and pound signs, but they don't work on my pager. If you are paging an alphabetic pager, then param3 can contain any printable ASCII characters (32 to 126 decimal) and can be up to 120 bytes long. REQUIREMENTS: You will also need four of the HyperCard XCMDs/XFCNs for serial port control: configureSPort, recvUpTo, sendSPort, and closeSPort. These commands are all availabe via the "HyperCard Serial ToolKit" from APDA. For those of you who are translating this into other languages, those all do what you'd expect except for recvUpTo, which takes three parameters. Param1 is the byte to stop at; if "", then it runs until it times out. Param2 is the maximum wait time, in 60ths of a second. Param3 is optional, and if it's anything but empty then it gets inserted before the serial port data. IMPLEMENTATION LIMITS: The IXO/TAP protocol supports sending multiple messages and multiple phone numbers in a single transaction. Since I didn't need it for my purposes, I didn't implement them. If you feel brave (and have the cooperation of your local paging company), you can send a theoretically infinite number of pager id/message packets in a single phone call by ending every packet except the last one with instead of . NOTE TO HYPERCARD/SUPERCARD USERS: Since this version of this file was put together to be distributed over non-Macintosh systems, the line- continuation character (option-return) has been stripped off of the longer lines. I'm giving you credit for figuring out where it belongs; the continuation lines are indented (as per SuperCard format). NOTE TO SUPERCARD USERS: SuperCard predefines a constant CR that means the same thing as when I use it, so delete it from the global variable lists and delete the line where I initialize it at the top of DialPager. CREDITS: Thanks to Brent Chapman of Telebit for providing me with a copy of the IXO/TAP protocol spec. The spec itself is excerpted from Glenayre Electronics' manual number GLP-3000-180, issue 5 (30 Jan 91), chapter 7, pages 7-1 to 7-13, and may be available from them at 1-604-263-1611. The HyperCard Serial Toolkit is provided by Apple, and available through the Apple Programmers and Developers Assocation (APDA). All other code was written by Brad Hicks at MasterCard International. CONTACTING THE AUTHOR: J. Brad Hicks can be most reliably contacted via MCI Mail at JBHICKS or Internet to the same address, jbhicks@mcimail.com. CompuServe users can also send mail to 76012,300. AppleLink subscribers can send mail to B0186. Via US mail, send to 12364 Spanish Trace Dr., Apt. G, Maryland Heights, MO 63043-2354, USA. Absolute last-ditch efforts only may be made to 1-314-275-3645, roughly 8:30 am to 5:30 pm Central Time (UCT+6). DISCLAIMER: This script is provided as-is and for free, and warranted to be worth at least that much. Although I developed it while at MasterCard, neither MasterCard International nor its membership endorses this product. The author denies responsibility for any consequences, positive or negative, arising out of anybody's use of this code, or any work derived from this code. Test thoroughly. Protect yourself. _______________________________________________________________________ on DialPager PhoneNumber,PagerID,theMessage global SPortGlobals global SaveBuffer global STX,ETX,EOT,ACK,CR,NAK,ESC,RS -- load constants put numToChar(02) into STX put numToChar(03) into ETX put numToChar(04) into EOT put numToChar(06) into ACK put numToChar(13) into CR put numToChar(21) into NAK put numToChar(27) into ESC put numToChar(30) into RS -- initialize variables put empty into SaveBuffer put MsgPacket(PagerID,theMessage) into theMsgPacket put 1 into OverAllAttempts put false into OverAllSuccess -- initialize port, modem configureSPort "modemPort","baud300","stop10","parityEven","data7", "XOnOutOff","CTSOutOff","lineFeedsOff","echoOff","editOff", "stripOn","stripControlsOff","autoWrapOff" sendSPort "ATZ" & CR get recvUpTo(empty,60,empty) -- and throw it away repeat until OverAllSuccess or (OverAllAttempts > 5) put "Attempt #" & OverAllAttempts && "Status: " into the message -- hang up, dial modem put false into DialSuccess put false into DialFailure put "Dialing" after the message sendSPort "+++" wait 1 second sendSPort "ATH" & CR get recvUpTo(empty,120,empty) put it after SaveBuffer sendSPort "ATM0DT" & PhoneNumber & CR put the seconds + 30 into TimeOut repeat until DialSuccess or DialFailure get recvUpTo(CR,1800,empty) put it after SaveBuffer if it contains "CONNECT" then put true into DialSuccess else if it contains "NO CARRIER" then put true into DialFailure put "No Carrier" into FailureReason else if it contains "ERROR" then put true into DialFailure put "Unknown Error" into FailureReason else if it contains "NO DIALTONE" then put true into DialFailure put "No Dialtone!" into FailureReason else if it contains "BUSY" then put true into DialFailure put "Busy" into FailureReason else if it contains "NO ANSWER" then put true into DialFailure put "No Answer" into DialFailure else if it contains "VOICE" then put true into DialFailure put "Wrong Number! (Voice Answered)" into last word of the message exit to HyperCard else if the seconds >= TimeOut then put true into DialFailure put "Timed Out" into FailureReason end if end repeat if DialFailure then put FailureReason into last word of the message else put "DialSuccess, Waiting" into last word of the message -- whack CR, wait for "ID=" put the seconds + 10 into TimeOut put true into IDSuccess put false into IDFailure put empty into TempBuffer repeat until IDSuccess or IDFailure sendSPort CR put recvUpTo(empty,90,TempBuffer) into TempBuffer if TempBuffer contains "ID=" then put true into IDSuccess else if the seconds >= timeOut then put true into IDFailure end repeat put TempBuffer after SaveBuffer if IDSuccess then put false into LoginACKed put false into HangUp put 1 into LoginAttempts repeat until LoginACKed or HangUp or (LoginAttempts > 5) -- indicate paging, wait for ACK/NAK put "LogOn" into last word of the message sendSPort ESC & "PG1" & CR put the seconds + 10 into TimeOut put false into LoginACKed put false into LoginNAKed put false into TimeOutExceeded put false into HangUp put empty into TempBuffer repeat until LoginACKed or LoginNAKed or TimeOutExceeded or HangUp put recvUpTo(empty,90,TempBuffer) into TempBuffer if TempBuffer contains (CR & ACK & CR) then put true into LoginACKed else if TempBuffer contains (CR & NAK & CR) then put true into LoginNAKed else if TempBuffer contains (CR & ESC & EOT & CR) then put true into HangUp else if the seconds >= timeOut then put true into TimeOutExceeded end if end repeat put TempBuffer after SaveBuffer add 1 to LoginAttempts end repeat if LoginACKed then put false into MsgACKed put false into HangUp put 1 into SendAttempts put "LoggedIn, Sending" into last word of the message repeat until MsgACKed or HangUp or (SendAttempts > 5) -- send message, wait for ACK/NAK sendSPort theMsgPacket put the seconds + 10 into TimeOut put false into MsgACKed put false into MsgNAKed put false into MsgInvalid put false into TimeOutExceeded put false into HangUp put empty into TempBuffer repeat until MsgACKed or MsgNAKed or TimeOutExceeded or HangUp put recvUpTo(empty,90,TempBuffer) into TempBuffer if TempBuffer contains (CR & ACK & CR) then put true into MsgACKed else if TempBuffer contains (CR & NAK & CR) then put true into MsgNAKed else if TempBuffer contains (CR & RS & CR) then put true into MsgInvalid else if TempBuffer contains (CR & ESC & EOT & CR) then put true into HangUp else if the seconds >= timeOut then put true into TimeOutExceeded end if end repeat if MsgACKed then put true into OverAllSuccess put ", Success!" after the message else put ", Failure" after the message end if put TempBuffer after SaveBuffer add 1 to SendAttempts end repeat else if HangUp then put "CyberTelHungUp!" into last word of the message else put "LoginFailed!" into last word of the message end if end if end if -- hang up sendSPort EOT & CR put the seconds + 10 into TimeOut put false into EOTrcvd put false into TimeOutExceeded put empty into TempBuffer repeat until EOTrcvd or TimeOutExceeded put recvUpTo(empty,90,TempBuffer) into TempBuffer if TempBuffer contains (ESC & EOT & CR) then put true into EOTrcvd else if the seconds >= timeOut then put true into TimeOutExceeded end repeat put TempBuffer after SaveBuffer sendSPort "+++" wait 1 second sendSPort "ATH" & CR get recvUpTo(empty,60,empty) put it after SaveBuffer add 1 to OverAllAttempts end repeat closeSPort put empty into the message end DialPager function MsgPacket PagerID,theMessage global STX,ETX,EOT,ACK,CR,NAK,ESC,RS -- strip illegal characters from PagerID repeat with i = the length of PagerID down to 1 get char i of PagerID if not (it is in "0123456789") then delete char i of PagerID end repeat -- left-pad to 8 digits -- recommended by CyberTel, not in IXO spec get 8 - the length of PagerID repeat with i = 1 to it put "0" before PagerID end repeat -- clean, trim theMessage -- NOTE: edit code below assumes numeric pager; -- alpha pagers accept all printable ASCII, -- up to 120 bytes per message. repeat with i = the length of theMessage down to 1 get char i of theMessage if not (it is in "0123456789*#- ") then delete char i of theMessage end repeat get char 1 to 12 of theMessage put it into theMessage -- assemble message packet put STX & PagerID & CR & theMessage & CR & ETX into TempPacket -- calculate checkSum put 0 into checkSum repeat with i = 1 to the length of TempPacket add charToNum(char i of TempPacket) to checkSum end repeat put numToChar((checkSum div 256) mod 16 + 48) into checkSumString put numToChar((checkSum div 16) mod 16 + 48) after checkSumString put numToChar(checkSum mod 16 + 48) after checkSumString -- append checksum to packet put checkSumString & CR after TempPacket return TempPacket end MsgPacket