Skip to content

Commit

Permalink
Merge branch 'traccar:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
petgnss authored Oct 3, 2024
2 parents ee27bad + a11be97 commit 67fa02a
Show file tree
Hide file tree
Showing 53 changed files with 2,636 additions and 3,699 deletions.
2,351 changes: 2,351 additions & 0 deletions openapi.yaml

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions schema/changelog-6.6.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"
logicalFilePath="changelog-6.6">

<changeSet author="author" id="changelog-6.6">

<addColumn tableName="tc_notifications">
<column name="description" type="VARCHAR(4000)" />
</addColumn>

</changeSet>

</databaseChangeLog>
1 change: 1 addition & 0 deletions schema/changelog-master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@

<include file="changelog-6.2.xml" relativeToChangelogFile="true" />
<include file="changelog-6.3.xml" relativeToChangelogFile="true" />
<include file="changelog-6.6.xml" relativeToChangelogFile="true" />

</databaseChangeLog>
3 changes: 2 additions & 1 deletion src/main/java/org/traccar/ProcessingHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public ProcessingHandler(
bufferingManager = new BufferingManager(config, this);

positionHandlers = Stream.of(
ComputedAttributesHandler.Early.class,
OutdatedHandler.class,
TimeHandler.class,
GeolocationHandler.class,
Expand All @@ -105,7 +106,7 @@ public ProcessingHandler(
GeocoderHandler.class,
SpeedLimitHandler.class,
MotionHandler.class,
ComputedAttributesHandler.class,
ComputedAttributesHandler.Late.class,
EngineHoursHandler.class,
DriverHandler.class,
CopyAttributesHandler.class,
Expand Down
31 changes: 20 additions & 11 deletions src/main/java/org/traccar/api/resource/AttributeResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.traccar.model.Device;
import org.traccar.model.Position;
import org.traccar.handler.ComputedAttributesHandler;
import org.traccar.storage.StorageException;
import org.traccar.session.cache.CacheManager;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
import org.traccar.storage.query.Request;
Expand All @@ -44,30 +44,39 @@
public class AttributeResource extends ExtendedObjectResource<Attribute> {

@Inject
private ComputedAttributesHandler computedAttributesHandler;
private CacheManager cacheManager;

@Inject
private ComputedAttributesHandler.Late computedAttributesHandler;

public AttributeResource() {
super(Attribute.class);
}

@POST
@Path("test")
public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) throws StorageException {
public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) throws Exception {
permissionsService.checkAdmin(getUserId());
permissionsService.checkPermission(Device.class, getUserId(), deviceId);

Position position = storage.getObject(Position.class, new Request(
new Columns.All(),
new Condition.LatestPositions(deviceId)));

Object result = computedAttributesHandler.computeAttribute(entity, position);
if (result != null) {
return switch (entity.getType()) {
case "number", "boolean" -> Response.ok(result).build();
default -> Response.ok(result.toString()).build();
};
} else {
return Response.noContent().build();
var key = new Object();
try {
cacheManager.addDevice(position.getDeviceId(), key);
Object result = computedAttributesHandler.computeAttribute(entity, position);
if (result != null) {
return switch (entity.getType()) {
case "number", "boolean" -> Response.ok(result).build();
default -> Response.ok(result.toString()).build();
};
} else {
return Response.noContent().build();
}
} finally {
cacheManager.removeDevice(position.getDeviceId(), key);
}
}

Expand Down
18 changes: 15 additions & 3 deletions src/main/java/org/traccar/api/resource/NotificationResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.slf4j.LoggerFactory;
import org.traccar.api.ExtendedObjectResource;
import org.traccar.model.Event;
import org.traccar.model.ManagedUser;
import org.traccar.model.Notification;
import org.traccar.model.Typed;
import org.traccar.model.User;
Expand Down Expand Up @@ -113,15 +114,26 @@ public Response testMessage(@PathParam("notificator") String notificator)
public Response sendMessage(
@PathParam("notificator") String notificator, @QueryParam("userId") List<Long> userIds,
NotificationMessage message) throws MessageException, StorageException {
permissionsService.checkAdmin(getUserId());
permissionsService.checkManager(getUserId());
List<User> users;
if (userIds.isEmpty()) {
users = storage.getObjects(User.class, new Request(new Columns.All()));
if (permissionsService.notAdmin(getUserId())) {
users = storage.getObjects(User.class, new Request(new Columns.All(),
new Condition.Permission(User.class, getUserId(), ManagedUser.class).excludeGroups()));
} else {
users = storage.getObjects(User.class, new Request(new Columns.All()));
}
} else {
users = new ArrayList<>();
for (long userId : userIds) {
var conditions = new LinkedList<Condition>();
conditions.add(new Condition.Equals("id", userId));
if (permissionsService.notAdmin(getUserId())) {
conditions.add(new Condition.Permission(
User.class, getUserId(), ManagedUser.class).excludeGroups());
}
users.add(storage.getObject(
User.class, new Request(new Columns.All(), new Condition.Equals("id", userId))));
User.class, new Request(new Columns.All(), Condition.merge(conditions))));
}
}
for (User user : users) {
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/org/traccar/api/resource/UserResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.Collection;
import java.util.LinkedList;

@Path("users")
@Produces(MediaType.APPLICATION_JSON)
Expand All @@ -70,10 +71,13 @@ public Collection<User> get(
new Columns.All(),
new Condition.Permission(User.class, userId, ManagedUser.class).excludeGroups()));
} else if (deviceId > 0) {
permissionsService.checkAdmin(getUserId());
return storage.getObjects(baseClass, new Request(
new Columns.All(),
new Condition.Permission(User.class, Device.class, deviceId).excludeGroups()));
permissionsService.checkManager(getUserId());
var conditions = new LinkedList<Condition>();
conditions.add(new Condition.Permission(User.class, Device.class, deviceId).excludeGroups());
if (permissionsService.notAdmin(getUserId())) {
conditions.add(new Condition.Permission(User.class, getUserId(), ManagedUser.class).excludeGroups());
}
return storage.getObjects(baseClass, new Request(new Columns.All(), Condition.merge(conditions)));
} else if (permissionsService.notAdmin(getUserId())) {
return storage.getObjects(baseClass, new Request(
new Columns.All(),
Expand Down
25 changes: 22 additions & 3 deletions src/main/java/org/traccar/handler/ComputedAttributesHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand All @@ -48,6 +50,7 @@ public class ComputedAttributesHandler extends BasePositionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(ComputedAttributesHandler.class);

private final CacheManager cacheManager;
private boolean early;

private final JexlEngine engine;

Expand All @@ -56,15 +59,30 @@ public class ComputedAttributesHandler extends BasePositionHandler {
private final boolean includeDeviceAttributes;
private final boolean includeLastAttributes;

@Inject
public ComputedAttributesHandler(Config config, CacheManager cacheManager) {
public static class Early extends ComputedAttributesHandler {
@Inject
public Early(Config config, CacheManager cacheManager) {
super(config, cacheManager, true);
}
}

public static class Late extends ComputedAttributesHandler {
@Inject
public Late(Config config, CacheManager cacheManager) {
super(config, cacheManager, false);
}
}

public ComputedAttributesHandler(Config config, CacheManager cacheManager, boolean early) {
this.cacheManager = cacheManager;
this.early = early;
JexlSandbox sandbox = new JexlSandbox(false);
sandbox.allow("com.safe.Functions");
sandbox.allow(Math.class.getName());
List.of(
Double.class, Float.class, Integer.class, Long.class, Short.class,
Character.class, Boolean.class, String.class, Byte.class, Date.class)
Character.class, Boolean.class, String.class, Byte.class, Date.class,
HashMap.class, LinkedHashMap.class, double[].class, int[].class, boolean[].class, String[].class)
.forEach((type) -> sandbox.allow(type.getName()));
features = new JexlFeatures()
.localVar(config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES))
Expand Down Expand Up @@ -141,6 +159,7 @@ public Object computeAttribute(Attribute attribute, Position position) throws Je
@Override
public void onPosition(Position position, Callback callback) {
var attributes = cacheManager.getDeviceObjects(position.getDeviceId(), Attribute.class).stream()
.filter(attribute -> attribute.getPriority() < 0 == early)
.sorted(Comparator.comparing(Attribute::getPriority).reversed())
.toList();
for (Attribute attribute : attributes) {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/traccar/model/Calendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.util.Date;
Expand Down Expand Up @@ -87,6 +88,8 @@ public boolean checkMoment(Date date) {
private static Instant temporalToInstant(Temporal temporal) {
if (temporal instanceof ZonedDateTime) {
return ((ZonedDateTime) temporal).toInstant();
} else if (temporal instanceof OffsetDateTime) {
return ((OffsetDateTime) temporal).toInstant();
} else if (temporal instanceof Instant) {
return (Instant) temporal;
} else {
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/traccar/model/Notification.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
@StorageName("tc_notifications")
public class Notification extends ExtendedModel implements Schedulable {

private String description;

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

private long calendarId;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public boolean getCompressed(long deviceId) {
TAG_LENGTH_MAP.put(0x5b, 7); // variable length
TAG_LENGTH_MAP.put(0x5c, 68);
TAG_LENGTH_MAP.put(0xfd, 8);
TAG_LENGTH_MAP.put(0xfe, 8);
TAG_LENGTH_MAP.put(0xfe, 8); // TODO this is probably incorrect
}

private static int getTagLength(int tag) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ private Object decodeEri(Channel channel, SocketAddress remoteAddress, String[]
position.set(Position.KEY_HOURS, parseHours(v[index++]));
position.set(Position.PREFIX_ADC + 1, v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]) * 0.001);
}
if (model.startsWith("GV") && !model.startsWith("GV6")) {
if (model.startsWith("GV") && !model.startsWith("GV6") && !model.equals("GV350M")) {
position.set(Position.PREFIX_ADC + 2, v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]) * 0.001);
}
if (model.equals("GV200") || model.equals("GV310LAU")) {
Expand Down Expand Up @@ -1051,7 +1051,7 @@ private Object decodeIgn(
index += 1; // device name
index += 1; // duration of ignition on/off

decodeLocation(position, model, v, index);
index = decodeLocation(position, model, v, index);

position.set(Position.KEY_IGNITION, type.contains("GN"));
position.set(Position.KEY_HOURS, parseHours(v[index++]));
Expand Down
55 changes: 19 additions & 36 deletions src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,21 +234,6 @@ private static boolean hasStatus(int type) {
}
}

private static boolean hasLanguage(int type) {
switch (type) {
case MSG_GPS_PHONE:
case MSG_HEARTBEAT:
case MSG_GPS_LBS_STATUS_3:
case MSG_LBS_MULTIPLE_1:
case MSG_LBS_MULTIPLE_2:
case MSG_LBS_2:
case MSG_FENCE_MULTI:
return true;
default:
return false;
}
}

private void sendResponse(Channel channel, boolean extended, int type, int index, ByteBuf content) {
if (channel != null) {
ByteBuf response = Unpooled.buffer();
Expand Down Expand Up @@ -836,19 +821,25 @@ private Object decodeBasic(Channel channel, SocketAddress remoteAddress, ByteBuf
if (type == MSG_GPS_LBS_STATUS_5) {
position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
}
int battery = buf.readUnsignedByte();
if (battery <= 6) {
position.set(Position.KEY_BATTERY_LEVEL, battery * 100 / 6);
} else if (battery <= 100) {
position.set(Position.KEY_BATTERY_LEVEL, battery);
if (type == MSG_STATUS && "R11".equals(model)) {
position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
} else {
int battery = buf.readUnsignedByte();
if (battery <= 6) {
position.set(Position.KEY_BATTERY_LEVEL, battery * 100 / 6);
} else if (battery <= 100) {
position.set(Position.KEY_BATTERY_LEVEL, battery);
}
}
position.set(Position.KEY_RSSI, buf.readUnsignedByte());
if (modelLW && type == MSG_STATUS) {
if (type == MSG_STATUS && modelLW) {
position.set(Position.KEY_POWER, BitUtil.to(buf.readUnsignedShort(), 12) / 10.0);
} else {
short alarmExtension = buf.readUnsignedByte();
if (variant != Variant.VXT01) {
position.addAlarm(decodeAlarm(alarmExtension, modelLW));
short extension = buf.readUnsignedByte();
if (type == MSG_STATUS && "SEEWORLD".equals(model)) {
position.set(Position.KEY_POWER, (double) extension);
} else if (variant != Variant.VXT01) {
position.addAlarm(decodeAlarm(extension, modelLW));
}
}
}
Expand Down Expand Up @@ -985,6 +976,10 @@ private Object decodeBasic(Channel channel, SocketAddress remoteAddress, ByteBuf
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
}

if (type == MSG_GPS_LBS_STATUS_3 || type == MSG_FENCE_MULTI) {
position.set(Position.KEY_GEOFENCE, buf.readUnsignedByte());
}

} else if (type == MSG_ALARM) {

boolean extendedAlarm = dataLength > 7;
Expand Down Expand Up @@ -1033,18 +1028,6 @@ private Object decodeBasic(Channel channel, SocketAddress remoteAddress, ByteBuf

}

if (hasLanguage(type)) {
if (modelLW && type == MSG_STATUS) {
position.set(Position.KEY_POWER, BitUtil.to(buf.readUnsignedShort(), 12) * 0.1);
} else {
buf.readUnsignedShort(); // language
}
}

if (type == MSG_GPS_LBS_STATUS_3 || type == MSG_FENCE_MULTI) {
position.set(Position.KEY_GEOFENCE, buf.readUnsignedByte());
}

sendResponse(channel, false, type, buf.getShort(buf.writerIndex() - 6), null);

return position;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ private Position decodeLocation(DeviceSession deviceSession, ByteBuf buf) {

position.addAlarm(decodeAlarm(buf.readUnsignedInt()));

String model = getDeviceModel(deviceSession);

decodeCoordinates(position, deviceSession, buf);

position.setAltitude(buf.readShort());
Expand Down Expand Up @@ -603,7 +605,9 @@ private Position decodeLocation(DeviceSession deviceSession, ByteBuf buf) {
position.set("cover", BitUtil.check(deviceStatus, 3));
break;
case 0xE2:
position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedInt() * 0.1);
if (!"DT800".equals(model)) {
position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedInt() * 0.1);
}
break;
case 0xE3:
buf.readUnsignedByte(); // reserved
Expand Down
Loading

0 comments on commit 67fa02a

Please sign in to comment.