diff options
-rw-r--r-- | src/org/traccar/Context.java | 4 | ||||
-rw-r--r-- | src/org/traccar/protocol/WatchProtocolDecoder.java | 36 | ||||
-rw-r--r-- | test/org/traccar/protocol/WatchProtocolDecoderTest.java | 43 |
3 files changed, 73 insertions, 10 deletions
diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index 95d433795..b0db90416 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -516,6 +516,10 @@ public final class Context { identityManager = testIdentityManager; } + public static void initMediaManager(MediaManager mediaManager) { + Context.mediaManager = mediaManager; + } + public static <T extends BaseModel> BaseObjectManager<T> getManager(Class<T> clazz) { if (clazz.equals(Device.class)) { return (BaseObjectManager<T>) deviceManager; diff --git a/src/org/traccar/protocol/WatchProtocolDecoder.java b/src/org/traccar/protocol/WatchProtocolDecoder.java index 78b190030..bf4d99a49 100644 --- a/src/org/traccar/protocol/WatchProtocolDecoder.java +++ b/src/org/traccar/protocol/WatchProtocolDecoder.java @@ -17,6 +17,8 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; import org.traccar.DeviceSession; @@ -38,6 +40,8 @@ import java.util.regex.Pattern; public class WatchProtocolDecoder extends BaseProtocolDecoder { + private static final Logger LOGGER = LoggerFactory.getLogger(WatchProtocolDecoder.class); + public WatchProtocolDecoder(Protocol protocol) { super(protocol); } @@ -174,41 +178,45 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { return manufacturer; } + protected int nextIndexOf(ByteBuf buf, char delimiter) { + return buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) delimiter); + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - buf.skipBytes(1); // header + buf.skipBytes(1); // '[' header manufacturer = buf.readSlice(2).toString(StandardCharsets.US_ASCII); - buf.skipBytes(1); // delimiter + buf.skipBytes(1); // '*' delimiter - int idIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) '*'); + int idIndex = nextIndexOf(buf, '*'); String id = buf.readSlice(idIndex - buf.readerIndex()).toString(StandardCharsets.US_ASCII); DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id); if (deviceSession == null) { return null; } - buf.skipBytes(1); // delimiter + buf.skipBytes(1); // '*' delimiter String index = null; - int contentIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) '*'); + int contentIndex = nextIndexOf(buf, '*'); if (contentIndex + 5 < buf.writerIndex() && buf.getByte(contentIndex + 5) == '*' && buf.toString(contentIndex + 1, 4, StandardCharsets.US_ASCII).matches("\\p{XDigit}+")) { - int indexLength = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) '*') - buf.readerIndex(); + int indexLength = nextIndexOf(buf, '*') - buf.readerIndex(); hasIndex = true; index = buf.readSlice(indexLength).toString(StandardCharsets.US_ASCII); - buf.skipBytes(1); // delimiter + buf.skipBytes(1); // '*' delimiter } buf.skipBytes(4); // length - buf.skipBytes(1); // delimiter + buf.skipBytes(1); // '*' delimiter - buf.writerIndex(buf.writerIndex() - 1); // ignore ending + buf.writerIndex(buf.writerIndex() - 1); // ']' ignore ending - contentIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ','); + contentIndex = nextIndexOf(buf, ','); if (contentIndex < 0) { contentIndex = buf.writerIndex(); } @@ -296,6 +304,14 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { } else if (type.equals("TK")) { + if (buf.readableBytes() == 1) { + byte result = buf.readByte(); + if (result != '1') { + LOGGER.error(type + "," + result); + } + return null; + } + Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); diff --git a/test/org/traccar/protocol/WatchProtocolDecoderTest.java b/test/org/traccar/protocol/WatchProtocolDecoderTest.java index b7c8d83f9..c4e5bf61a 100644 --- a/test/org/traccar/protocol/WatchProtocolDecoderTest.java +++ b/test/org/traccar/protocol/WatchProtocolDecoderTest.java @@ -1,7 +1,17 @@ package org.traccar.protocol; +import io.netty.buffer.ByteBuf; import org.junit.Test; +import org.traccar.Context; import org.traccar.ProtocolTest; +import org.traccar.database.MediaManager; +import org.traccar.model.Position; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class WatchProtocolDecoderTest extends ProtocolTest { @@ -101,7 +111,40 @@ public class WatchProtocolDecoderTest extends ProtocolTest { verifyPosition(decoder, buffer( "[ZJ*014111001350304*0038*008a*UD,070318,021027,V,00.000000,N,000.000000,E,0,0,0,0,100,18,1000,50,00000000,4,255,460,0,9346,5223,42,9346,5214,20,9784,4083,11,9346,5221,5]")); + } + + @Test + public void testDecodeTK() throws Exception { + WatchProtocolDecoder decoder = new WatchProtocolDecoder(null); + verifyNull(decoder.decode(null, null, buffer("[CS*1234567890*0004*TK,1]"))); + + MockMediaManager mockMediaManager = new MockMediaManager("/tmp"); + Context.initMediaManager(mockMediaManager); + String hex = "7d5b5d2c2aff"; + Object decodedObject = decoder.decode(null, null, concatenateBuffers(buffer("[CS*1234567890*000e*TK,#!AMR"), binary(hex), buffer("]"))); + assertTrue("not a position", decodedObject instanceof Position); + Position position = (Position) decodedObject; + assertEquals("1234567890/mock.amr", position.getAttributes().get("audio")); + verifyFrame(concatenateBuffers(buffer("#!AMR"), binary(hex)), mockMediaManager.readFile("1234567890/mock.amr")); } + private static class MockMediaManager extends MediaManager { + Map<String, ByteBuf> files = new HashMap<>(); + + MockMediaManager(String path) { + super(path); + } + + @Override + public String writeFile(String uniqueId, ByteBuf buf, String extension) { + String fileName = uniqueId + "/mock." + extension; + files.put(fileName, buf); + return fileName; + } + + ByteBuf readFile(String fileName) { + return files.get(fileName); + } + } } |