removed no needed logic from geofencing arugment

This commit is contained in:
dshvaika 2025-08-08 17:28:57 +03:00
parent fb84eb0695
commit 409328dbe3
8 changed files with 33 additions and 87 deletions

View File

@ -36,8 +36,6 @@ import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.Argument;
import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
import org.thingsboard.server.common.data.cf.configuration.CFArgumentDynamicSourceType;
import org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration;
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
import org.thingsboard.server.common.data.cf.configuration.OutputType;
import org.thingsboard.server.common.data.cf.configuration.RelationQueryDynamicSourceConfiguration;
import org.thingsboard.server.common.data.id.CalculatedFieldId;
@ -131,18 +129,18 @@ public class DefaultCalculatedFieldProcessingService implements CalculatedFieldP
@Override
public ListenableFuture<CalculatedFieldState> fetchStateFromDb(CalculatedFieldCtx ctx, EntityId entityId) {
Map<String, ListenableFuture<ArgumentEntry>> argFutures = new HashMap<>();
if (ctx.getCalculatedField().getType().equals(CalculatedFieldType.GEOFENCING)) {
fetchGeofencingCalculatedFieldArguments(ctx, entityId, argFutures, false);
} else {
for (var entry : ctx.getArguments().entrySet()) {
var argEntityId = resolveEntityId(entityId, entry);
var argValueFuture = fetchKvEntry(ctx.getTenantId(), argEntityId, entry.getValue());
argFutures.put(entry.getKey(), argValueFuture);
Map<String, ListenableFuture<ArgumentEntry>> argFutures = switch (ctx.getCalculatedField().getType()) {
case GEOFENCING -> fetchGeofencingCalculatedFieldArguments(ctx, entityId, false);
case SIMPLE, SCRIPT -> {
Map<String, ListenableFuture<ArgumentEntry>> futures = new HashMap<>();
for (var entry : ctx.getArguments().entrySet()) {
var argEntityId = resolveEntityId(entityId, entry);
var argValueFuture = fetchKvEntry(ctx.getTenantId(), argEntityId, entry.getValue());
futures.put(entry.getKey(), argValueFuture);
}
yield futures;
}
}
};
return Futures.whenAllComplete(argFutures.values()).call(() -> {
var result = createStateByType(ctx);
result.updateState(ctx, resolveArgumentFutures(argFutures));
@ -156,14 +154,11 @@ public class DefaultCalculatedFieldProcessingService implements CalculatedFieldP
if (!ctx.getCalculatedField().getType().equals(CalculatedFieldType.GEOFENCING)) {
return Map.of();
}
Map<String, ListenableFuture<ArgumentEntry>> argFutures = new HashMap<>();
fetchGeofencingCalculatedFieldArguments(ctx, entityId, argFutures, true);
return resolveArgumentFutures(argFutures);
return resolveArgumentFutures(fetchGeofencingCalculatedFieldArguments(ctx, entityId, true));
}
private void fetchGeofencingCalculatedFieldArguments(CalculatedFieldCtx ctx, EntityId entityId, Map<String, ListenableFuture<ArgumentEntry>> argFutures, boolean dynamicArgumentsOnly) {
var configuration = (GeofencingCalculatedFieldConfiguration) ctx.getCalculatedField().getConfiguration();
var zoneGroupConfigs = configuration.getGeofencingZoneGroupConfigurations();
private Map<String, ListenableFuture<ArgumentEntry>> fetchGeofencingCalculatedFieldArguments(CalculatedFieldCtx ctx, EntityId entityId, boolean dynamicArgumentsOnly) {
Map<String, ListenableFuture<ArgumentEntry>> argFutures = new HashMap<>();
Set<Entry<String, Argument>> entries = ctx.getArguments().entrySet();
if (dynamicArgumentsOnly) {
entries = entries.stream()
@ -175,13 +170,13 @@ public class DefaultCalculatedFieldProcessingService implements CalculatedFieldP
case ENTITY_ID_LATITUDE_ARGUMENT_KEY, ENTITY_ID_LONGITUDE_ARGUMENT_KEY ->
argFutures.put(entry.getKey(), fetchKvEntry(ctx.getTenantId(), resolveEntityId(entityId, entry), entry.getValue()));
default -> {
var zoneGroupConfiguration = zoneGroupConfigs.get(entry.getKey());
var resolvedEntityIdsFuture = resolveGeofencingEntityIds(ctx.getTenantId(), entityId, entry);
argFutures.put(entry.getKey(), Futures.transformAsync(resolvedEntityIdsFuture, resolvedEntityIds ->
fetchGeofencingKvEntry(ctx.getTenantId(), resolvedEntityIds, entry.getValue(), zoneGroupConfiguration), calculatedFieldCallbackExecutor));
fetchGeofencingKvEntry(ctx.getTenantId(), resolvedEntityIds, entry.getValue()), calculatedFieldCallbackExecutor));
}
}
}
return argFutures;
}
@Override
@ -321,12 +316,11 @@ public class DefaultCalculatedFieldProcessingService implements CalculatedFieldP
};
}
private ListenableFuture<ArgumentEntry> fetchGeofencingKvEntry(TenantId tenantId, List<EntityId> geofencingEntities,
Argument argument, GeofencingZoneGroupConfiguration zoneGroupConfiguration) {
private ListenableFuture<ArgumentEntry> fetchGeofencingKvEntry(TenantId tenantId, List<EntityId> geofencingEntities, Argument argument) {
if (argument.getRefEntityKey().getType() != ArgumentType.ATTRIBUTE) {
throw new IllegalStateException("Unsupported argument key type: " + argument.getRefEntityKey().getType());
}
List<ListenableFuture<Map.Entry<EntityId, AttributeKvEntry>>> kvFutures = geofencingEntities.stream()
List<ListenableFuture<Entry<EntityId, AttributeKvEntry>>> kvFutures = geofencingEntities.stream()
.map(entityId -> {
var attributesFuture = attributesService.find(
tenantId,
@ -341,10 +335,10 @@ public class DefaultCalculatedFieldProcessingService implements CalculatedFieldP
);
}).collect(Collectors.toList());
ListenableFuture<List<Map.Entry<EntityId, AttributeKvEntry>>> allFutures = Futures.allAsList(kvFutures);
ListenableFuture<List<Entry<EntityId, AttributeKvEntry>>> allFutures = Futures.allAsList(kvFutures);
return Futures.transform(allFutures, entries -> ArgumentEntry.createGeofencingValueArgument(entries.stream()
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)), zoneGroupConfiguration),
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))),
calculatedFieldCallbackExecutor
);
}

View File

@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.thingsboard.script.api.tbel.TbelCfArg;
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
@ -62,8 +61,8 @@ public interface ArgumentEntry {
return new TsRollingArgumentEntry(kvEntries, limit, timeWindow);
}
static ArgumentEntry createGeofencingValueArgument(Map<EntityId, KvEntry> entityIdkvEntryMap, GeofencingZoneGroupConfiguration zoneGroupConfiguration) {
return new GeofencingArgumentEntry(entityIdkvEntryMap, zoneGroupConfiguration);
static ArgumentEntry createGeofencingValueArgument(Map<EntityId, KvEntry> entityIdkvEntryMap) {
return new GeofencingArgumentEntry(entityIdkvEntryMap);
}
}

View File

@ -19,7 +19,6 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.script.api.tbel.TbelCfArg;
import org.thingsboard.script.api.tbel.TbelCfTsGeofencingArg;
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.kv.KvEntry;
@ -32,17 +31,14 @@ import java.util.stream.Collectors;
public class GeofencingArgumentEntry implements ArgumentEntry {
private Map<EntityId, GeofencingZoneState> zoneStates;
private GeofencingZoneGroupConfiguration zoneGroupConfiguration;
private boolean forceResetPrevious;
public GeofencingArgumentEntry() {
}
public GeofencingArgumentEntry(Map<EntityId, KvEntry> entityIdkvEntryMap,
GeofencingZoneGroupConfiguration zoneGroupConfiguration) {
public GeofencingArgumentEntry(Map<EntityId, KvEntry> entityIdkvEntryMap) {
this.zoneStates = toZones(entityIdkvEntryMap);
this.zoneGroupConfiguration = zoneGroupConfiguration;
}
@Override

View File

@ -23,7 +23,9 @@ import lombok.Data;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.geo.Coordinates;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration;
import org.thingsboard.server.common.data.cf.configuration.GeofencingEvent;
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
import org.thingsboard.server.service.cf.CalculatedFieldResult;
import org.thingsboard.server.service.cf.ctx.CalculatedFieldEntityCtxId;
import org.thingsboard.server.utils.CalculatedFieldUtils;
@ -119,9 +121,12 @@ public class GeofencingCalculatedFieldState implements CalculatedFieldState {
double longitude = (double) arguments.get(ENTITY_ID_LONGITUDE_ARGUMENT_KEY).getValue();
Coordinates entityCoordinates = new Coordinates(latitude, longitude);
var configuration = (GeofencingCalculatedFieldConfiguration) ctx.getCalculatedField().getConfiguration();
Map<String, GeofencingZoneGroupConfiguration> geofencingZoneGroupConfigurations = configuration.getGeofencingZoneGroupConfigurations();
ObjectNode resultNode = JacksonUtil.newObjectNode();
getGeofencingArguments().forEach((argumentKey, argumentEntry) -> {
var zoneGroupConfig = argumentEntry.getZoneGroupConfiguration();
var zoneGroupConfig = geofencingZoneGroupConfigurations.get(argumentKey);
Set<GeofencingEvent> zoneEvents = argumentEntry.getZoneStates()
.values()
.stream()

View File

@ -18,8 +18,6 @@ package org.thingsboard.server.utils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.GeofencingEvent;
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
@ -30,7 +28,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldEntit
import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldIdProto;
import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldStateProto;
import org.thingsboard.server.gen.transport.TransportProtos.GeofencingArgumentProto;
import org.thingsboard.server.gen.transport.TransportProtos.GeofencingEventProto;
import org.thingsboard.server.gen.transport.TransportProtos.GeofencingZoneIdProto;
import org.thingsboard.server.gen.transport.TransportProtos.GeofencingZoneProto;
import org.thingsboard.server.gen.transport.TransportProtos.SingleValueArgumentProto;
@ -48,7 +45,6 @@ import org.thingsboard.server.service.cf.ctx.state.SimpleCalculatedFieldState;
import org.thingsboard.server.service.cf.ctx.state.SingleValueArgumentEntry;
import org.thingsboard.server.service.cf.ctx.state.TsRollingArgumentEntry;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
@ -127,15 +123,11 @@ public class CalculatedFieldUtils {
private static GeofencingArgumentProto toGeofencingArgumentProto(String argName, GeofencingArgumentEntry geofencingArgumentEntry) {
var zoneGroupConfiguration = geofencingArgumentEntry.getZoneGroupConfiguration();
Map<EntityId, GeofencingZoneState> zoneStates = geofencingArgumentEntry.getZoneStates();
GeofencingArgumentProto.Builder builder = GeofencingArgumentProto.newBuilder()
.setArgName(argName)
.setTelemetryPrefix(zoneGroupConfiguration.getReportTelemetryPrefix());
.setArgName(argName);
zoneStates.forEach((entityId, zoneState) ->
builder.addZones(toGeofencingZoneProto(entityId, zoneState)));
zoneGroupConfiguration.getReportEvents().forEach(event ->
builder.addReportEvents(GeofencingEventProto.forNumber(event.getProtoNumber())));
return builder.build();
}
@ -213,14 +205,8 @@ public class CalculatedFieldUtils {
.stream()
.map(GeofencingZoneState::new)
.collect(Collectors.toMap(GeofencingZoneState::getZoneId, Function.identity()));
List<GeofencingEvent> geofencingEvents = proto.getReportEventsList()
.stream()
.map(geofencingEventProto -> GeofencingEvent.fromProtoNumber(geofencingEventProto.getNumber()))
.toList();
var zoneGroupConfiguration = new GeofencingZoneGroupConfiguration(proto.getTelemetryPrefix(), geofencingEvents);
GeofencingArgumentEntry geofencingArgumentEntry = new GeofencingArgumentEntry();
geofencingArgumentEntry.setZoneStates(zoneStates);
geofencingArgumentEntry.setZoneGroupConfiguration(zoneGroupConfiguration);
return geofencingArgumentEntry;
}

View File

@ -40,6 +40,8 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
ENTITY_ID_LONGITUDE_ARGUMENT_KEY
);
private String zoneRelationType;
private boolean trackZoneRelations;
private Map<String, GeofencingZoneGroupConfiguration> geofencingZoneGroupConfigurations;
@Override

View File

@ -15,35 +15,8 @@
*/
package org.thingsboard.server.common.data.cf.configuration;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum GeofencingEvent {
ENTERED(0), LEFT(1), INSIDE(2), OUTSIDE(3);
private final int protoNumber; // Corresponds to GeofencingEvent
GeofencingEvent(int protoNumber) {
this.protoNumber = protoNumber;
}
private static final GeofencingEvent[] BY_PROTO;
static {
BY_PROTO = new GeofencingEvent[Arrays.stream(values()).mapToInt(GeofencingEvent::getProtoNumber).max().orElse(0) + 1];
for (var event : values()) {
BY_PROTO[event.getProtoNumber()] = event;
}
}
public static GeofencingEvent fromProtoNumber(int protoNumber) {
if (protoNumber < 0 || protoNumber >= BY_PROTO.length) {
throw new IllegalArgumentException("Invalid GeofencingEvent proto number " + protoNumber);
}
return BY_PROTO[protoNumber];
}
ENTERED, LEFT, INSIDE, OUTSIDE;
}

View File

@ -908,17 +908,8 @@ message GeofencingZoneProto {
optional bool inside = 5;
}
enum GeofencingEventProto {
ENTERED = 0;
LEFT = 1;
INSIDE = 2;
OUTSIDE = 3;
}
message GeofencingArgumentProto {
string argName = 1;
string telemetryPrefix = 2;
repeated GeofencingEventProto reportEvents = 3;
repeated GeofencingZoneProto zones = 4;
}