diff options
Diffstat (limited to 'src/org/traccar/protocol')
-rw-r--r-- | src/org/traccar/protocol/WatchFrameDecoder.java | 12 | ||||
-rw-r--r-- | src/org/traccar/protocol/WatchProtocol.java | 3 | ||||
-rw-r--r-- | src/org/traccar/protocol/WatchProtocolDecoder.java | 36 | ||||
-rw-r--r-- | src/org/traccar/protocol/WatchProtocolEncoder.java | 77 |
4 files changed, 77 insertions, 51 deletions
diff --git a/src/org/traccar/protocol/WatchFrameDecoder.java b/src/org/traccar/protocol/WatchFrameDecoder.java index b2ac5b4f7..f99bd52e2 100644 --- a/src/org/traccar/protocol/WatchFrameDecoder.java +++ b/src/org/traccar/protocol/WatchFrameDecoder.java @@ -31,9 +31,10 @@ public class WatchFrameDecoder extends BaseFrameDecoder { if (endIndex > 0) { ByteBuf frame = Unpooled.buffer(); while (buf.readerIndex() < endIndex) { - byte b = buf.readByte(); - if (b == '}') { - switch (buf.readByte()) { + byte b1 = buf.readByte(); + if (b1 == '}') { + byte b2 = buf.readByte(); + switch (b2) { case 0x01: frame.writeByte('}'); break; @@ -50,10 +51,11 @@ public class WatchFrameDecoder extends BaseFrameDecoder { frame.writeByte('*'); break; default: - throw new IllegalArgumentException(); + throw new IllegalArgumentException(String.format( + "unexpected byte at %d: 0x%02x", buf.readerIndex() - 1, b2)); } } else { - frame.writeByte(b); + frame.writeByte(b1); } } return frame; diff --git a/src/org/traccar/protocol/WatchProtocol.java b/src/org/traccar/protocol/WatchProtocol.java index 5d923106d..b8c990b84 100644 --- a/src/org/traccar/protocol/WatchProtocol.java +++ b/src/org/traccar/protocol/WatchProtocol.java @@ -20,8 +20,6 @@ import org.traccar.PipelineBuilder; import org.traccar.TrackerServer; import org.traccar.model.Command; -import io.netty.handler.codec.string.StringEncoder; - public class WatchProtocol extends BaseProtocol { public WatchProtocol() { @@ -45,7 +43,6 @@ public class WatchProtocol extends BaseProtocol { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { pipeline.addLast(new WatchFrameDecoder()); - pipeline.addLast(new StringEncoder()); pipeline.addLast(new WatchProtocolEncoder()); pipeline.addLast(new WatchProtocolDecoder(WatchProtocol.this)); } diff --git a/src/org/traccar/protocol/WatchProtocolDecoder.java b/src/org/traccar/protocol/WatchProtocolDecoder.java index 78b190030..70b207e9b 100644 --- a/src/org/traccar/protocol/WatchProtocolDecoder.java +++ b/src/org/traccar/protocol/WatchProtocolDecoder.java @@ -16,7 +16,10 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; 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 +41,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); } @@ -64,13 +69,16 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { private void sendResponse(Channel channel, String id, String index, String content) { if (channel != null) { + String response; if (index != null) { - channel.writeAndFlush(new NetworkMessage(String.format("[%s*%s*%s*%04x*%s]", - manufacturer, id, index, content.length(), content), channel.remoteAddress())); + response = String.format("[%s*%s*%s*%04x*%s]", + manufacturer, id, index, content.length(), content); } else { - channel.writeAndFlush(new NetworkMessage(String.format("[%s*%s*%04x*%s]", - manufacturer, id, content.length(), content), channel.remoteAddress())); + response = String.format("[%s*%s*%04x*%s]", + manufacturer, id, content.length(), content); } + ByteBuf buf = Unpooled.copiedBuffer(response, StandardCharsets.US_ASCII); + channel.writeAndFlush(new NetworkMessage(buf, channel.remoteAddress())); } } @@ -180,9 +188,9 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { 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) '*'); String id = buf.readSlice(idIndex - buf.readerIndex()).toString(StandardCharsets.US_ASCII); @@ -191,7 +199,7 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { return null; } - buf.skipBytes(1); // delimiter + buf.skipBytes(1); // '*' delimiter String index = null; int contentIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) '*'); @@ -200,13 +208,13 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { int indexLength = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) '*') - 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) ','); if (contentIndex < 0) { @@ -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.warn(type + "," + result); + } + return null; + } + Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); diff --git a/src/org/traccar/protocol/WatchProtocolEncoder.java b/src/org/traccar/protocol/WatchProtocolEncoder.java index 431b0455a..df29d83a9 100644 --- a/src/org/traccar/protocol/WatchProtocolEncoder.java +++ b/src/org/traccar/protocol/WatchProtocolEncoder.java @@ -15,6 +15,8 @@ */ package org.traccar.protocol; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import org.traccar.StringProtocolEncoder; import org.traccar.helper.DataConverter; @@ -38,13 +40,21 @@ public class WatchProtocolEncoder extends StringProtocolEncoder implements Strin return fmt.format(offset); } else if (key.equals(Command.KEY_MESSAGE)) { return DataConverter.printHex(value.toString().getBytes(StandardCharsets.UTF_16BE)); + } else if (key.equals(Command.KEY_ENABLE)) { + return (boolean) value ? "1" : "0"; } return null; } - protected String formatCommand(Channel channel, Command command, String format, String... keys) { + protected ByteBuf formatTextCommand(Channel channel, Command command, String format, String... keys) { + String content = formatCommand(command, format, this, keys); + ByteBuf buf = Unpooled.copiedBuffer(content, StandardCharsets.US_ASCII); + + return formatBinaryCommand(channel, command, "", buf); + } + protected ByteBuf formatBinaryCommand(Channel channel, Command command, String textPrefix, ByteBuf data) { boolean hasIndex = false; String manufacturer = "CS"; if (channel != null) { @@ -55,23 +65,24 @@ public class WatchProtocolEncoder extends StringProtocolEncoder implements Strin } } - String content = formatCommand(command, format, this, keys); - + ByteBuf buf = Unpooled.buffer(); + buf.writeByte('['); + buf.writeCharSequence(manufacturer, StandardCharsets.US_ASCII); + buf.writeByte('*'); + buf.writeCharSequence(getUniqueId(command.getDeviceId()), StandardCharsets.US_ASCII); + buf.writeByte('*'); if (hasIndex) { - return String.format("[%s*%s*0001*%04x*%s]", - manufacturer, getUniqueId(command.getDeviceId()), content.length(), content); - } else { - return String.format("[%s*%s*%04x*%s]", - manufacturer, getUniqueId(command.getDeviceId()), content.length(), content); - } - } - - private int getEnableFlag(Command command) { - if (command.getBoolean(Command.KEY_ENABLE)) { - return 1; - } else { - return 0; + buf.writeCharSequence("0001", StandardCharsets.US_ASCII); + buf.writeByte('*'); } + buf.writeCharSequence(String.format("%04x", data.readableBytes() + textPrefix.length()), + StandardCharsets.US_ASCII); + buf.writeByte('*'); + buf.writeCharSequence(textPrefix, StandardCharsets.US_ASCII); + buf.writeBytes(data); + buf.writeByte(']'); + + return buf; } private static Map<Byte, Byte> mapping = new HashMap<>(); @@ -84,7 +95,7 @@ public class WatchProtocolEncoder extends StringProtocolEncoder implements Strin mapping.put((byte) 0x2A, (byte) 0x05); } - private String getBinaryData(Command command) { + private ByteBuf getBinaryData(Command command) { byte[] data = DataConverter.parseHex(command.getString(Command.KEY_DATA)); int encodedLength = data.length; @@ -109,7 +120,7 @@ public class WatchProtocolEncoder extends StringProtocolEncoder implements Strin index += 1; } - return new String(encodedData, StandardCharsets.US_ASCII); + return Unpooled.copiedBuffer(encodedData); } @Override @@ -117,35 +128,35 @@ public class WatchProtocolEncoder extends StringProtocolEncoder implements Strin switch (command.getType()) { case Command.TYPE_CUSTOM: - return formatCommand(channel, command, command.getString(Command.KEY_DATA)); + return formatTextCommand(channel, command, command.getString(Command.KEY_DATA)); case Command.TYPE_POSITION_SINGLE: - return formatCommand(channel, command, "RG"); + return formatTextCommand(channel, command, "RG"); case Command.TYPE_SOS_NUMBER: - return formatCommand(channel, command, "SOS{%s},{%s}", Command.KEY_INDEX, Command.KEY_PHONE); + return formatTextCommand(channel, command, "SOS{%s},{%s}", Command.KEY_INDEX, Command.KEY_PHONE); case Command.TYPE_ALARM_SOS: - return formatCommand(channel, command, "SOSSMS," + getEnableFlag(command)); + return formatTextCommand(channel, command, "SOSSMS,{%s}", Command.KEY_ENABLE); case Command.TYPE_ALARM_BATTERY: - return formatCommand(channel, command, "LOWBAT," + getEnableFlag(command)); + return formatTextCommand(channel, command, "LOWBAT,{%s}", Command.KEY_ENABLE); case Command.TYPE_REBOOT_DEVICE: - return formatCommand(channel, command, "RESET"); + return formatTextCommand(channel, command, "RESET"); case Command.TYPE_ALARM_REMOVE: - return formatCommand(channel, command, "REMOVE," + getEnableFlag(command)); + return formatTextCommand(channel, command, "REMOVE,{%s}", Command.KEY_ENABLE); case Command.TYPE_SILENCE_TIME: - return formatCommand(channel, command, "SILENCETIME,{%s}", Command.KEY_DATA); + return formatTextCommand(channel, command, "SILENCETIME,{%s}", Command.KEY_DATA); case Command.TYPE_ALARM_CLOCK: - return formatCommand(channel, command, "REMIND,{%s}", Command.KEY_DATA); + return formatTextCommand(channel, command, "REMIND,{%s}", Command.KEY_DATA); case Command.TYPE_SET_PHONEBOOK: - return formatCommand(channel, command, "PHB,{%s}", Command.KEY_DATA); + return formatTextCommand(channel, command, "PHB,{%s}", Command.KEY_DATA); case Command.TYPE_MESSAGE: - return formatCommand(channel, command, "MESSAGE,{%s}", Command.KEY_MESSAGE); + return formatTextCommand(channel, command, "MESSAGE,{%s}", Command.KEY_MESSAGE); case Command.TYPE_VOICE_MESSAGE: - return formatCommand(channel, command, "TK,%s", getBinaryData(command)); + return formatBinaryCommand(channel, command, "TK,", getBinaryData(command)); case Command.TYPE_POSITION_PERIODIC: - return formatCommand(channel, command, "UPLOAD,{%s}", Command.KEY_FREQUENCY); + return formatTextCommand(channel, command, "UPLOAD,{%s}", Command.KEY_FREQUENCY); case Command.TYPE_SET_TIMEZONE: - return formatCommand(channel, command, "LZ,,{%s}", Command.KEY_TIMEZONE); + return formatTextCommand(channel, command, "LZ,,{%s}", Command.KEY_TIMEZONE); case Command.TYPE_SET_INDICATOR: - return formatCommand(channel, command, "FLOWER,{%s}", Command.KEY_DATA); + return formatTextCommand(channel, command, "FLOWER,{%s}", Command.KEY_DATA); default: return null; } |