From fe6d161c1701527e874c8a6f675ddebd42b8bcf9 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 26 Jun 2017 22:47:39 +1200 Subject: Add support for X1 GT06 photos --- src/org/traccar/protocol/Gt06ProtocolDecoder.java | 87 ++++++++++++++++++----- 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/org/traccar/protocol/Gt06ProtocolDecoder.java index 64365aee0..4d8161af9 100644 --- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -28,11 +28,14 @@ import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; import org.traccar.model.CellTower; +import org.traccar.model.Device; import org.traccar.model.Network; import org.traccar.model.Position; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; import java.util.TimeZone; import java.util.regex.Pattern; @@ -41,6 +44,8 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { private boolean forceTimeZone = false; private final TimeZone timeZone = TimeZone.getTimeZone("UTC"); + private final Map photos = new HashMap<>(); + public Gt06ProtocolDecoder(Gt06Protocol protocol) { super(protocol); @@ -95,15 +100,34 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { || type == MSG_GPS_LBS_STATUS_1 || type == MSG_GPS_LBS_STATUS_2 || type == MSG_GPS_LBS_STATUS_3; } - private static void sendResponse(Channel channel, int type, int index) { + private void sendResponse(Channel channel, int type, int index) { if (channel != null) { ChannelBuffer response = ChannelBuffers.dynamicBuffer(); - response.writeByte(0x78); response.writeByte(0x78); // header + response.writeShort(0x7878); // header response.writeByte(5); // size response.writeByte(type); response.writeShort(index); - response.writeShort(Checksum.crc16(Checksum.CRC16_X25, response.toByteBuffer(2, 4))); - response.writeByte(0x0D); response.writeByte(0x0A); // ending + response.writeShort(Checksum.crc16(Checksum.CRC16_X25, + response.toByteBuffer(2, response.writerIndex() - 2))); + response.writeByte('\r'); response.writeByte('\n'); // ending + channel.write(response); + } + } + + private void sendPhotoRequest(Channel channel, int pictureId) { + if (channel != null) { + ChannelBuffer photo = photos.get(pictureId); + ChannelBuffer response = ChannelBuffers.dynamicBuffer(); + response.writeShort(0x7878); // header + response.writeByte(15); // size + response.writeByte(MSG_X1_PHOTO_DATA); + response.writeInt(pictureId); + response.writeInt(photo.writerIndex()); + response.writeShort(Math.min(photo.writableBytes(), 1024)); + response.writeShort(1); + response.writeShort(Checksum.crc16(Checksum.CRC16_X25, + response.toByteBuffer(2, response.writerIndex() - 2))); + response.writeByte('\r'); response.writeByte('\n'); // ending channel.write(response); } } @@ -277,6 +301,14 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { int dataLength = length - 5; int type = buf.readUnsignedByte(); + DeviceSession deviceSession = null; + if (type != MSG_LOGIN) { + deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession == null) { + return null; + } + } + if (type == MSG_LOGIN) { String imei = ChannelBuffers.hexDump(buf.readBytes(8)).substring(1); @@ -303,11 +335,6 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { } else if (type == MSG_X1_GPS) { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession == null) { - return null; - } - Position position = new Position(); position.setDeviceId(deviceSession.getDeviceId()); position.setProtocol(getProtocolName()); @@ -324,19 +351,24 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShort(), buf.readUnsignedByte(), buf.readUnsignedShort(), buf.readUnsignedInt()))); - if (buf.readableBytes() > 6) { - buf.skipBytes(buf.readableBytes() - 6); - } - sendResponse(channel, type, buf.readUnsignedShort()); - return position; - } else { + } else if (type == MSG_X1_PHOTO_INFO) { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession == null) { - return null; - } + buf.skipBytes(6); // time + buf.readUnsignedByte(); // fix status + buf.readUnsignedInt(); // latitude + buf.readUnsignedInt(); // longitude + buf.readUnsignedByte(); // camera id + buf.readUnsignedByte(); // photo source + buf.readUnsignedByte(); // picture format + + ChannelBuffer photo = ChannelBuffers.buffer(buf.readInt()); + int pictureId = buf.readInt(); + photos.put(pictureId, photo); + sendPhotoRequest(channel, pictureId); + + } else { Position position = new Position(); position.setDeviceId(deviceSession.getDeviceId()); @@ -466,6 +498,23 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { } + } else if (type == MSG_X1_PHOTO_DATA) { + + int pictureId = buf.readInt(); + + ChannelBuffer photo = photos.get(pictureId); + + buf.readUnsignedInt(); // offset + buf.readBytes(photo, buf.readUnsignedShort()); + + if (buf.writableBytes() > 0) { + sendPhotoRequest(channel, pictureId); + } else { + Device device = Context.getDeviceManager().getDeviceById(deviceSession.getDeviceId()); + Context.getMediaManager().writeFile(device.getUniqueId(), photo, "jpg"); + photos.remove(pictureId); + } + } return null; -- cgit v1.2.3