diff options
Diffstat (limited to 'src/org/traccar/protocol/Gl200TextProtocolDecoder.java')
-rw-r--r-- | src/org/traccar/protocol/Gl200TextProtocolDecoder.java | 1266 |
1 files changed, 0 insertions, 1266 deletions
diff --git a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java b/src/org/traccar/protocol/Gl200TextProtocolDecoder.java deleted file mode 100644 index aeb57a116..000000000 --- a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.traccar.protocol; - -import org.traccar.BaseProtocolDecoder; -import org.traccar.Context; -import org.traccar.DeviceSession; -import org.traccar.NetworkMessage; -import org.traccar.Protocol; -import org.traccar.helper.BitUtil; -import org.traccar.helper.Parser; -import org.traccar.helper.PatternBuilder; -import org.traccar.helper.UnitsConverter; -import org.traccar.model.CellTower; -import org.traccar.model.Network; -import org.traccar.model.Position; -import org.traccar.model.WifiAccessPoint; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.Channel; - -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.LinkedList; -import java.util.List; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Gl200TextProtocolDecoder extends BaseProtocolDecoder { - - private boolean ignoreFixTime; - - public Gl200TextProtocolDecoder(Protocol protocol) { - super(protocol); - - ignoreFixTime = Context.getConfig().getBoolean(getProtocolName() + ".ignoreFixTime"); - } - - private static final Pattern PATTERN_ACK = new PatternBuilder() - .text("+ACK:GT") - .expression("...,") // type - .number("([0-9A-Z]{2}xxxx),") // protocol version - .number("(d{15}|x{14}),") // imei - .any().text(",") - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd),") // time (hhmmss) - .number("(xxxx)") // counter - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_INF = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF):GTINF,") - .number("[0-9A-Z]{2}xxxx,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("(?:[0-9A-Z]{17},)?") // vin - .expression("(?:[^,]+)?,") // device name - .number("(xx),") // state - .expression("(?:[0-9Ff]{20})?,") // iccid - .number("(d{1,2}),") // rssi - .number("d{1,2},") - .expression("[01],") // external power - .number("([d.]+)?,") // odometer or external power - .number("d*,") // backup battery or lightness - .number("(d+.d+),") // battery - .expression("([01]),") // charging - .number("(?:d),") // led - .number("(?:d)?,") // gps on need - .number("(?:d)?,") // gps antenna type - .number("(?:d)?,").optional() // gps antenna state - .number("d{14},") // last fix time - .groupBegin() - .number("(d+),") // battery percentage - .number("[d.]*,") // flash type / power - .number("(-?[d.]+)?,,,") // temperature - .or() - .expression("(?:[01])?,").optional() // pin15 mode - .number("(d+)?,") // adc1 - .number("(d+)?,").optional() // adc2 - .number("(xx)?,") // digital input - .number("(xx)?,") // digital output - .number("[-+]dddd,") // timezone - .expression("[01],") // daylight saving - .groupEnd() - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd),") // time (hhmmss) - .number("(xxxx)") // counter - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_VER = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF):GTVER,") - .number("[0-9A-Z]{2}xxxx,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .expression("([^,]*),") // device type - .number("(xxxx),") // firmware version - .number("(xxxx),") // hardware version - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd),") // time (hhmmss) - .number("(xxxx)") // counter - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_LOCATION = new PatternBuilder() - .number("(d{1,2})?,") // hdop - .number("(d{1,3}.d)?,") // speed - .number("(d{1,3})?,") // course - .number("(-?d{1,5}.d)?,") // altitude - .number("(-?d{1,3}.d{6})?,") // longitude - .number("(-?d{1,2}.d{6})?,") // latitude - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(d+)?,") // mcc - .number("(d+)?,") // mnc - .groupBegin() - .number("(d+),") // lac - .number("(d+),") // cid - .or() - .number("(x+)?,") // lac - .number("(x+)?,") // cid - .groupEnd() - .number("(?:d+|(d+.d))?,") // odometer - .compile(); - - private static final Pattern PATTERN_OBD = new PatternBuilder() - .text("+RESP:GTOBD,") - .number("[0-9A-Z]{2}xxxx,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("(?:[0-9A-Z]{17})?,") // vin - .expression("[^,]{0,20},") // device name - .expression("[01],") // report type - .number("x{1,8},") // report mask - .expression("(?:[0-9A-Z]{17})?,") // vin - .number("[01],") // obd connect - .number("(?:d{1,5})?,") // obd voltage - .number("(?:x{8})?,") // support pids - .number("(d{1,5})?,") // engine rpm - .number("(d{1,3})?,") // speed - .number("(-?d{1,3})?,") // coolant temp - .number("(d+.?d*|Inf|NaN)?,") // fuel consumption - .number("(d{1,5})?,") // dtcs cleared distance - .number("(?:d{1,5})?,") - .expression("([01])?,") // obd connect - .number("(d{1,3})?,") // number of dtcs - .number("(x*),") // dtcs - .number("(d{1,3})?,") // throttle - .number("(?:d{1,3})?,") // engine load - .number("(d{1,3})?,") // fuel level - .expression("(?:[0-9A],)?") // obd protocol - .number("(d+),") // odometer - .expression(PATTERN_LOCATION.pattern()) - .number("(d{1,7}.d)?,") // odometer - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_FRI = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF):GT...,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("(?:([0-9A-Z]{17}),)?") // vin - .expression("[^,]*,") // device name - .number("(d+)?,") // power - .number("d{1,2},").optional() // report type - .number("d{1,2},").optional() // count - .number(",").optional() // reserved - .number("(d+),").optional() // battery - .expression("((?:") - .expression(PATTERN_LOCATION.pattern()) - .expression(")+)") - .groupBegin() - .number("(d{1,7}.d)?,") // odometer - .number("(d{5}:dd:dd)?,") // hour meter - .number("(x+)?,") // adc 1 - .number("(x+)?,") // adc 2 - .number("(d{1,3})?,") // battery - .number("(?:(xx)(xx)(xx))?,") // device status - .number("(d+)?,") // rpm - .number("(?:d+.?d*|Inf|NaN)?,") // fuel consumption - .number("(d+)?,") // fuel level - .or() - .number("(d{1,7}.d)?,").optional() // odometer - .number("(d{1,3})?,") // battery - .groupEnd() - .any() - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_ERI = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF):GTERI,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .number("(x{8}),") // mask - .number("(d+)?,") // power - .number("d{1,2},") // report type - .number("d{1,2},") // count - .expression("((?:") - .expression(PATTERN_LOCATION.pattern()) - .expression(")+)") - .number("(d{1,7}.d)?,") // odometer - .number("(d{5}:dd:dd)?,") // hour meter - .number("(x+)?,") // adc 1 - .number("(x+)?,").optional() // adc 2 - .number("(d{1,3})?,") // battery - .number("(?:(xx)(xx)(xx))?,") // device status - .expression("(.*)") // additional data - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_IGN = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF):GTIG[NF],") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .number("d+,") // ignition off duration - .expression(PATTERN_LOCATION.pattern()) - .number("(d{5}:dd:dd)?,") // hour meter - .number("(d{1,7}.d)?,") // odometer - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_LSW = new PatternBuilder() - .text("+RESP:").expression("GT[LT]SW,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .number("[01],") // type - .number("([01]),") // state - .expression(PATTERN_LOCATION.pattern()) - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_IDA = new PatternBuilder() - .text("+RESP:GTIDA,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,,") // device name - .number("([^,]+),") // rfid - .expression("[01],") // report type - .number("1,") // count - .expression(PATTERN_LOCATION.pattern()) - .number("(d+.d),") // odometer - .text(",,,,") - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_WIF = new PatternBuilder() - .text("+RESP:GTWIF,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .number("(d+),") // count - .number("((?:x{12},-?d+,,,,)+),,,,") // wifi - .number("(d{1,3}),") // battery - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_GSM = new PatternBuilder() - .text("+RESP:GTGSM,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("(?:STR|CTN|NMR|RTL),") // fix type - .expression("(.*)") // cells - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_PNA = new PatternBuilder() - .text("+RESP:GT").expression("P[NF]A,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF):GT...,") - .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version - .number("(d{15}|x{14}),") // imei - .expression("[^,]*,") // device name - .number("d*,") - .number("(x{1,2}),") // report type - .number("d{1,2},") // count - .expression(PATTERN_LOCATION.pattern()) - .groupBegin() - .number("(d{1,7}.d)?,").optional() // odometer - .number("(d{1,3})?,") // battery - .or() - .number("(d{1,7}.d)?,") // odometer - .groupEnd() - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)") // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private static final Pattern PATTERN_BASIC = new PatternBuilder() - .text("+").expression("(?:RESP|BUFF)").text(":") - .expression("GT...,") - .number("(?:[0-9A-Z]{2}xxxx)?,").optional() // protocol version - .number("(d{15}|x{14}),") // imei - .any() - .number("(d{1,2})?,") // hdop - .number("(d{1,3}.d)?,") // speed - .number("(d{1,3})?,") // course - .number("(-?d{1,5}.d)?,") // altitude - .number("(-?d{1,3}.d{6})?,") // longitude - .number("(-?d{1,2}.d{6})?,") // latitude - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(d+),") // mcc - .number("(d+),") // mnc - .number("(x+),") // lac - .number("(x+),").optional(4) // cell - .any() - .number("(dddd)(dd)(dd)") // date (yyyymmdd) - .number("(dd)(dd)(dd)").optional(2) // time (hhmmss) - .text(",") - .number("(xxxx)") // count number - .text("$").optional() - .compile(); - - private Object decodeAck(Channel channel, SocketAddress remoteAddress, String sentence, String type) { - Parser parser = new Parser(PATTERN_ACK, sentence); - if (parser.matches()) { - String protocolVersion = parser.next(); - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); - if (deviceSession == null) { - return null; - } - if (type.equals("HBD")) { - if (channel != null) { - parser.skip(6); - channel.writeAndFlush(new NetworkMessage( - "+SACK:GTHBD," + protocolVersion + "," + parser.next() + "$", remoteAddress)); - } - } else { - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - getLastLocation(position, parser.nextDateTime()); - position.setValid(false); - position.set(Position.KEY_RESULT, "Command " + type + " accepted"); - return position; - } - } - return null; - } - - private Position initPosition(Parser parser, Channel channel, SocketAddress remoteAddress) { - if (parser.matches()) { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); - if (deviceSession != null) { - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - return position; - } - } - return null; - } - - private void decodeDeviceTime(Position position, Parser parser) { - if (parser.hasNext(6)) { - if (ignoreFixTime) { - position.setTime(parser.nextDateTime()); - } else { - position.setDeviceTime(parser.nextDateTime()); - } - } - } - - private Long parseHours(String hoursString) { - if (hoursString != null) { - String[] hours = hoursString.split(":"); - return (long) (Integer.parseInt(hours[0]) * 3600 - + (hours.length > 1 ? Integer.parseInt(hours[1]) * 60 : 0) - + (hours.length > 2 ? Integer.parseInt(hours[2]) : 0)) * 1000; - } - return null; - } - - private Object decodeInf(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_INF, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - switch (parser.nextHexInt()) { - case 0x16: - case 0x1A: - case 0x12: - position.set(Position.KEY_IGNITION, false); - position.set(Position.KEY_MOTION, true); - break; - case 0x11: - position.set(Position.KEY_IGNITION, false); - position.set(Position.KEY_MOTION, false); - break; - case 0x21: - position.set(Position.KEY_IGNITION, true); - position.set(Position.KEY_MOTION, false); - break; - case 0x22: - position.set(Position.KEY_IGNITION, true); - position.set(Position.KEY_MOTION, true); - break; - case 0x41: - position.set(Position.KEY_MOTION, false); - break; - case 0x42: - position.set(Position.KEY_MOTION, true); - break; - default: - break; - } - - position.set(Position.KEY_RSSI, parser.nextInt()); - - parser.next(); // odometer or external power - - position.set(Position.KEY_BATTERY, parser.nextDouble()); - position.set(Position.KEY_CHARGE, parser.nextInt() == 1); - - position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt()); - - position.set(Position.PREFIX_TEMP + 1, parser.next()); - - position.set(Position.PREFIX_ADC + 1, parser.next()); - position.set(Position.PREFIX_ADC + 2, parser.next()); - - position.set(Position.KEY_INPUT, parser.next()); - position.set(Position.KEY_OUTPUT, parser.next()); - - getLastLocation(position, parser.nextDateTime()); - - position.set(Position.KEY_INDEX, parser.nextHexInt()); - - return position; - } - - private Object decodeVer(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_VER, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - position.set("deviceType", parser.next()); - position.set(Position.KEY_VERSION_FW, parser.nextHexInt()); - position.set(Position.KEY_VERSION_HW, parser.nextHexInt()); - - getLastLocation(position, parser.nextDateTime()); - - return position; - } - - private void skipLocation(Parser parser) { - parser.skip(19); - } - - private void decodeLocation(Position position, Parser parser) { - Integer hdop = parser.nextInt(); - position.setValid(hdop == null || hdop > 0); - position.set(Position.KEY_HDOP, hdop); - - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); - position.setCourse(parser.nextDouble(0)); - position.setAltitude(parser.nextDouble(0)); - - if (parser.hasNext(8)) { - position.setValid(true); - position.setLongitude(parser.nextDouble()); - position.setLatitude(parser.nextDouble()); - position.setTime(parser.nextDateTime()); - } else { - getLastLocation(position, null); - } - - if (parser.hasNext(6)) { - int mcc = parser.nextInt(); - int mnc = parser.nextInt(); - if (parser.hasNext(2)) { - position.setNetwork(new Network(CellTower.from(mcc, mnc, parser.nextInt(), parser.nextInt()))); - } - if (parser.hasNext(2)) { - position.setNetwork(new Network(CellTower.from(mcc, mnc, parser.nextHexInt(), parser.nextHexInt()))); - } - } - - if (parser.hasNext()) { - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - } - } - - private Object decodeObd(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_OBD, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - position.set(Position.KEY_RPM, parser.nextInt()); - position.set(Position.KEY_OBD_SPEED, parser.nextInt()); - position.set(Position.PREFIX_TEMP + 1, parser.nextInt()); - position.set(Position.KEY_FUEL_CONSUMPTION, parser.next()); - position.set("dtcsClearedDistance", parser.nextInt()); - if (parser.hasNext()) { - position.set("odbConnect", parser.nextInt() == 1); - } - position.set("dtcsNumber", parser.nextInt()); - position.set("dtcsCodes", parser.next()); - position.set(Position.KEY_THROTTLE, parser.nextInt()); - position.set(Position.KEY_FUEL_LEVEL, parser.nextInt()); - if (parser.hasNext()) { - position.set(Position.KEY_OBD_ODOMETER, parser.nextInt() * 1000); - } - - decodeLocation(position, parser); - - if (parser.hasNext()) { - position.set(Position.KEY_OBD_ODOMETER, (int) (parser.nextDouble() * 1000)); - } - - decodeDeviceTime(position, parser); - - return position; - } - - private Object decodeCan(Channel channel, SocketAddress remoteAddress, String sentence) throws ParseException { - Position position = new Position(getProtocolName()); - - int index = 0; - String[] values = sentence.split(","); - - index += 1; // header - index += 1; // protocol version - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]); - position.setDeviceId(deviceSession.getDeviceId()); - - index += 1; // device name - index += 1; // report type - index += 1; // canbus state - long reportMask = Long.parseLong(values[index++], 16); - long reportMaskExt = 0; - - if (BitUtil.check(reportMask, 0)) { - position.set(Position.KEY_VIN, values[index++]); - } - if (BitUtil.check(reportMask, 1)) { - position.set(Position.KEY_IGNITION, Integer.parseInt(values[index++]) > 0); - } - if (BitUtil.check(reportMask, 2)) { - position.set(Position.KEY_OBD_ODOMETER, values[index++]); - } - if (BitUtil.check(reportMask, 3) && !values[index++].isEmpty()) { - position.set(Position.KEY_FUEL_USED, Double.parseDouble(values[index - 1])); - } - if (BitUtil.check(reportMask, 5) && !values[index++].isEmpty()) { - position.set(Position.KEY_RPM, Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 4) && !values[index++].isEmpty()) { - position.set(Position.KEY_OBD_SPEED, UnitsConverter.knotsFromKph(Integer.parseInt(values[index - 1]))); - } - if (BitUtil.check(reportMask, 6) && !values[index++].isEmpty()) { - position.set(Position.KEY_COOLANT_TEMP, Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 7) && !values[index++].isEmpty()) { - position.set(Position.KEY_FUEL_CONSUMPTION, Double.parseDouble(values[index - 1].substring(1))); - } - if (BitUtil.check(reportMask, 8) && !values[index++].isEmpty()) { - position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(values[index - 1].substring(1))); - } - if (BitUtil.check(reportMask, 9) && !values[index++].isEmpty()) { - position.set("range", Long.parseLong(values[index - 1]) * 100); - } - if (BitUtil.check(reportMask, 10) && !values[index++].isEmpty()) { - position.set(Position.KEY_THROTTLE, Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 11) && !values[index++].isEmpty()) { - position.set(Position.KEY_HOURS, UnitsConverter.msFromHours(Double.parseDouble(values[index - 1]))); - } - if (BitUtil.check(reportMask, 12)) { - position.set("drivingHours", Double.parseDouble(values[index++])); - } - if (BitUtil.check(reportMask, 13)) { - position.set("idleHours", Double.parseDouble(values[index++])); - } - if (BitUtil.check(reportMask, 14) && !values[index++].isEmpty()) { - position.set("idleFuelConsumption", Double.parseDouble(values[index - 1])); - } - if (BitUtil.check(reportMask, 15) && !values[index++].isEmpty()) { - position.set(Position.KEY_AXLE_WEIGHT, Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 16) && !values[index++].isEmpty()) { - position.set("tachographInfo", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 17) && !values[index++].isEmpty()) { - position.set("indicators", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 18) && !values[index++].isEmpty()) { - position.set("lights", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 19) && !values[index++].isEmpty()) { - position.set("doors", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMask, 20) && !values[index++].isEmpty()) { - position.set("vehicleOverspeed", Double.parseDouble(values[index - 1])); - } - if (BitUtil.check(reportMask, 21) && !values[index++].isEmpty()) { - position.set("engineOverspeed", Double.parseDouble(values[index - 1])); - } - if (BitUtil.check(reportMask, 29)) { - reportMaskExt = Long.parseLong(values[index++], 16); - } - if (BitUtil.check(reportMaskExt, 0) && !values[index++].isEmpty()) { - position.set("adBlueLevel", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMaskExt, 1) && !values[index++].isEmpty()) { - position.set("axleWeight1", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMaskExt, 2) && !values[index++].isEmpty()) { - position.set("axleWeight3", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMaskExt, 3) && !values[index++].isEmpty()) { - position.set("axleWeight4", Integer.parseInt(values[index - 1])); - } - if (BitUtil.check(reportMaskExt, 4)) { - index += 1; // tachograph overspeed - } - if (BitUtil.check(reportMaskExt, 5)) { - index += 1; // tachograph motion - } - if (BitUtil.check(reportMaskExt, 6)) { - index += 1; // tachograph direction - } - if (BitUtil.check(reportMaskExt, 7) && !values[index++].isEmpty()) { - position.set(Position.PREFIX_ADC + 1, Integer.parseInt(values[index - 1]) * 0.001); - } - if (BitUtil.check(reportMaskExt, 8)) { - index += 1; // pedal breaking factor - } - if (BitUtil.check(reportMaskExt, 9)) { - index += 1; // engine breaking factor - } - if (BitUtil.check(reportMaskExt, 10)) { - index += 1; // total accelerator kick-downs - } - if (BitUtil.check(reportMaskExt, 11)) { - index += 1; // total effective engine speed - } - if (BitUtil.check(reportMaskExt, 12)) { - index += 1; // total cruise control time - } - if (BitUtil.check(reportMaskExt, 13)) { - index += 1; // total accelerator kick-down time - } - if (BitUtil.check(reportMaskExt, 14)) { - index += 1; // total brake application - } - if (BitUtil.check(reportMaskExt, 15) && !values[index++].isEmpty()) { - position.set("driver1Card", values[index - 1]); - } - if (BitUtil.check(reportMaskExt, 16) && !values[index++].isEmpty()) { - position.set("driver2Card", values[index - 1]); - } - if (BitUtil.check(reportMaskExt, 17) && !values[index++].isEmpty()) { - position.set("driver1Name", values[index - 1]); - } - if (BitUtil.check(reportMaskExt, 18) && !values[index++].isEmpty()) { - position.set("driver2Name", values[index - 1]); - } - if (BitUtil.check(reportMaskExt, 19) && !values[index++].isEmpty()) { - position.set("registration", values[index - 1]); - } - if (BitUtil.check(reportMaskExt, 20)) { - index += 1; // expansion information - } - if (BitUtil.check(reportMaskExt, 21)) { - index += 1; // rapid brakings - } - if (BitUtil.check(reportMaskExt, 22)) { - index += 1; // rapid accelerations - } - if (BitUtil.check(reportMaskExt, 23)) { - index += 1; // engine torque - } - - DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - - if (BitUtil.check(reportMask, 30)) { - while (values[index].isEmpty()) { - index += 1; - } - position.setValid(Integer.parseInt(values[index++]) > 0); - if (!values[index].isEmpty()) { - position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++]))); - position.setCourse(Integer.parseInt(values[index++])); - position.setAltitude(Double.parseDouble(values[index++])); - position.setLongitude(Double.parseDouble(values[index++])); - position.setLatitude(Double.parseDouble(values[index++])); - position.setTime(dateFormat.parse(values[index++])); - } else { - index += 6; // no location - getLastLocation(position, null); - } - } else { - getLastLocation(position, null); - } - - if (BitUtil.check(reportMask, 31)) { - index += 4; // cell - index += 1; // reserved - } - - if (ignoreFixTime) { - position.setTime(dateFormat.parse(values[index])); - } else { - position.setDeviceTime(dateFormat.parse(values[index])); - } - - return position; - } - - private void decodeStatus(Position position, Parser parser) { - if (parser.hasNext(3)) { - int ignition = parser.nextHexInt(); - if (BitUtil.check(ignition, 4)) { - position.set(Position.KEY_IGNITION, false); - } else if (BitUtil.check(ignition, 5)) { - position.set(Position.KEY_IGNITION, true); - } - position.set(Position.KEY_INPUT, parser.nextHexInt()); - position.set(Position.KEY_OUTPUT, parser.nextHexInt()); - } - } - - private Object decodeFri(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_FRI, sentence); - if (!parser.matches()) { - return null; - } - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); - if (deviceSession == null) { - return null; - } - - LinkedList<Position> positions = new LinkedList<>(); - - String vin = parser.next(); - Integer power = parser.nextInt(); - Integer battery = parser.nextInt(); - - Parser itemParser = new Parser(PATTERN_LOCATION, parser.next()); - while (itemParser.find()) { - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - position.set(Position.KEY_VIN, vin); - - decodeLocation(position, itemParser); - - positions.add(position); - } - - Position position = positions.getLast(); - - skipLocation(parser); - - if (power != null && power > 10) { - position.set(Position.KEY_POWER, power * 0.001); // only on some devices - } - if (battery != null) { - position.set(Position.KEY_BATTERY_LEVEL, battery); - } - - if (parser.hasNext()) { - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - } - position.set(Position.KEY_HOURS, parseHours(parser.next())); - position.set(Position.PREFIX_ADC + 1, parser.next()); - position.set(Position.PREFIX_ADC + 2, parser.next()); - position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt()); - - decodeStatus(position, parser); - - position.set(Position.KEY_RPM, parser.nextInt()); - position.set(Position.KEY_FUEL_LEVEL, parser.nextInt()); - - if (parser.hasNext()) { - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - } - position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt()); - - decodeDeviceTime(position, parser); - if (ignoreFixTime) { - positions.clear(); - positions.add(position); - } - - return positions; - } - - private Object decodeEri(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_ERI, sentence); - if (!parser.matches()) { - return null; - } - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); - if (deviceSession == null) { - return null; - } - - long mask = parser.nextHexLong(); - - LinkedList<Position> positions = new LinkedList<>(); - - Integer power = parser.nextInt(); - - Parser itemParser = new Parser(PATTERN_LOCATION, parser.next()); - while (itemParser.find()) { - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - decodeLocation(position, itemParser); - - positions.add(position); - } - - Position position = positions.getLast(); - - skipLocation(parser); - - if (power != null) { - position.set(Position.KEY_POWER, power * 0.001); - } - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - position.set(Position.KEY_HOURS, parseHours(parser.next())); - position.set(Position.PREFIX_ADC + 1, parser.next()); - position.set(Position.PREFIX_ADC + 2, parser.next()); - position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt()); - - decodeStatus(position, parser); - - int index = 0; - String[] data = parser.next().split(","); - - index += 1; // device type - - if (BitUtil.check(mask, 0)) { - index += 1; // digital fuel sensor data - } - - if (BitUtil.check(mask, 1)) { - int deviceCount = Integer.parseInt(data[index++]); - for (int i = 1; i <= deviceCount; i++) { - index += 1; // id - index += 1; // type - if (!data[index++].isEmpty()) { - position.set(Position.PREFIX_TEMP + i, (short) Integer.parseInt(data[index - 1], 16) * 0.0625); - } - } - } - - if (BitUtil.check(mask, 2)) { - index += 1; // can data - } - - if (BitUtil.check(mask, 3) || BitUtil.check(mask, 4)) { - int deviceCount = Integer.parseInt(data[index++]); - for (int i = 1; i <= deviceCount; i++) { - index += 1; // type - if (BitUtil.check(mask, 3)) { - position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(data[index++])); - } - if (BitUtil.check(mask, 4)) { - index += 1; // volume - } - } - } - - decodeDeviceTime(position, parser); - if (ignoreFixTime) { - positions.clear(); - positions.add(position); - } - - return positions; - } - - private Object decodeIgn(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_IGN, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - decodeLocation(position, parser); - - position.set(Position.KEY_IGNITION, sentence.contains("IGN")); - position.set(Position.KEY_HOURS, parseHours(parser.next())); - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - - decodeDeviceTime(position, parser); - - return position; - } - - private Object decodeLsw(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_LSW, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - position.set(Position.PREFIX_IN + (sentence.contains("LSW") ? 1 : 2), parser.nextInt() == 1); - - decodeLocation(position, parser); - - decodeDeviceTime(position, parser); - - return position; - } - - private Object decodeIda(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_IDA, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next()); - - decodeLocation(position, parser); - - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - - decodeDeviceTime(position, parser); - - return position; - } - - private Object decodeWif(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_WIF, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - getLastLocation(position, null); - - Network network = new Network(); - - parser.nextInt(); // count - Matcher matcher = Pattern.compile("([0-9a-fA-F]{12}),(-?\\d+),,,,").matcher(parser.next()); - while (matcher.find()) { - String mac = matcher.group(1).replaceAll("(..)", "$1:"); - network.addWifiAccessPoint(WifiAccessPoint.from( - mac.substring(0, mac.length() - 1), Integer.parseInt(matcher.group(2)))); - } - - position.setNetwork(network); - - position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt()); - - return position; - } - - private Object decodeGsm(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_GSM, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - getLastLocation(position, null); - - Network network = new Network(); - - String[] data = parser.next().split(","); - for (int i = 0; i < 6; i++) { - if (!data[i * 6].isEmpty()) { - network.addCellTower(CellTower.from( - Integer.parseInt(data[i * 6]), Integer.parseInt(data[i * 6 + 1]), - Integer.parseInt(data[i * 6 + 2], 16), Integer.parseInt(data[i * 6 + 3], 16), - Integer.parseInt(data[i * 6 + 4]))); - } - } - - position.setNetwork(network); - - return position; - } - - private Object decodePna(Channel channel, SocketAddress remoteAddress, String sentence) { - Parser parser = new Parser(PATTERN_PNA, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - getLastLocation(position, null); - - position.set(Position.KEY_ALARM, sentence.contains("PNA") ? Position.ALARM_POWER_ON : Position.ALARM_POWER_OFF); - - return position; - } - - private Object decodeOther(Channel channel, SocketAddress remoteAddress, String sentence, String type) { - Parser parser = new Parser(PATTERN, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - int reportType = parser.nextHexInt(); - if (type.equals("NMR")) { - position.set(Position.KEY_MOTION, reportType == 1); - } else if (type.equals("SOS")) { - position.set(Position.KEY_ALARM, Position.ALARM_SOS); - } else if (type.equals("DIS")) { - position.set(Position.PREFIX_IN + reportType / 0x10, reportType % 0x10 == 1); - } else if (type.equals("IGL")) { - position.set(Position.KEY_IGNITION, reportType % 0x10 == 1); - } - - decodeLocation(position, parser); - - if (parser.hasNext()) { - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - } - position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt()); - - if (parser.hasNext()) { - position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); - } - - decodeDeviceTime(position, parser); - - if (Context.getConfig().getBoolean(getProtocolName() + ".ack") && channel != null) { - channel.writeAndFlush(new NetworkMessage("+SACK:" + parser.next() + "$", remoteAddress)); - } - - return position; - } - - private Object decodeBasic(Channel channel, SocketAddress remoteAddress, String sentence, String type) { - Parser parser = new Parser(PATTERN_BASIC, sentence); - Position position = initPosition(parser, channel, remoteAddress); - if (position == null) { - return null; - } - - if (parser.hasNext()) { - int hdop = parser.nextInt(); - position.setValid(hdop > 0); - position.set(Position.KEY_HDOP, hdop); - } - - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); - position.setCourse(parser.nextDouble(0)); - position.setAltitude(parser.nextDouble(0)); - - if (parser.hasNext(2)) { - position.setLongitude(parser.nextDouble()); - position.setLatitude(parser.nextDouble()); - } else { - getLastLocation(position, null); - } - - if (parser.hasNext(6)) { - position.setTime(parser.nextDateTime()); - } - - if (parser.hasNext(4)) { - position.setNetwork(new Network(CellTower.from( - parser.nextInt(), parser.nextInt(), parser.nextHexInt(), parser.nextHexInt()))); - } - - decodeDeviceTime(position, parser); - - switch (type) { - case "TOW": - position.set(Position.KEY_ALARM, Position.ALARM_TOW); - break; - case "IDL": - position.set(Position.KEY_ALARM, Position.ALARM_IDLE); - break; - case "PNA": - position.set(Position.KEY_ALARM, Position.ALARM_POWER_ON); - break; - case "PFA": - position.set(Position.KEY_ALARM, Position.ALARM_POWER_OFF); - break; - case "EPN": - case "MPN": - position.set(Position.KEY_ALARM, Position.ALARM_POWER_RESTORED); - break; - case "EPF": - case "MPF": - position.set(Position.KEY_ALARM, Position.ALARM_POWER_CUT); - break; - case "BPL": - position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY); - break; - case "STT": - position.set(Position.KEY_ALARM, Position.ALARM_MOVEMENT); - break; - case "SWG": - position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE); - break; - case "TMP": - case "TEM": - position.set(Position.KEY_ALARM, Position.ALARM_TEMPERATURE); - break; - case "JDR": - case "JDS": - position.set(Position.KEY_ALARM, Position.ALARM_JAMMING); - break; - default: - break; - } - - return position; - } - - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - - String sentence = ((ByteBuf) msg).toString(StandardCharsets.US_ASCII); - - int typeIndex = sentence.indexOf(":GT"); - if (typeIndex < 0) { - return null; - } - - Object result; - String type = sentence.substring(typeIndex + 3, typeIndex + 6); - if (sentence.startsWith("+ACK")) { - result = decodeAck(channel, remoteAddress, sentence, type); - } else { - switch (type) { - case "INF": - result = decodeInf(channel, remoteAddress, sentence); - break; - case "OBD": - result = decodeObd(channel, remoteAddress, sentence); - break; - case "CAN": - result = decodeCan(channel, remoteAddress, sentence); - break; - case "FRI": - case "GEO": - case "STR": - result = decodeFri(channel, remoteAddress, sentence); - break; - case "ERI": - result = decodeEri(channel, remoteAddress, sentence); - break; - case "IGN": - case "IGF": - result = decodeIgn(channel, remoteAddress, sentence); - break; - case "LSW": - case "TSW": - result = decodeLsw(channel, remoteAddress, sentence); - break; - case "IDA": - result = decodeIda(channel, remoteAddress, sentence); - break; - case "WIF": - result = decodeWif(channel, remoteAddress, sentence); - break; - case "GSM": - result = decodeGsm(channel, remoteAddress, sentence); - break; - case "VER": - result = decodeVer(channel, remoteAddress, sentence); - break; - case "PNA": - case "PFA": - result = decodePna(channel, remoteAddress, sentence); - break; - default: - result = decodeOther(channel, remoteAddress, sentence, type); - break; - } - - if (result == null) { - result = decodeBasic(channel, remoteAddress, sentence, type); - } - - if (result != null) { - if (result instanceof Position) { - ((Position) result).set(Position.KEY_TYPE, type); - } else { - for (Position p : (List<Position>) result) { - p.set(Position.KEY_TYPE, type); - } - } - } - } - - return result; - } - -} |