Java tutorial
// Copyright 2012 (C) Matthew Brejza // // 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 3 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. package ukhas; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.apache.commons.codec.binary.Base64; public class Telemetry_string { public String callsign = ""; public Date time = null; public int packetID = 0; public Gps_coordinate coords; private String raw_string = ""; public String[] user_fields; public double frequency = 0; public boolean checksum_valid; private double[] extraFields; public String doc_time_created; public String getSentence() { return "$$" + raw_string + "\n"; } public Telemetry_string(String telem, TelemetryConfig tc) { parse_telem(telem, System.currentTimeMillis() / 1000L, tc); checksum_valid = check_checksum(telem, 0); //get time created Date time = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); String t = dateFormat.format(time); t = t.substring(0, t.length() - 2) + ":" + t.substring(t.length() - 2, t.length()); doc_time_created = t; } public Telemetry_string(String telem, long timerx, TelemetryConfig tc) { parse_telem(telem, timerx, tc); checksum_valid = check_checksum(telem, 0); //get time created Date time = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); String t = dateFormat.format(time); t = t.substring(0, t.length() - 2) + ":" + t.substring(t.length() - 2, t.length()); doc_time_created = t; } public Telemetry_string(String telem, boolean _checksum_valid, TelemetryConfig tc) { parse_telem(telem, System.currentTimeMillis() / 1000L, tc); checksum_valid = _checksum_valid; //get time created Date time = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); String t = dateFormat.format(time); t = t.substring(0, t.length() - 2) + ":" + t.substring(t.length() - 2, t.length()); doc_time_created = t; } private void parse_telem(String str, long timerx, TelemetryConfig tc) { int start = str.lastIndexOf('$'); if (start < 0) start = 0; else start++; raw_string = str.substring(start, str.length()).trim(); String[] fields; String[] cksplit = raw_string.split("\\*", 0); //remove checksum if (cksplit.length > 0) fields = cksplit[0].split("\\,", -1); else fields = raw_string.split("\\,", -1); if (fields.length > 6) { user_fields = new String[fields.length - 6]; System.arraycopy(fields, 6, user_fields, 0, fields.length - 6); } int ci = 0; int offset = 0; if (fields.length > 1) { //see if counter exists ci = fields[1].indexOf(':'); offset = 0; if (ci > 0) offset = -1; } if (fields.length >= 6 + offset) { callsign = fields[0]; //handle time SimpleDateFormat ft; if (fields[2 + offset].length() > 6) ft = new SimpleDateFormat("HH:mm:ss"); else ft = new SimpleDateFormat("HHmmss"); try //this is all a bit horrible :( { if (offset == 0) packetID = Integer.parseInt(fields[1]); //get time rx @ 12am Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("UTC")); ft.setTimeZone(TimeZone.getTimeZone("UTC")); time = ft.parse(fields[2 + offset]); cal2.setTime(time); cal.setTimeInMillis(timerx * 1000); cal.set(Calendar.HOUR_OF_DAY, cal2.get(Calendar.HOUR_OF_DAY)); cal.set(Calendar.MINUTE, cal2.get(Calendar.MINUTE)); cal.set(Calendar.SECOND, cal2.get(Calendar.SECOND)); //long best_guess = cal2.getTimeInMillis(); if (cal.getTimeInMillis() < timerx * 1000 - 1 * 60 * 60 * 1000) cal.roll(Calendar.DAY_OF_YEAR, 1); if (cal.getTimeInMillis() < timerx * 1000 + 12 * 60 * 60 * 1000) ; else cal.roll(Calendar.DAY_OF_YEAR, -1); time = cal.getTime(); } catch (Exception e) { System.out.println("Error parsing - " + e.toString()); } coords = new Gps_coordinate(fields[3 + offset], fields[4 + offset], fields[5 + offset]); //now parse extra data extraFields = new double[fields.length - 1]; for (int j = 6 + offset; j < fields.length; j++) { if (tc == null) { try { extraFields[j - 1] = Double.parseDouble(fields[j]); } catch (Exception e) { } } else if (tc.getTotalFields() <= j - 1) { try { extraFields[j - 1] = Double.parseDouble(fields[j]); } catch (Exception e) { } } else { if (tc.getFieldDataType(j - 1) == TelemetryConfig.DataType.FLOAT) { try { extraFields[j - 1] = Double.parseDouble(fields[j]); } catch (Exception e) { } } else if (tc.getFieldDataType(j - 1) == TelemetryConfig.DataType.INT) { try { extraFields[j - 1] = (double) Integer.parseInt(fields[j]); } catch (Exception e) { } } } } } } public boolean getExtraFieldExists(int index) { if (extraFields == null) return false; if (!(index < extraFields.length)) return false; return true; } public double getExtraFields(int index) { if (index < 0) return 0; if (extraFields == null) return 0; if (!(index < extraFields.length)) return 0; return extraFields[index]; } public String toSha256() { String str = "$$" + raw_string + "\n"; byte[] enc = Base64.encodeBase64(str.getBytes()); byte[] sha = null; MessageDigest md; try { md = MessageDigest.getInstance("SHA-256"); md.update(enc); sha = md.digest(); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bytesToHexStr(sha); } //ref: http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-java public static String bytesToHexStr(byte[] bytes) { final char[] hexArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char[] hexChars = new char[bytes.length * 2]; int v; for (int j = 0; j < bytes.length; j++) { v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } public String raw_64_str() { String str = "$$" + raw_string + "\n"; byte[] enc = Base64.encodeBase64(str.getBytes()); String out = new String(enc); return out; } public static boolean check_checksum(String in, int start) { int crc = 0xFFFF; int i = 0; while (i < in.length() && in.charAt(i) != '*') { if (in.charAt(i) != '$') { int j; crc = (crc ^ (in.charAt(i) << 8)); for (j = 0; j < 8; j++) { if ((crc & 0x8000) != 0) crc = ((crc << 1) ^ 0x1021); else crc = (crc << 1); } } i++; } int ckloc = in.indexOf((int) '*', start); if (ckloc < 0) return false; if (ckloc + 4 >= in.length()) return false; //now extract checksum based on its known location and compare String crcstr = in.substring(ckloc + 1, ckloc + 5); crcstr = crcstr.toLowerCase(); for (i = 0; i < crcstr.length(); i++) { int c = (int) crcstr.charAt(i); if (c < 48 || c > 102 || (c < 97 && c > 57)) return false; } int rccrc = Integer.parseInt(crcstr, 16); if (rccrc == (crc & 0xFFFF)) return true; else return false; } public boolean isZeroGPS() { return (coords.latitude == 0.0 || coords.longitude == 0.0); } }