mirror of
https://github.com/traccar/traccar.git
synced 2026-04-22 16:17:16 -04:00
Refactor computed attributes
This commit is contained in:
@@ -57,8 +57,6 @@ public abstract class BasePipelineFactory extends ChannelInitializer<Channel> {
|
||||
private final TrackerServer server;
|
||||
private int timeout;
|
||||
|
||||
private ComputedAttributesHandler computedAttributesHandler;
|
||||
|
||||
private CommandResultEventHandler commandResultEventHandler;
|
||||
private OverspeedEventHandler overspeedEventHandler;
|
||||
private FuelDropEventHandler fuelDropEventHandler;
|
||||
@@ -77,10 +75,6 @@ public abstract class BasePipelineFactory extends ChannelInitializer<Channel> {
|
||||
timeout = Context.getConfig().getInteger(Keys.SERVER_TIMEOUT);
|
||||
}
|
||||
|
||||
if (Context.getConfig().getBoolean("processing.computedAttributes.enable")) {
|
||||
computedAttributesHandler = new ComputedAttributesHandler();
|
||||
}
|
||||
|
||||
if (Context.getConfig().getBoolean("event.enable")) {
|
||||
commandResultEventHandler = new CommandResultEventHandler();
|
||||
overspeedEventHandler = Context.getOverspeedEventHandler();
|
||||
@@ -157,7 +151,7 @@ public abstract class BasePipelineFactory extends ChannelInitializer<Channel> {
|
||||
Main.getInjector().getInstance(MotionHandler.class),
|
||||
Main.getInjector().getInstance(EngineHoursHandler.class),
|
||||
Main.getInjector().getInstance(CopyAttributesHandler.class),
|
||||
computedAttributesHandler);
|
||||
Main.getInjector().getInstance(ComputedAttributesHandler.class));
|
||||
|
||||
if (Context.getDataManager() != null) {
|
||||
pipeline.addLast(new DefaultDataHandler());
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import org.traccar.config.Config;
|
||||
import org.traccar.config.Keys;
|
||||
import org.traccar.database.AttributesManager;
|
||||
import org.traccar.database.DataManager;
|
||||
import org.traccar.database.IdentityManager;
|
||||
import org.traccar.database.StatisticsManager;
|
||||
@@ -43,6 +44,7 @@ import org.traccar.geolocation.GoogleGeolocationProvider;
|
||||
import org.traccar.geolocation.MozillaGeolocationProvider;
|
||||
import org.traccar.geolocation.OpenCellIdGeolocationProvider;
|
||||
import org.traccar.geolocation.UnwiredGeolocationProvider;
|
||||
import org.traccar.handler.ComputedAttributesHandler;
|
||||
import org.traccar.handler.CopyAttributesHandler;
|
||||
import org.traccar.handler.DistanceHandler;
|
||||
import org.traccar.handler.EngineHoursHandler;
|
||||
@@ -89,6 +91,11 @@ public class MainModule extends AbstractModule {
|
||||
return Context.getTripsConfig();
|
||||
}
|
||||
|
||||
@Provides
|
||||
public static AttributesManager provideAttributesManager() {
|
||||
return Context.getAttributesManager();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
public static StatisticsManager provideStatisticsManager(Config config, DataManager dataManager, Client client) {
|
||||
@@ -247,6 +254,16 @@ public class MainModule extends AbstractModule {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
public static ComputedAttributesHandler provideComputedAttributesHandler(
|
||||
Config config, IdentityManager identityManager, AttributesManager attributesManager) {
|
||||
if (config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ENABLE)) {
|
||||
return new ComputedAttributesHandler(config, identityManager, attributesManager);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
binder().requireExplicitBindings();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org)
|
||||
* Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org)
|
||||
* Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -46,12 +46,15 @@ public class AttributeResource extends ExtendedObjectResource<Attribute> {
|
||||
|
||||
@POST
|
||||
@Path("test")
|
||||
public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) throws SQLException {
|
||||
public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) {
|
||||
Context.getPermissionsManager().checkAdmin(getUserId());
|
||||
Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
|
||||
Position last = Context.getIdentityManager().getLastPosition(deviceId);
|
||||
if (last != null) {
|
||||
Object result = new ComputedAttributesHandler().computeAttribute(entity, last);
|
||||
Object result = new ComputedAttributesHandler(
|
||||
Context.getConfig(),
|
||||
Context.getIdentityManager(),
|
||||
Context.getAttributesManager()).computeAttribute(entity, last);
|
||||
if (result != null) {
|
||||
switch (entity.getType()) {
|
||||
case "number":
|
||||
|
||||
@@ -192,6 +192,18 @@ public final class Keys {
|
||||
public static final ConfigKey PROCESSING_COPY_ATTRIBUTES_ENABLE = new ConfigKey(
|
||||
"processing.copyAttributes.enable", Boolean.class);
|
||||
|
||||
/**
|
||||
* Enable computed attributes processing.
|
||||
*/
|
||||
public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ENABLE = new ConfigKey(
|
||||
"processing.computedAttributes.enable", Boolean.class);
|
||||
|
||||
/**
|
||||
* Enable computed attributes processing.
|
||||
*/
|
||||
public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new ConfigKey(
|
||||
"processing.computedAttributes.deviceAttributes", Boolean.class);
|
||||
|
||||
/**
|
||||
* Boolean flag to enable or disable reverse geocoder.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 Anton Tananaev (anton@traccar.org)
|
||||
* Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org)
|
||||
* Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -32,7 +32,10 @@ import org.apache.commons.jexl2.MapContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.traccar.BaseDataHandler;
|
||||
import org.traccar.Context;
|
||||
import org.traccar.config.Config;
|
||||
import org.traccar.config.Keys;
|
||||
import org.traccar.database.AttributesManager;
|
||||
import org.traccar.database.IdentityManager;
|
||||
import org.traccar.model.Attribute;
|
||||
import org.traccar.model.Device;
|
||||
import org.traccar.model.Position;
|
||||
@@ -42,23 +45,27 @@ public class ComputedAttributesHandler extends BaseDataHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ComputedAttributesHandler.class);
|
||||
|
||||
private JexlEngine engine;
|
||||
private final IdentityManager identityManager;
|
||||
private final AttributesManager attributesManager;
|
||||
|
||||
private boolean mapDeviceAttributes;
|
||||
private final JexlEngine engine;
|
||||
|
||||
public ComputedAttributesHandler() {
|
||||
private final boolean includeDeviceAttributes;
|
||||
|
||||
public ComputedAttributesHandler(
|
||||
Config config, IdentityManager identityManager, AttributesManager attributesManager) {
|
||||
this.identityManager = identityManager;
|
||||
this.attributesManager = attributesManager;
|
||||
engine = new JexlEngine();
|
||||
engine.setStrict(true);
|
||||
engine.setFunctions(Collections.singletonMap("math", (Object) Math.class));
|
||||
if (Context.getConfig() != null) {
|
||||
mapDeviceAttributes = Context.getConfig().getBoolean("processing.computedAttributes.deviceAttributes");
|
||||
}
|
||||
engine.setFunctions(Collections.singletonMap("math", Math.class));
|
||||
includeDeviceAttributes = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES);
|
||||
}
|
||||
|
||||
private MapContext prepareContext(Position position) {
|
||||
MapContext result = new MapContext();
|
||||
if (mapDeviceAttributes) {
|
||||
Device device = Context.getIdentityManager().getById(position.getDeviceId());
|
||||
if (includeDeviceAttributes) {
|
||||
Device device = identityManager.getById(position.getDeviceId());
|
||||
if (device != null) {
|
||||
for (Object key : device.getAttributes().keySet()) {
|
||||
result.set((String) key, device.getAttributes().get(key));
|
||||
@@ -87,14 +94,18 @@ public class ComputedAttributesHandler extends BaseDataHandler {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated logic needs to be extracted to be used in API resource
|
||||
*/
|
||||
@Deprecated
|
||||
public Object computeAttribute(Attribute attribute, Position position) throws JexlException {
|
||||
return engine.createExpression(attribute.getExpression()).evaluate(prepareContext(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Position handlePosition(Position position) {
|
||||
Collection<Attribute> attributes = Context.getAttributesManager().getItems(
|
||||
Context.getAttributesManager().getAllDeviceItems(position.getDeviceId()));
|
||||
Collection<Attribute> attributes = attributesManager.getItems(
|
||||
attributesManager.getAllDeviceItems(position.getDeviceId()));
|
||||
for (Attribute attribute : attributes) {
|
||||
if (attribute.getAttribute() != null) {
|
||||
Object result = null;
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.traccar.handler;
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.traccar.config.Config;
|
||||
import org.traccar.model.Attribute;
|
||||
import org.traccar.model.Position;
|
||||
|
||||
@@ -12,9 +13,11 @@ public class ComputedAttributesTest {
|
||||
|
||||
@Test
|
||||
public void testComputedAttributes() {
|
||||
Position position = new Position();
|
||||
ComputedAttributesHandler computedAttributesHandler = new ComputedAttributesHandler();
|
||||
|
||||
ComputedAttributesHandler handler = new ComputedAttributesHandler(new Config(), null, null);
|
||||
|
||||
Date date = new Date();
|
||||
Position position = new Position();
|
||||
position.setTime(date);
|
||||
position.setSpeed(42);
|
||||
position.setValid(false);
|
||||
@@ -27,40 +30,40 @@ public class ComputedAttributesTest {
|
||||
Attribute attribute = new Attribute();
|
||||
|
||||
attribute.setExpression("adc1");
|
||||
assertEquals(128, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(128, handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("!booleanFlag");
|
||||
assertEquals(false, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(false, handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("adc2 * 2 + 50");
|
||||
assertEquals(250, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(250, handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("(bitFlag & 4) != 0");
|
||||
assertEquals(true, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(true, handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("if (event == 42) \"lowBattery\"");
|
||||
assertEquals("lowBattery", computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals("lowBattery", handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("speed > 5 && valid");
|
||||
assertEquals(false, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(false, handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("fixTime");
|
||||
assertEquals(date, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(date, handler.computeAttribute(attribute, position));
|
||||
|
||||
attribute.setExpression("math:pow(adc1, 2)");
|
||||
assertEquals(16384.0, computedAttributesHandler.computeAttribute(attribute, position));
|
||||
assertEquals(16384.0, handler.computeAttribute(attribute, position));
|
||||
|
||||
// modification tests
|
||||
attribute.setExpression("adc1 = 256");
|
||||
computedAttributesHandler.computeAttribute(attribute, position);
|
||||
handler.computeAttribute(attribute, position);
|
||||
assertEquals(128, position.getInteger("adc1"));
|
||||
|
||||
attribute.setExpression("result = \"fail\"");
|
||||
computedAttributesHandler.computeAttribute(attribute, position);
|
||||
handler.computeAttribute(attribute, position);
|
||||
assertEquals("success", position.getString("result"));
|
||||
|
||||
attribute.setExpression("fixTime = \"2017-10-18 10:00:01\"");
|
||||
computedAttributesHandler.computeAttribute(attribute, position);
|
||||
handler.computeAttribute(attribute, position);
|
||||
assertEquals(date, position.getFixTime());
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user