24. NS BASIC Tech Note: Using Endpoints with NSBASIC  6 JUNE 1996.
------------------------------------------------------------
Contributed by Jonathan Kipling Knight (KKnight-COS3© Kaman.com), Colorado 
Springs, CO.

[Note: NS BASIC provides a standard, easy to use interface to 
communications, based on the INPUT and PRINT statements. WIth Rev 3.5, we 
also provided a more direct interface to the underlying communications in 
the Newton. While this is more complex to use, it is also much more 
powerful. Here'a a tech note showing how to roll your own communications - 
Ed.]

If you have a special purpose for a program that involves talking to the 
outside world, you might be glad to see the large document "Newton 
Programmers Guide: Communications" at 
http://dev.info.apple.com/newton/techinfo/techinfo.html.  This document 
was designed to be used with Newton 2.0 in conjunction with the Newton 
ToolKit.  If you planned to use endpoints with NSBASIC then you'll run 
into a snag.  Apple doesn't provide the values of the necessary constants 
to start communicating.  The following is a list of constants that are 
missing from that document.

Constants missing from NPG:Communications
Protos:
oldProtoEndpoint        © 174  // provided for compatibility with NOS 1.x
protoBasicEndpoint      © 383  // the normal proto for endpoints
protoStreamingEndpoint  © 466  // use to "stream" large objects onto stores

Services:
kCMSMNPID               "mnps"  // Asynchronous Serial with MNP Compression
kCMSSlowIR              "slir"  // Infrared
kCMSModemID             "mods"  // Modem
kCMSAsynchSerial        "aser"  // Asynchronous Serial
kCMSAppleTalkID         "atlk"  // AppleTalk

The following listing is the special purpose that drove me to find these 
missing constants.  It is a program that calls up the NIST Atomic Clock 
computer (located in Boulder, Colorado) and sets the Newton's time to the 
received time strings.  This is a working program but could use some more 
error checking and state checking to make it dependable.  It's offered 
here to provide an example of how to set up and use endpoints with 
NSBASIC.  The functions are extended for clarity and should be typed in 
without carriage returns.

0010  LET kCMSModemID="mods"
0020  LET protoBasicEndpoint:=© 383
0030  LET opSetRequired=512
0040  LET unicodeLF=chr(10)
0050  LET unicodeCR=chr(13)
0060  LET EOL:=Stringer([unicodeCR,unicodeLF]) // End of Line characters
0070  LET OTM:="*"  // Character received on the seconds mark
0080  LET 
connectService={label:kCMSModemID,type:'service,opCode:opSetRequired}
0090  LET dialOps:=MakeModemOption()  // Gets Extras\Prefs\Modem options
0100  LET initConfig=[connectService,dialOps]
0110  LET NISTAddress=MakePhoneOption("1(303)494-4774")
0120  LET ep={_proto:protoBasicEndpoint}
0130  FUNCTION InitFunc(ep,data,term,ops)
      begin
      SetValue(u.inWindow,'text,data);
      if StrPosExact(data,"",0) then
       ep:SetInputSpec(u.rxTimeSpec);
      end
0140  FUNCTION RxTimeFunc(ep,data,term,ops)
      begin
      local dt;
      SetValue(u.inWindow,'text,data);
      dt:=u:DecodeNISTTime(data);
      if Abs(dt-TimeInSeconds())<60*60 then
       begin
       SetTimeInSeconds(dt);
       u:FinishConnect(ep);
       end;
      end
0150  FUNCTION DecodeNISTTime(data)
      begin
      local dst,ds,secs,hrPos:=StrPos(data,":",0)-2;
      ds:=StringToNumber(SubStr(data,hrPos+9,2));
      dst:=if ds<51 and ds<>0 then 3600 else 0;
      secs:=(StringToNumber(SubStr(data,hrPos-15,5))-48988)*86400;
      
secs:=secs+(StringToTime(SubStr(data,hrPos,5))-StringToTime("00:00"))*60;
      secs:=secs+StringToNumber(SubStr(data,hrPos+6,2));
      secs:=secs+dst+GetUserConfig('location).gmt;
      RintToL(secs) end
0160  FUNCTION FinishConnect(ep)
      begin
      ep:SetInputSpec(nil);
      ep:FlushInput();
      ep:Disconnect(True,nil);
      ep:UnBind(nil);
      end
0170  LET initSpec={termination:{endSequence:EOL},form:'string, 
inputScript:InitFunc}
0180  LET rxTimeSpec={termination:{endSequence:OTM},form:'string, 
inputScript:RxTimeFunc}
0190  LET inWindow:={text:"",viewBounds:RelBounds(5,5,230,50)}
0200  WINDOW inW,inWindow
0210  SHOW inW
0220  u.ep:Instantiate(ep,initConfig)
0230  u.ep:Bind(nil,nil)  // bind endpoint to service
0240  u.ep:Connect(NISTAddress,{reqTimeout:30000}) // Stop calling after 
30 secs
0250  u.ep:SetInputSpec(initSpec)  // Start receiving
0260  WAIT 30000 // Wait 30 secs for connection to finish
0270  u.ep:Dispose()  // Dispose endpoint
0280  HIDE
0290  END


All of the other services can be used in a similar manner if you use the 
above constants and follow NPG:Communications.  BASIC 3.5 now provides for 
more communication services but for highly specialized communications, it 
is possible to use endpoints directly.  By the way, the above program 
makes a 2-5 second phone call so it shouldn't increase your phone bill by 
much.  I've seen it at 15 cents a call.