package altimeter; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.UnsupportedCommOperationException; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.TimeZone; /** * Class to interface the PerfectFlite Alt15K/WD altimeter. * * Also includes a main method that retrieves all flight profiles and saves them to files. * * @author Sampo Niskanen */ public class Alt15K { public static final int TIMEOUT = 500; public static final int RWDELAY = 5; private static final boolean DEBUG = false; private static final Charset CHARSET = StandardCharsets.ISO_8859_1; private final CommPortIdentifier portID; private SerialPort port = null; private InputStream is = null; private OutputStream os = null; public static String[] getNames() { ArrayList list = new ArrayList(); Enumeration pids = CommPortIdentifier.getPortIdentifiers(); while (pids.hasMoreElements()) { CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement(); if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL) list.add(pid.getName()); } return list.toArray(new String[0]); } public Alt15K(String name) throws IOException { CommPortIdentifier pID = null; Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers(); while (portIdentifiers.hasMoreElements()) { CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement(); if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL && pid.getName().equals(name)) { pID = pid; break; } } if (pID==null) { throw new IOException("Port '"+name+"' not found."); } this.portID = pID; } /** * Get altimeter flight data. The flight profile is chosen by the parameter n, * 0 = latest flight, 1 = second latest, etc. * * @param n Which flight profile to use (0=newest, 1=second newest, etc) * @return The altimeter flight data * @throws IOException in case of IOException * @throws PortInUseException in case of PortInUseException */ public AltData getData(int n) throws IOException, PortInUseException { AltData alt = new AltData(); ArrayList data = new ArrayList(); byte[] buf; byte[] buf2 = new byte[0]; boolean identical = false; // Whether identical lines have been read if (DEBUG) System.out.println(" Retrieving altimeter data n="+n); try { open(); // Get version and position data byte[] ver = getVersionData(); alt.setVersion(new byte[] { ver[0],ver[1] }); // Calculate the position requested if (n > 2) n = 2; int position = ver[2] - n; while (position < 0) position += 3; if (DEBUG) System.out.println(" Requesting data from position "+position); // Request the data write("D"); write((byte)position); write("PS"); sleep(); // Read preliminary data buf = read(4); int msl_level = combine(buf[0],buf[1]); int datacount = combine(buf[2],buf[3]); if (DEBUG) System.out.println(" Preliminary data msl="+msl_level+" count="+datacount); alt.setMslLevel(msl_level-6000); alt.setDataSamples(datacount); if (DEBUG) System.out.println(" Retrieving "+datacount+" samples"); long t = System.currentTimeMillis(); int count = 0; while (count < datacount) { sleep(); write("G"); sleep(); buf = read(17); if (buf.length == 17) { // Checksum = sum of all bytes + 1 // (signedness does not change the result) byte checksum = 1; for (int i=0; i<16; i++) checksum += buf[i]; if (checksum != buf[16]) { printBytes("ERROR: Checksum fail on data (computed="+checksum+ " orig="+buf[16]+")",buf); System.out.println("Ignoring error"); } } else { System.err.println("ERROR: Only "+buf.length+" bytes read, should be 17"); } for (int i=0; i 0) { System.err.println("ERROR: Data available after transfer! (length="+buf.length+")"); } // Create an int[] array and set it int[] d = new int[data.size()]; for (int i=0; i"); System.err.println("Files will be saved -old.log, -med and -new"); return; } String device = null; String[] devices = Alt15K.getNames(); for (int i=0; i= 0) return b; else return 256 + b; } @SuppressWarnings("unused") static private int combine(int a, int b) { return 256*a + b; } static private int combine(byte a, byte b) { int val = 256*unsign(a)+unsign(b); if (val <= 32767) return val; else return val-65536; } }