diff options
Diffstat (limited to 'src/org/traccar/protocol/MeitrackProtocolDecoder.java')
-rw-r--r-- | src/org/traccar/protocol/MeitrackProtocolDecoder.java | 165 |
1 files changed, 147 insertions, 18 deletions
diff --git a/src/org/traccar/protocol/MeitrackProtocolDecoder.java b/src/org/traccar/protocol/MeitrackProtocolDecoder.java index efc9c24db..5b67aebe3 100644 --- a/src/org/traccar/protocol/MeitrackProtocolDecoder.java +++ b/src/org/traccar/protocol/MeitrackProtocolDecoder.java @@ -16,6 +16,7 @@ package org.traccar.protocol; import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; @@ -37,6 +38,8 @@ import java.util.regex.Pattern; public class MeitrackProtocolDecoder extends BaseProtocolDecoder { + private ChannelBuffer photo; + public MeitrackProtocolDecoder(MeitrackProtocol protocol) { super(protocol); } @@ -109,7 +112,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { } } - private Position decodeRegularMessage(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { + private Position decodeRegular(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { Parser parser = new Parser(PATTERN, buf.toString(StandardCharsets.US_ASCII)); if (!parser.matches()) { @@ -219,13 +222,13 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { if (parser.hasNext()) { for (String temp : parser.next().split("\\|")) { - int index = Integer.valueOf(temp.substring(0, 2), 16); + int index = Integer.parseInt(temp.substring(0, 2), 16); if (protocol >= 3) { - double value = Short.valueOf(temp.substring(2), 16); + double value = (short) Integer.parseInt(temp.substring(2), 16); position.set(Position.PREFIX_TEMP + index, value * 0.01); } else { - double value = Byte.valueOf(temp.substring(2, 4), 16); - value += (value < 0 ? -0.01 : 0.01) * Integer.valueOf(temp.substring(4), 16); + double value = Byte.parseByte(temp.substring(2, 4), 16); + value += (value < 0 ? -0.01 : 0.01) * Integer.parseInt(temp.substring(4), 16); position.set(Position.PREFIX_TEMP + index, value); } } @@ -234,7 +237,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { return position; } - private List<Position> decodeBinaryMessage(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { + private List<Position> decodeBinaryC(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { List<Position> positions = new LinkedList<>(); String flag = buf.toString(2, 1, StandardCharsets.US_ASCII); @@ -308,6 +311,108 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { return positions; } + private List<Position> decodeBinaryE(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { + List<Position> positions = new LinkedList<>(); + + buf.readerIndex(buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ',') + 1); + String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII); + buf.skipBytes(1 + 3 + 1); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); + if (deviceSession == null) { + return null; + } + + buf.readUnsignedInt(); // remaining cache + int count = buf.readUnsignedShort(); + + for (int i = 0; i < count; i++) { + Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + buf.readUnsignedShort(); // length + buf.readUnsignedShort(); // index + + int paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + int id = buf.readUnsignedByte(); + switch (id) { + case 0x01: + position.set(Position.KEY_EVENT, buf.readUnsignedByte()); + break; + case 0x05: + position.setValid(buf.readUnsignedByte() > 0); + break; + case 0x06: + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); + break; + default: + buf.readUnsignedByte(); + break; + } + } + + paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + int id = buf.readUnsignedByte(); + switch (id) { + case 0x08: + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); + break; + case 0x09: + position.setCourse(buf.readUnsignedShort() * 0.1); + break; + case 0x0B: + position.setAltitude(buf.readShort()); + break; + default: + buf.readUnsignedShort(); + break; + } + } + + paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + int id = buf.readUnsignedByte(); + switch (id) { + case 0x02: + position.setLatitude(buf.readInt() * 0.000001); + break; + case 0x03: + position.setLongitude(buf.readInt() * 0.000001); + break; + case 0x04: + position.setTime(new Date((946684800 + buf.readUnsignedInt()) * 1000)); // 2000-01-01 + break; + default: + buf.readUnsignedInt(); + break; + } + } + + paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + buf.readUnsignedByte(); // id + buf.skipBytes(buf.readUnsignedByte()); // value + } + + positions.add(position); + } + + return positions; + } + + private void requestPhotoPacket(Channel channel, String imei, int index) { + if (channel != null) { + String content = "D00,camera_picture.jpg," + index; + int length = 1 + imei.length() + 1 + content.length() + 5; + String response = String.format("@@O%02d,%s,%s*", length, imei, content); + response += Checksum.sum(response) + "\r\n"; + channel.write(response); + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -315,25 +420,49 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { ChannelBuffer buf = (ChannelBuffer) msg; int index = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ','); + String imei = buf.toString(index + 1, 15, StandardCharsets.US_ASCII); index = buf.indexOf(index + 1, buf.writerIndex(), (byte) ','); - String type = buf.toString(index + 1, 3, StandardCharsets.US_ASCII); + switch (type) { - case "D03": - if (channel != null) { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - String imei = Context.getIdentityManager().getById(deviceSession.getDeviceId()).getUniqueId(); - String content = "D00,camera_picture.jpg,0"; - int length = 1 + imei.length() + 1 + content.length() + 5; - String response = String.format("@@O%02d,%s,%s*", length, imei, content); - response += Checksum.sum(response) + "\r\n"; - channel.write(response); + case "D00": + index = buf.indexOf(index + 1 + type.length() + 1, buf.writerIndex(), (byte) ',') + 1; + int endIndex = buf.indexOf(index, buf.writerIndex(), (byte) ','); + int total = Integer.parseInt(buf.toString(index, endIndex - index, StandardCharsets.US_ASCII)); + index = endIndex + 1; + endIndex = buf.indexOf(index, buf.writerIndex(), (byte) ','); + int current = Integer.parseInt(buf.toString(index, endIndex - index, StandardCharsets.US_ASCII)); + + buf.readerIndex(endIndex + 1); + photo.writeBytes(buf.readBytes(buf.readableBytes() - 1 - 2 - 2)); + + if (current == total - 1) { + Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(getDeviceSession(channel, remoteAddress, imei).getDeviceId()); + + getLastLocation(position, null); + + position.set(Position.KEY_IMAGE, Context.getMediaManager().writeFile(imei, photo, "jpg")); + photo = null; + + return position; + } else { + if ((current + 1) % 8 == 0) { + requestPhotoPacket(channel, imei, current + 1); + } + return null; } + case "D03": + photo = ChannelBuffers.dynamicBuffer(); + requestPhotoPacket(channel, imei, 0); return null; case "CCC": - return decodeBinaryMessage(channel, remoteAddress, buf); + return decodeBinaryC(channel, remoteAddress, buf); + case "CCE": + return decodeBinaryE(channel, remoteAddress, buf); default: - return decodeRegularMessage(channel, remoteAddress, buf); + return decodeRegular(channel, remoteAddress, buf); } } |