// EPS: Elgaard Positioning System: GPS navigation software. // Copyright (C) 1997, 1999 Niels Elgaard Larsen // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Niels Elgaard Larsen, // // Garmin communication code is based on Gpstrans by Carsten Tschach // (tschach@zedat.fu-berlin.de) // FIXME: // Assumes only one GPS per EPS import java.net.*; import java.io.*; import java.awt.*; import java.util.*; class Garmincomm { /* define global variables */ static byte gGarminMessage[] = new byte[Gpsmessage.MAX_LENGTH]; static int NMEA_comm =48; static int GRM_comm = 96; static int mode = Gpsmessage.GARMIN; static Process gpsPrc; static int GPS_port =0; static boolean javaCommOK = true; static String NMEA_Port_init[] = new String[3]; static String GRM_Port_init[] = new String[3]; static File PortFile; static FileReader epscommNMEA; static OutputStream epscommRTCM; static RandomAccessFile epscommGRM; static OutputStream epscommOut; static InputStream epscommIn; static BufferedReader nmeaIn; // Mode does not work on win95! static void setup() { javaCommOK = GPS.javaCommOK; CAux.perr( "garminComm setup javacommOK="+javaCommOK,3 ); if (javaCommOK && GMenv.commAPI.equals("commapi")) { try { JavaxIO.setup(); // } catch (ClassNotFoundException cnfe) { } catch (NoClassDefFoundError cnfe) { javaCommOK = false; System.out.println("Garmincomm: No JAVA Communication API: "); } catch (Exception cnfe) { javaCommOK = false; System.out.println("Garmincm: No Java Communication API: "); } } else { if (! GMenv.isWin && GMenv.commAPI.equals("sttyapi")) { NMEA_Port_init[0] = GRM_Port_init[0] = "/bin/sh"; NMEA_Port_init[1] = GRM_Port_init[1] = "-c"; NMEA_Port_init[2] = "stty 4800 -parenb -istrip cs8 -inlcr ixany -ixon < " + GMenv.portName.wval; GRM_Port_init[2] = "stty 9600 -parenb -istrip cs8 -echo raw -onlret < " + GMenv.portName.wval; PortFile = new File(GMenv.portName.wval); } } } /****************************************************************************/ /* Calculate checksum, prepare package and send to GPS. */ /****************************************************************************/ static void sendAndGetMessage(byte message[], int bytes) { int ml=5; int err; do { Garmincomm.sendGPSMessage(message, 60); /* make sure GPS respond */ err=Garmincomm.getGPSMessage(); } while (gGarminMessage[1]==Gpsmessage.NACK && ml-- >0); } static void sendGPSMessage(byte message[], int bytes) { int i,xi=0; int pi; int nBytes; int csum = 0; byte pd[] = new byte[Gpsmessage.MAX_LENGTH]; pd[0] = 0x10; /* Define start of message */ CAux.perr( "sGPS " + bytes +" bytes",4); System.out.flush(); for (i = 0; i < bytes; i++) { xi++; pd[xi] = message[i]; csum += Getgpsinfo.ubyte(message[i]); if (message[i] == 0x10){ xi++; pd[xi] = 0x10; } } xi++; pd[xi++] = (byte)(256-(csum%256)); /* i hate this */ if (pd[xi-1] == 0x10) { pd[xi++] = 0x10; } CAux.perr( "csum "+csum + "="+(256-(csum%256)),9); pd[xi++] = 0x10; pd[xi++] = 0x03; nBytes = xi; int ii; CAux.perr( "sending="+nBytes,3); try { int step = 100; while (nBytes > 0) { epscommOut.write(pd,0,(nBytes>step)?step:nBytes); nBytes = nBytes-step; CAux.perr( "left="+nBytes,3); } } catch( IOException ex ) { System.out.println( "Failed write to port: " + ex ); ex.printStackTrace(); throw (new Error("Failed write to port")); } CAux.perr( "w sGPS ",4); System.out.flush(); } /****************************************************************************/ /* Sent a "are-you-ready" message to GPS - return TRUE if GPS responds or */ /* FALSE if GPS did not respond (GPS off? / incorrect format?) */ /****************************************************************************/ static boolean CheckGPS() { long count = 1L; byte p[] = gGarminMessage; byte last = 0; byte c; int err=0; byte theB; int px=0; int igot, i; short length = 0; /* Open device, FALSE if unable to open device */ CAux.perr(" GPS CheckGPS " ,4); if ((err = serialOpen(Garmincomm.GRM_comm)) != 0) { CAux.perr( "The port initialization of ?? has failed.",4); serialClose(); return false; } sendGPSMessage(Gpsmessage.test, 4); px=0; CAux.perr(" GPS check rcv: " ,7); while ( (px<2 || p[px-1] != 3 || p[px-2]!=0x10)) { if (px >= Gpsmessage.MAX_LENGTH-1) { CAux.perr("GPS check receiver communication protocol error.",4); mode = Gpsmessage.NONE; return (false); } try { // theB = epscommIn.read(); // p[px] = theB; epscommIn.read(p,px,1); //System.out.println("" + (int)theB ); } catch (IOException ee) { CAux.perr("read prb" + ee, 7); return(false); } if (px>0 && p[px] == 0x10 && p[px-1] == 0x10) { px--; } px ++; } CAux.perr("Check GPSsend OK got"+ p + " px=" +px, 6); serialClose(); return(true); } /****************************************************************************/ /* Get respond from GPS - returns number of bytes received, 0 if timeout */ /* period elapsed without completing a package. */ /****************************************************************************/ static int getGPSMessage() { CAux.perr( "get GPS* ",4); try { Thread.sleep(50L); } catch( InterruptedException exp ) { System.out.println( "int exp: " + exp ); } long count = 1L; byte pd[] = gGarminMessage; byte last = 0; byte c; int px; short length = 0; int igot, i; /* exit if timeout exceeded */ px = 0; while (px<2 || (pd[px-1] != 3 && pd[px-1] != 90) || pd[px-2]!=0x10) { if (px >= Gpsmessage.MAX_LENGTH-1) { CAux.perr(("GPS receiver communication protocol error. px " + px),4); mode = Gpsmessage.NONE; return 0; } try { epscommIn.read(pd,px,1); // pd[px] = epscommIn.readByte(); //System.out.println("r"+px + "rd="+pd[px]); } catch (IOException ee) { System.out.println("read" + ee); return(-1); } if (px>0 && pd[px] == 0x10 && pd[px-1] == 0x10){ px--; } px ++; } CAux.perr("Receiving: ", 4); CAux.perr("got GPS* ",4); return px; } static int serialOpen(int commType) { int err =0; CAux.perr( "open Serial: "+ commType, 3); setup(); CAux.perr( "open Serial: portName=\""+ GMenv.portName.wval + "\" commType=" + commType + " init= "+ GRM_Port_init[0]+ " " +GRM_Port_init[1]+" " +GRM_Port_init[2], 2); if (GPS.NMEAThread !=null) { // If both NMEA DISPLAY and DGPSIP CAux.perr( " NMEA Already open: "+ commType, 1); } if (GPS.DGPSIPThread !=null) { // If both NMEA DISPLAY and DGPSIP CAux.perr( " DGPS IPAlready open: "+ commType, 1); } if (javaCommOK) { JavaxIO.initPort(commType); } else if (! GMenv.isWin ) { try { int ch=1; gpsPrc=Runtime.getRuntime().exec(commType==NMEA_comm? NMEA_Port_init:GRM_Port_init); CAux.perr( "gpsPrc started exit="+err,3); } catch( IOException ex) { System.out.println( " exec error :"+ ex); ex.printStackTrace(); } catch( SecurityException ex) { System.out.println( " security exec error :"+ ex); ex.printStackTrace(); } try { err = gpsPrc.waitFor(); } catch(InterruptedException ex) { CAux.perr( "gpsPrc interrupted "+ex,-3); } try { if (commType == GRM_comm) { FileDescriptor theFD; // epscommGRM = new RandomAccessFile(portName.wval, "rw"); epscommOut = new FileOutputStream(GMenv.portName.wval); epscommIn = new FileInputStream(GMenv.portName.wval); CAux.perr("Get fd for "+GMenv.portName.wval,3); } else { CAux.perr("make RA fd ", 3); epscommNMEA = new FileReader(GMenv.portName.wval); epscommRTCM = new FileOutputStream(GMenv.portName.wval); nmeaIn = new BufferedReader(epscommNMEA,600); } } catch( IOException ex ) { System.out.println( "SERIAL port Failure "+ ex + "\n portFile=\""+PortFile+"\"" ); ex.printStackTrace(); } catch( SecurityException ex) { System.out.println( " rd error :"+ ex + "URL="); } CAux.perr("Return from serial open, err="+err,3); } return (err); } static int serialClose() { // close the port neat and clean after releasing objects CAux.perr(" GPS serialClose: ",2); if (javaCommOK && GMenv.isWin) { JavaxIO.cclose(); } else { try { if (epscommGRM != null){ epscommGRM.close(); epscommGRM=null; } } catch( IOException ex ) { System.out.println( "Failed write to I port: " + ex ); throw (new Error("Failed write to port")); } try { if (epscommNMEA != null){ epscommNMEA.close(); epscommNMEA=null; } } catch( IOException e ) { System.out.println( "Failed write to NMEA port: " + e ); throw (new Error("Failed write to port")); } } return(0); } }