aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup/default.xml2
-rw-r--r--src/org/traccar/BaseProtocol.java54
-rw-r--r--src/org/traccar/Protocol.java8
-rw-r--r--src/org/traccar/ServerManager.java10
-rw-r--r--src/org/traccar/api/resource/CommandResource.java6
-rw-r--r--src/org/traccar/api/resource/CommandTypeResource.java7
-rw-r--r--src/org/traccar/database/ActiveDevice.java18
-rw-r--r--src/org/traccar/database/DeviceManager.java50
-rw-r--r--src/org/traccar/model/Command.java12
-rw-r--r--src/org/traccar/notification/NotificationSms.java4
-rw-r--r--src/org/traccar/protocol/CarcellProtocol.java2
-rw-r--r--src/org/traccar/protocol/CellocatorProtocol.java2
-rw-r--r--src/org/traccar/protocol/CityeasyProtocol.java2
-rw-r--r--src/org/traccar/protocol/DmtProtocol.java46
-rw-r--r--src/org/traccar/protocol/DmtProtocolDecoder.java147
-rw-r--r--src/org/traccar/protocol/EelinkProtocol.java2
-rw-r--r--src/org/traccar/protocol/Gl200Protocol.java2
-rw-r--r--src/org/traccar/protocol/Gps103Protocol.java2
-rw-r--r--src/org/traccar/protocol/GranitProtocol.java9
-rw-r--r--src/org/traccar/protocol/GranitProtocolSmsEncoder.java38
-rw-r--r--src/org/traccar/protocol/Gt06Protocol.java2
-rw-r--r--src/org/traccar/protocol/H02Protocol.java2
-rw-r--r--src/org/traccar/protocol/HuabaoProtocol.java2
-rw-r--r--src/org/traccar/protocol/Jt600Protocol.java2
-rw-r--r--src/org/traccar/protocol/KhdProtocol.java2
-rw-r--r--src/org/traccar/protocol/MeiligaoProtocol.java2
-rw-r--r--src/org/traccar/protocol/MeitrackProtocol.java2
-rw-r--r--src/org/traccar/protocol/MiniFinderProtocol.java2
-rw-r--r--src/org/traccar/protocol/NoranProtocol.java2
-rw-r--r--src/org/traccar/protocol/Pt502Protocol.java2
-rw-r--r--src/org/traccar/protocol/RuptelaProtocol.java2
-rw-r--r--src/org/traccar/protocol/StarLinkProtocol.java47
-rw-r--r--src/org/traccar/protocol/StarLinkProtocolDecoder.java110
-rw-r--r--src/org/traccar/protocol/SuntechProtocol.java2
-rw-r--r--src/org/traccar/protocol/T800xProtocol.java2
-rw-r--r--src/org/traccar/protocol/TeltonikaProtocol.java2
-rw-r--r--src/org/traccar/protocol/TotemProtocol.java2
-rw-r--r--src/org/traccar/protocol/WatchProtocol.java2
-rw-r--r--src/org/traccar/protocol/WialonProtocol.java2
-rw-r--r--src/org/traccar/protocol/WondexProtocol.java3
-rw-r--r--src/org/traccar/protocol/XexunProtocol.java2
-rw-r--r--src/org/traccar/smpp/ClientSmppSessionHandler.java8
-rw-r--r--src/org/traccar/smpp/SmppClient.java50
-rw-r--r--test/org/traccar/protocol/DmtProtocolDecoderTest.java23
-rw-r--r--test/org/traccar/protocol/LaipacProtocolDecoderTest.java3
-rw-r--r--test/org/traccar/protocol/StarLinkProtocolDecoderTest.java27
46 files changed, 646 insertions, 84 deletions
diff --git a/setup/default.xml b/setup/default.xml
index a146a6d63..9fe49edbe 100644
--- a/setup/default.xml
+++ b/setup/default.xml
@@ -506,5 +506,7 @@
<entry key='pretrace.port'>5133</entry>
<entry key='pricol.port'>5134</entry>
<entry key='siwi.port'>5135</entry>
+ <entry key='starlink.port'>5136</entry>
+ <entry key='dmt.port'>5137</entry>
</properties>
diff --git a/src/org/traccar/BaseProtocol.java b/src/org/traccar/BaseProtocol.java
index 59331d7cc..90b9f21f2 100644
--- a/src/org/traccar/BaseProtocol.java
+++ b/src/org/traccar/BaseProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,10 @@ import java.util.Set;
public abstract class BaseProtocol implements Protocol {
private final String name;
- private final Set<String> supportedCommands = new HashSet<>();
+ private final Set<String> supportedDataCommands = new HashSet<>();
+ private final Set<String> supportedTextCommands = new HashSet<>();
+
+ private StringProtocolEncoder textCommandEncoder = null;
public BaseProtocol(String name) {
this.name = name;
@@ -40,20 +43,36 @@ public abstract class BaseProtocol implements Protocol {
return name;
}
+ public void setSupportedDataCommands(String... commands) {
+ supportedDataCommands.addAll(Arrays.asList(commands));
+ }
+
+ public void setSupportedTextCommands(String... commands) {
+ supportedTextCommands.addAll(Arrays.asList(commands));
+ }
+
public void setSupportedCommands(String... commands) {
- supportedCommands.addAll(Arrays.asList(commands));
+ supportedDataCommands.addAll(Arrays.asList(commands));
+ supportedTextCommands.addAll(Arrays.asList(commands));
+ }
+
+ @Override
+ public Collection<String> getSupportedDataCommands() {
+ Set<String> commands = new HashSet<>(supportedDataCommands);
+ commands.add(Command.TYPE_CUSTOM);
+ return commands;
}
@Override
- public Collection<String> getSupportedCommands() {
- Set<String> commands = new HashSet<>(supportedCommands);
+ public Collection<String> getSupportedTextCommands() {
+ Set<String> commands = new HashSet<>(supportedTextCommands);
commands.add(Command.TYPE_CUSTOM);
return commands;
}
@Override
- public void sendCommand(ActiveDevice activeDevice, Command command) {
- if (supportedCommands.contains(command.getType())) {
+ public void sendDataCommand(ActiveDevice activeDevice, Command command) {
+ if (supportedDataCommands.contains(command.getType())) {
activeDevice.write(command);
} else if (command.getType().equals(Command.TYPE_CUSTOM)) {
String data = command.getString(Command.KEY_DATA);
@@ -67,4 +86,25 @@ public abstract class BaseProtocol implements Protocol {
}
}
+ public void setTextCommandEncoder(StringProtocolEncoder textCommandEncoder) {
+ this.textCommandEncoder = textCommandEncoder;
+ }
+
+ @Override
+ public void sendTextCommand(String destAddress, Command command) throws Exception {
+ if (Context.getSmppManager() != null) {
+ if (command.getType().equals(Command.TYPE_CUSTOM)) {
+ Context.getSmppManager().sendMessageSync(destAddress, command.getString(Command.KEY_DATA), true);
+ } else if (supportedTextCommands.contains(command.getType()) && textCommandEncoder != null) {
+ Context.getSmppManager().sendMessageSync(destAddress,
+ (String) textCommandEncoder.encodeCommand(command), true);
+ } else {
+ throw new RuntimeException(
+ "Command " + command.getType() + " is not supported in protocol " + getName());
+ }
+ } else {
+ throw new RuntimeException("SMPP client is not enabled");
+ }
+ }
+
}
diff --git a/src/org/traccar/Protocol.java b/src/org/traccar/Protocol.java
index c99fd8ecb..87ac05298 100644
--- a/src/org/traccar/Protocol.java
+++ b/src/org/traccar/Protocol.java
@@ -10,10 +10,14 @@ public interface Protocol {
String getName();
- Collection<String> getSupportedCommands();
+ Collection<String> getSupportedDataCommands();
- void sendCommand(ActiveDevice activeDevice, Command command);
+ void sendDataCommand(ActiveDevice activeDevice, Command command);
void initTrackerServers(List<TrackerServer> serverList);
+ Collection<String> getSupportedTextCommands();
+
+ void sendTextCommand(String destAddress, Command command) throws Exception;
+
}
diff --git a/src/org/traccar/ServerManager.java b/src/org/traccar/ServerManager.java
index 953428b8f..9b1e2650d 100644
--- a/src/org/traccar/ServerManager.java
+++ b/src/org/traccar/ServerManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2017 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,12 +23,15 @@ import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ServerManager {
private final List<TrackerServer> serverList = new LinkedList<>();
+ private final Map<String, BaseProtocol> protocolList = new ConcurrentHashMap<>();
public ServerManager() throws Exception {
@@ -64,10 +67,15 @@ public class ServerManager {
if (BaseProtocol.class.isAssignableFrom(protocolClass)) {
BaseProtocol baseProtocol = (BaseProtocol) protocolClass.newInstance();
initProtocolServer(baseProtocol);
+ protocolList.put(baseProtocol.getName(), baseProtocol);
}
}
}
+ public BaseProtocol getProtocol(String name) {
+ return protocolList.get(name);
+ }
+
public void start() {
for (TrackerServer server: serverList) {
server.start();
diff --git a/src/org/traccar/api/resource/CommandResource.java b/src/org/traccar/api/resource/CommandResource.java
index 41b263bf9..9ed92d3d5 100644
--- a/src/org/traccar/api/resource/CommandResource.java
+++ b/src/org/traccar/api/resource/CommandResource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,10 +32,10 @@ import javax.ws.rs.core.Response;
public class CommandResource extends BaseResource {
@POST
- public Response add(Command entity) {
+ public Response add(Command entity) throws Exception {
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkDevice(getUserId(), entity.getDeviceId());
- Context.getConnectionManager().getActiveDevice(entity.getDeviceId()).sendCommand(entity);
+ Context.getDeviceManager().sendCommand(entity);
return Response.ok(entity).build();
}
diff --git a/src/org/traccar/api/resource/CommandTypeResource.java b/src/org/traccar/api/resource/CommandTypeResource.java
index ce27f5241..d5d220547 100644
--- a/src/org/traccar/api/resource/CommandTypeResource.java
+++ b/src/org/traccar/api/resource/CommandTypeResource.java
@@ -1,5 +1,6 @@
/*
* Copyright 2016 Gabor Somogyi (gabor.g.somogyi@gmail.com)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +26,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
-import java.sql.SQLException;
import java.util.Collection;
@Path("commandtypes")
@@ -34,9 +34,10 @@ import java.util.Collection;
public class CommandTypeResource extends BaseResource {
@GET
- public Collection<CommandType> get(@QueryParam("deviceId") long deviceId) throws SQLException {
+ public Collection<CommandType> get(@QueryParam("deviceId") long deviceId,
+ @QueryParam("textChannel") boolean textChannel) {
Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
- return Context.getConnectionManager().getActiveDevice(deviceId).getCommandTypes();
+ return Context.getDeviceManager().getCommandTypes(deviceId, textChannel);
}
}
diff --git a/src/org/traccar/database/ActiveDevice.java b/src/org/traccar/database/ActiveDevice.java
index 6109bc517..f491111e1 100644
--- a/src/org/traccar/database/ActiveDevice.java
+++ b/src/org/traccar/database/ActiveDevice.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,12 +18,8 @@ package org.traccar.database;
import org.jboss.netty.channel.Channel;
import org.traccar.Protocol;
import org.traccar.model.Command;
-import org.traccar.model.CommandType;
import java.net.SocketAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
public class ActiveDevice {
@@ -47,18 +43,8 @@ public class ActiveDevice {
return deviceId;
}
- public Collection<CommandType> getCommandTypes() {
- List<CommandType> result = new ArrayList<>();
-
- for (String commandKey : protocol.getSupportedCommands()) {
- result.add(new CommandType(commandKey));
- }
-
- return result;
- }
-
public void sendCommand(Command command) {
- protocol.sendCommand(this, command);
+ protocol.sendDataCommand(this, command);
}
public void write(Object message) {
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
index 8e75903db..f5fde9e1f 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/org/traccar/database/DeviceManager.java
@@ -26,9 +26,12 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
+import org.traccar.BaseProtocol;
import org.traccar.Config;
import org.traccar.Context;
import org.traccar.helper.Log;
+import org.traccar.model.Command;
+import org.traccar.model.CommandType;
import org.traccar.model.Device;
import org.traccar.model.DeviceTotalDistance;
import org.traccar.model.Group;
@@ -53,11 +56,14 @@ public class DeviceManager implements IdentityManager {
private final Map<Long, Position> positions = new ConcurrentHashMap<>();
+ private boolean fallbackToText;
+
public DeviceManager(DataManager dataManager) {
this.dataManager = dataManager;
this.config = Context.getConfig();
dataRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000;
lookupGroupsAttribute = config.getBoolean("deviceManager.lookupGroupsAttribute");
+ fallbackToText = config.getBoolean("command.fallbackToSms");
if (dataManager != null) {
try {
updateGroupCache(true);
@@ -420,4 +426,48 @@ public class DeviceManager implements IdentityManager {
throw new IllegalArgumentException();
}
}
+
+ public void sendCommand(Command command) throws Exception {
+ long deviceId = command.getDeviceId();
+ if (command.getTextChannel()) {
+ Position lastPosition = getLastPosition(deviceId);
+ if (lastPosition != null) {
+ BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol());
+ protocol.sendTextCommand(devicesById.get(deviceId).getPhone(), command);
+ } else if (command.getType().equals(Command.TYPE_CUSTOM)) {
+ Context.getSmppManager().sendMessageSync(devicesById.get(deviceId).getPhone(),
+ command.getString(Command.KEY_DATA), true);
+ } else {
+ throw new RuntimeException("Command " + command.getType() + " is not supported");
+ }
+ } else {
+ ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(deviceId);
+ if (activeDevice != null) {
+ activeDevice.sendCommand(command);
+ } else {
+ if (fallbackToText) {
+ command.setTextChannel(true);
+ sendCommand(command);
+ } else {
+ throw new RuntimeException("Device is not online");
+ }
+ }
+ }
+ }
+
+ public Collection<CommandType> getCommandTypes(long deviceId, boolean textChannel) {
+ List<CommandType> result = new ArrayList<>();
+ Position lastPosition = Context.getDeviceManager().getLastPosition(deviceId);
+ if (lastPosition != null) {
+ BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol());
+ Collection<String> commands;
+ commands = textChannel ? protocol.getSupportedTextCommands() : protocol.getSupportedDataCommands();
+ for (String commandKey : commands) {
+ result.add(new CommandType(commandKey));
+ }
+ } else {
+ result.add(new CommandType(Command.TYPE_CUSTOM));
+ }
+ return result;
+ }
}
diff --git a/src/org/traccar/model/Command.java b/src/org/traccar/model/Command.java
index 84f5d95ce..016862214 100644
--- a/src/org/traccar/model/Command.java
+++ b/src/org/traccar/model/Command.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,4 +66,14 @@ public class Command extends Message {
public static final String KEY_INDEX = "index";
public static final String KEY_PHONE = "phone";
+ private boolean textChannel;
+
+ public boolean getTextChannel() {
+ return textChannel;
+ }
+
+ public void setTextChannel(boolean textChannel) {
+ this.textChannel = textChannel;
+ }
+
}
diff --git a/src/org/traccar/notification/NotificationSms.java b/src/org/traccar/notification/NotificationSms.java
index cb5dd563a..7b265e3ce 100644
--- a/src/org/traccar/notification/NotificationSms.java
+++ b/src/org/traccar/notification/NotificationSms.java
@@ -35,7 +35,7 @@ public final class NotificationSms {
User user = Context.getPermissionsManager().getUser(userId);
if (Context.getSmppManager() != null && user.getPhone() != null) {
Context.getSmppManager().sendMessageAsync(user.getPhone(),
- NotificationFormatter.formatSmsMessage(userId, event, position));
+ NotificationFormatter.formatSmsMessage(userId, event, position), false);
}
}
@@ -44,7 +44,7 @@ public final class NotificationSms {
User user = Context.getPermissionsManager().getUser(userId);
if (Context.getSmppManager() != null && user.getPhone() != null) {
Context.getSmppManager().sendMessageSync(user.getPhone(),
- NotificationFormatter.formatSmsMessage(userId, event, position));
+ NotificationFormatter.formatSmsMessage(userId, event, position), false);
}
}
}
diff --git a/src/org/traccar/protocol/CarcellProtocol.java b/src/org/traccar/protocol/CarcellProtocol.java
index e53a10eb5..c9fedad65 100644
--- a/src/org/traccar/protocol/CarcellProtocol.java
+++ b/src/org/traccar/protocol/CarcellProtocol.java
@@ -30,7 +30,7 @@ public class CarcellProtocol extends BaseProtocol {
public CarcellProtocol() {
super("carcell");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME);
}
diff --git a/src/org/traccar/protocol/CellocatorProtocol.java b/src/org/traccar/protocol/CellocatorProtocol.java
index 7c8510204..4a20bc977 100644
--- a/src/org/traccar/protocol/CellocatorProtocol.java
+++ b/src/org/traccar/protocol/CellocatorProtocol.java
@@ -29,7 +29,7 @@ public class CellocatorProtocol extends BaseProtocol {
public CellocatorProtocol() {
super("cellocator");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_OUTPUT_CONTROL);
}
diff --git a/src/org/traccar/protocol/CityeasyProtocol.java b/src/org/traccar/protocol/CityeasyProtocol.java
index c5ad05fcd..7e5ca0ba0 100644
--- a/src/org/traccar/protocol/CityeasyProtocol.java
+++ b/src/org/traccar/protocol/CityeasyProtocol.java
@@ -28,7 +28,7 @@ public class CityeasyProtocol extends BaseProtocol {
public CityeasyProtocol() {
super("cityeasy");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_POSITION_SINGLE,
Command.TYPE_POSITION_PERIODIC,
Command.TYPE_POSITION_STOP,
diff --git a/src/org/traccar/protocol/DmtProtocol.java b/src/org/traccar/protocol/DmtProtocol.java
new file mode 100644
index 000000000..18bb1524a
--- /dev/null
+++ b/src/org/traccar/protocol/DmtProtocol.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ *
+ * 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.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
+import org.traccar.BaseProtocol;
+import org.traccar.TrackerServer;
+
+import java.nio.ByteOrder;
+import java.util.List;
+
+public class DmtProtocol extends BaseProtocol {
+
+ public DmtProtocol() {
+ super("dmt");
+ }
+
+ @Override
+ public void initTrackerServers(List<TrackerServer> serverList) {
+ TrackerServer server = new TrackerServer(new ServerBootstrap(), getName()) {
+ @Override
+ protected void addSpecificHandlers(ChannelPipeline pipeline) {
+ pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 3, 2));
+ pipeline.addLast("objectDecoder", new DmtProtocolDecoder(DmtProtocol.this));
+ }
+ };
+ server.setEndianness(ByteOrder.LITTLE_ENDIAN);
+ serverList.add(server);
+ }
+
+}
diff --git a/src/org/traccar/protocol/DmtProtocolDecoder.java b/src/org/traccar/protocol/DmtProtocolDecoder.java
new file mode 100644
index 000000000..4c641f397
--- /dev/null
+++ b/src/org/traccar/protocol/DmtProtocolDecoder.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ *
+ * 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.jboss.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+public class DmtProtocolDecoder extends BaseProtocolDecoder {
+
+ public DmtProtocolDecoder(DmtProtocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_HELLO = 0x00;
+ public static final int MSG_HELLO_RESPONSE = 0x01;
+ public static final int MSG_DATA_RECORD = 0x04;
+ public static final int MSG_COMMIT = 0x05;
+ public static final int MSG_COMMIT_RESPONSE = 0x06;
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
+
+ buf.skipBytes(2); // header
+
+ int type = buf.readUnsignedByte();
+
+ buf.readUnsignedShort(); // length
+
+ if (type == MSG_HELLO) {
+
+ buf.readUnsignedInt(); // device serial number
+
+ DeviceSession deviceSession = getDeviceSession(
+ channel, remoteAddress, buf.readBytes(15).toString(StandardCharsets.US_ASCII));
+
+ if (channel != null) {
+ ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 0);
+ response.writeByte(0x02); response.writeByte(0x55); // header
+ response.writeByte(MSG_HELLO_RESPONSE);
+ response.writeShort(4 + 4);
+ response.writeInt((int) (System.currentTimeMillis() / 1000));
+ response.writeInt(deviceSession != null ? 0 : 1); // flags
+ channel.write(response);
+ }
+
+ } else if (type == MSG_COMMIT) {
+
+ if (channel != null) {
+ ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 0);
+ response.writeByte(0x02); response.writeByte(0x55); // header
+ response.writeByte(MSG_COMMIT_RESPONSE);
+ response.writeShort(1);
+ response.writeByte(1); // flags (success)
+ channel.write(response);
+ }
+
+ } else if (type == MSG_DATA_RECORD) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ List<Position> positions = new LinkedList<>();
+
+ while (buf.readable()) {
+
+ int recordEnd = buf.readerIndex() + buf.readUnsignedShort();
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_INDEX, buf.readUnsignedInt());
+
+ position.setDeviceTime(new Date(1356998400000L + buf.readUnsignedInt() * 1000)); // since 1 Jan 2013
+
+ position.set(Position.KEY_EVENT, buf.readUnsignedByte());
+
+ while (buf.readerIndex() < recordEnd) {
+
+ int fieldId = buf.readUnsignedByte();
+ int fieldLength = buf.readUnsignedByte();
+ int fieldEnd = buf.readerIndex() + (fieldLength == 255 ? buf.readUnsignedShort() : fieldLength);
+
+ if (fieldId == 0) {
+
+ position.setFixTime(new Date(1356998400000L + buf.readUnsignedInt() * 1000));
+ position.setLatitude(buf.readInt() * 0.0000001);
+ position.setLongitude(buf.readInt() * 0.0000001);
+ position.setSpeed(UnitsConverter.knotsFromCps(buf.readUnsignedShort()));
+
+ buf.readUnsignedByte(); // speed accuracy
+
+ position.setCourse(buf.readUnsignedByte() * 2);
+
+ position.set(Position.KEY_PDOP, buf.readUnsignedByte() * 0.1);
+
+ position.setAccuracy(buf.readUnsignedByte());
+ position.setValid(buf.readUnsignedByte() != 0);
+
+ }
+
+ buf.readerIndex(fieldEnd);
+
+ }
+
+ positions.add(position);
+
+ }
+
+ return positions;
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/protocol/EelinkProtocol.java b/src/org/traccar/protocol/EelinkProtocol.java
index 5900f0059..5499094d9 100644
--- a/src/org/traccar/protocol/EelinkProtocol.java
+++ b/src/org/traccar/protocol/EelinkProtocol.java
@@ -28,7 +28,7 @@ public class EelinkProtocol extends BaseProtocol {
public EelinkProtocol() {
super("eelink");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_CUSTOM,
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME,
diff --git a/src/org/traccar/protocol/Gl200Protocol.java b/src/org/traccar/protocol/Gl200Protocol.java
index b6f01c773..b3743042c 100644
--- a/src/org/traccar/protocol/Gl200Protocol.java
+++ b/src/org/traccar/protocol/Gl200Protocol.java
@@ -31,7 +31,7 @@ public class Gl200Protocol extends BaseProtocol {
public Gl200Protocol() {
super("gl200");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_POSITION_SINGLE,
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME,
diff --git a/src/org/traccar/protocol/Gps103Protocol.java b/src/org/traccar/protocol/Gps103Protocol.java
index a4d563bfc..a5bd32261 100644
--- a/src/org/traccar/protocol/Gps103Protocol.java
+++ b/src/org/traccar/protocol/Gps103Protocol.java
@@ -31,7 +31,7 @@ public class Gps103Protocol extends BaseProtocol {
public Gps103Protocol() {
super("gps103");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_CUSTOM,
Command.TYPE_POSITION_SINGLE,
Command.TYPE_POSITION_PERIODIC,
diff --git a/src/org/traccar/protocol/GranitProtocol.java b/src/org/traccar/protocol/GranitProtocol.java
index a5d5458f0..32e8e00b0 100644
--- a/src/org/traccar/protocol/GranitProtocol.java
+++ b/src/org/traccar/protocol/GranitProtocol.java
@@ -1,5 +1,6 @@
/*
- * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,10 +29,14 @@ public class GranitProtocol extends BaseProtocol {
public GranitProtocol() {
super("granit");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_IDENTIFICATION,
Command.TYPE_REBOOT_DEVICE,
Command.TYPE_POSITION_SINGLE);
+ setTextCommandEncoder(new GranitProtocolSmsEncoder());
+ setSupportedTextCommands(
+ Command.TYPE_REBOOT_DEVICE,
+ Command.TYPE_POSITION_PERIODIC);
}
@Override
diff --git a/src/org/traccar/protocol/GranitProtocolSmsEncoder.java b/src/org/traccar/protocol/GranitProtocolSmsEncoder.java
new file mode 100644
index 000000000..668e5d4d3
--- /dev/null
+++ b/src/org/traccar/protocol/GranitProtocolSmsEncoder.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * 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.traccar.StringProtocolEncoder;
+import org.traccar.helper.Log;
+import org.traccar.model.Command;
+
+public class GranitProtocolSmsEncoder extends StringProtocolEncoder {
+
+ @Override
+ protected String encodeCommand(Command command) {
+ switch (command.getType()) {
+ case Command.TYPE_REBOOT_DEVICE:
+ return "BB+RESET";
+ case Command.TYPE_POSITION_PERIODIC:
+ return formatCommand(command, "BB+BBMD={%s}", Command.KEY_FREQUENCY);
+ default:
+ Log.warning(new UnsupportedOperationException(command.getType()));
+ return null;
+ }
+ }
+
+}
diff --git a/src/org/traccar/protocol/Gt06Protocol.java b/src/org/traccar/protocol/Gt06Protocol.java
index e96679799..aa8f1f0c0 100644
--- a/src/org/traccar/protocol/Gt06Protocol.java
+++ b/src/org/traccar/protocol/Gt06Protocol.java
@@ -27,7 +27,7 @@ public class Gt06Protocol extends BaseProtocol {
public Gt06Protocol() {
super("gt06");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME);
}
diff --git a/src/org/traccar/protocol/H02Protocol.java b/src/org/traccar/protocol/H02Protocol.java
index 498f63c0e..df64402f8 100644
--- a/src/org/traccar/protocol/H02Protocol.java
+++ b/src/org/traccar/protocol/H02Protocol.java
@@ -29,7 +29,7 @@ public class H02Protocol extends BaseProtocol {
public H02Protocol() {
super("h02");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ALARM_ARM,
Command.TYPE_ALARM_DISARM,
Command.TYPE_ENGINE_STOP,
diff --git a/src/org/traccar/protocol/HuabaoProtocol.java b/src/org/traccar/protocol/HuabaoProtocol.java
index d5e68e091..c74cb58c7 100644
--- a/src/org/traccar/protocol/HuabaoProtocol.java
+++ b/src/org/traccar/protocol/HuabaoProtocol.java
@@ -27,7 +27,7 @@ public class HuabaoProtocol extends BaseProtocol {
public HuabaoProtocol() {
super("huabao");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME);
}
diff --git a/src/org/traccar/protocol/Jt600Protocol.java b/src/org/traccar/protocol/Jt600Protocol.java
index 132770511..8c71ca4f6 100644
--- a/src/org/traccar/protocol/Jt600Protocol.java
+++ b/src/org/traccar/protocol/Jt600Protocol.java
@@ -28,7 +28,7 @@ public class Jt600Protocol extends BaseProtocol {
public Jt600Protocol() {
super("jt600");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_RESUME,
Command.TYPE_ENGINE_STOP,
Command.TYPE_SET_TIMEZONE,
diff --git a/src/org/traccar/protocol/KhdProtocol.java b/src/org/traccar/protocol/KhdProtocol.java
index bf0d2855d..167727191 100644
--- a/src/org/traccar/protocol/KhdProtocol.java
+++ b/src/org/traccar/protocol/KhdProtocol.java
@@ -28,7 +28,7 @@ public class KhdProtocol extends BaseProtocol {
public KhdProtocol() {
super("khd");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME);
}
diff --git a/src/org/traccar/protocol/MeiligaoProtocol.java b/src/org/traccar/protocol/MeiligaoProtocol.java
index 23af19ef1..dbdd2619a 100644
--- a/src/org/traccar/protocol/MeiligaoProtocol.java
+++ b/src/org/traccar/protocol/MeiligaoProtocol.java
@@ -28,7 +28,7 @@ public class MeiligaoProtocol extends BaseProtocol {
public MeiligaoProtocol() {
super("meiligao");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_POSITION_SINGLE,
Command.TYPE_POSITION_PERIODIC,
Command.TYPE_ENGINE_STOP,
diff --git a/src/org/traccar/protocol/MeitrackProtocol.java b/src/org/traccar/protocol/MeitrackProtocol.java
index 918729f97..e89825da5 100644
--- a/src/org/traccar/protocol/MeitrackProtocol.java
+++ b/src/org/traccar/protocol/MeitrackProtocol.java
@@ -30,7 +30,7 @@ public class MeitrackProtocol extends BaseProtocol {
public MeitrackProtocol() {
super("meitrack");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_POSITION_SINGLE,
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME,
diff --git a/src/org/traccar/protocol/MiniFinderProtocol.java b/src/org/traccar/protocol/MiniFinderProtocol.java
index 3bbdc1beb..c36acb238 100644
--- a/src/org/traccar/protocol/MiniFinderProtocol.java
+++ b/src/org/traccar/protocol/MiniFinderProtocol.java
@@ -30,7 +30,7 @@ public class MiniFinderProtocol extends BaseProtocol {
public MiniFinderProtocol() {
super("minifinder");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_SET_TIMEZONE,
Command.TYPE_VOICE_MONITORING,
Command.TYPE_ALARM_SPEED,
diff --git a/src/org/traccar/protocol/NoranProtocol.java b/src/org/traccar/protocol/NoranProtocol.java
index bf10eb127..7d3dc4852 100644
--- a/src/org/traccar/protocol/NoranProtocol.java
+++ b/src/org/traccar/protocol/NoranProtocol.java
@@ -28,7 +28,7 @@ public class NoranProtocol extends BaseProtocol {
public NoranProtocol() {
super("noran");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_POSITION_SINGLE,
Command.TYPE_POSITION_PERIODIC,
Command.TYPE_POSITION_STOP,
diff --git a/src/org/traccar/protocol/Pt502Protocol.java b/src/org/traccar/protocol/Pt502Protocol.java
index a15938dc3..ad97a777e 100644
--- a/src/org/traccar/protocol/Pt502Protocol.java
+++ b/src/org/traccar/protocol/Pt502Protocol.java
@@ -30,7 +30,7 @@ public class Pt502Protocol extends BaseProtocol {
public Pt502Protocol() {
super("pt502");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_SET_TIMEZONE,
Command.TYPE_ALARM_SPEED,
Command.TYPE_OUTPUT_CONTROL,
diff --git a/src/org/traccar/protocol/RuptelaProtocol.java b/src/org/traccar/protocol/RuptelaProtocol.java
index 54cdcc267..4be07307d 100644
--- a/src/org/traccar/protocol/RuptelaProtocol.java
+++ b/src/org/traccar/protocol/RuptelaProtocol.java
@@ -28,7 +28,7 @@ public class RuptelaProtocol extends BaseProtocol {
public RuptelaProtocol() {
super("ruptela");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_CUSTOM);
}
diff --git a/src/org/traccar/protocol/StarLinkProtocol.java b/src/org/traccar/protocol/StarLinkProtocol.java
new file mode 100644
index 000000000..e71d94fd0
--- /dev/null
+++ b/src/org/traccar/protocol/StarLinkProtocol.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ *
+ * 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.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder;
+import org.jboss.netty.handler.codec.string.StringDecoder;
+import org.jboss.netty.handler.codec.string.StringEncoder;
+import org.traccar.BaseProtocol;
+import org.traccar.TrackerServer;
+
+import java.util.List;
+
+public class StarLinkProtocol extends BaseProtocol {
+
+ public StarLinkProtocol() {
+ super("starlink");
+ }
+
+ @Override
+ public void initTrackerServers(List<TrackerServer> serverList) {
+ serverList.add(new TrackerServer(new ServerBootstrap(), getName()) {
+ @Override
+ protected void addSpecificHandlers(ChannelPipeline pipeline) {
+ pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(1024));
+ pipeline.addLast("stringEncoder", new StringEncoder());
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("objectDecoder", new StarLinkProtocolDecoder(StarLinkProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/org/traccar/protocol/StarLinkProtocolDecoder.java b/src/org/traccar/protocol/StarLinkProtocolDecoder.java
new file mode 100644
index 000000000..46d8ee9cc
--- /dev/null
+++ b/src/org/traccar/protocol/StarLinkProtocolDecoder.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ *
+ * 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.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.helper.DateBuilder;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.model.CellTower;
+import org.traccar.model.Network;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.util.regex.Pattern;
+
+public class StarLinkProtocolDecoder extends BaseProtocolDecoder {
+
+ public StarLinkProtocolDecoder(StarLinkProtocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .expression(".") // protocol head
+ .text("SLU") // message head
+ .number("(x{6}|d{15}),") // id
+ .number("(d+),") // type
+ .number("(d+),") // index
+ .number("(dd)(dd)(dd)") // event date
+ .number("(dd)(dd)(dd),") // event time
+ .number("(d+),") // event
+ .number("(dd)(dd)(dd)") // fix date
+ .number("(dd)(dd)(dd),") // fix time
+ .number("([-+])(dd)(dd.d+),") // latitude
+ .number("([-+])(ddd)(dd.d+),") // longitude
+ .number("(d+.d+),") // speed
+ .number("(d+),") // course
+ .number("(d+),") // odometer
+ .number("(d+),") // lac
+ .number("(d+),") // cid
+ .number("(d+.d+),") // power
+ .number("(d+.d+)") // battery
+ .any()
+ .compile();
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ Parser parser = new Parser(PATTERN, (String) msg);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_TYPE, parser.nextInt());
+ position.set(Position.KEY_INDEX, parser.nextInt());
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt())
+ .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setDeviceTime(dateBuilder.getDate());
+
+ position.set(Position.KEY_EVENT, parser.nextInt());
+
+ dateBuilder = new DateBuilder()
+ .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt())
+ .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setFixTime(dateBuilder.getDate());
+
+ position.setValid(true);
+ position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN));
+ position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN));
+
+ position.setSpeed(parser.nextDouble());
+ position.setCourse(parser.nextInt());
+
+ position.set(Position.KEY_ODOMETER, parser.nextInt());
+
+ position.setNetwork(new Network(CellTower.fromLacCid(parser.nextInt(), parser.nextInt())));
+
+ position.set(Position.KEY_POWER, parser.nextDouble());
+ position.set(Position.KEY_BATTERY, parser.nextDouble());
+
+ return position;
+ }
+
+}
diff --git a/src/org/traccar/protocol/SuntechProtocol.java b/src/org/traccar/protocol/SuntechProtocol.java
index 410dc8af7..871c3becd 100644
--- a/src/org/traccar/protocol/SuntechProtocol.java
+++ b/src/org/traccar/protocol/SuntechProtocol.java
@@ -30,7 +30,7 @@ public class SuntechProtocol extends BaseProtocol {
public SuntechProtocol() {
super("suntech");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_OUTPUT_CONTROL,
Command.TYPE_REBOOT_DEVICE,
Command.TYPE_POSITION_SINGLE,
diff --git a/src/org/traccar/protocol/T800xProtocol.java b/src/org/traccar/protocol/T800xProtocol.java
index 70341d0dc..830ff4de6 100644
--- a/src/org/traccar/protocol/T800xProtocol.java
+++ b/src/org/traccar/protocol/T800xProtocol.java
@@ -28,7 +28,7 @@ public class T800xProtocol extends BaseProtocol {
public T800xProtocol() {
super("t800x");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_CUSTOM);
}
diff --git a/src/org/traccar/protocol/TeltonikaProtocol.java b/src/org/traccar/protocol/TeltonikaProtocol.java
index f0ed61886..524e6d5b5 100644
--- a/src/org/traccar/protocol/TeltonikaProtocol.java
+++ b/src/org/traccar/protocol/TeltonikaProtocol.java
@@ -28,7 +28,7 @@ public class TeltonikaProtocol extends BaseProtocol {
public TeltonikaProtocol() {
super("teltonika");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_CUSTOM);
}
diff --git a/src/org/traccar/protocol/TotemProtocol.java b/src/org/traccar/protocol/TotemProtocol.java
index 860fff894..1c5cf5b02 100644
--- a/src/org/traccar/protocol/TotemProtocol.java
+++ b/src/org/traccar/protocol/TotemProtocol.java
@@ -29,7 +29,7 @@ public class TotemProtocol extends BaseProtocol {
public TotemProtocol() {
super("totem");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_RESUME,
Command.TYPE_ENGINE_STOP
);
diff --git a/src/org/traccar/protocol/WatchProtocol.java b/src/org/traccar/protocol/WatchProtocol.java
index abce3d16a..f664691c3 100644
--- a/src/org/traccar/protocol/WatchProtocol.java
+++ b/src/org/traccar/protocol/WatchProtocol.java
@@ -30,7 +30,7 @@ public class WatchProtocol extends BaseProtocol {
public WatchProtocol() {
super("watch");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_POSITION_SINGLE,
Command.TYPE_POSITION_PERIODIC,
Command.TYPE_SOS_NUMBER,
diff --git a/src/org/traccar/protocol/WialonProtocol.java b/src/org/traccar/protocol/WialonProtocol.java
index 04e18cd85..02da154e2 100644
--- a/src/org/traccar/protocol/WialonProtocol.java
+++ b/src/org/traccar/protocol/WialonProtocol.java
@@ -32,7 +32,7 @@ public class WialonProtocol extends BaseProtocol {
public WialonProtocol() {
super("wialon");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_REBOOT_DEVICE,
Command.TYPE_SEND_USSD,
Command.TYPE_IDENTIFICATION,
diff --git a/src/org/traccar/protocol/WondexProtocol.java b/src/org/traccar/protocol/WondexProtocol.java
index 0cc21d2b4..e7e13c63a 100644
--- a/src/org/traccar/protocol/WondexProtocol.java
+++ b/src/org/traccar/protocol/WondexProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ public class WondexProtocol extends BaseProtocol {
public WondexProtocol() {
super("wondex");
+ setTextCommandEncoder(new WondexProtocolEncoder());
setSupportedCommands(
Command.TYPE_REBOOT_DEVICE,
Command.TYPE_POSITION_SINGLE,
diff --git a/src/org/traccar/protocol/XexunProtocol.java b/src/org/traccar/protocol/XexunProtocol.java
index a52d9ff45..b90cbfaaf 100644
--- a/src/org/traccar/protocol/XexunProtocol.java
+++ b/src/org/traccar/protocol/XexunProtocol.java
@@ -31,7 +31,7 @@ public class XexunProtocol extends BaseProtocol {
public XexunProtocol() {
super("xexun");
- setSupportedCommands(
+ setSupportedDataCommands(
Command.TYPE_ENGINE_STOP,
Command.TYPE_ENGINE_RESUME);
}
diff --git a/src/org/traccar/smpp/ClientSmppSessionHandler.java b/src/org/traccar/smpp/ClientSmppSessionHandler.java
index 721243f9f..2a538a40f 100644
--- a/src/org/traccar/smpp/ClientSmppSessionHandler.java
+++ b/src/org/traccar/smpp/ClientSmppSessionHandler.java
@@ -44,14 +44,14 @@ public class ClientSmppSessionHandler extends DefaultSmppSessionHandler {
try {
if (request instanceof DeliverSm) {
if (request.getOptionalParameters() != null) {
- Log.debug("Message Delivered: "
+ Log.debug("SMS Message Delivered: "
+ request.getOptionalParameter(SmppConstants.TAG_RECEIPTED_MSG_ID).getValueAsString()
+ ", State: "
+ request.getOptionalParameter(SmppConstants.TAG_MSG_STATE).getValueAsByte());
} else {
- Log.debug("Message Received: "
+ Log.debug("SMS Message Received: "
+ CharsetUtil.decode(((DeliverSm) request).getShortMessage(),
- smppClient.mapDataCodingToCharset(((DeliverSm) request).getDataCoding()))
+ smppClient.mapDataCodingToCharset(((DeliverSm) request).getDataCoding())).trim()
+ ", Source Address: "
+ ((DeliverSm) request).getSourceAddress().getAddress());
}
@@ -68,7 +68,7 @@ public class ClientSmppSessionHandler extends DefaultSmppSessionHandler {
@Override
public void fireChannelUnexpectedlyClosed() {
- Log.warning("Smpp session channel unexpectedly closed");
+ Log.warning("SMPP session channel unexpectedly closed");
smppClient.scheduleReconnect();
}
}
diff --git a/src/org/traccar/smpp/SmppClient.java b/src/org/traccar/smpp/SmppClient.java
index 0bec60fd2..317d6debf 100644
--- a/src/org/traccar/smpp/SmppClient.java
+++ b/src/org/traccar/smpp/SmppClient.java
@@ -60,8 +60,10 @@ public class SmppClient {
private String sourceAddress;
private int submitTimeout;
- private String charsetName;
- private byte dataCoding;
+ private String notificationsCharsetName;
+ private byte notificationsDataCoding;
+ private String commandsCharsetName;
+ private byte commandsDataCoding;
private byte sourceTon;
private byte sourceNpi;
@@ -84,8 +86,15 @@ public class SmppClient {
sourceAddress = Context.getConfig().getString("sms.smpp.sourceAddress", "");
submitTimeout = Context.getConfig().getInteger("sms.smpp.submitTimeout", 10000);
- charsetName = Context.getConfig().getString("sms.smpp.charsetName", CharsetUtil.NAME_UCS_2);
- dataCoding = (byte) Context.getConfig().getInteger("sms.smpp.dataCoding", SmppConstants.DATA_CODING_UCS2);
+ notificationsCharsetName = Context.getConfig().getString("sms.smpp.notificationsCharset",
+ CharsetUtil.NAME_UCS_2);
+ notificationsDataCoding = (byte) Context.getConfig().getInteger("sms.smpp.notificationsDataCoding",
+ SmppConstants.DATA_CODING_UCS2);
+ commandsCharsetName = Context.getConfig().getString("sms.smpp.commandsCharset",
+ CharsetUtil.NAME_GSM);
+ commandsDataCoding = (byte) Context.getConfig().getInteger("sms.smpp.commandsDataCoding",
+ SmppConstants.DATA_CODING_DEFAULT);
+
sourceTon = (byte) Context.getConfig().getInteger("sms.smpp.sourceTon", SmppConstants.TON_ALPHANUMERIC);
sourceNpi = (byte) Context.getConfig().getInteger("sms.smpp.sourceNpi", SmppConstants.NPI_UNKNOWN);
@@ -140,10 +149,10 @@ public class SmppClient {
smppSession = clientBootstrap.bind(sessionConfig, sessionHandler);
stopReconnectionkTask();
runEnquireLinkTask();
- Log.info("Smpp session connected");
+ Log.info("SMPP session connected");
} catch (SmppTimeoutException | SmppChannelException
| UnrecoverablePduException | InterruptedException error) {
- Log.warning("Unable to connect to smpp server: ", error);
+ Log.warning("Unable to connect to SMPP server: ", error);
}
}
@@ -180,37 +189,42 @@ public class SmppClient {
private void destroySession() {
if (smppSession != null) {
- Log.debug("Cleaning up smpp session... ");
+ Log.debug("Cleaning up SMPP session... ");
smppSession.destroy();
smppSession = null;
}
}
- public synchronized void sendMessageSync(String destAddress, String message) throws RecoverablePduException,
- UnrecoverablePduException, SmppTimeoutException, SmppChannelException, InterruptedException {
+ public synchronized void sendMessageSync(String destAddress, String message, boolean command)
+ throws RecoverablePduException, UnrecoverablePduException, SmppTimeoutException, SmppChannelException,
+ InterruptedException, IllegalStateException {
if (getSession() != null && getSession().isBound()) {
- byte[] textBytes = CharsetUtil.encode(message, charsetName);
-
SubmitSm submit = new SubmitSm();
+ byte[] textBytes;
+ textBytes = CharsetUtil.encode(message, command ? commandsCharsetName : notificationsCharsetName);
+ submit.setDataCoding(command ? commandsDataCoding : notificationsDataCoding);
+ submit.setShortMessage(textBytes);
submit.setSourceAddress(new Address(sourceTon, sourceNpi, sourceAddress));
submit.setDestAddress(new Address(destTon, destNpi, destAddress));
- submit.setDataCoding(dataCoding);
- submit.setShortMessage(textBytes);
SubmitSmResp submitResponce = getSession().submit(submit, submitTimeout);
- Log.debug("SMS submited, msg_id: " + submitResponce.getMessageId());
+ if (submitResponce.getCommandStatus() == SmppConstants.STATUS_OK) {
+ Log.debug("SMS submitted, message id: " + submitResponce.getMessageId());
+ } else {
+ throw new IllegalStateException(submitResponce.getResultMessage());
+ }
} else {
- throw new SmppChannelException("Smpp session is not connected");
+ throw new SmppChannelException("SMPP session is not connected");
}
}
- public void sendMessageAsync(final String destAddress, final String message) {
+ public void sendMessageAsync(final String destAddress, final String message, final boolean command) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
- sendMessageSync(destAddress, message);
+ sendMessageSync(destAddress, message, command);
} catch (InterruptedException | RecoverablePduException | UnrecoverablePduException
- | SmppTimeoutException | SmppChannelException error) {
+ | SmppTimeoutException | SmppChannelException | IllegalStateException error) {
Log.warning(error);
}
}
diff --git a/test/org/traccar/protocol/DmtProtocolDecoderTest.java b/test/org/traccar/protocol/DmtProtocolDecoderTest.java
new file mode 100644
index 000000000..fa43c661d
--- /dev/null
+++ b/test/org/traccar/protocol/DmtProtocolDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import java.nio.ByteOrder;
+
+public class DmtProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ DmtProtocolDecoder decoder = new DmtProtocolDecoder(new DmtProtocol());
+
+ verifyNothing(decoder, binary(ByteOrder.LITTLE_ENDIAN,
+ "025500310038f90100333533333233303831363639373330003839363130313435363839393333303030303835002202010900000000"));
+
+ verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN,
+ "0255043D003D004746000096D684020B001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF08"));
+
+ }
+
+}
diff --git a/test/org/traccar/protocol/LaipacProtocolDecoderTest.java b/test/org/traccar/protocol/LaipacProtocolDecoderTest.java
index d1fafe71a..b1bb954db 100644
--- a/test/org/traccar/protocol/LaipacProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/LaipacProtocolDecoderTest.java
@@ -10,6 +10,9 @@ public class LaipacProtocolDecoderTest extends ProtocolTest {
LaipacProtocolDecoder decoder = new LaipacProtocolDecoder(new LaipacProtocol());
+ verifyPosition(decoder, text(
+ "$AVRMC,80006405,212645,r,3013.9938,N,08133.3998,W,0.00,0.00,010317,a,4076,0,1,0,0,53170583,310260*78"));
+
verifyNothing(decoder, text(
"$AVSYS,99999999,V1.50,SN0000103,32768*15"));
diff --git a/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java b/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java
new file mode 100644
index 000000000..33ee49812
--- /dev/null
+++ b/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class StarLinkProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ StarLinkProtocolDecoder decoder = new StarLinkProtocolDecoder(new StarLinkProtocol());
+
+ verifyNothing(decoder, text(
+ "$SLU005F20,06,22743,170116091944,01,170116091944,+3206.0991,+03452.0605,003.6,008,064675,1,1,0,0,0,0,0,0,10424,2521,14.156,01.163,,1,1,1,4*BE"));
+
+ verifyNothing(decoder, text(
+ "$SLU005F20,06,22718,170116091422,01,170116091422,+3205.1777,+03450.7595,046.8,359,064671,1,1,0,0,0,0,0,0,10424,64072,14.148,01.161,,1,1,1,4*03"));
+
+ verifyNothing(decoder, text(
+ "$SLU005F20,06,22695,170116090730,24,170116090730,+3203.6062,+03449.6945,013.9,181,064666,1,1,0,0,0,0,0,0,10422,30631,14.089,01.163,,1,1*43"));
+
+ verifyPosition(decoder, text(
+ "$SLU0004D2,06,32,071106135931,01,071106135930,+3159.4376,+03445.3298,021.3,087,000554,31071,11704,13.45,3.87*3E"));
+
+ }
+
+}