aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/org/traccar/MainEventHandler.java4
-rw-r--r--src/org/traccar/WindowsService.java4
-rw-r--r--src/org/traccar/protocol/EelinkProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/Gl200TextProtocolDecoder.java38
-rw-r--r--src/org/traccar/protocol/Gps103ProtocolDecoder.java6
-rw-r--r--src/org/traccar/protocol/ItsProtocolDecoder.java11
-rw-r--r--src/org/traccar/protocol/T55ProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/TeltonikaProtocolDecoder.java97
8 files changed, 135 insertions, 29 deletions
diff --git a/src/org/traccar/MainEventHandler.java b/src/org/traccar/MainEventHandler.java
index c905508e0..75dafcc29 100644
--- a/src/org/traccar/MainEventHandler.java
+++ b/src/org/traccar/MainEventHandler.java
@@ -117,14 +117,14 @@ public class MainEventHandler extends ChannelInboundHandlerAdapter {
}
@Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ public void channelActive(ChannelHandlerContext ctx) {
if (!(ctx.channel() instanceof DatagramChannel)) {
LOGGER.info(formatChannel(ctx.channel()) + " connected");
}
}
@Override
- public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ public void channelInactive(ChannelHandlerContext ctx) {
LOGGER.info(formatChannel(ctx.channel()) + " disconnected");
closeChannel(ctx.channel());
diff --git a/src/org/traccar/WindowsService.java b/src/org/traccar/WindowsService.java
index 1906a6d50..4a8955608 100644
--- a/src/org/traccar/WindowsService.java
+++ b/src/org/traccar/WindowsService.java
@@ -56,8 +56,8 @@ public abstract class WindowsService {
File jar = new File(WindowsService.class.getProtectionDomain().getCodeSource().getLocation().toURI());
String command = javaBinary
- + " -Duser.dir=\"" + jar.getAbsolutePath() + "\""
- + " -jar \"" + jar.getParentFile().getAbsolutePath() + "\""
+ + " -Duser.dir=\"" + jar.getParentFile().getAbsolutePath() + "\""
+ + " -jar \"" + jar.getAbsolutePath() + "\""
+ " --service \"" + config + "\"";
boolean success = false;
diff --git a/src/org/traccar/protocol/EelinkProtocolDecoder.java b/src/org/traccar/protocol/EelinkProtocolDecoder.java
index 14bf44fbf..fce176ec5 100644
--- a/src/org/traccar/protocol/EelinkProtocolDecoder.java
+++ b/src/org/traccar/protocol/EelinkProtocolDecoder.java
@@ -268,7 +268,7 @@ public class EelinkProtocolDecoder extends BaseProtocolDecoder {
}
if (buf.readableBytes() >= 2) {
- position.set(Position.PREFIX_TEMP + 2, buf.readUnsignedShort() / 16.0);
+ position.set(Position.PREFIX_TEMP + 2, buf.readShort() / 16.0);
}
}
diff --git a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java b/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
index 31ff4a670..aeb57a116 100644
--- a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
@@ -314,6 +314,18 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
.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
@@ -497,6 +509,10 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
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);
@@ -806,7 +822,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
Position position = positions.getLast();
- decodeLocation(position, parser);
+ skipLocation(parser);
if (power != null && power > 10) {
position.set(Position.KEY_POWER, power * 0.001); // only on some devices
@@ -871,7 +887,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
Position position = positions.getLast();
- decodeLocation(position, parser);
+ skipLocation(parser);
if (power != null) {
position.set(Position.KEY_POWER, power * 0.001);
@@ -1034,6 +1050,20 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
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);
@@ -1206,6 +1236,10 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
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;
diff --git a/src/org/traccar/protocol/Gps103ProtocolDecoder.java b/src/org/traccar/protocol/Gps103ProtocolDecoder.java
index 27b94739b..aa02e8ad4 100644
--- a/src/org/traccar/protocol/Gps103ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gps103ProtocolDecoder.java
@@ -81,10 +81,10 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder {
.number(",([01])?").optional() // ignition
.number(",([01])?").optional() // door
.groupBegin()
- .number(",(?:(d+.d+)%)?") // fuel 1
- .number(",(?:(d+.d+)%|d+)?") // fuel 2
+ .number(",(?:(d+.d+)%)?") // fuel 1
+ .number(",(?:(d+.d+)%|d+)?") // fuel 2
.groupEnd("?")
- .number(",([-+]?d+)?") // temperature
+ .number(",([-+]?d+)?").optional() // temperature
.groupEnd()
.any()
.compile();
diff --git a/src/org/traccar/protocol/ItsProtocolDecoder.java b/src/org/traccar/protocol/ItsProtocolDecoder.java
index 62bf1f1e6..e2b1dc238 100644
--- a/src/org/traccar/protocol/ItsProtocolDecoder.java
+++ b/src/org/traccar/protocol/ItsProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2018 - 2019 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.
@@ -35,6 +35,7 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
}
private static final Pattern PATTERN = new PatternBuilder()
+ .expression("[^$]*")
.text("$,")
.expression("[^,]+,") // event
.groupBegin()
@@ -59,8 +60,8 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
.number("(d+.d+),([NS]),") // latitude
.number("(d+.d+),([EW]),") // longitude
.groupBegin()
- .number("(d+.d+),") // speed
- .number("(d+.d+),") // course
+ .number("(d+.?d*),") // speed
+ .number("(d+.?d*),") // course
.number("(d+),") // satellites
.or()
.number("(-?d+.d+),") // altitude
@@ -108,8 +109,8 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_SATELLITES, parser.nextInt());
}
- if (parser.hasNext()) {
- position.setAltitude(parser.nextDouble(0));
+ if (parser.hasNext(2)) {
+ position.setAltitude(parser.nextDouble());
position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble()));
}
diff --git a/src/org/traccar/protocol/T55ProtocolDecoder.java b/src/org/traccar/protocol/T55ProtocolDecoder.java
index 214a40a49..ba231a635 100644
--- a/src/org/traccar/protocol/T55ProtocolDecoder.java
+++ b/src/org/traccar/protocol/T55ProtocolDecoder.java
@@ -249,6 +249,8 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
if (sentence.startsWith("$PGID")) {
getDeviceSession(channel, remoteAddress, sentence.substring(6, sentence.length() - 3));
+ } else if (sentence.startsWith("$DEVID")) {
+ getDeviceSession(channel, remoteAddress, sentence.substring(7, sentence.lastIndexOf('*')));
} else if (sentence.startsWith("$PCPTI")) {
getDeviceSession(channel, remoteAddress, sentence.substring(7, sentence.indexOf(",", 7)));
} else if (sentence.startsWith("IMEI")) {
diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
index f69059104..c80cd9cda 100644
--- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2019 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.
@@ -25,6 +25,7 @@ import org.traccar.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
import org.traccar.helper.BitUtil;
+import org.traccar.helper.Checksum;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.CellTower;
import org.traccar.model.Network;
@@ -33,13 +34,18 @@ import org.traccar.model.Position;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Date;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
+ private static final int IMAGE_PACKET_MAX = 2048;
+
private boolean connectionless;
private boolean extended;
+ private Map<Long, ByteBuf> photos = new HashMap<>();
public void setExtended(boolean extended) {
this.extended = extended;
@@ -51,7 +57,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
this.extended = Context.getConfig().getBoolean(getProtocolName() + ".extended");
}
- private DeviceSession parseIdentification(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
+ private void parseIdentification(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
int length = buf.readUnsignedShort();
String imei = buf.toString(buf.readerIndex(), length, StandardCharsets.US_ASCII);
@@ -66,7 +72,6 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
- return deviceSession;
}
public static final int CODEC_GH3000 = 0x07;
@@ -75,14 +80,74 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
public static final int CODEC_12 = 0x0C;
public static final int CODEC_16 = 0x10;
- private void decodeSerial(Position position, ByteBuf buf) {
+ private void sendImageRequest(Channel channel, SocketAddress remoteAddress, long id, int offset, int size) {
+ if (channel != null) {
+ ByteBuf response = Unpooled.buffer();
+ response.writeInt(0);
+ response.writeShort(0);
+ response.writeShort(19); // length
+ response.writeByte(CODEC_12);
+ response.writeByte(1); // nod
+ response.writeByte(0x0D); // camera
+ response.writeInt(11); // payload length
+ response.writeByte(2); // command
+ response.writeInt((int) id);
+ response.writeInt(offset);
+ response.writeShort(size);
+ response.writeByte(1); // nod
+ response.writeShort(0);
+ response.writeShort(Checksum.crc16(
+ Checksum.CRC16_IBM, response.nioBuffer(8, response.readableBytes() - 8)));
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
+ }
+ }
+
+ private void decodeSerial(Channel channel, SocketAddress remoteAddress, Position position, ByteBuf buf) {
getLastLocation(position, null);
- position.set(Position.KEY_TYPE, buf.readUnsignedByte());
+ int type = buf.readUnsignedByte();
+ if (type == 0x0D) {
+
+ buf.readInt(); // length
+ int subtype = buf.readUnsignedByte();
+ if (subtype == 0x01) {
+
+ long photoId = buf.readUnsignedInt();
+ ByteBuf photo = Unpooled.buffer(buf.readInt());
+ photos.put(photoId, photo);
+ sendImageRequest(
+ channel, remoteAddress, photoId,
+ 0, Math.min(IMAGE_PACKET_MAX, photo.capacity()));
+
+ } else if (subtype == 0x02) {
+
+ long photoId = buf.readUnsignedInt();
+ buf.readInt(); // offset
+ ByteBuf photo = photos.get(photoId);
+ photo.writeBytes(buf, buf.readUnsignedShort());
+ if (photo.writableBytes() > 0) {
+ sendImageRequest(
+ channel, remoteAddress, photoId,
+ photo.writerIndex(), Math.min(IMAGE_PACKET_MAX, photo.writableBytes()));
+ } else {
+ String uniqueId = Context.getIdentityManager().getById(position.getDeviceId()).getUniqueId();
+ photos.remove(photoId);
+ try {
+ position.set(Position.KEY_IMAGE, Context.getMediaManager().writeFile(uniqueId, photo, "jpg"));
+ } finally {
+ photo.release();
+ }
+ }
+
+ }
- position.set(Position.KEY_RESULT, buf.readSlice(buf.readInt()).toString(StandardCharsets.US_ASCII));
+ } else {
+ position.set(Position.KEY_TYPE, type);
+ position.set(Position.KEY_RESULT, buf.readSlice(buf.readInt()).toString(StandardCharsets.US_ASCII));
+
+ }
}
private long readValue(ByteBuf buf, int length, boolean signed) {
@@ -121,6 +186,12 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
case 21:
position.set(Position.KEY_RSSI, readValue(buf, length, false));
break;
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ position.set(Position.PREFIX_TEMP + (id - 24), readValue(buf, length, true) * 0.1);
+ break;
case 66:
position.set(Position.KEY_POWER, readValue(buf, length, false) * 0.001);
break;
@@ -131,13 +202,9 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
position.set("gpsStatus", readValue(buf, length, false));
break;
case 72:
- position.set(Position.PREFIX_TEMP + 1, readValue(buf, length, true) * 0.1);
- break;
case 73:
- position.set(Position.PREFIX_TEMP + 2, readValue(buf, length, true) * 0.1);
- break;
case 74:
- position.set(Position.PREFIX_TEMP + 3, readValue(buf, length, true) * 0.1);
+ position.set(Position.PREFIX_TEMP + (id - 71), readValue(buf, length, true) * 0.1);
break;
case 78:
long driverUniqueId = readValue(buf, length, false);
@@ -462,12 +529,14 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
position.setValid(true);
if (codec == CODEC_12) {
- decodeSerial(position, buf);
+ decodeSerial(channel, remoteAddress, position, buf);
} else {
decodeLocation(position, buf, codec);
}
- positions.add(position);
+ if (!position.getOutdated() || !position.getAttributes().isEmpty()) {
+ positions.add(position);
+ }
}
if (channel != null) {
@@ -486,7 +555,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
}
- return positions;
+ return positions.isEmpty() ? null : positions;
}
@Override