aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2015-07-17 22:51:09 +1200
committerAnton Tananaev <anton.tananaev@gmail.com>2015-07-17 22:51:09 +1200
commit466e704934894ed44458bec798fa9fad0532bb4c (patch)
treeeaf48175234c9d4d1b0456a542887a90c1377d00
parent6bfaa4bdedcf6719de75afa905a309296aa1bd9d (diff)
parentff640cf8eb19cfeb3c8475ffd9b0aeccbd769f96 (diff)
downloadtraccar-server-466e704934894ed44458bec798fa9fad0532bb4c.tar.gz
traccar-server-466e704934894ed44458bec798fa9fad0532bb4c.tar.bz2
traccar-server-466e704934894ed44458bec798fa9fad0532bb4c.zip
Merge commands implementation (fix #7)
-rw-r--r--src/org/traccar/BaseProtocol.java34
-rw-r--r--src/org/traccar/BaseProtocolDecoder.java5
-rw-r--r--src/org/traccar/BaseProtocolEncoder.java41
-rw-r--r--src/org/traccar/Protocol.java8
-rw-r--r--src/org/traccar/command/CommandTemplate.java8
-rw-r--r--src/org/traccar/command/CommandType.java25
-rw-r--r--src/org/traccar/command/CommandValueConversion.java5
-rw-r--r--src/org/traccar/command/Duration.java38
-rw-r--r--src/org/traccar/command/FixPositioningCommand.java25
-rw-r--r--src/org/traccar/command/GpsCommand.java27
-rw-r--r--src/org/traccar/command/NoParameterCommand.java11
-rw-r--r--src/org/traccar/command/StringCommandTemplate.java54
-rw-r--r--src/org/traccar/database/ActiveDevice.java14
-rw-r--r--src/org/traccar/database/ConnectionManager.java10
-rw-r--r--src/org/traccar/model/Command.java33
-rw-r--r--src/org/traccar/model/Event.java5
-rw-r--r--src/org/traccar/protocol/Gps103Protocol.java33
-rw-r--r--src/org/traccar/protocol/Gps103ProtocolEncoder.java66
-rw-r--r--src/org/traccar/protocol/GpsMarkerProtocol.java1
-rw-r--r--src/org/traccar/protocol/Gt06Protocol.java60
-rw-r--r--src/org/traccar/protocol/Gt06ProtocolEncoder.java64
-rw-r--r--src/org/traccar/web/CommandServlet.java51
-rw-r--r--src/org/traccar/web/CommandsServlet.java58
-rw-r--r--src/org/traccar/web/EnumFactory.java20
-rw-r--r--src/org/traccar/web/JsonConverter.java20
-rw-r--r--src/org/traccar/web/WebServer.java2
-rw-r--r--test/org/traccar/helper/TestIdentityManager.java13
-rw-r--r--test/org/traccar/protocol/Gps103ProtocolEncoderTest.java29
-rw-r--r--test/org/traccar/web/JsonConverterTest.java187
29 files changed, 391 insertions, 556 deletions
diff --git a/src/org/traccar/BaseProtocol.java b/src/org/traccar/BaseProtocol.java
index 86bebacc7..aa98d776c 100644
--- a/src/org/traccar/BaseProtocol.java
+++ b/src/org/traccar/BaseProtocol.java
@@ -15,42 +15,36 @@
*/
package org.traccar;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
import org.traccar.database.ActiveDevice;
-import org.traccar.command.CommandType;
-import org.traccar.command.CommandTemplate;
-import org.traccar.command.GpsCommand;
-
-import java.util.HashMap;
-import java.util.Map;
+import org.traccar.model.Command;
public abstract class BaseProtocol implements Protocol {
private final String name;
- private Map<CommandType, CommandTemplate> commandTemplates = new HashMap<>();
+ private final Set<String> supportedCommands = new HashSet<>();
public BaseProtocol(String name) {
this.name = name;
- this.initCommandsTemplates(commandTemplates);
}
+ @Override
public String getName() {
return name;
}
- @Override
- public void sendCommand(ActiveDevice activeDevice, GpsCommand command) {
- CommandTemplate commandMessage = commandTemplates.get(command.getType());
-
- if (commandMessage == null) {
- throw new RuntimeException("The command " + command + " is not yet supported in protocol " + this.getName());
- }
-
- Object response = commandMessage.applyTo(activeDevice, command);
-
- activeDevice.write(response);
+ public void setSupportedCommands(String... commands) {
+ supportedCommands.addAll(Arrays.asList(commands));
}
- protected void initCommandsTemplates(Map<CommandType, CommandTemplate> templates) {
+ @Override
+ public void sendCommand(ActiveDevice activeDevice, Command command) {
+ if (!supportedCommands.contains(command.getType())) {
+ throw new RuntimeException("Command " + command + " is not supported in protocol " + getName());
+ }
+ activeDevice.write(command);
}
}
diff --git a/src/org/traccar/BaseProtocolDecoder.java b/src/org/traccar/BaseProtocolDecoder.java
index 61f11367c..3509ec4cf 100644
--- a/src/org/traccar/BaseProtocolDecoder.java
+++ b/src/org/traccar/BaseProtocolDecoder.java
@@ -20,9 +20,6 @@ import org.jboss.netty.channel.Channel;
import org.traccar.helper.Log;
import org.traccar.model.Device;
-/**
- * Base class for protocol decoders
- */
public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder {
private final Protocol protocol;
@@ -46,7 +43,7 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder {
Device device = Context.getIdentityManager().getDeviceByUniqueId(uniqueId);
if (device != null) {
deviceId = device.getId();
- Context.getConnectionManager().setActiveDevice(device.getUniqueId(), protocol, channel, remoteAddress);
+ Context.getConnectionManager().setActiveDevice(deviceId, protocol, channel, remoteAddress);
return true;
} else {
deviceId = 0;
diff --git a/src/org/traccar/BaseProtocolEncoder.java b/src/org/traccar/BaseProtocolEncoder.java
new file mode 100644
index 000000000..2589e4994
--- /dev/null
+++ b/src/org/traccar/BaseProtocolEncoder.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
+import org.traccar.model.Command;
+
+public abstract class BaseProtocolEncoder extends OneToOneEncoder {
+
+ protected String getUniqueId(long deviceId) {
+ return Context.getIdentityManager().getDeviceById(deviceId).getUniqueId();
+ }
+
+ @Override
+ protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
+
+ if (msg instanceof Command) {
+ return encodeCommand((Command) msg);
+ }
+
+ return msg;
+ }
+
+ protected abstract Object encodeCommand(Command command);
+
+}
diff --git a/src/org/traccar/Protocol.java b/src/org/traccar/Protocol.java
index 08d75a0ea..cd37853d0 100644
--- a/src/org/traccar/Protocol.java
+++ b/src/org/traccar/Protocol.java
@@ -1,15 +1,15 @@
package org.traccar;
-import org.traccar.database.ActiveDevice;
-import org.traccar.command.GpsCommand;
-
import java.util.List;
+import org.traccar.database.ActiveDevice;
+import org.traccar.model.Command;
public interface Protocol {
public String getName();
- void sendCommand(ActiveDevice activeDevice, GpsCommand command);
+ void sendCommand(ActiveDevice activeDevice, Command command);
void initTrackerServers(List<TrackerServer> serverList);
+
}
diff --git a/src/org/traccar/command/CommandTemplate.java b/src/org/traccar/command/CommandTemplate.java
deleted file mode 100644
index cdc9be7ab..000000000
--- a/src/org/traccar/command/CommandTemplate.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.traccar.command;
-
-import org.traccar.database.ActiveDevice;
-import org.traccar.command.GpsCommand;
-
-public interface CommandTemplate<T extends GpsCommand> {
- Object applyTo(ActiveDevice activeDevice, T command);
-}
diff --git a/src/org/traccar/command/CommandType.java b/src/org/traccar/command/CommandType.java
deleted file mode 100644
index 56596fa41..000000000
--- a/src/org/traccar/command/CommandType.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.traccar.command;
-
-import org.traccar.model.Factory;
-
-public enum CommandType implements Factory {
- STOP_POSITIONING(NoParameterCommand.class),
- FIX_POSITIONING(FixPositioningCommand.class),
- STOP_ENGINE(NoParameterCommand.class),
- RESUME_ENGINE(NoParameterCommand.class);
-
- private final Class<? extends GpsCommand> commandClass;
-
- CommandType(Class<? extends GpsCommand> commandClass) {
- this.commandClass = commandClass;
- }
-
- @Override
- public Object create() {
- try {
- return commandClass.newInstance();
- } catch (InstantiationException | IllegalAccessException error) {
- throw new RuntimeException(error);
- }
- }
-}
diff --git a/src/org/traccar/command/CommandValueConversion.java b/src/org/traccar/command/CommandValueConversion.java
deleted file mode 100644
index 5c8b75313..000000000
--- a/src/org/traccar/command/CommandValueConversion.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.traccar.command;
-
-public interface CommandValueConversion<T> {
- public String convert(T value);
-}
diff --git a/src/org/traccar/command/Duration.java b/src/org/traccar/command/Duration.java
deleted file mode 100644
index a2ed2c991..000000000
--- a/src/org/traccar/command/Duration.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.traccar.command;
-
-public class Duration {
-
- public enum TimeUnit {
- SECOND("s"), MINUTE("m"), HOUR("h");
-
- private final String commandFormat;
-
- TimeUnit(String commandFormat) {
- this.commandFormat = commandFormat;
- }
-
- public String getCommandFormat() {
- return commandFormat;
- }
- }
-
-
- private TimeUnit unit;
- private int value;
-
- public TimeUnit getUnit() {
- return unit;
- }
-
- public void setUnit(TimeUnit unit) {
- this.unit = unit;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
-}
diff --git a/src/org/traccar/command/FixPositioningCommand.java b/src/org/traccar/command/FixPositioningCommand.java
deleted file mode 100644
index 18d5f32fb..000000000
--- a/src/org/traccar/command/FixPositioningCommand.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.traccar.command;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class FixPositioningCommand extends GpsCommand {
- public static final String FREQUENCY = "frequency";
-
- private Duration data;
-
- @Override
- public Map<String, Object> getReplacements() {
- Map<String, Object> replacements = new HashMap<>();
- replacements.put(FREQUENCY, data);
- return replacements;
- }
-
- public Duration getData() {
- return data;
- }
-
- public void setData(Duration data) {
- this.data = data;
- }
-}
diff --git a/src/org/traccar/command/GpsCommand.java b/src/org/traccar/command/GpsCommand.java
deleted file mode 100644
index 7097c4807..000000000
--- a/src/org/traccar/command/GpsCommand.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.traccar.command;
-
-import java.util.Map;
-
-public abstract class GpsCommand {
- public static final String UNIQUE_ID = "uniqueId";
- private String uniqueId;
- private CommandType type;
-
- public String getUniqueId() {
- return uniqueId;
- }
-
- public void setUniqueId(String uniqueId) {
- this.uniqueId = uniqueId;
- }
-
- public CommandType getType() {
- return type;
- }
-
- public void setType(CommandType type) {
- this.type = type;
- }
-
- public abstract Map<String, Object> getReplacements();
-}
diff --git a/src/org/traccar/command/NoParameterCommand.java b/src/org/traccar/command/NoParameterCommand.java
deleted file mode 100644
index f4e139b7b..000000000
--- a/src/org/traccar/command/NoParameterCommand.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.traccar.command;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class NoParameterCommand extends GpsCommand {
- @Override
- public Map<String, Object> getReplacements() {
- return new HashMap<>();
- }
-}
diff --git a/src/org/traccar/command/StringCommandTemplate.java b/src/org/traccar/command/StringCommandTemplate.java
deleted file mode 100644
index 3f326e534..000000000
--- a/src/org/traccar/command/StringCommandTemplate.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.traccar.command;
-
-import org.traccar.database.ActiveDevice;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class StringCommandTemplate<T extends GpsCommand> implements CommandTemplate<T> {
-
- private String messageTemplate;
- private Map<Class<?>, CommandValueConversion> converters = new HashMap<>();
-
- public StringCommandTemplate(String template, Object... replacements) {
- this.messageTemplate = String.format(template, replacements);
- }
-
- @Override
- public Object applyTo(ActiveDevice activeDevice, T command) {
- String currentMessage = messageTemplate;
- currentMessage = this.replace(currentMessage, GpsCommand.UNIQUE_ID, activeDevice.getUniqueId());
-
- Map<String, Object> replacements = command.getReplacements();
-
- for (Map.Entry<String, Object> entry : replacements.entrySet()) {
- currentMessage = this.replace(currentMessage, entry.getKey(), entry.getValue());
- }
-
- return currentMessage;
- }
-
- public CommandTemplate addConverter(Class<?> type, CommandValueConversion converter) {
- converters.put(type, converter);
- return this;
- }
-
- protected CommandValueConversion getConverter(Class<?> type) {
- return converters.containsKey(type) ? converters.get(type) : idConverter();
- }
-
- private CommandValueConversion idConverter() {
- return new CommandValueConversion() {
- @Override
- public String convert(Object value) {
- return value.toString();
- }
- };
- }
-
- private String replace(String currentMessage, String key, Object value) {
- String replacementValue = getConverter(value.getClass()).convert(value);
- return currentMessage.replace("[" + key + "]", replacementValue);
- }
-
-}
diff --git a/src/org/traccar/database/ActiveDevice.java b/src/org/traccar/database/ActiveDevice.java
index f94e1b12a..33d9adad3 100644
--- a/src/org/traccar/database/ActiveDevice.java
+++ b/src/org/traccar/database/ActiveDevice.java
@@ -17,19 +17,19 @@ package org.traccar.database;
import org.jboss.netty.channel.Channel;
import org.traccar.Protocol;
-import org.traccar.command.GpsCommand;
+import org.traccar.model.Command;
import java.net.SocketAddress;
public class ActiveDevice {
- private String uniqueId;
+ private long deviceId;
private Protocol protocol;
private Channel channel;
private SocketAddress remoteAddress;
- public ActiveDevice(String uniqueId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
- this.uniqueId = uniqueId;
+ public ActiveDevice(long deviceId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
+ this.deviceId = deviceId;
this.protocol = protocol;
this.channel = channel;
this.remoteAddress = remoteAddress;
@@ -39,11 +39,11 @@ public class ActiveDevice {
return channel;
}
- public String getUniqueId() {
- return uniqueId;
+ public long getDeviceId() {
+ return deviceId;
}
- public void sendCommand(GpsCommand command) {
+ public void sendCommand(Command command) {
protocol.sendCommand(this, command);
}
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java
index dc125d7b0..39ec465e6 100644
--- a/src/org/traccar/database/ConnectionManager.java
+++ b/src/org/traccar/database/ConnectionManager.java
@@ -31,7 +31,7 @@ import org.traccar.model.Position;
public class ConnectionManager {
- private final Map<String, ActiveDevice> activeDevices = new HashMap<>();
+ private final Map<Long, ActiveDevice> activeDevices = new HashMap<>();
private final Map<Long, Position> positions = new HashMap<>();
private final Map<Long, Set<DataCacheListener>> listeners = new HashMap<>();
@@ -47,12 +47,12 @@ public class ConnectionManager {
}
}
- public void setActiveDevice(String uniqueId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
- activeDevices.put(uniqueId, new ActiveDevice(uniqueId, protocol, channel, remoteAddress));
+ public void setActiveDevice(long deviceId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
+ activeDevices.put(deviceId, new ActiveDevice(deviceId, protocol, channel, remoteAddress));
}
- public ActiveDevice getActiveDevice(String uniqueId) {
- return activeDevices.get(uniqueId);
+ public ActiveDevice getActiveDevice(long deviceId) {
+ return activeDevices.get(deviceId);
}
public synchronized void update(Position position) {
diff --git a/src/org/traccar/model/Command.java b/src/org/traccar/model/Command.java
new file mode 100644
index 000000000..f7702dbd0
--- /dev/null
+++ b/src/org/traccar/model/Command.java
@@ -0,0 +1,33 @@
+package org.traccar.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class Command implements Factory {
+
+ @Override
+ public Command create() {
+ return new Command();
+ }
+
+ private long deviceId;
+ public long getDeviceId() { return deviceId; }
+ public void setDeviceId(long deviceId) { this.deviceId = deviceId; }
+
+ private String type;
+ public String getType() { return type; }
+ public void setType(String type) { this.type = type; }
+
+ private Map<String, Object> other = new LinkedHashMap<>();
+ public Map<String, Object> getOther() { return other; }
+ public void setOther(Map<String, Object> other) { this.other = other; }
+
+ public static final String TYPE_POSITION_STOP = "positionStop";
+ public static final String TYPE_POSITION_FIX = "positionFix";
+ public static final String TYPE_ENGINE_STOP = "engineStop";
+ public static final String TYPE_ENGINE_RESUME = "engineResume";
+
+ public static final String KEY_UNIQUE_ID = "uniqueId";
+ public static final String KEY_FREQUENCY = "frequency";
+
+}
diff --git a/src/org/traccar/model/Event.java b/src/org/traccar/model/Event.java
index 0768ec9f3..b42a776ae 100644
--- a/src/org/traccar/model/Event.java
+++ b/src/org/traccar/model/Event.java
@@ -42,13 +42,14 @@ public abstract class Event {
public void setDeviceTime(Date deviceTime) { this.deviceTime = deviceTime; }
private Map<String, Object> other = new LinkedHashMap<>();
+ public Map<String, Object> getOther() { return other; }
+ public void setOther(Map<String, Object> other) { this.other = other; }
+
public void set(String key, Object value) {
if (value != null && (!(value instanceof String) || !((String) value).isEmpty())) {
other.put(key, value);
}
}
- public void setOther(Map<String, Object> other) { this.other = other; }
- public Map<String, Object> getOther() { return other; }
public static final String KEY_INDEX = "index";
public static final String KEY_HDOP = "hdop";
diff --git a/src/org/traccar/protocol/Gps103Protocol.java b/src/org/traccar/protocol/Gps103Protocol.java
index 84275a556..59d8e62a7 100644
--- a/src/org/traccar/protocol/Gps103Protocol.java
+++ b/src/org/traccar/protocol/Gps103Protocol.java
@@ -15,6 +15,7 @@
*/
package org.traccar.protocol;
+import java.util.List;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
@@ -23,35 +24,17 @@ import org.jboss.netty.handler.codec.string.StringEncoder;
import org.traccar.BaseProtocol;
import org.traccar.CharacterDelimiterFrameDecoder;
import org.traccar.TrackerServer;
-import org.traccar.command.CommandType;
-import org.traccar.command.Duration;
-import org.traccar.command.FixPositioningCommand;
-import org.traccar.command.GpsCommand;
-import org.traccar.command.CommandTemplate;
-import org.traccar.command.CommandValueConversion;
-import org.traccar.command.StringCommandTemplate;
-
-import java.util.List;
-import java.util.Map;
+import org.traccar.model.Command;
public class Gps103Protocol extends BaseProtocol {
public Gps103Protocol() {
super("gps103");
- }
-
- @Override
- protected void initCommandsTemplates(Map<CommandType, CommandTemplate> templates) {
- templates.put(CommandType.STOP_POSITIONING, new StringCommandTemplate("**,imei:[%s],A", GpsCommand.UNIQUE_ID));
- templates.put(CommandType.FIX_POSITIONING, new StringCommandTemplate("**,imei:[%s],C,[%s]", GpsCommand.UNIQUE_ID, FixPositioningCommand.FREQUENCY)
- .addConverter(Duration.class, new CommandValueConversion<Duration>() {
- @Override
- public String convert(Duration value) {
- return String.format("%02d%s", value.getValue(), value.getUnit().getCommandFormat());
- }
- }));
- templates.put(CommandType.RESUME_ENGINE, new StringCommandTemplate("**,imei:[%s],J", GpsCommand.UNIQUE_ID));
- templates.put(CommandType.STOP_ENGINE, new StringCommandTemplate("**,imei:[%s],K", GpsCommand.UNIQUE_ID));
+ setSupportedCommands(
+ Command.TYPE_POSITION_STOP,
+ Command.TYPE_POSITION_FIX,
+ Command.TYPE_ENGINE_STOP,
+ Command.TYPE_ENGINE_RESUME);
}
@Override
@@ -63,6 +46,7 @@ public class Gps103Protocol extends BaseProtocol {
pipeline.addLast("stringDecoder", new StringDecoder());
pipeline.addLast("stringEncoder", new StringEncoder());
pipeline.addLast("objectDecoder", new Gps103ProtocolDecoder(Gps103Protocol.this));
+ pipeline.addLast("objectEncoder", new Gps103ProtocolEncoder());
}
});
serverList.add(new TrackerServer(new ConnectionlessBootstrap(), this.getName()) {
@@ -71,6 +55,7 @@ public class Gps103Protocol extends BaseProtocol {
pipeline.addLast("stringDecoder", new StringDecoder());
pipeline.addLast("stringEncoder", new StringEncoder());
pipeline.addLast("objectDecoder", new Gps103ProtocolDecoder(Gps103Protocol.this));
+ pipeline.addLast("objectEncoder", new Gps103ProtocolEncoder());
}
});
}
diff --git a/src/org/traccar/protocol/Gps103ProtocolEncoder.java b/src/org/traccar/protocol/Gps103ProtocolEncoder.java
new file mode 100644
index 000000000..27fea8237
--- /dev/null
+++ b/src/org/traccar/protocol/Gps103ProtocolEncoder.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import java.util.Map;
+import org.traccar.BaseProtocolEncoder;
+import org.traccar.model.Command;
+
+public class Gps103ProtocolEncoder extends BaseProtocolEncoder {
+
+ private String formatCommand(Command command, String format, String... keys) {
+
+ String result = String.format(format, (Object[]) keys);
+
+ result = result.replaceAll("\\{" + Command.KEY_UNIQUE_ID + "}", getUniqueId(command.getDeviceId()));
+ for (Map.Entry<String, Object> entry : command.getOther().entrySet()) {
+ String value;
+ if (entry.getKey().equals(Command.KEY_FREQUENCY)) {
+ long frequency = (Long) entry.getValue();
+ if (frequency / 60 / 60 > 0) {
+ value = String.format("%02dh", frequency / 60 / 60);
+ } else if (frequency / 60 > 0) {
+ value = String.format("%02dm", frequency / 60);
+ } else {
+ value = String.format("%02ds", frequency);
+ }
+ } else {
+ value = entry.getValue().toString();
+ }
+ result = result.replaceAll("\\{" + entry.getKey() + "}", value);
+ }
+
+ return result;
+ }
+
+ @Override
+ protected Object encodeCommand(Command command) {
+
+ switch (command.getType()) {
+ case Command.TYPE_POSITION_STOP:
+ return formatCommand(command, "**,imei:{%s},A", Command.KEY_UNIQUE_ID);
+ case Command.TYPE_POSITION_FIX:
+ return formatCommand(command, "**,imei:{%s},C,{%s}", Command.KEY_UNIQUE_ID, Command.KEY_FREQUENCY);
+ case Command.TYPE_ENGINE_STOP:
+ return formatCommand(command, "**,imei:{%s},K", Command.KEY_UNIQUE_ID);
+ case Command.TYPE_ENGINE_RESUME:
+ return formatCommand(command, "**,imei:{%s},J", Command.KEY_UNIQUE_ID);
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/protocol/GpsMarkerProtocol.java b/src/org/traccar/protocol/GpsMarkerProtocol.java
index 0ef8cad70..7961e2340 100644
--- a/src/org/traccar/protocol/GpsMarkerProtocol.java
+++ b/src/org/traccar/protocol/GpsMarkerProtocol.java
@@ -23,7 +23,6 @@ import org.jboss.netty.handler.codec.string.StringEncoder;
import org.traccar.BaseProtocol;
import org.traccar.CharacterDelimiterFrameDecoder;
import org.traccar.TrackerServer;
-import org.traccar.command.*;
import java.util.List;
import java.util.Map;
diff --git a/src/org/traccar/protocol/Gt06Protocol.java b/src/org/traccar/protocol/Gt06Protocol.java
index d4bd48288..0c59f3a0c 100644
--- a/src/org/traccar/protocol/Gt06Protocol.java
+++ b/src/org/traccar/protocol/Gt06Protocol.java
@@ -15,31 +15,20 @@
*/
package org.traccar.protocol;
+import java.util.List;
import org.jboss.netty.bootstrap.ServerBootstrap;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelPipeline;
import org.traccar.BaseProtocol;
import org.traccar.TrackerServer;
-import org.traccar.database.ActiveDevice;
-import org.traccar.helper.Crc;
-import org.traccar.command.CommandType;
-import org.traccar.command.NoParameterCommand;
-import org.traccar.command.CommandTemplate;
-
-import java.util.List;
-import java.util.Map;
+import org.traccar.model.Command;
public class Gt06Protocol extends BaseProtocol {
public Gt06Protocol() {
super("gt06");
- }
-
- @Override
- protected void initCommandsTemplates(Map<CommandType, CommandTemplate> templates) {
- templates.put(CommandType.STOP_ENGINE, new Gt06CommandTemplate("DYD#"));
- templates.put(CommandType.RESUME_ENGINE, new Gt06CommandTemplate("HFYD#"));
+ setSupportedCommands(
+ Command.TYPE_ENGINE_STOP,
+ Command.TYPE_ENGINE_STOP);
}
@Override
@@ -53,43 +42,4 @@ public class Gt06Protocol extends BaseProtocol {
});
}
- class Gt06CommandTemplate implements CommandTemplate<NoParameterCommand> {
-
- private String commandContent;
-
- public Gt06CommandTemplate(String commandContent) {
- this.commandContent = commandContent;
- }
-
- @Override
- public Object applyTo(ActiveDevice activeDevice, NoParameterCommand command) {
- int serverFlagBit = 0x0;
- int commandLength = serverFlagBit + commandContent.length();
- int packetLength = 0x80 /*Protocol Number */ + commandContent.length() /* Information Content */ + 2 /*Information Serial Number */+ 2 /*Error Check */;
-
- int informationSerialNumber = 1;
-
-
- ChannelBuffer response = ChannelBuffers.directBuffer(10);
- response.writeBytes(new byte[]{0x78, 0x78}); // Start Bit
- response.writeByte(packetLength); // Packet Length
- response.writeByte(0x80); // Protocol Number
-
- // Information Content
- response.writeByte(commandLength); // Length of command
- response.writeByte(serverFlagBit); // Server Flag Bit
- response.writeBytes(commandContent.getBytes()); // Command Content
- response.writeBytes(new byte[]{0x00, 0x02}); // Language
-
- response.writeShort(informationSerialNumber); // Information Serial Number
-
- int crc = Crc.crc16Ccitt(response.toByteBuffer(2, response.writerIndex()));
- response.writeShort(crc); // Error Check
-
- response.writeBytes(new byte[] {0x0D, 0x0A}); // Stop Bit
-
- return response;
- }
- }
-
}
diff --git a/src/org/traccar/protocol/Gt06ProtocolEncoder.java b/src/org/traccar/protocol/Gt06ProtocolEncoder.java
new file mode 100644
index 000000000..b8177d60b
--- /dev/null
+++ b/src/org/traccar/protocol/Gt06ProtocolEncoder.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.traccar.BaseProtocolEncoder;
+import org.traccar.helper.Crc;
+import org.traccar.model.Command;
+
+public class Gt06ProtocolEncoder extends BaseProtocolEncoder {
+
+ @Override
+ protected Object encodeCommand(Command command) {
+
+ String content = "";
+ switch (command.getType()) {
+ case Command.TYPE_ENGINE_STOP:
+ content = "DYD#";
+ break;
+ case Command.TYPE_ENGINE_RESUME:
+ content = "HFYD#";
+ break;
+ }
+
+ int serverFlagBit = 0x00;
+ int commandLength = serverFlagBit + content.length();
+ int packetLength = 0x80 + content.length() + 2 + 2;
+
+ ChannelBuffer response = ChannelBuffers.directBuffer(10);
+ response.writeBytes(new byte[]{0x78, 0x78}); // Start Bit
+ response.writeByte(packetLength); // Packet Length
+ response.writeByte(0x80); // Protocol Number
+
+ // Information Content
+ response.writeByte(commandLength); // Length of command
+ response.writeByte(serverFlagBit); // Server Flag Bit
+ response.writeBytes(content.getBytes()); // Command Content
+ response.writeBytes(new byte[]{0x00, 0x02}); // Language
+
+ response.writeShort(1); // Information Serial Number
+
+ int crc = Crc.crc16Ccitt(response.toByteBuffer(2, response.writerIndex()));
+ response.writeShort(crc); // Error Check
+
+ response.writeBytes(new byte[] {0x0D, 0x0A}); // Stop Bit
+
+ return response;
+ }
+
+}
diff --git a/src/org/traccar/web/CommandServlet.java b/src/org/traccar/web/CommandServlet.java
new file mode 100644
index 000000000..049a0534d
--- /dev/null
+++ b/src/org/traccar/web/CommandServlet.java
@@ -0,0 +1,51 @@
+package org.traccar.web;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.traccar.Context;
+import org.traccar.model.Command;
+import org.traccar.database.ActiveDevice;
+
+public class CommandServlet extends BaseServlet {
+
+ @Override
+ protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+
+ switch (command) {
+ case "/send":
+ send(req, resp);
+ return true;
+ case "/raw":
+ raw(req, resp);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public ActiveDevice getActiveDevice(long deviceId) {
+ ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(deviceId);
+ if (activeDevice == null) {
+ throw new RuntimeException("The device is not registered on the server");
+ }
+ return activeDevice;
+ }
+
+ private void send(HttpServletRequest req, HttpServletResponse resp) throws Exception {
+
+ Command command = JsonConverter.objectFromJson(req.getReader(), new Command());
+ getActiveDevice(command.getDeviceId()).write(command);
+ sendResponse(resp.getWriter(), true);
+ }
+
+ private void raw(HttpServletRequest req, HttpServletResponse resp) throws Exception {
+
+ JsonObject json = Json.createReader(req.getReader()).readObject();
+ long deviceId = json.getJsonNumber("deviceId").longValue();
+ String command = json.getString("command");
+ getActiveDevice(deviceId).write(command);
+ sendResponse(resp.getWriter(), true);
+ }
+}
diff --git a/src/org/traccar/web/CommandsServlet.java b/src/org/traccar/web/CommandsServlet.java
deleted file mode 100644
index b12c0fa53..000000000
--- a/src/org/traccar/web/CommandsServlet.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.traccar.web;
-
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.traccar.Context;
-import org.traccar.command.CommandType;
-import org.traccar.command.GpsCommand;
-import org.traccar.database.ActiveDevice;
-
-public class CommandsServlet extends BaseServlet {
-
- @Override
- protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception {
-
- switch (command) {
- case "/send":
- send(req, resp);
- return true;
- case "/raw":
- sendRawCommand(req, resp);
- return true;
- default:
- return false;
- }
- }
-
- private void send(HttpServletRequest req, HttpServletResponse resp) throws Exception {
- GpsCommand command = JsonConverter.<GpsCommand>enumObjectFromJson(req.getReader(), new EnumFactory(CommandType.class, "type"));
-
- String uniqueId = command.getUniqueId();
-
- ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(uniqueId);
- if(activeDevice == null) {
- throw new RuntimeException("The device has not yet registered to the server");
- }
-
- activeDevice.sendCommand(command);
-
- sendResponse(resp.getWriter(), JsonConverter.objectToJson(new Object()));
- }
-
- private void sendRawCommand(HttpServletRequest req, HttpServletResponse resp) throws Exception {
- JsonObject json = Json.createReader(req.getReader()).readObject();
- String uniqueId = json.getString("uniqueId");
-
- ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(uniqueId);
- if(activeDevice == null) {
- throw new RuntimeException("The device has not yet registered to the server");
- }
-
- String command = json.getString("command");
- activeDevice.write(command);
-
- sendResponse(resp.getWriter(), JsonConverter.objectToJson(new Object()));
- }
-}
diff --git a/src/org/traccar/web/EnumFactory.java b/src/org/traccar/web/EnumFactory.java
deleted file mode 100644
index efbfd4b20..000000000
--- a/src/org/traccar/web/EnumFactory.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.traccar.web;
-
-import org.traccar.model.Factory;
-
-import javax.json.JsonObject;
-
-public class EnumFactory<T extends Enum<T> & Factory> {
- private Class<T> commandTypeClass;
- private String jsonKey;
-
- public EnumFactory(Class<T> commandTypeClass, String type) {
- this.commandTypeClass = commandTypeClass;
- jsonKey = type;
- }
-
- public <K> K create(JsonObject json) {
- Factory factory = Enum.valueOf(commandTypeClass, json.getString(jsonKey));
- return (K) factory.create();
- }
-}
diff --git a/src/org/traccar/web/JsonConverter.java b/src/org/traccar/web/JsonConverter.java
index 7962ac8ab..0dc4f24eb 100644
--- a/src/org/traccar/web/JsonConverter.java
+++ b/src/org/traccar/web/JsonConverter.java
@@ -46,20 +46,9 @@ public class JsonConverter {
return objectFromJson(Json.createReader(reader).readObject(), prototype);
}
- public static <T> T enumObjectFromJson(Reader reader, EnumFactory<? extends Enum<?>> factory) throws ParseException {
- JsonObject json = Json.createReader(reader).readObject();
- T object = factory.<T>create(json);
- populateObject(json, object);
- return object;
- }
-
public static <T extends Factory> T objectFromJson(JsonObject json, T prototype) throws ParseException {
T object = (T) prototype.create();
- populateObject(json, object);
- return object;
- }
- private static void populateObject(JsonObject json, Object object) throws ParseException {
Method[] methods = object.getClass().getMethods();
for (final Method method : methods) {
@@ -86,17 +75,14 @@ public class JsonConverter {
} else if (parameterType.isEnum()) {
method.invoke(object, Enum.valueOf((Class<? extends Enum>) parameterType, json.getString(name)));
} else if (parameterType.equals(Map.class)) {
- //method.invoke(object, json.getString(name));
- } else {
- Object nestedObject = parameterType.newInstance();
- populateObject(json.getJsonObject(name), nestedObject);
- method.invoke(object, nestedObject);
+ // TODO: method.invoke(object, json.getString(name));
}
- } catch (IllegalAccessException | InvocationTargetException | InstantiationException error) {
+ } catch (IllegalAccessException | InvocationTargetException error) {
}
}
}
+ return object;
}
public static <T> JsonObject objectToJson(T object) {
diff --git a/src/org/traccar/web/WebServer.java b/src/org/traccar/web/WebServer.java
index 698796467..38345ffe7 100644
--- a/src/org/traccar/web/WebServer.java
+++ b/src/org/traccar/web/WebServer.java
@@ -74,7 +74,7 @@ public class WebServer {
servletHandler.addServlet(new ServletHolder(new UserServlet()), "/user/*");
servletHandler.addServlet(new ServletHolder(new DeviceServlet()), "/device/*");
servletHandler.addServlet(new ServletHolder(new PositionServlet()), "/position/*");
- servletHandler.addServlet(new ServletHolder(new CommandsServlet()), "/commands/*");
+ servletHandler.addServlet(new ServletHolder(new CommandServlet()), "/command/*");
servletHandler.addServlet(new ServletHolder(new MainServlet()), "/*");
/*ResourceHandler mobileResourceHandler = new ResourceHandler();
diff --git a/test/org/traccar/helper/TestIdentityManager.java b/test/org/traccar/helper/TestIdentityManager.java
index a4ddeeb09..d279241e4 100644
--- a/test/org/traccar/helper/TestIdentityManager.java
+++ b/test/org/traccar/helper/TestIdentityManager.java
@@ -4,17 +4,22 @@ import org.traccar.database.IdentityManager;
import org.traccar.model.Device;
public class TestIdentityManager implements IdentityManager {
+
+ private final Device device;
+
+ public TestIdentityManager() {
+ device = new Device();
+ device.setId(1);
+ device.setUniqueId("123456789012345");
+ }
@Override
public Device getDeviceById(long id) {
- return null;
+ return device;
}
@Override
public Device getDeviceByUniqueId(String imei) {
- Device device = new Device();
- device.setId(new Long(1));
- device.setUniqueId("123456789012345");
return device;
}
diff --git a/test/org/traccar/protocol/Gps103ProtocolEncoderTest.java b/test/org/traccar/protocol/Gps103ProtocolEncoderTest.java
new file mode 100644
index 000000000..74091d0e0
--- /dev/null
+++ b/test/org/traccar/protocol/Gps103ProtocolEncoderTest.java
@@ -0,0 +1,29 @@
+package org.traccar.protocol;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+import org.traccar.model.Command;
+
+public class Gps103ProtocolEncoderTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gps103ProtocolEncoder encoder = new Gps103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_FIX);
+
+ Map<String, Object> other = new HashMap<>();
+ other.put(Command.KEY_FREQUENCY, 300l);
+
+ command.setOther(other);
+
+ Assert.assertEquals("**,imei:123456789012345,C,05m", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/test/org/traccar/web/JsonConverterTest.java b/test/org/traccar/web/JsonConverterTest.java
index 07d70d3f2..b02ec2d40 100644
--- a/test/org/traccar/web/JsonConverterTest.java
+++ b/test/org/traccar/web/JsonConverterTest.java
@@ -1,170 +1,75 @@
package org.traccar.web;
-import org.junit.Test;
-import org.traccar.model.Factory;
-
-import java.io.Reader;
import java.io.StringReader;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
-
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import org.junit.Test;
+import org.traccar.model.Factory;
public class JsonConverterTest {
- private <T extends Factory> T convert(String jsonString, T prototype) throws ParseException {
- Reader r = new StringReader(
- jsonString);
-
- return JsonConverter.objectFromJson(r, prototype);
- }
-
@Test
public void primitiveConversion() throws ParseException {
- AllPrimitives o = convert("{" +
- "\"aBoolean\": true, " +
- "\"anInt\": 42, " +
- "\"aDouble\": 41.99, " +
- "\"aString\": \"discworld\", " +
- "\"aDate\":\"2015-07-09T19:02:17\"" +
- "}",
- new AllPrimitives());
-
- assertEquals(true, o.getaBoolean());
- assertEquals(42, o.getAnInt());
- assertEquals(41.99, o.getaDouble(), 0.001);
- assertEquals("discworld", o.getaString());
+ Primitives o = JsonConverter.objectFromJson(new StringReader(
+ "{" +
+ "\"boolean\": true, " +
+ "\"int\": 42, " +
+ "\"double\": 41.99, " +
+ "\"string\": \"discworld\", " +
+ "\"date\":\"2015-07-09T19:02:17\"" +
+ "}"),
+ new Primitives());
+
+ assertEquals(true, o.getBoolean());
+ assertEquals(42, o.getInt());
+ assertEquals(41.99, o.getDouble(), 0.001);
+ assertEquals("discworld", o.getString());
Calendar c = Calendar.getInstance();
- c.setTime(o.getaDate());
+ c.setTime(o.getDate());
assertEquals(2015, c.get(Calendar.YEAR));
assertEquals(Calendar.JULY, c.get(Calendar.MONTH));
assertEquals(9, c.get(Calendar.DAY_OF_MONTH));
assertEquals(19, c.get(Calendar.HOUR_OF_DAY));
assertEquals(2, c.get(Calendar.MINUTE));
assertEquals(17, c.get(Calendar.SECOND));
- }
-
- public static class AllPrimitives implements Factory {
-
- private boolean aBoolean;
- private int anInt;
- private double aDouble;
- private String aString;
- private Date aDate;
-
-
- @Override
- public Object create() {
- return new AllPrimitives();
- }
-
- public boolean getaBoolean() {
- return aBoolean;
- }
-
- public void setaBoolean(boolean aBoolean) {
- this.aBoolean = aBoolean;
- }
-
- public int getAnInt() {
- return anInt;
- }
-
- public void setAnInt(int anInt) {
- this.anInt = anInt;
- }
-
- public double getaDouble() {
- return aDouble;
- }
-
- public void setaDouble(double aDouble) {
- this.aDouble = aDouble;
- }
-
- public String getaString() {
- return aString;
- }
-
- public void setaString(String aString) {
- this.aString = aString;
- }
- public Date getaDate() {
- return aDate;
- }
-
- public void setaDate(Date aDate) {
- this.aDate = aDate;
- }
- }
-
-
- @Test
- public void enumConversion() throws ParseException {
- ObjectWithEnum o = convert("{\"anEnum\": \"VALUE2\"}", new ObjectWithEnum());
- assertEquals(TestEnum.VALUE2, o.getAnEnum());
- }
-
-
- public enum TestEnum {
- VALUE1, VALUE2
}
- public static class ObjectWithEnum implements Factory {
- private TestEnum anEnum;
-
- public TestEnum getAnEnum() {
- return anEnum;
- }
-
- public void setAnEnum(TestEnum anEnum) {
- this.anEnum = anEnum;
- }
-
+ public static class Primitives implements Factory {
+
@Override
- public Object create() {
- return new ObjectWithEnum();
- }
- }
-
+ public Primitives create() {
+ return new Primitives();
+ }
+
+ private boolean b;
+ public boolean getBoolean() { return b; }
+ public void setBoolean(boolean b) { this.b = b; }
+
+ private int i;
+ public int getInt() { return i; }
+ public void setInt(int i) { this.i = i; }
+
+ private long l;
+ public long getLong() { return l; }
+ public void setLong(long l) { this.l = l; }
+
+ private double d;
+ public double getDouble() { return d; }
+ public void setDouble(double d) { this.d = d; }
+
+ private String s;
+ public String getString() { return s; }
+ public void setString(String s) { this.s = s; }
+
+ private Date t;
+ public Date getDate() { return t; }
+ public void setDate(Date t) { this.t = t; }
- @Test
- public void nestedObjectsConversion() throws ParseException {
- NestedObjects o = convert("{\"name\": \"Rincewind\", \"nestedObject\": {\"anEnum\":\"VALUE1\"}}", new NestedObjects());
- assertEquals("Rincewind", o.getName());
- assertNotNull("The nested object should be populated", o.getNestedObject());
- assertEquals(TestEnum.VALUE1, o.getNestedObject().getAnEnum());
}
- public static class NestedObjects implements Factory {
-
- private String name;
- private ObjectWithEnum nestedObject;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public ObjectWithEnum getNestedObject() {
- return nestedObject;
- }
-
- public void setNestedObject(ObjectWithEnum nestedObject) {
- this.nestedObject = nestedObject;
- }
-
- @Override
- public Object create() {
- return new NestedObjects();
- }
- }
}