aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/traccar/protocol')
-rw-r--r--src/org/traccar/protocol/WatchFrameDecoder.java12
-rw-r--r--src/org/traccar/protocol/WatchProtocol.java3
-rw-r--r--src/org/traccar/protocol/WatchProtocolDecoder.java36
-rw-r--r--src/org/traccar/protocol/WatchProtocolEncoder.java77
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;
}