Using
your AS/400 for Alphanumeric Paging
Introduction
I was recently
assigned a tasked from my client to modify their
existing paging system. All page entries are done on
the AS/400, but the pages are directly routed to an
integrated PC. The PC software communicates directly
with the paging company limiting the
functionality on the AS/400. Occasionally, paging
will be down and the PC group blames the AS/400 for
the backlog.
In order to minimize
the finger pointing between the PC group and the
AS/400 Tech group, we decided to have all the pages
sent out directly from the AS/400. This reduces the
transmission time downloading pages to the PC, and at
the same time, the AS/400 Tech group knows exactly
where the backlog occurs.
There are several
AS/400 companies that sell software and hardware for
automated paging system. The software monitors the
system messages and channels the messages to
alphanumeric pagers.
The method of sending
alphanumeric pages was early introduced using the
Motorola Page Entry (PET). It uses the IXO
alphanumeric entry protocol until it was adopted by
Telocator (now known as Personal Communications
Industry Association PCIA. You may visit their
web site at www.pcia.com.) in September of 1988 as an
industry standard protocol for sending alphanumeric
pages. It is now referred to as Telocator
Alphanumeric Protocol (TAP).
PCIA and the Paging
Services Council report that the average rate of
successful completion for attempts to reach some one
by telephone is less than 20 percent. However, when a
person carries a pager, the success rate jumps to 90
percent!
TAP Operating System
TAP protocol will be
ASCII, using XON, XOFF in either direction. It is
configured using the 10 bit code (1 start, 7 data,
even parity, and 1 stop). The 10 bit code must be
configured properly with our line description in
order for TAP to work.
Paging companies like
MCI and PAGENET are equipped to receive 1200 baud
rate. SKYTEL is equipped to receive up to 2400 baud.
They can also receive full duplex data. No echo must
be employed in full duplex mode.
The example I will
used later attempts to connect at an automatic baud
rate determination. Any of the aforementioned
companies can handle automatic determination.
Sequence of Call
Delivery between AS/400 and Paging company
The first column shows
the steps followed by the AS/400, the second column
describes the transmission received from the Paging
company. These steps are based on the standard TAP
protocol. The AS/400 must conform to this standard
for the alphanumeric pages to work.
Note: All
quotation marks and the symbol <> are used
for notation only. The characters between the
symbols <> are control codes. The control
codes transmitted from the AS/400 will be EBCDIC;
the operating system translate the codes to
EBCDIC prior to sending to the modem. The paging
company I tested these steps with are SKYTEL and
MCI. Both company responded similarly. (MCI
sub-contracts SKYTEL to doing their paging
system.)
|
AS/400 Does |
Paging Company Does |
Comments |
1 |
Dial up the paging service.
Use the ATDT modem command to start the modem. The modem returns
one of the following"
CONNECT
NO
CARRIER
OK
|
|
|
2 |
|
Connection established |
|
3 |
<CR> |
|
The carriage return
<CR> is repeated at 2 seconds intervals
until the paging company responds with ID= at the
correct baud rate or until 3 transmissions have
been completed. |
4 |
|
ID= |
Request for ID returned
within 1 second of the receipt of <CR>. The
paging service may, at its option, send
<CR> or <CR> followed by line feed
<LF> after the ID=. The paging company waits up
to 8 seconds for response to "ID=". The
paging company may resend "ID=" up to 3
times if a proper response is not received.
|
5 |
<ESC>PG1<CR> or for password
entry
<ESC>PG1pppppp<CR>
|
|
<ESC> signifies that
the AS/400 wants to communicate with the paging
company in automatic baud mode. The next 2
characters "PG" signifies the type of
service to be accessed. P stands for the pager id
and G for the message text. Contact your pager
service provider if pager id is not used with the
message text.
The next
character represents the type of terminal or
device attempting to send the pages:
1
is a category using the same protocol. The PETs
and IXO devices are members of this category.
7, 8
or 9 are reserved for wild card terminals
or devices which relate to specific users
system
The
6-character pppppp stands for alphanumeric
password. Password is optional. Contact your
pager service provider is password is necessary.
When an
incorrect logon sequence beginning with
<ESC> is received, the paging company sends
"ID=" back to the AS/400 for
re-transmission.
|
6 |
|
<CR><ACK><CR>
or
|
ID Acknowledged --Logon
accepted or
|
|
|
<CR><NAK><CR> or
|
No acknowledgement -- re-send
again or
|
|
|
<CR><ESC><EOT> |
Forced disconnect |
7 |
|
<ESC>[p<CR> |
Message go ahead is sent when
the paging company is ready to receive the first
transaction. The p is in
lowercase.
This
response is sent within 10 seconds after step 6.
|
8 |
<STX> Pin<CR>Message<CR>
<ETX>Checksum<CR>
|
|
A transaction must be sent by
the AS/400 within 4 seconds of a response from
the paging company. The message block is up to
256 characters. Up to 250 characters of info,
plus 3 character checksum and 3 character control
codes. A block is 1 transaction. A block may be
less than 256 characters to accommodate short
transaction. Trailing spaces must be eliminated
from the messages in order to conserve over-the-air
transmission time when the page is
transmitted.
A block
always begin with "Start of Text"
<STX> control code and ends with a checksum
followed by <CR>. The Pin number and the
page messages must be delimited by <CR>.
The <CR> delimeter may not be used within
your page messages.
The
<ETX> is used as a block terminator in a
given transaction.
Some paging
company may be limited to 1 block per transaction
and 1 transaction per phone connection.
Valid Pin
numbers are determined by the paging
service. Most pin numbers are 7 digit long.
PAGENET will use 10 digit in the near future.
There is no restriction placed on the Pin number
by the TAP protocol. It may be any length and
contain any character that is valid in the
protocol character set.
|
9 |
|
<CR><ACK><CR> or
|
Message acknowledged
send next block |
|
|
<CR><NAK><CR> or
|
Checksum or transmission
error, send the last block again |
|
|
<CR><RS><CR> or
|
Abandon this transaction and
go to the next. <RS> means that the current
transmission violates the TAP protocol.
<RS> typically follows an attempt to page
an invalid pin number. |
|
|
<CR><ESC><EOT> |
The paging company is
abandoning the current call. When this occur, the
AS/400 must re-connect back to the paging company
and send the last block of messages.
|
10 |
<EOT><CR> |
|
After reception of an
<ACK> or <RS> for the last
transaction, the AS/400 must send
<EOT><CR> to end the paging
transmission. |
11 |
|
<Message><CR> |
This is an optional message
sent back to indicate the degree of acceptability
of the transaction received. Please review the
response code from the paging company (see table
below).
|
12 |
|
<ESC><EOT><CR> |
Paging company is
disconnecting. The carrier will be dropped. |
Response Code
The definitions in
the following table, describe the meaning of the
numeric response code. The response codes may
optionally be followed by a text string or
strings which may vary between paging terminals.
Certain text strings are required to follow a
specific format as described in this section.
Response Code
|
Definition |
110
|
Paging
Company TAP Specification Supported see
Note below |
111
|
Paging
terminal is processing the previous input --
please wait |
112
|
Maximum
pages entered for session |
113
|
Maximum
time reached for session |
114
|
Welcome
banners |
115
|
Exit
Messages (Service related messages sent before
the Pager Service Provider terminates) |
211
|
Page(s)
Sent Successfully |
212
|
Long
message truncated and sent |
213
|
Message
accepted - held for deferred delivery |
214
|
###
character maximum, message has been truncated and
sent. |
501
|
A
"time-out" occurred waiting for user
input |
502
|
Unexpected
characters received before the start of a
transaction. A character sequence other then
<STX> or <EOT><CR> was received
while the paging company was waiting to receive a
transaction block from the AS/400. |
503
|
Excessive
attempts to send/re-send a transaction with
checksum errors. |
504
|
The
message field of the TAP transaction contained
characters, but message characters are not
allowed for the Pager format. Perhaps the paging
receiver (your pager) for the given PIN is a
`Tone Only' pager. |
505
|
Message
portion of the TAP transaction contained
alphabetic characters, but alphabetic characters
are not allowed for the Pager format. Perhaps the
paging receiver for the given PIN is a `numeric'
pager. |
506
|
Excessive
invalid pages received |
507
|
Invalid
Logon attempt: Incorrectly formed logon sequence |
508
|
Invalid
Logon attempt: Service type and category given is
not supported |
509
|
Invalid
Logon attempt: Invalid password supplied |
510
|
Illegal
Pin Number - The pin number contains illegal
characters or is too long or short |
511
|
Invalid
Pin Number - There is no subscriber to match this
ID |
512
|
Temporarily
cannot deliver to Pin Number - Try Later |
513
|
Long
message rejected for exceeding maximum character
length |
514
|
Checksum
error |
515
|
Message
format error |
516
|
Message
quota temporarily exceeded |
517
|
###
character maximum, message rejected |
Note: The
"special" response code 110 will always
contain the text indicating the version of the
TAP specification supported with no other message
text. The format of this message will be:
"110
M.m<CR>"
where M.m
indicates the current major and minor version
number. For Version 1.8 of the TAP specification,
the optional message sequence "110
1.8<CR>" would represent the version.
It is recommended that the paging company always
send this optional message to the Remote Device
(e.g. AS/400) as part of the messages sent at
logon. This will allow the Remote Entry software
to determine what version of the TAP protocol is
implemented by the paging companyl.
The
Personal Communications Industry Association
(PCIA) maintains the list of response code
numbers. The list of response codes is intended
to be comprehensive for all messages that paging
companiess will send.
Implementation Notes
There are numerous
systems worldwide capable of accepting alphanumeric
message using the TAP protocol. Unfortunately, many
of the service providers are not strictly adhering to
all the aspects of the protocol. The section below
are some of the anomalies which may be found in
sending TAP messages.
The carriage return
<CR> as an end-of-line marker in TAP. Some
paging company uses line feed <LF> or a
combination of <LF> and <CR>. Contact
your pager service provider for the en-of-line
control code.
Some paging company
sends "ID=" followed by the end-of-line or
line feed command. It is best for the AS/400 to scan
for "ID=".
Some EBCDIC
characters, once converted to ASCII, does not have
the same character representation when displaying on
the pager. For example, exclamation point
"!", when entered on the paging terminal
display a left bracket on the pager.
The interpretation to
non-printable ASCII control-characters sent to a
paging receiver is specific to the model of the
paging receiver in use.
There is a message
size limitation placed on input in many systems. Some
systems may only accept 80 characters, 200
characters, 1000 characters, or another message size
limit specified by the pager service provider.
Consult your pager company for this limitation.
Some pager company
place a limit on the number of messages which may be
sent on a single connection.
Although the TAP
transaction block may contain 250 characters of
information, the entire block need not be filled if
there are fewer characters to be sent to the pager.
Trailing spaces should be eliminated from messages in
order to conserve "over-the-air"
transmission time when the page request is
transmitted. Follow the computation of checksum to
compute for the number of characters transmitted.
The Pin Number which
is entered through telephone dial access to a paging
company, is normally the same number as that
specified in the Pin Number field of TAP input. In
some services, the Pin Number entered from the
telephone includes a trailing digit (normally
"#") which is known as the Check Digit. It
is utilized to detect common touch-tone keypad
keystroke errors during entry of a subscriber's Pin
Number. This Check Digit can be thought of as part of
the Pin Number, and is usually included as part of
the Pin Number field for TAP input. There are
services which require that the trailing Check Digit
be removed when specifying the Pin Number for TAP
input. PAGENET, SKYTEL & MCI does not require the
check digit.
Configurations on the
AS/400
We will be using
LIN011 resource which happens to be the default
communication line used by IBM for its Electronic
Customer Support (ECS). We will be using an
asynchronous modem. LIN011 is the default V.24 Port
Enhanced. Most of the pager service providers connect
with the remote devices using asynchronous
connection.
A line, controller and
device need to be created before the program can be
implemented. Review the following code to create the
simple configurations for the line, controller and
device. An Intersystem Communications Function (ICF)
file has to be created in order to communicate with
the modem.
Creating Asynchronous
line, controller, device and ICF file
I started out by
creating the line description using the Create
Line Description-Asynch (CRTLINASC) command.
There are several significant parameters in the
line description. The number of data bits per
character must be set to 7, type of parity must
be *EVEN, stop bits set to 1 and the duplex set
to *FULL. These 4 parameters are very important
since this is the standard for all TAP protocols.
The baud rate is dependent on the line speed of
the paging company. I set the line speed to 2400
(this was the speed specified by PAGENET and
SKYTEL). See Figure 2.
I also specified
the end-of-record table. The transmission
returned by the paging company has a carriage
return (Hex 0D) at the end. The
parameter EORTBL in the CRTLINASC command defines
the carriage return. With the end-of-record table
defined, the communications subsystem ensures
that only one transmission record is returned to
our program each time. See Figure 2.
The next step is
to create the asynchronous controller. We will
define the controller as switched (*YES) and the
initial connection as *DIAL. The asynchronous
device is created next. The attached controller
will be the name of our asynchronous controller.
The remote location name can be any name. There
is no special consideration for the remote
location attribute. This is used more for
information when problem arises and the remote
paging company is referred to as the name you
specified in the remote location. See Figure 2.
The next step is
to create the ICF file using the CRTICFF command
(See Figure 1). After the ICF file has been
created, use the Add ICF Device Entry
(ADDICFDEVE) command to permanently attach the
ICF file to a program device entry. The name of
the program device entry is the asynchronous
device we created earlier. The remote location
name is the same remote location name you
specified with the asynchronous device. The
communication type must be set to *ASYNC. See
Figure 2.
Use the following
DDS source to create the ICF file PAGEICF.
A R RCVR
A RCVCMD 5A TEXT('Received command')
A R MODEMR
A MODEMCMD 31A TEXT('Modem Command')
A R CRR
A CRCMD 1A TEXT('Carriage Return')
A R SERVICER
A SERVCMD 5A TEXT('Type of Service')
A R PAGER
A PAGECMD 120A TEXT('Page Command')
A R EOTR
A EOTCMD 2A TEXT('End of Transmission')
A R WAITR TIMER(&SECONDS)
A SECONDS 6S P TEXT('Wait in Seconds')
A R INVITE INVITE
Figure
1
pgm
/*--------------------------------------------------------*/
/* declaration */
/*--------------------------------------------------------*/
dcl &errorsw *lgl /* std err */
dcl &msgid *char 7 /* std err */
dcl &msgdta *char 100 /* std err */
dcl &msgf *char 10 /* std err */
dcl &msgflib *char 10 /* std err */
monmsg msgid(cpf0000) exec(goto stderr1) /* std err */
/*--------------------------------------------------------*/
/* Create the line description */
/*--------------------------------------------------------*/
CrtLinASC Lind(PAGER) +
RsrcName(LIN011) +
OnLine(*No) +
Interface(*RS232V24) +
Cnn(*SWTPP) +
VryWait(*NOWAIT) +
AutoCall(*NO) +
BitsChar(7) +
Parity(*EVEN) +
StopBits(1) +
Duplex(*Full) +
Echo(*None) +
LineSpeed(2400) +
Modem(*Normal) +
ModemRate(*Full) +
Swtcnn(*Dial) +
AutoAns(*No) +
AutoDial(*Yes) +
DialCmd(*Other) +
CallNbr('9,18007596366') +
InActTmr(*Nomax) +
MaxBuffer(896) +
ThresHold(*Off) +
FlowCntl(*No) +
IdlTmr(1) +
EORTBL((0D 0)) +
Dsrdrptmr(6) +
AutoAnsTyp(*Dtr) +
CtsTmr(25) +
RmtAnsTmr(60) +
CmnRcyLmt(2 5) +
Text('PAGER Async Line')
/*--------------------------------------------------------*/
/* Create the controller description */
/*--------------------------------------------------------*/
CrtCtlAsc Ctld(PAGER) +
LinkType(*ASYNC) +
OnLine(*NO) +
Switched(*YES) +
InlCnn(*DIAL) +
CnnNbr('9,18007596366') +
Text('PAGER Controller')
/*--------------------------------------------------------*/
/* Create the device description */
/*--------------------------------------------------------*/
CrtDevAsc Devd(PAGER) +
RmtLocName(PAGER) +
Online(*NO) +
Ctl(PAGER) +
Text('PAGER Device')
ChgLinAsc LIND(PAGER) +
SwtCtllst(PAGER)
ChgCtlAsc Ctld(PAGER) +
SwtLinLst(PAGER)
Chkobj PAGEICF *FILE
Monmsg cpf9801 exec(goto theend)
AddICFDeve file(PAGEICF) +
pgmdev(PAGER) +
rmtlocname(PAGER) +
cmntype(*ASYNC) +
fmtslt(*PGM)
theend:
return
/*--------------------------------------------------------*/
/* error routine: */
/*--------------------------------------------------------*/
stderr1: /* Standard error handling routine */
if &errorsw sndpgmmsg msgid(cpf9999) +
msgf(qcpfmsg) msgtype(*escape) /* Func chk */
chgvar &errorsw '1' /* Set to fail ir error occurs */
stderr2: rcvmsg msgtype(*diag) msgdta(&msgdta) msgid(&msgid) +
msgf(&msgf) msgflib(&msgflib)
if (&msgid *eq ' ') goto stderr3
sndpgmmsg msgid(&msgid) msgf(&msgflib/&msgf) +
msgdta(&msgdta) msgtype(*diag)
goto stderr2 /* Loop back for addl diagnostics */
stderr3: rcvmsg msgtype(*excp) msgdta(&msgdta) msgid(&msgid) +
msgf(&msgf) msgflib(&msgflib)
sndpgmmsg msgid(&msgid) msgf(&msgflib/&msgf) +
msgdta(&msgdta) msgtype(*escape)
end: endpgm
Figure
2
Creating the paging
application
We start out by
creating the paging command (PAGE). The command
will require you to enter the Pin Number and the
alphanumeric message text. The message text will
be limited to 100 characters for our example. See
Figure 3. The CPP for the command is PAGERC.
cmd ('Page with Pin #')
/* -------------------------------------------- */
/* Enter the Pin # */
/* -------------------------------------------- */
parm pin *char 10 +
min(1) +
prompt('PIN number')
/* -------------------------------------------- */
/* Enter the message */
/* -------------------------------------------- */
parm TxtMsg *char 100 +
min(1) +
prompt('Text message')
Figure
3
Create the module
PAGERC (Figure 4). This will be the initial
module for the program PAGERC.
pgm (&pin /* Pager PIN Number */ +
&TxtMsg) /* Text Message */
/*--------------------------------------------------------*/
/* declaration */
/*--------------------------------------------------------*/
dcl &Pin *char 10
dcl &txtmsg *char 100
dcl &ModemAct *char 8
dcl &PAGERSts *dec (5 0)
dcl &errorsw *lgl /* std err */
dcl &msgid *char 7 /* std err */
dcl &msgdta *char 100 /* std err */
dcl &msgf *char 10 /* std err */
dcl &msgflib *char 10 /* std err */
monmsg msgid(cpf0000) exec(goto stderr1) /* std err */
/*--------------------------------------------------------*/
/* Determine if the modem is up & running */
/*--------------------------------------------------------*/
RtvCfgSts cfgd(PAGER) +
cfgtype(*DEV) +
stscde(&PAGERSts)
Monmsg cpf0000
/*----------------------------------------------*/
/* Reset the modem if not *ACTIVE */
/*----------------------------------------------*/
chgvar &ModemAct '*DIAL'
If (&PAGERSts *ne 60) then(Goto Reset)
/*----------------------------------------------*/
/* Modem is varied on, bypass the reset */
/*----------------------------------------------*/
chgvar &ModemAct '*NODIAL'
Goto SndPage
/*--------------------------------------------------------*/
/* Reset the Controller & Line Description for PAGER */
/*--------------------------------------------------------*/
Reset:
Vrycfg cfgobj(PAGER) +
cfgtype(*CTL) +
status(*OFF)
Monmsg cpf0000
Vrycfg cfgobj(PAGER) +
cfgtype(*LIN) +
status(*OFF)
Monmsg cpf0000
Vrycfg cfgobj(PAGER) +
cfgtype(*LIN) +
status(*ON)
Monmsg cpf0000
Vrycfg cfgobj(PAGER) +
cfgtype(*CTL) +
status(*ON)
Monmsg cpf0000
/*--------------------------------------------------------*/
/* Call the paging program to send the message */
/*--------------------------------------------------------*/
SndPage:
Callprc prc(PAGERR) +
parm(&Pin +
&TxtMsg +
&ModemAct)
Vrycfg cfgobj(PAGER) +
cfgtype(*CTL) +
status(*OFF)
Monmsg cpf0000
Vrycfg cfgobj(PAGER) +
cfgtype(*LIN) +
status(*OFF)
Monmsg cpf0000
theend:
return
/*--------------------------------------------------------*/
/* error routine: */
/*--------------------------------------------------------*/
stderr1: /* Standard error handling routine */
if &errorsw sndpgmmsg msgid(cpf9999) +
msgf(qcpfmsg) msgtype(*escape) /* Func chk */
chgvar &errorsw '1' /* Set to fail ir error occurs */
stderr2: rcvmsg msgtype(*diag) msgdta(&msgdta) msgid(&msgid) +
msgf(&msgf) msgflib(&msgflib)
if (&msgid *eq ' ') goto stderr3
sndpgmmsg msgid(&msgid) msgf(&msgflib/&msgf) +
msgdta(&msgdta) msgtype(*diag)
goto stderr2 /* Loop back for addl diagnostics */
stderr3: rcvmsg msgtype(*excp) msgdta(&msgdta) msgid(&msgid) +
msgf(&msgf) msgflib(&msgflib)
sndpgmmsg msgid(&msgid) msgf(&msgflib/&msgf) +
msgdta(&msgdta) msgtype(*escape)
end: endpgm
Figure
4
PAGERC starts out
by monitoring whether the PAGER device is active
or not (This is the device acquired in the
program). The line description, controller and
device are all reset for the dial up networking.
PAGERC calls PAGERR module to execute the TAP
transmission between the AS/400 and the paging
company. The paging company I used for testing is
SKYTEL.
Figure 5 (module
PAGERR) illustrates the TAP protocol executed
from the AS/400. We used the PAGEICF file to
communicate directly with the paging company. The
previous module PAGERC passes the pin number,
message text and action to be taken. If the
action is to *DIAL to the paging company, the
ATDT modem command is used to start up the
asynchronous modem. The "AT" command
automatically dials a call for you. The
"DT" stands for dial tone. You may also
use "DP" dial pulse" is pulsed is
used. The telephone number to dial follows after
the modem command "DT". The comma is
used to pause the modem. Each comma corresponds
to a 2 seconds pause.
The AT modem
command, telephone number & pause are all
stored in a data area PAGER. To create the data
area, do the following:
CRTDTAARA
DTAARA(YOURLIB/PAGER) TYPE(*CHAR) LEN(100)
VALUE(ATDT9,18007596366,,,,,)
TEXT(TAP Parameter used by
SKYTEL)
CHGDTAARA
DTAARA(PAGER (31 6)) VALUE('000002')
CHGDTAARA
DTAARA(PAGER (37 6)) VALUE('000008)
CHGDTAARA
DTAARA(PAGER (43 6)) VALUE('000000')
CHGDTAARA
DTAARA(PAGER (49 6)) VALUE('000000')
CHGDTAARA
DTAARA(PAGER (55 6)) VALUE('000000')
CHGDTAARA
DTAARA(PAGER (61 6)) VALUE('000000')
CHGDTAARA
DTAARA(PAGER (67 6)) VALUE('000001')
CHGDTAARA
DTAARA(PAGER (73 6)) VALUE('000001)
CHGDTAARA
DTAARA(PAGER (79 6)) VALUE('000000')
CHGDTAARA
DTAARA(PAGER (85 6)) VALUE('000000')
Positions 31 to 90
of the data area contains the wait time (in
seconds) we used to control how long to wait for
the modem. Different vendors react to different
TAP protocol that is why the wait period for
SKYTEL may not work with the wait period for
PAGENET. Position 31 to 42 is used to wait for
"ID=" back from the paging company.
Positions 43 to 54 is used to wait for
acknowledgement after we send out our service
type. Positions 55 to 66 is used to wait for the
"go ahead" control codes from the
paging company informing up that they are
ready to receive alphanumeric transmission.
Positions 67 to 78 is used to wait for
acknowledge back from the paging company to find
out whether our page was delivered or not. And
positions 79 to 90 is used to wait for "end
of transmission" control code from the
paging company.
During the initial
dial to the paging company, I monitored for
"CONNECT", "OK" or "NO
CARRIER" response back from the modem. The
process continues once the modem has establish
connection with the paging company.
The sequence of
call delivery between the AS/400 and the paging
company must be followed within PAGERR. The
AS/400 cannot send any information back to the
paging company without receiving acknowledgement
from the paging company. The AS/400 must re-act
quickly to every acknowledgement because the
paging company waits or reacts if no activity is
received within a specific amount of time.
The asynchronous
transmission in which the length of time between
transmitted characters may vary. Because the
time-lapses between transmitted characters are
not uniform, the receiving modem must be signaled
as to when the data transmission can begin and
when do they end. When an INVITE keyword is sent
(written) to the ICF file, it signals the paging
company to start sending data. There could be
overlapping sending & receiving of
transmission that is why I looped within each
READ until the correct acknowledgement is
received. The carriage return (Hex
0D) serves as a stop code to inform
the paging company transmission of data has
finished.
It is best to scan
for received data because certain paging company
may not strictly conform to the TAP protocol.
I left the display
op-code (DISPLY) to determine the ICF status when
error occurs. This information can be useful in
diagnosing those communications problems. A full
description of these return status codes are
supplied in the ICF Programming Manual and APPC
Programming Manual.
Note:
All test pages are done using SKYTEL
& MCI for the paging service. Pagers
tested are Motorola Advisor Gold FLX and
Motorola PAGEFINDER.
Alphanumeric
pages are not limited to 100 characters long.
SKYTEL & MCI can deliver 2000 bytes per
transaction. Advisor Gold & PAGEFINDER
pagers are recommended when delivering 2000
bytes of transaction block.
****************************************************************
* F I L E D E S C R I P T I O N S P E C I F I C A T I O N *
****************************************************************
FPAGEICF CF E WORKSTN USROPN
F MAXDEV(*FILE)
F DEVID(DEVICE)
F INFDS(FEEDBACK)
*
* ICF file used for the modem
*
*--------------------------------------------------------------*
D/EJECT
****************************************************************
* D E F I N I T I O N S P E C I F I C A T I O N *
****************************************************************
*
* ICF Input/Output Feedback Area
*
D FEEDBACK DS
D FileName *FILE
D FormatNm *RECORD
D Statement 30 37
D PgmDev 273 282
D MajMin 401 404
D MajorCode 401 402
D MinorCode 403 404
*
* Program Status Data Structure
*
D PGMDS SDS
D Pgmq## *PROC
D ErrorSts *STATUS
D PrvStatus 16 20S 0
D SrcLinNum 21 28
D Routine *ROUTINE
D NumParms *PARMS
D ExcpType 40 42
D ExcpNum 43 46
D MsgId 40 46
*
D PgmLib 81 90
D ExcpData 91 170
D ExcpId 171 174
D LastFile 201 208
D FileErr 209 243
D JobName 244 253
D User 254 263
D JobNumA 264 269
D JobNum 264 269S 0
D JobDate 270 275S 0
D RunDate 276 281S 0
D RunTime 282 287S 0
D PgmCrtDt 288 293
D PgmCrtTm 294 299
D CmplrLvl 300 303
D SrcFile 304 313
D SrcLib 314 323
D SrcMbr 324 333
D ProcPgm 334 343
D ProcMod 344 353
*
* Program Status Data Structure
*
D PAGER_DS UDS 100 DTAARA(PAGER)
D Pagethis 30
D WtID01 6S 0
D WtID02 6S 0
D WtAckSrv01 6S 0
D WtAckSrv02 6S 0
D WtGoAhd01 6S 0
D WtGoAhd02 6S 0
D WtAckPag01 6S 0
D WtAckPag02 6S 0
D WtEOT01 6S 0
D WtEOT02 6S 0
*
* Variables to convert to CheckSum
*
D DS
D @Decimal 1 2B 0
D @Ascii 2 2
D @Dec1 3 4B 0
D @Asc1 4 4
D @Dec2 5 6B 0
D @Asc2 6 6
D @Dec3 7 8B 0
D @Asc3 8 8
*
D DS
D @ChkSum 1 3
D @Chk1 1 1
D @Chk2 2 2
D @Chk3 3 3
*
D @DecChk S 9 0
D @Q S 9 0
D @ASC S 1 DIM(120)
D @CvtAsc S Like(PAGECMD)
D @CvtSize S 5 0
D @Pos S 5 0
*
* Standalone fields
*
D @Len S 5 0
D @XL8Table S 10
D ReturnPt S 6
D @IDRcv S 3
D @ACKRcv S 3
D @ESC1 S 1
D @ESC4 S 4
*
* Constant
*
D @Dev C Const('PAGER')
D @Dial C Const('*DIAL')
D @NoDial C Const('*NODIAL')
D @AckDial C Const('*GOOD')
D @RSDial C Const('*ABANDON')
D @EotDial C Const('*BAD')
D @Connect C Const('CONNECT')
D @OK C Const('OK')
D @NoCarrier C Const('NO CARRIER')
D @NoError C Const('0000')
D @TimeOut C Const('0310')
D @Parity C Const('0016')
D @DataLoss C Const('0024')
D @EndSessn C Const('830B')
D @LineDrop C Const('8191')
D @# C Const('#')
D @ID C Const('ID')
D @PG1 C Const('PG1')
*
* ASCII Constants
*
D @IDAS C Const(X'4944')
D @PG1AS C Const(X'504731')
D @ACKCRAS C Const(X'060D')
D @NAKCRAS C Const(X'150D')
D @RSCRAS C Const(X'1E0D')
D @ESCAS C Const(X'1B')
D @ESCEOTAS C Const(X'1B04')
*
* Pager Commands/Constants (in EBCDIC)
*
D @ESC C Const(X'27')
D @STX C Const(X'02')
D @ETX C Const(X'03')
D @EOT C Const(X'37')
D @LF C Const(X'25')
D @CR C Const(X'0D')
D @SUB C Const(X'3F')
D @ETB C Const(X'26')
D @ACKCR C Const(X'2E0D')
D @NAKCR C Const(X'3D0D')
D @RSCR C Const(X'350D')
D @ESCEOT C Const(X'2737')
C/EJECT
C
****************************************************************
* C A L C U L A T I O N S P E C I F I C A T I O N *
****************************************************************
*
* Entry parameters Ä
C *ENTRY PLIST
C Parm Pin 10
C Parm Message 100
C Parm ModemActn 8
*
*----------------------------------------------------*
* Build pager command now. When we receive message *
* go ahead command from the paging company, we have *
* 5 seconds to respond back to the paging company, *
* otherwise, we get a parity check & we need to *
* retransmit. *
*----------------------------------------------------*
C Eval @CvtAsc = *Blanks
C Eval @CvtAsc = @STX +
C %Trimr(Pin) +
C @CR +
C %Trimr(Message) +
C @CR +
C @ETX
C Exsr $ChkSum
*
C Eval PageCmd = *Blanks
C Eval PageCmd = @STX +
C %Trimr(Pin) +
C @CR +
C %Trimr(Message) +
C @CR +
C @ETX +
C @ChkSum +
C @CR
*----------*
C RepeatDial Tag
*----------*
*----------------------------------------------------*
* Check if connection needs to be made *
*----------------------------------------------------*
C ModemActn CasEq @Dial $DialServ
C EndCs
*-----*
C Dow Not *InLr
*----------*
C RepeatTxn Tag
*----------*
*----------------------------------------------------*
* <CR> Carriage Return *
* Send Command & Wait for "ID=" *
* This step is normally repeated every 2 seconds *
* if the paging company has not responded. *
*----------------------------------------------------*
C Eval CRCmd = @CR
C Eval *In01 = *Off
C Z-add WtId01 Seconds 01
*
C DOW MajMin <= @TimeOut
C Write CRR 98
C Exsr $ModemChk
C Write INVITE
C 01 Write WAITR
C 01 Read PAGEICF 9897
C N01 Read RCVR 9897
C If MajMin > @TimeOut
C Exsr *PSSR
C EndIf
*
* *------------------------------------------*
* * Wait for "ID=" *
* *------------------------------------------*
C @ID SCAN RcvCmd 97
C If *IN97
C Leave
C EndIf
* *------------------------------------------*
* * Line Drop, acquire device again. *
* *------------------------------------------*
C MajMin CabEq @LineDrop RepeatDial
* *------------------------------------------*
* * Modem disconnected, acquire device again*
* *------------------------------------------*
C MajMin CabEq @EndSessn RepeatDial
* *------------------------------------------*
* * Change the wait time to WtID02. The *
* * WtID01 waits for the <CR> command. *
* *------------------------------------------*
C Eval *In01 = *Off
C Z-add WtId02 Seconds 01
C EndDo
*----------------------------------------------------*
* <ESC>PG1<CR> Type of Service *
* Send automatic remote entry for this type of *
* service. The paging co. sends acknowledgement *
* back to us. *
*----------------------------------------------------*
C Eval ServCmd = @ESC + @PG1 + @CR
C Write SERVICER 98
C Exsr $ModemChk
* *------------------------------------------*
* * Wait for Acknowledgement. This response *
* * shall come within 10 seconds of the *
* * previous step. *
* *------------------------------------------*
C DOW MajMin = @NoError
C Write INVITE
C Read RCVR 9897
C If MajMin > @DataLoss and
C Not *In98
C Exsr *PSSR
C EndIf
C MajMin CabGT @NoError RepeatTxn
*
C @ACKCR SCAN RcvCmd 97
C If *IN97
C Leave
C EndIf
C EndDo
*----------------------------------------------------*
* <ESC>[p<CR> Message go Ahead *
* This tells us that the paging company is ready to *
* receive the transaction. *
* This response is received within 10 seconds from *
* the previous acknowledgement. *
*----------------------------------------------------*
C DOW MajMin = @NoError
C Write INVITE
C Read RCVR 9897
C If MajMin > @DataLoss and
C Not *In98
C Exsr *PSSR
C EndIf
C MajMin CabGT @NoError RepeatTxn
*
C @ESC SCAN RcvCmd 97
C If *IN97
C Leave
C EndIf
C EndDo
*
*----------------------------------------------------*
* <STX>Pin<#>Message<#><CR><ETX><CR> Your Page *
* Send the page. Follow the page stream when *
* sending to the paging company: *
* *
* <STX> Start of Text *
* *--> Pin Pin number of the pager *
* | <CR> Carriage return to break *
* Loop| Msg Alphanumeric message (100 *
* here| bytes for this program) *
* *--- <CR> Carriage return to break *
* between messages. *
* <ETX> End of Text *
* @ChkSum 3 character checksum value that *
* informs the paging company the *
* length of the transmission we *
* are sending. *
* <CR> Carriage Return. *
* *
* Note: The message (w/ Pin) may be bundled to *
* send more than 1 page *
* *
*----------------------------------------------------*
*
*----------*
C AlphaPage Tag
*----------*
*
C Write PAGER 98
C Exsr $ModemChk
C Eval *In01 = *Off
C Z-add WtAckPag01 Seconds 01
* *------------------------------------------*
* * Wait for Acknowledgement. This response *
* * shall come after 10 seconds of the *
* * previous step. *
* *------------------------------------------*
C DOW MajMin <= @TimeOut
C Write INVITE
C 01 Write WAITR
C 01 Read PAGEICF 9897
C N01 Read RCVR 9897
* *------------------------------------------*
* * If data is loss or parity error occured,*
* * resend the alphanumeric page. *
* *------------------------------------------*
C If MajMin > @TimeOut
C Exsr *PSSR
C EndIf
C If MajMin = @DataLoss or
C MajMin = @Parity
C Goto AlphaPage
C EndIf
* *------------------------------------------*
* * <RS><CR> Resend last transaction *
* *------------------------------------------*
C @RSCR SCAN RcvCmd 97
C If *IN97
C Goto AlphaPage
C EndIf
* *------------------------------------------*
* * <NAK><CR> Checksum or Transmission *
* * error, repeat alpha page *
* *------------------------------------------*
C @NAKCR SCAN RcvCmd 97
C If *IN97
C Goto AlphaPage
C EndIf
* *------------------------------------------*
* * <ACK><CR> Acknowledgement received *
* *------------------------------------------*
C @ACKCR SCAN RcvCmd 97
C If *IN97
C Eval ModemActn= @AckDial
C Leave
C EndIf
* *------------------------------------------*
* * <ESC><EOT> Begin disconnect. Page not *
* * accepted. *
* *------------------------------------------*
C @ESCEOT SCAN RcvCmd 97
C If *IN97
C Eval ModemActn= @EOTDial
C ModemActn Dsply
C MajMin Dsply
C Leave
C EndIf
* *------------------------------------------*
* * Change the wait time to be long enough *
* * to have the paging company react to the *
* * request. The initial WtAckPag01 waits *
* * for the <CR> command *
* *------------------------------------------*
C Eval *In01 = *Off
C Z-add WtAckPag02 Seconds 01
C EndDo
*
*----------------------------------------------------*
* <EOT><CR> End of Transmission Ä*
* There is no more transmission. *
*----------------------------------------------------*
*
* *------------------------------------------*
* * If the paging company ended the *
* * transmission, do not send the EOTR *
* * record anymore *
* *------------------------------------------*
C If ModemActn= @EOTDial
C Leave
C EndIf
*
C Eval EOTCmd = @EOT + @CR
C Write EOTR 98
C Exsr $ModemChk
C Eval *InLr = *On
C EndDo
*-----*
C Return
*
/EJECT
*==============================================================*
* *
* Dial to Paging Service Provider *
* *
C $DialServ BEGSR *
*==============================================================*
*------------------------------------------*
* Combine the string to start the modem, *
* then call the paging service provider. *
*------------------------------------------*
C Open PAGEICF
C Eval DEVICE = @Dev
C DEVICE Acq PAGEICF 99
C If *In99
C Goto #DialServ
C EndIf
*
*------------------------------------------*
* Send the Dial command to wake modem up *
*------------------------------------------*
C Connect Tag
C IN Pager_Ds
C Eval ModemCmd = PageThis
C Eval %Subst(ModemCmd: 31: 1) = @CR
C Write MODEMR 98
C Exsr $ModemChk
C Eval ModemCmd = *Blanks
*
*------------------------------------------*
* Wait for CONNECT *
*------------------------------------------*
C DOW MajMin = @NoError
C Read MODEMR 9897
C @Connect SCAN ModemCmd 97
C If *IN97
C Leave
C EndIf
C @OK SCAN ModemCmd 97
C N97@NoCarrier SCAN ModemCmd 97
C If *IN97
C Goto Connect
C EndIf
C EndDo
*
C #DialServ ENDSR
/SPACE 4
*==============================================================*
* *
* Check Modem Error *
* *
C $ModemChk BEGSR *
*==============================================================*
C If MajMin > @NoError or
C *In98
C Exsr *PSSR
C EndIf
*
C #ModemChk ENDSR
/SPACE 4
*==============================================================*
* *
* Compute for 3 character Checksum *
* *
C $ChkSum BEGSR *
*==============================================================*
*------------------------------------------*
* Retrieve the Size - to determine the *
* number of times to loop. *
*------------------------------------------*
C ' ' CheckR @CvtAsc @CvtSize
*------------------------------------------*
* Convert entry to ASCII *
*------------------------------------------*
C Call 'QDCXLATE'
C Parm @CvtSize @Len
C Parm @CvtAsc
C Parm 'QASCII' @Xl8Table
*------------------------------------------*
* Loop thru the size of the entry for *
* each byte. Retrieve the decimal *
* representation of the ASCII byte. This *
* decimal value is added to the Checksum *
* value (@CHKSUM). The CheckSum tells *
* the paging company the length of the *
* variable you are sending them. *
*------------------------------------------*
C Movea @CvtAsc @Asc
C Eval @DecChk = 0
C Eval @Decimal = 0
*
C 1 Do @CvtSize @Pos
C Move @Asc(@Pos) @Ascii
C BitOff '0' @Ascii
C Eval @DecChk = @DecChk + @Decimal
C EndDo
*------------------------------------------*
* Use Base 16 in computing for Checksum *
*------------------------------------------*
*
*------------------------------------------*
* Third position Checksum (@Chk3) *
*------------------------------------------*
C Eval @Dec3 = 0
C Eval @Q = @DecChk / 16
C Eval @Dec3 = (48 + @DecChk) - (@Q * 16)
C Eval @DecChk = @DecChk / 16
*------------------------------------------*
* Second position Checksum (@Chk2) *
*------------------------------------------*
C Eval @Dec2 = 0
C Eval @Q = @DecChk / 16
C Eval @Dec2 = (48 + @DecChk) - (@Q * 16)
C Eval @DecChk = @DecChk / 16
*------------------------------------------*
* First position Checksum (@Chk1) *
*------------------------------------------*
C Eval @Dec1 = 0
C Eval @Q = @DecChk / 16
C Eval @Dec1 = (48 + @DecChk) - (@Q * 16)
*------------------------------------------*
* Concatenate 3 checksum value & convert *
* back to EBCDIC prior to paging *
*------------------------------------------*
C Eval @Chk1 = @Asc1
C Eval @Chk2 = @Asc2
C Eval @Chk3 = @Asc3
*
C Call 'QDCXLATE'
C Parm 3 @Len
C Parm @ChkSum
C Parm 'QEBCDIC' @Xl8Table
*
C #ChkSum ENDSR
/EJECT
*==============================================================*
* *
* Program Error Subroutine *
* *
C *PSSR BEGSR *
*==============================================================*
*------------------------------------------*
* End the program *
*------------------------------------------*
C MajMin Dsply
C Move '*CANCL' ReturnPt
*
C EndSr ReturnPt
Figure
5
The following
tables are provided to better understand the
control codes used by the TAP protocol. Use this
table to determine the data received from the
paging company.
ASCII
Character Code to Hexadecimal Value Conversion
Table |
2nd
Hex |
First Hex Digit
|
Digit |
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
0
|
NUL
|
DLE
|
SP
|
0
|
@
|
P
|
`
|
p
|
1
|
SOH
|
DC1
|
!
|
1
|
A
|
Q
|
a
|
q
|
2
|
STX
|
DC2
|
"
|
2
|
B
|
R
|
b
|
r
|
3
|
ETX
|
DC3
|
#
|
3
|
C
|
S
|
c
|
s
|
4
|
EOT
|
DC4
|
$
|
4
|
D
|
T
|
d
|
t
|
5
|
ENG
|
NAK
|
%
|
5
|
E
|
U
|
e
|
u
|
6
|
ACK
|
SYN
|
&
|
6
|
F
|
V
|
f
|
v
|
7
|
BEL
|
ETB
|
|
7
|
G
|
W
|
g
|
w
|
8
|
BS
|
CAN
|
(
|
8
|
H
|
X
|
h
|
x
|
9
|
HT
|
EM
|
)
|
9
|
I
|
Y
|
I
|
y
|
A
|
LF
|
SUB
|
*
|
:
|
J
|
Z
|
j
|
z
|
B
|
VT
|
ESC
|
+
|
;
|
K
|
[
|
k
|
{
|
C
|
FF
|
FS
|
,
|
<
|
L
|
\
|
l
|
|
|
D
|
CR
|
GS
|
-
|
=
|
M
|
]
|
m
|
}
|
E
|
SO
|
RS
|
.
|
>
|
N
|
^
|
n
|
~
|
F
|
SI
|
US
|
/
|
?
|
O
|
--
|
o
|
DEL
|
EBCDIC
Character Code to Hexadecimal Value Conversion
Table (Part 1) |
2nd
Hex |
First Hex Digit
|
Digit |
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
0
|
NUL
|
DLE
|
DS
|
|
SP
|
&
|
-
|
|
1
|
SOH
|
DC1
|
SOS
|
|
|
|
/
|
|
2
|
STX
|
DC2
|
FS
|
SYN
|
|
|
|
|
3
|
ETX
|
TM
|
|
|
|
|
|
|
4
|
PF
|
RES
|
BYP
|
PN
|
|
|
|
|
5
|
HT
|
NL
|
LF
|
RS
|
|
|
|
|
6
|
LC
|
BS
|
ETB
|
UC
|
|
|
|
|
7
|
DEL
|
IL
|
ESC
|
EOT
|
|
|
|
|
8
|
|
CAN
|
|
|
|
|
|
|
9
|
|
EM
|
|
|
|
|
|
|
A
|
SMM
|
CC
|
SM
|
|
¢
|
!
|
¦
|
:
|
B
|
VT
|
CU1
|
CU2
|
CU3
|
.
|
$
|
,
|
#
|
C
|
FF
|
IFS
|
|
DC4
|
<
|
*
|
%
|
@
|
D
|
CR
|
IGS
|
ENQ
|
NAK
|
(
|
)
|
--
|
'
|
E
|
SO
|
IRS
|
ACK
|
|
+
|
;
|
>
|
XXX
|
F
|
SI
|
IUS
|
BEL
|
SUB
|
|
|
¬
|
?
|
"
|
EBCDIC
Character Code to Hexadecimal Value Conversion
Table (Part 2) |
2nd
Hex |
First Hex Digit
|
Digit |
8
|
9
|
A
|
B
|
C
|
D
|
E
|
F
|
0
|
|
|
(minus)
|
(0)
|
|
|
\
|
0
|
1
|
a
|
j
|
°
|
(1)
|
A
|
J
|
|
1
|
2
|
b
|
k
|
s
|
(2)
|
B
|
K
|
S
|
2
|
3
|
c
|
l
|
t
|
(3)
|
C
|
L
|
T
|
3
|
4
|
d
|
m
|
u
|
(4)
|
D
|
M
|
U
|
4
|
5
|
e
|
n
|
v
|
(5)
|
E
|
N
|
V
|
5
|
6
|
f
|
o
|
w
|
(6)
|
F
|
O
|
W
|
6
|
7
|
g
|
p
|
x
|
(7)
|
G
|
P
|
X
|
7
|
8
|
h
|
q
|
y
|
(8)
|
H
|
Q
|
Y
|
8
|
9
|
I
|
r
|
z
|
(9)
|
I
|
R
|
Z
|
9
|
A
|
|
|
|
|
|
|
|
|
B
|
{
|
}
|
+
|
+
|
|
|
|
|
C
|
=
|
¦
|
+
|
+
|
|
|
|
|
D
|
(
|
)
|
[
|
]
|
|
|
|
|
E
|
+
|
±
|
=
|
&ne.
|
|
|
|
|
F
|
+
|
¦
|
|
-
|
|
|
|
|
Debugging your pages
Some paging companies
do not follow strictly with the TAP protocol. Chances
are you may received unrecognizable characters you
did not anticipate. Because of the asynchronous
handshaking with the paging company, you want to be
sure you received the next message sequence you
monitor for prior to sending your response.
The AS/400 is equipped
with 2 facilities to monitor our pages. The first one
is using the ICF trace. To start the trace, enter the
Trace ICF command:
TRCICF
*ON
All entries (both send
& received) for the ICF file will be monitored
and traced. Enter the PAGE command after the TRCICF
command. When the PAGE command finishes, use the
TRCICF *OFF command to end the trace. Prompt the
trace command. You have an option to print it or save
it to an output file. I use the report to determine
the return codes from the ICF, the data transmitted
back from the paging company and the time it took
between each message sequence.
The second way of
testing your pages is by using communication trace.
Enter the Start Communication Trace (STRCMNTRC)
command. Enter PAGER on the configuration object and
the type must be *LIN:
STRCMNTRC
CFGOBJ(PAGER) CFGTYPE(*LIN)
Enter the PAGE command
after the STRCMNTRC is executed. When the PAGE
command finishes, print the communication trace using
the Print Communication Trace (PRTCMNTRC) command:
PRTCMNTRC
CFGOBJ(PAGER) CFGTYPE(*LIN) CODE(*CALC)
Change the code
parameter to *CALC to view the ASCII representation
of what comes back from the paging company. The
default code is EBCDIC.
You may also use the
service tool (STRSST) command to start the
communications trace.
References
The PCIA may be
reached in their Alexandria, Virginia, offices at
(703) 739-0300 (Phone) or (703) 836-1608 (Fax).
The PCIAs
web-site is http://www.pcia.com/navfr.htm.
OS/400 ICF Programming
Version 3
AS/400 Asynchronous
Communications Programming Version 3
OS/400 Workstation
Customization Programming -- Version 3
OS/400 APPC
Programming -- Version 3