From bfaa57707b8a9d9dc122e139a06b3632a749c628 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 20 Oct 2015 11:19:29 +1300 Subject: Refactor Megastek protocol decoder --- .../traccar/protocol/MegastekProtocolDecoder.java | 370 +++++++++------------ 1 file changed, 161 insertions(+), 209 deletions(-) (limited to 'src/org/traccar/protocol/MegastekProtocolDecoder.java') diff --git a/src/org/traccar/protocol/MegastekProtocolDecoder.java b/src/org/traccar/protocol/MegastekProtocolDecoder.java index 17e9dc6d7..4b957b879 100644 --- a/src/org/traccar/protocol/MegastekProtocolDecoder.java +++ b/src/org/traccar/protocol/MegastekProtocolDecoder.java @@ -16,12 +16,12 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; -import java.util.TimeZone; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.DateBuilder; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; import org.traccar.model.Event; import org.traccar.model.Position; @@ -31,96 +31,68 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static final Pattern PATTERN_GPRMC = Pattern.compile( - "\\$GPRMC," + - "(\\d{2})(\\d{2})(\\d{2})\\.\\d+," + // Time (HHMMSS.SSS) - "([AV])," + // Validity - "(\\d+)(\\d{2}\\.\\d+)," + // Latitude (DDMM.MMMM) - "([NS])," + - "(\\d+)(\\d{2}\\.\\d+)," + // Longitude (DDDMM.MMMM) - "([EW])," + - "(\\d+\\.\\d+)?," + // Speed - "(\\d+\\.\\d+)?," + // Course - "(\\d{2})(\\d{2})(\\d{2})" + // Date (DDMMYY) - ".*"); // Checksum - - private static final Pattern PATTERN_SIMPLE = Pattern.compile( - "[FL]," + // Flag - "([^,]*)," + // Alarm - "imei:(\\d+)," + // IMEI - "(\\d+/?\\d*)?," + // Satellites - "(\\d+\\.\\d+)?," + // Altitude - "Battery=(\\d+)%,," + // Battery - "(\\d)?," + // Charger - "(\\d+)?," + // MCC - "(\\d+)?," + // MNC - "(\\p{XDigit}{4},\\p{XDigit}{4});" + // Location code - ".+"); // Checksum - - private static final Pattern PATTERN_ALTERNATIVE = Pattern.compile( - "(\\d+)," + // MCC - "(\\d+)," + // MNC - "(\\p{XDigit}{4},\\p{XDigit}{4})," + // Location code - "(\\d+)," + // GSM signal - "(\\d+)," + // Battery - "(\\d+)," + // Flags - "(\\d+)," + // Inputs - "(?:(\\d+),)?" + // Outputs - "(\\d\\.?\\d*)," + // ADC 1 - "(?:(\\d\\.\\d{2})," + // ADC 2 - "(\\d\\.\\d{2}),)?" + // ADC 3 - "([^;]+);" + // Alarm - ".*"); // Checksum - - private boolean parseGPRMC(String gprmc, Position position) { - - // Parse message - Matcher parser = PATTERN_GPRMC.matcher(gprmc); + private static final Pattern PATTERN_GPRMC = new PatternBuilder() + .txt("$GPRMC,") + .num("(dd)(dd)(dd).d+,") // time + .xpr("([AV]),") // validity + .num("(d+)(dd.d+),([NS]),") // latitude + .num("(d+)(dd.d+),([EW]),") // longitude + .num("(d+.d+)?,") // speed + .num("(d+.d+)?,") // course + .num("(dd)(dd)(dd)") // date (ddmmyy) + .any() // checksum + .compile(); + + private static final Pattern PATTERN_SIMPLE = new PatternBuilder() + .xpr("[FL],") // flag + .xpr("([^,]*),") // alarm + .num("imei:(d+),") // imei + .num("(d+/?d*)?,") // satellites + .num("(d+.d+)?,") // altitude + .num("Battery=(d+)%,,") // battery + .num("(d)?,") // charger + .num("(d+)?,") // mcc + .num("(d+)?,") // mnc + .num("(xxxx,xxxx);") // location code + .any() // checksum + .compile(); + + private static final Pattern PATTERN_ALTERNATIVE = new PatternBuilder() + .num("(d+),") // mcc + .num("(d+),") // mnc + .num("(xxxx,xxxx),") // location code + .num("(d+),") // gsm signal + .num("(d+),") // battery + .num("(d+),") // flags + .num("(d+),") // inputs + .num("(?:(d+),)?") // outputs + .num("(d.?d*),") // adc 1 + .groupBegin() + .num("(d.dd),") // adc 2 + .num("(d.dd),") // adc 3 + .groupEnd(true) + .xpr("([^;]+);") // alarm + .any() // checksum + .compile(); + + private boolean parseLocation(String location, Position position) { + + Parser parser = new Parser(PATTERN_GPRMC, location); if (!parser.matches()) { return false; } - int index = 1; - - // Time - Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - time.clear(); - time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++))); - time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++))); - time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++))); - - // Validity - position.setValid(parser.group(index++).compareTo("A") == 0); - - // Latitude - Double latitude = Double.parseDouble(parser.group(index++)); - latitude += Double.parseDouble(parser.group(index++)) / 60; - if (parser.group(index++).compareTo("S") == 0) latitude = -latitude; - position.setLatitude(latitude); - - // Longitude - Double longitude = Double.parseDouble(parser.group(index++)); - longitude += Double.parseDouble(parser.group(index++)) / 60; - if (parser.group(index++).compareTo("W") == 0) longitude = -longitude; - position.setLongitude(longitude); - - // Speed - String speed = parser.group(index++); - if (speed != null) { - position.setSpeed(Double.parseDouble(speed)); - } + DateBuilder dateBuilder = new DateBuilder() + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); - // Course - String course = parser.group(index++); - if (course != null) { - position.setCourse(Double.parseDouble(course)); - } + position.setValid(parser.next().equals("A")); + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + position.setSpeed(parser.nextDouble()); + position.setCourse(parser.nextDouble()); - // Date - time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++))); - time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1); - time.set(Calendar.YEAR, 2000 + Integer.parseInt(parser.group(index++))); - position.setTime(time.getTime()); + dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); return true; } @@ -132,7 +104,7 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { // Split message String id; - String gprmc; + String location; String status; if (simple) { @@ -147,7 +119,7 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { } else { endIndex = sentence.length(); } - gprmc = sentence.substring(beginIndex, endIndex); + location = sentence.substring(beginIndex, endIndex); beginIndex = endIndex + 1; if (beginIndex > sentence.length()) { @@ -163,54 +135,45 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { beginIndex = endIndex + 2; endIndex = sentence.indexOf('*', beginIndex) + 3; - gprmc = sentence.substring(beginIndex, endIndex); + location = sentence.substring(beginIndex, endIndex); beginIndex = endIndex + 1; status = sentence.substring(beginIndex); } - // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); - - // Parse location data - if (!parseGPRMC(gprmc, position)) { + if (!parseLocation(location, position)) { return null; } if (simple) { - Matcher parser = PATTERN_SIMPLE.matcher(status); + Parser parser = new Parser(PATTERN_SIMPLE, status); if (parser.matches()) { - int index = 1; - - position.set(Event.KEY_ALARM, parser.group(index++)); + position.set(Event.KEY_ALARM, parser.next()); - // IMEI - if (!identify(parser.group(index++), channel, null, false) && !identify(id, channel)) { + if (!identify(parser.next(), channel, null, false) && !identify(id, channel)) { return null; } position.setDeviceId(getDeviceId()); - position.set(Event.KEY_SATELLITES, parser.group(index++)); + position.set(Event.KEY_SATELLITES, parser.next()); - String altitude = parser.group(index++); - if (altitude != null) { - position.setAltitude(Double.parseDouble(altitude)); - } + position.setAltitude(parser.nextDouble()); - position.set(Event.KEY_POWER, Double.parseDouble(parser.group(index++))); + position.set(Event.KEY_POWER, parser.nextDouble()); - String charger = parser.group(index++); + String charger = parser.next(); if (charger != null) { position.set(Event.KEY_CHARGE, Integer.parseInt(charger) == 1); } - position.set(Event.KEY_MCC, parser.group(index++)); - position.set(Event.KEY_MNC, parser.group(index++)); - position.set(Event.KEY_LAC, parser.group(index++)); + position.set(Event.KEY_MCC, parser.next()); + position.set(Event.KEY_MNC, parser.next()); + position.set(Event.KEY_LAC, parser.next()); } else { @@ -223,155 +186,144 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { } else { - Matcher parser = PATTERN_ALTERNATIVE.matcher(status); - if (!parser.matches()) { - - int index = 1; + Parser parser = new Parser(PATTERN_ALTERNATIVE, status); + if (parser.matches()) { if (!identify(id, channel)) { return null; } position.setDeviceId(getDeviceId()); - position.set(Event.KEY_MCC, parser.group(index++)); - position.set(Event.KEY_MNC, parser.group(index++)); - position.set(Event.KEY_LAC, parser.group(index++)); - position.set(Event.KEY_GSM, parser.group(index++)); + position.set(Event.KEY_MCC, parser.next()); + position.set(Event.KEY_MNC, parser.next()); + position.set(Event.KEY_LAC, parser.next()); + position.set(Event.KEY_GSM, parser.next()); - position.set(Event.KEY_BATTERY, Double.parseDouble(parser.group(index++))); + position.set(Event.KEY_BATTERY, Double.parseDouble(parser.next())); + + position.set(Event.KEY_FLAGS, parser.next()); + position.set(Event.KEY_INPUT, parser.next()); + position.set(Event.KEY_OUTPUT, parser.next()); + position.set(Event.PREFIX_ADC + 1, parser.next()); + position.set(Event.PREFIX_ADC + 2, parser.next()); + position.set(Event.PREFIX_ADC + 3, parser.next()); + position.set(Event.KEY_ALARM, parser.next()); - position.set(Event.KEY_FLAGS, parser.group(index++)); - position.set(Event.KEY_INPUT, parser.group(index++)); - position.set(Event.KEY_OUTPUT, parser.group(index++)); - position.set(Event.PREFIX_ADC + 1, parser.group(index++)); - position.set(Event.PREFIX_ADC + 2, parser.group(index++)); - position.set(Event.PREFIX_ADC + 3, parser.group(index++)); - position.set(Event.KEY_ALARM, parser.group(index++)); } } return position; } - private static final Pattern PATTERN_NEW = Pattern.compile( - "\\$MGV\\d{3}," + - "(\\d+)," + // IMEI - "[^,]*," + // Name - "([RS])," + - "(\\d{2})(\\d{2})(\\d{2})," + // Date (DDMMYY) - "(\\d{2})(\\d{2})(\\d{2})," + // Time (HHMMSS) - "([AV])," + // Validity - "(\\d+)(\\d{2}\\.\\d+)," + // Latitude (DDMM.MMMM) - "([NS])," + - "(\\d+)(\\d{2}\\.\\d+)," + // Longitude (DDDMM.MMMM) - "([EW])," + - "\\d{2}," + - "(\\d{2})," + // Satellites - "\\d{2}," + - "(\\d+\\.\\d+)," + // HDOP - "(\\d+\\.\\d+)," + // Speed - "(\\d+\\.\\d+)," + // Course - "(\\d+\\.\\d+)," + // Altitude - "(\\d+\\.\\d+)," + // Odometer - "(\\d+)," + // MCC - "(\\d+)," + // MNC - "(\\p{XDigit}{4},\\p{XDigit}{4})," + // Cell - "(\\d+)?," + // GSM - "([01]+)," + // Input - "([01]+)," + // Output - "(\\d+)," + // ADC1 - "(\\d+)," + // ADC2 - "(\\d+)," + // ADC3 - "(?:(-?\\d+\\.?\\d*)| )," + // Temperature 1 - "(?:(-?\\d+\\.?\\d*)| )," + // Temperature 2 - "(\\d+)?,," + // RFID - "(\\d+)?," + // Battery - "([^,]*);" + // Alert - ".*"); + private static final Pattern PATTERN_NEW = new PatternBuilder() + .txt("$MGV") + .num("ddd,") + .num("(d+),") // imei + .nxt(",") // name + .xpr("([RS]),") + .num("(dd)(dd)(dd),") // date (ddmmyy) + .num("(dd)(dd)(dd),") // time + .xpr("([AV]),") // validity + .num("(d+)(dd.d+),([NS]),") // latitude + .num("(d+)(dd.d+),([EW]),") // longitude + .num("dd,") + .num("(dd),") // satellites + .num("dd,") + .num("(d+.d+),") // hdop + .num("(d+.d+),") // speed + .num("(d+.d+),") // course + .num("(d+.d+),") // altitude + .num("(d+.d+),") // odometer + .num("(d+),") // mcc + .num("(d+),") // mnc + .num("(xxxx,xxxx),") // cell + .num("(d+)?,") // gsm + .xpr("([01]+),") // input + .xpr("([01]+),") // output + .num("(d+),") // adc1 + .num("(d+),") // adc2 + .num("(d+),") // adc3 + .groupBegin() + .num("(-?d+.?d*)") // temperature 1 + .or().txt(" ") + .groupEnd(false).txt(",") + .groupBegin() + .num("(-?d+.?d*)") // temperature 2 + .or().txt(" ") + .groupEnd(false).txt(",") + .num("(d+)?,,") // rfid + .num("(d+)?,") // battery + .xpr("([^,]*);") // alert + .any() + .compile(); private Position decodeNew(Channel channel, String sentence) { - Matcher parser = PATTERN_NEW.matcher(sentence); + Parser parser = new Parser(PATTERN_NEW, sentence); if (!parser.matches()) { return null; } - int index = 1; Position position = new Position(); position.setProtocol(getProtocolName()); - if (!identify(parser.group(index++), channel)) { + if (!identify(parser.next(), channel)) { return null; } position.setDeviceId(getDeviceId()); - if (parser.group(index++).equals("S")) { + if (parser.next().equals("S")) { position.set(Event.KEY_ARCHIVE, true); } - Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - time.clear(); - time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++))); - time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1); - time.set(Calendar.YEAR, 2000 + Integer.parseInt(parser.group(index++))); - time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++))); - time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++))); - time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++))); - position.setTime(time.getTime()); - - position.setValid(parser.group(index++).equals("A")); - - // Latitude - double latitude = Double.parseDouble(parser.group(index++)); - latitude += Double.parseDouble(parser.group(index++)) / 60; - if (parser.group(index++).equals("S")) latitude = -latitude; - position.setLatitude(latitude); - - // Longitude - double longitude = Double.parseDouble(parser.group(index++)); - longitude += Double.parseDouble(parser.group(index++)) / 60; - if (parser.group(index++).equals("W")) longitude = -longitude; - position.setLongitude(longitude); - - position.set(Event.KEY_SATELLITES, Integer.parseInt(parser.group(index++))); - position.set(Event.KEY_HDOP, Double.parseDouble(parser.group(index++))); - - position.setSpeed(Double.parseDouble(parser.group(index++))); - position.setCourse(Double.parseDouble(parser.group(index++))); - position.setAltitude(Double.parseDouble(parser.group(index++))); - - position.set(Event.KEY_ODOMETER, Double.parseDouble(parser.group(index++))); - position.set(Event.KEY_MCC, Integer.parseInt(parser.group(index++))); - position.set(Event.KEY_MNC, Integer.parseInt(parser.group(index++))); - position.set(Event.KEY_CELL, parser.group(index++)); - - String gsm = parser.group(index++); + DateBuilder dateBuilder = new DateBuilder() + .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()) + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); + + position.setValid(parser.next().equals("A")); + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + + position.set(Event.KEY_SATELLITES, parser.nextInt()); + position.set(Event.KEY_HDOP, parser.nextDouble()); + + position.setSpeed(parser.nextDouble()); + position.setCourse(parser.nextDouble()); + position.setAltitude(parser.nextDouble()); + + position.set(Event.KEY_ODOMETER, parser.nextDouble()); + position.set(Event.KEY_MCC, parser.nextInt()); + position.set(Event.KEY_MNC, parser.nextInt()); + position.set(Event.KEY_CELL, parser.next()); + + String gsm = parser.next(); if (gsm != null) { position.set(Event.KEY_GSM, Integer.parseInt(gsm)); } - position.set(Event.KEY_INPUT, Integer.parseInt(parser.group(index++), 2)); - position.set(Event.KEY_OUTPUT, Integer.parseInt(parser.group(index++), 2)); + position.set(Event.KEY_INPUT, parser.nextInt(2)); + position.set(Event.KEY_OUTPUT, parser.nextInt(2)); for (int i = 1; i <= 3; i++) { - position.set(Event.PREFIX_ADC + i, Integer.parseInt(parser.group(index++))); + position.set(Event.PREFIX_ADC + i, parser.nextInt()); } for (int i = 1; i <= 2; i++) { - String adc = parser.group(index++); + String adc = parser.next(); if (adc != null) { position.set(Event.PREFIX_TEMP + i, Double.parseDouble(adc)); } } - position.set(Event.KEY_RFID, parser.group(index++)); + position.set(Event.KEY_RFID, parser.next()); - String battery = parser.group(index++); + String battery = parser.next(); if (battery != null) { position.set(Event.KEY_BATTERY, Integer.parseInt(battery)); } - position.set(Event.KEY_ALARM, parser.group(index++)); + position.set(Event.KEY_ALARM, parser.next()); return position; } -- cgit v1.2.3