private static String formatSentence(Position position) { StringBuilder s = new StringBuilder("$GPRMC,"); try (Formatter f = new Formatter(s, Locale.ENGLISH)) { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ENGLISH); calendar.setTimeInMillis(position.getFixTime().getTime()); f.format("%1$tH%1$tM%1$tS.%1$tL,A,", calendar); double lat = position.getLatitude(); double lon = position.getLongitude(); f.format("%02d%07.4f,%c,", (int) Math.abs(lat), Math.abs(lat) % 1 * 60, lat < 0 ? 'S' : 'N'); f.format("%03d%07.4f,%c,", (int) Math.abs(lon), Math.abs(lon) % 1 * 60, lon < 0 ? 'W' : 'E'); f.format("%.2f,%.2f,", position.getSpeed(), position.getCourse()); f.format("%1$td%1$tm%1$ty,,", calendar); } s.append(Checksum.nmea(s.toString())); return s.toString(); }
@Override protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; buf.skipBytes(2); // header buf.readUnsignedShort(); // length String imei = ChannelBuffers.hexDump(buf.readBytes(7)); if (!identify(imei, channel, null, false) && !identify(imei + Checksum.luhn(Long.parseLong(imei)), channel)) { return null; } int type = buf.readUnsignedShort(); if (type == MSG_LOCATION_REPORT || type == MSG_LOCATION_REQUEST) { String sentence = buf.toString(buf.readerIndex(), buf.readableBytes() - 8, Charset.defaultCharset()); Parser parser = new Parser(PATTERN, sentence); if (!parser.matches()) { return null; } Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); if (parser.hasNext(15)) { DateBuilder dateBuilder = new DateBuilder() .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); position.setTime(dateBuilder.getDate()); position.setValid(parser.next().equals("A")); position.set(Event.KEY_SATELLITES, parser.next()); position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG)); position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG)); position.setSpeed(parser.nextDouble()); position.set(Event.KEY_HDOP, parser.nextDouble()); position.setAltitude(parser.nextDouble()); } else { getLastLocation(position, null); } position.set(Event.KEY_MCC, parser.nextInt()); position.set(Event.KEY_MNC, parser.nextInt()); position.set(Event.KEY_LAC, parser.nextInt()); position.set(Event.KEY_CELL, parser.nextInt()); return position; } return null; }
private static boolean validateImei(long imei) { return Checksum.luhn(imei / 10) == imei % 10; }