aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/traccar/api/resource/CommandResource.java18
-rw-r--r--src/main/java/org/traccar/database/CommandsManager.java23
-rw-r--r--src/main/java/org/traccar/model/Event.java1
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java17
-rw-r--r--src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java4
-rw-r--r--templates/full/queuedCommandSent.vm11
-rw-r--r--templates/short/queuedCommandSent.vm2
7 files changed, 67 insertions, 9 deletions
diff --git a/src/main/java/org/traccar/api/resource/CommandResource.java b/src/main/java/org/traccar/api/resource/CommandResource.java
index d50c7ee0c..c23d91e77 100644
--- a/src/main/java/org/traccar/api/resource/CommandResource.java
+++ b/src/main/java/org/traccar/api/resource/CommandResource.java
@@ -117,20 +117,30 @@ public class CommandResource extends ExtendedObjectResource<Command> {
} else {
permissionsService.checkRestriction(getUserId(), UserRestrictions::getLimitCommands);
}
- boolean result = true;
+
if (groupId > 0) {
permissionsService.checkPermission(Group.class, getUserId(), groupId);
var devices = DeviceUtil.getAccessibleDevices(storage, getUserId(), List.of(), List.of(groupId));
+ List<QueuedCommand> queuedCommands = new ArrayList<>();
for (Device device : devices) {
Command command = QueuedCommand.fromCommand(entity).toCommand();
command.setDeviceId(device.getId());
- result = commandsManager.sendCommand(command) && result;
+ QueuedCommand queuedCommand = commandsManager.sendCommand(command);
+ if (queuedCommand != null) {
+ queuedCommands.add(queuedCommand);
+ }
+ }
+ if (!queuedCommands.isEmpty()) {
+ return Response.accepted(queuedCommands).build();
}
} else {
permissionsService.checkPermission(Device.class, getUserId(), entity.getDeviceId());
- result = commandsManager.sendCommand(entity);
+ QueuedCommand queuedCommand = commandsManager.sendCommand(entity);
+ if (queuedCommand != null) {
+ return Response.accepted(queuedCommand).build();
+ }
}
- return result ? Response.ok(entity).build() : Response.accepted(entity).build();
+ return Response.ok(entity).build();
}
@GET
diff --git a/src/main/java/org/traccar/database/CommandsManager.java b/src/main/java/org/traccar/database/CommandsManager.java
index fb8f2f9d6..90180b989 100644
--- a/src/main/java/org/traccar/database/CommandsManager.java
+++ b/src/main/java/org/traccar/database/CommandsManager.java
@@ -22,6 +22,7 @@ import org.traccar.broadcast.BroadcastInterface;
import org.traccar.broadcast.BroadcastService;
import org.traccar.model.Command;
import org.traccar.model.Device;
+import org.traccar.model.Event;
import org.traccar.model.Position;
import org.traccar.model.QueuedCommand;
import org.traccar.session.ConnectionManager;
@@ -38,6 +39,8 @@ import jakarta.annotation.Nullable;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
import java.util.stream.Collectors;
@Singleton
@@ -48,20 +51,23 @@ public class CommandsManager implements BroadcastInterface {
private final SmsManager smsManager;
private final ConnectionManager connectionManager;
private final BroadcastService broadcastService;
+ private final NotificationManager notificationManager;
@Inject
public CommandsManager(
Storage storage, ServerManager serverManager, @Nullable SmsManager smsManager,
- ConnectionManager connectionManager, BroadcastService broadcastService) {
+ ConnectionManager connectionManager, BroadcastService broadcastService,
+ NotificationManager notificationManager) {
this.storage = storage;
this.serverManager = serverManager;
this.smsManager = smsManager;
this.connectionManager = connectionManager;
this.broadcastService = broadcastService;
+ this.notificationManager = notificationManager;
broadcastService.registerListener(this);
}
- public boolean sendCommand(Command command) throws Exception {
+ public QueuedCommand sendCommand(Command command) throws Exception {
long deviceId = command.getDeviceId();
if (command.getTextChannel()) {
if (smsManager == null) {
@@ -84,12 +90,13 @@ public class CommandsManager implements BroadcastInterface {
if (deviceSession != null && deviceSession.supportsLiveCommands()) {
deviceSession.sendCommand(command);
} else {
- storage.addObject(QueuedCommand.fromCommand(command), new Request(new Columns.Exclude("id")));
+ QueuedCommand queuedCommand = QueuedCommand.fromCommand(command);
+ queuedCommand.setId(storage.addObject(queuedCommand, new Request(new Columns.Exclude("id"))));
broadcastService.updateCommand(true, deviceId);
- return false;
+ return queuedCommand;
}
}
- return true;
+ return null;
}
public Collection<Command> readQueuedCommands(long deviceId) {
@@ -102,10 +109,16 @@ public class CommandsManager implements BroadcastInterface {
new Columns.All(),
new Condition.Equals("deviceId", deviceId),
new Order("id", false, count)));
+ Map<Event, Position> events = new HashMap<>();
for (var command : commands) {
storage.removeObject(QueuedCommand.class, new Request(
new Condition.Equals("id", command.getId())));
+
+ Event event = new Event(Event.TYPE_QUEUED_COMMAND_SENT, command.getDeviceId());
+ event.set("id", command.getId());
+ events.put(event, null);
}
+ notificationManager.updateEvents(events);
return commands.stream().map(QueuedCommand::toCommand).collect(Collectors.toList());
} catch (StorageException e) {
throw new RuntimeException(e);
diff --git a/src/main/java/org/traccar/model/Event.java b/src/main/java/org/traccar/model/Event.java
index 0e851d748..6f90de9da 100644
--- a/src/main/java/org/traccar/model/Event.java
+++ b/src/main/java/org/traccar/model/Event.java
@@ -46,6 +46,7 @@ public class Event extends Message {
public static final String TYPE_DEVICE_UNKNOWN = "deviceUnknown";
public static final String TYPE_DEVICE_OFFLINE = "deviceOffline";
public static final String TYPE_DEVICE_INACTIVE = "deviceInactive";
+ public static final String TYPE_QUEUED_COMMAND_SENT = "queuedCommandSent";
public static final String TYPE_DEVICE_MOVING = "deviceMoving";
public static final String TYPE_DEVICE_STOPPED = "deviceStopped";
diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
index 161d04d8d..e9bdaf194 100644
--- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
@@ -124,6 +124,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
WETRUST,
JC400,
SL4X,
+ SEEWORLD,
}
private Variant variant;
@@ -901,6 +902,20 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
}
}
+ if (type == MSG_GPS_LBS_2 && variant == Variant.SEEWORLD) {
+ position.set(Position.KEY_IGNITION, buf.readUnsignedByte() > 0);
+ buf.readUnsignedByte(); // reporting mode
+ buf.readUnsignedByte(); // supplementary transmission
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ buf.readUnsignedInt(); // travel time
+ int temperature = buf.readUnsignedShort();
+ if (BitUtil.check(temperature, 15)) {
+ temperature = -BitUtil.to(temperature, 15);
+ }
+ position.set(Position.PREFIX_TEMP + 1, temperature * 0.01);
+ position.set("humidity", buf.readUnsignedShort() * 0.01);
+ }
+
if ((type == MSG_GPS_LBS_2 || type == MSG_GPS_LBS_3 || type == MSG_GPS_LBS_4)
&& buf.readableBytes() >= 3 + 6) {
position.set(Position.KEY_IGNITION, buf.readUnsignedByte() > 0);
@@ -1468,6 +1483,8 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
variant = Variant.JC400;
} else if (header == 0x7878 && type == MSG_LBS_3 && length == 0x37) {
variant = Variant.SL4X;
+ } else if (header == 0x7878 && type == MSG_GPS_LBS_2 && length == 0x2f) {
+ variant = Variant.SEEWORLD;
} else {
variant = Variant.STANDARD;
}
diff --git a/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java
index 9b196e501..a2ee4d1bc 100644
--- a/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java
+++ b/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java
@@ -18,6 +18,10 @@ public class Gt06ProtocolDecoderTest extends ProtocolTest {
"78780D01086471700328358100093F040D0A"));
verifyAttribute(decoder, binary(
+ "78782f22170a020b2737cf02c568a8089fc0dc125c4d01369a371b0a6967020000000007327a00000000001500260074544c0d0a"),
+ "humidity", 53.76);
+
+ verifyAttribute(decoder, binary(
"78785995ffff01170719152013df0163d45f041ee52018be002f00876900004556454e545f3836323739383035303137353131325f30303030303030305f323032335f30375f32355f31385f33325f30355f31342e6d70340119d15a0d0a"),
Position.KEY_EVENT, 0x69);
diff --git a/templates/full/queuedCommandSent.vm b/templates/full/queuedCommandSent.vm
new file mode 100644
index 000000000..148dd2094
--- /dev/null
+++ b/templates/full/queuedCommandSent.vm
@@ -0,0 +1,11 @@
+#set($subject = "$device.name: queued command sent")
+<!DOCTYPE html>
+<html>
+<body>
+Device: $device.name<br>
+Queued command sent<br>
+Time: $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.eventTime, $locale, $timezone)<br>
+<br>
+<a href="$webUrl/settings/notifications?token=$token">Unsubscribe</a>
+</body>
+</html>
diff --git a/templates/short/queuedCommandSent.vm b/templates/short/queuedCommandSent.vm
new file mode 100644
index 000000000..67f031280
--- /dev/null
+++ b/templates/short/queuedCommandSent.vm
@@ -0,0 +1,2 @@
+#set($subject = "$device.name: queued command sent")
+Queued command sent to $device.name at $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.eventTime, $locale, $timezone)