Browse Source

Alarm rules for customer entity

pull/14193/head
VIacheslavKlimov 12 months ago
parent
commit
60ef35ac8e
  1. 9
      application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldQueueService.java
  2. 1
      application/src/main/java/org/thingsboard/server/service/cf/OwnerService.java
  3. 7
      application/src/main/java/org/thingsboard/server/service/entitiy/cf/DefaultTbCalculatedFieldService.java
  4. 1
      application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java
  5. 106
      application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java
  6. 4
      common/data/src/main/java/org/thingsboard/server/common/data/alarm/rule/condition/AlarmConditionValue.java
  7. 11
      common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java

9
application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldQueueService.java

@ -25,6 +25,7 @@ import org.thingsboard.rule.engine.api.TimeseriesDeleteRequest;
import org.thingsboard.rule.engine.api.TimeseriesSaveRequest; import org.thingsboard.rule.engine.api.TimeseriesSaveRequest;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldLink; import org.thingsboard.server.common.data.cf.CalculatedFieldLink;
import org.thingsboard.server.common.data.id.CalculatedFieldId; import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
@ -45,9 +46,7 @@ import org.thingsboard.server.queue.TbQueueMsgMetadata;
import org.thingsboard.server.service.cf.ctx.state.CalculatedFieldCtx; import org.thingsboard.server.service.cf.ctx.state.CalculatedFieldCtx;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -73,10 +72,6 @@ public class DefaultCalculatedFieldQueueService implements CalculatedFieldQueueS
private final CalculatedFieldCache calculatedFieldCache; private final CalculatedFieldCache calculatedFieldCache;
private final TbClusterService clusterService; private final TbClusterService clusterService;
private static final Set<EntityType> supportedReferencedEntities = EnumSet.of(
EntityType.DEVICE, EntityType.ASSET, EntityType.CUSTOMER, EntityType.TENANT
);
@Override @Override
public void pushRequestToQueue(TimeseriesSaveRequest request, TimeseriesSaveResult result, FutureCallback<Void> callback) { public void pushRequestToQueue(TimeseriesSaveRequest request, TimeseriesSaveResult result, FutureCallback<Void> callback) {
var tenantId = request.getTenantId(); var tenantId = request.getTenantId();
@ -155,7 +150,7 @@ public class DefaultCalculatedFieldQueueService implements CalculatedFieldQueueS
} }
private boolean checkEntityForCalculatedFields(TenantId tenantId, EntityId entityId, Predicate<CalculatedFieldCtx> filter, Predicate<CalculatedFieldCtx> linkedEntityFilter, Predicate<CalculatedFieldCtx> dynamicSourceFilter) { private boolean checkEntityForCalculatedFields(TenantId tenantId, EntityId entityId, Predicate<CalculatedFieldCtx> filter, Predicate<CalculatedFieldCtx> linkedEntityFilter, Predicate<CalculatedFieldCtx> dynamicSourceFilter) {
if (!supportedReferencedEntities.contains(entityId.getEntityType())) { if (!CalculatedField.SUPPORTED_REFERENCED_ENTITIES.contains(entityId.getEntityType())) {
return false; return false;
} }

1
application/src/main/java/org/thingsboard/server/service/cf/OwnerService.java

@ -44,6 +44,7 @@ public class OwnerService {
return switch (entityId.getEntityType()) { return switch (entityId.getEntityType()) {
case DEVICE -> deviceService.findDeviceById(tenantId, (DeviceId) entityId).getOwnerId(); case DEVICE -> deviceService.findDeviceById(tenantId, (DeviceId) entityId).getOwnerId();
case ASSET -> assetService.findAssetById(tenantId, (AssetId) entityId).getOwnerId(); case ASSET -> assetService.findAssetById(tenantId, (AssetId) entityId).getOwnerId();
case CUSTOMER -> tenantId;
default -> throw new UnsupportedOperationException(); default -> throw new UnsupportedOperationException();
}; };
} }

7
application/src/main/java/org/thingsboard/server/service/entitiy/cf/DefaultTbCalculatedFieldService.java

@ -96,10 +96,11 @@ public class DefaultTbCalculatedFieldService extends AbstractTbEntityService imp
} }
private void checkEntityExistence(TenantId tenantId, EntityId entityId) { private void checkEntityExistence(TenantId tenantId, EntityId entityId) {
switch (entityId.getEntityType()) { if (CalculatedField.SUPPORTED_ENTITIES.contains(entityId.getEntityType())) {
case ASSET, DEVICE, ASSET_PROFILE, DEVICE_PROFILE -> Optional.ofNullable(entityService.fetchEntity(tenantId, entityId)) Optional.ofNullable(entityService.fetchEntity(tenantId, entityId))
.orElseThrow(() -> new IllegalArgumentException(entityId.getEntityType().getNormalName() + " with id [" + entityId.getId() + "] does not exist.")); .orElseThrow(() -> new IllegalArgumentException(entityId.getEntityType().getNormalName() + " with id [" + entityId.getId() + "] does not exist."));
default -> throw new IllegalArgumentException("Entity type '" + entityId.getEntityType() + "' does not support calculated fields."); } else {
throw new IllegalArgumentException("Entity type '" + entityId.getEntityType() + "' does not support calculated fields.");
} }
} }

1
application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java

@ -169,7 +169,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
addMainCallback(resultFuture, result -> { addMainCallback(resultFuture, result -> {
if (strategy.processCalculatedFields()) { if (strategy.processCalculatedFields()) {
// TODO: divide CFs and alarm rules processing
calculatedFieldQueueService.pushRequestToQueue(request, result, request.getCallback()); calculatedFieldQueueService.pushRequestToQueue(request, result, request.getCallback());
} else { } else {
request.getCallback().onSuccess(null); request.getCallback().onSuccess(null);

106
application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java

@ -17,7 +17,6 @@ package org.thingsboard.server.cf;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -42,6 +41,8 @@ import org.thingsboard.server.common.data.alarm.rule.condition.expression.Simple
import org.thingsboard.server.common.data.alarm.rule.condition.expression.TbelAlarmConditionExpression; import org.thingsboard.server.common.data.alarm.rule.condition.expression.TbelAlarmConditionExpression;
import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.NumericFilterPredicate; import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.NumericFilterPredicate;
import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.NumericFilterPredicate.NumericOperation; import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.NumericFilterPredicate.NumericOperation;
import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.StringFilterPredicate;
import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.StringFilterPredicate.StringOperation;
import org.thingsboard.server.common.data.cf.CalculatedField; import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldType; import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.AlarmCalculatedFieldConfiguration; import org.thingsboard.server.common.data.cf.configuration.AlarmCalculatedFieldConfiguration;
@ -53,7 +54,6 @@ import org.thingsboard.server.common.data.debug.DebugSettings;
import org.thingsboard.server.common.data.event.CalculatedFieldDebugEvent; import org.thingsboard.server.common.data.event.CalculatedFieldDebugEvent;
import org.thingsboard.server.common.data.event.EventType; import org.thingsboard.server.common.data.event.EventType;
import org.thingsboard.server.common.data.id.CalculatedFieldId; import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EventId; import org.thingsboard.server.common.data.id.EventId;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -81,14 +81,14 @@ public class AlarmRulesTest extends AbstractControllerTest {
private EventDao eventDao; private EventDao eventDao;
private Device device; private Device device;
private DeviceId deviceId; private EntityId originatorId;
private EventId latestEventId; private EventId latestEventId;
@Before @Before
public void beforeEach() throws Exception { public void beforeEach() throws Exception {
loginTenantAdmin(); loginTenantAdmin();
device = createDevice("Device A", "aaa"); device = createDevice("Device A", "aaa");
deviceId = device.getId(); originatorId = device.getId();
} }
@Test @Test
@ -106,33 +106,33 @@ public class AlarmRulesTest extends AbstractControllerTest {
); );
Condition clearRule = new Condition("return temperature <= 25;", null, null); Condition clearRule = new Condition("return temperature <= 25;", null, null);
CalculatedField calculatedField = createAlarmCf(deviceId, "High Temperature Alarm", CalculatedField calculatedField = createAlarmCf(originatorId, "High Temperature Alarm",
arguments, createRules, clearRule); arguments, createRules, clearRule);
assertThat(getCalculatedFields(deviceId, CalculatedFieldType.ALARM, new PageLink(1)).getData()) assertThat(getCalculatedFields(originatorId, CalculatedFieldType.ALARM, new PageLink(1)).getData())
.singleElement().isEqualTo(calculatedField); .singleElement().isEqualTo(calculatedField);
postTelemetry(deviceId, "{\"temperature\":50}"); postTelemetry(originatorId, "{\"temperature\":50}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCreated()).isTrue(); assertThat(alarmResult.isCreated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.MAJOR); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.MAJOR);
assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK); assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK);
}); });
postTelemetry(deviceId, "{\"temperature\":100}"); postTelemetry(originatorId, "{\"temperature\":100}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isSeverityUpdated()).isTrue(); assertThat(alarmResult.isSeverityUpdated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL);
assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK); assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK);
}); });
postTelemetry(deviceId, "{\"temperature\":101}"); postTelemetry(originatorId, "{\"temperature\":101}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isUpdated()).isTrue(); assertThat(alarmResult.isUpdated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL);
assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK); assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK);
}); });
postTelemetry(deviceId, "{\"temperature\":20}"); postTelemetry(originatorId, "{\"temperature\":20}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCleared()).isTrue(); assertThat(alarmResult.isCleared()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL);
@ -164,10 +164,10 @@ public class AlarmRulesTest extends AbstractControllerTest {
AlarmSeverity.CRITICAL, new Condition(simpleExpression, null, null) AlarmSeverity.CRITICAL, new Condition(simpleExpression, null, null)
); );
CalculatedField calculatedField = createAlarmCf(deviceId, "High Temperature Alarm", CalculatedField calculatedField = createAlarmCf(originatorId, "High Temperature Alarm",
arguments, createRules, null); arguments, createRules, null);
postTelemetry(deviceId, "{\"temperature\":100}"); postTelemetry(originatorId, "{\"temperature\":100}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCreated()).isTrue(); assertThat(alarmResult.isCreated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL);
@ -176,7 +176,7 @@ public class AlarmRulesTest extends AbstractControllerTest {
} }
/* /*
* todo: state restore (event count) * todo: test state restore (event count)
* */ * */
@Test @Test
public void testCreateAlarmForRepeatingCondition() throws Exception { public void testCreateAlarmForRepeatingCondition() throws Exception {
@ -194,14 +194,14 @@ public class AlarmRulesTest extends AbstractControllerTest {
AlarmSeverity.CRITICAL, new Condition("return temperature >= 50;", eventsCountCritical, null) AlarmSeverity.CRITICAL, new Condition("return temperature >= 50;", eventsCountCritical, null)
); );
CalculatedField calculatedField = createAlarmCf(deviceId, "High Temperature Alarm", CalculatedField calculatedField = createAlarmCf(originatorId, "High Temperature Alarm",
arguments, createRules, null); arguments, createRules, null);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
postTelemetry(deviceId, "{\"temperature\":50}"); postTelemetry(originatorId, "{\"temperature\":50}");
Thread.sleep(10); Thread.sleep(10);
} }
assertThat(getLatestAlarmResult(calculatedField.getId())).isNull(); assertThat(getLatestAlarmResult(calculatedField.getId())).isNull();
postTelemetry(deviceId, "{\"temperature\":50}"); postTelemetry(originatorId, "{\"temperature\":50}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCreated()).isTrue(); assertThat(alarmResult.isCreated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.MAJOR); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.MAJOR);
@ -210,7 +210,7 @@ public class AlarmRulesTest extends AbstractControllerTest {
}); });
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
postTelemetry(deviceId, "{\"temperature\":50}"); postTelemetry(originatorId, "{\"temperature\":50}");
Thread.sleep(10); Thread.sleep(10);
} }
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
@ -236,9 +236,9 @@ public class AlarmRulesTest extends AbstractControllerTest {
); );
Condition clearRule = new Condition("return powerConsumption < 3000;", null, createDurationMs); Condition clearRule = new Condition("return powerConsumption < 3000;", null, createDurationMs);
CalculatedField calculatedField = createAlarmCf(deviceId, "High power consumption during 5 seconds", CalculatedField calculatedField = createAlarmCf(originatorId, "High power consumption during 5 seconds",
arguments, createRules, clearRule); arguments, createRules, clearRule);
postTelemetry(deviceId, "{\"powerConsumption\":3500}"); postTelemetry(originatorId, "{\"powerConsumption\":3500}");
Thread.sleep(createDurationMs - 2000); Thread.sleep(createDurationMs - 2000);
assertThat(getLatestAlarmResult(calculatedField.getId())).isNull(); assertThat(getLatestAlarmResult(calculatedField.getId())).isNull();
@ -272,11 +272,11 @@ public class AlarmRulesTest extends AbstractControllerTest {
device.setCustomerId(customerId); device.setCustomerId(customerId);
device = doPost("/api/device", device, Device.class); device = doPost("/api/device", device, Device.class);
CalculatedField calculatedField = createAlarmCf(deviceId, "High Temperature Alarm", CalculatedField calculatedField = createAlarmCf(originatorId, "High Temperature Alarm",
arguments, createRules, null); arguments, createRules, null);
postAttributes(customerId, AttributeScope.SERVER_SCOPE, "{\"temperatureThreshold\":50}"); postAttributes(customerId, AttributeScope.SERVER_SCOPE, "{\"temperatureThreshold\":50}");
postTelemetry(deviceId, "{\"temperature\":51}"); postTelemetry(originatorId, "{\"temperature\":51}");
checkAlarmResult(calculatedField, alarmResult -> { checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCreated()).isTrue(); assertThat(alarmResult.isCreated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL);
@ -284,6 +284,53 @@ public class AlarmRulesTest extends AbstractControllerTest {
}); });
} }
@Test
public void testCreateAndClearAlarm_customerAlarmRule_simpleExpression() throws Exception {
Argument locationArgument = new Argument();
locationArgument.setRefEntityKey(new ReferencedEntityKey("location", ArgumentType.ATTRIBUTE, AttributeScope.SERVER_SCOPE));
locationArgument.setDefaultValue("unknown");
Argument locationFilterArgument = new Argument();
locationFilterArgument.setRefEntityKey(new ReferencedEntityKey("locationFilter", ArgumentType.ATTRIBUTE, AttributeScope.SERVER_SCOPE));
locationFilterArgument.setRefDynamicSourceConfiguration(new CurrentOwnerDynamicSourceConfiguration());
locationFilterArgument.setDefaultValue("None");
loginSysAdmin();
postAttributes(tenantId, AttributeScope.SERVER_SCOPE, "{\"locationFilter\":\"Kyiv\"}");
loginTenantAdmin();
Map<String, Argument> arguments = Map.of(
"location", locationArgument,
"locationFilter", locationFilterArgument
);
originatorId = customerId;
Map<AlarmSeverity, Condition> createRules = Map.of(
AlarmSeverity.INDETERMINATE, new Condition(createSimpleExpression(
"location", StringOperation.CONTAINS, new AlarmConditionValue<>(null, "locationFilter")
), null, null)
);
Condition clearRule = new Condition(createSimpleExpression(
"location", StringOperation.NOT_CONTAINS, new AlarmConditionValue<>(null, "locationFilter")
), null, null);
CalculatedField calculatedField = createAlarmCf(customerId, "New resident",
arguments, createRules, clearRule);
postAttributes(customerId, AttributeScope.SERVER_SCOPE, "{\"location\":\"Ukraine, Kyiv\"}");
checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCreated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.INDETERMINATE);
assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK);
});
postAttributes(customerId, AttributeScope.SERVER_SCOPE, "{\"location\":\"Ukraine, Lviv\"}");
checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCleared()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.INDETERMINATE);
assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.CLEARED_UNACK);
});
}
private void checkAlarmResult(CalculatedField calculatedField, Consumer<TbAlarmResult> assertion) { private void checkAlarmResult(CalculatedField calculatedField, Consumer<TbAlarmResult> assertion) {
await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> {
TbAlarmResult alarmResult = getLatestAlarmResult(calculatedField.getId()); TbAlarmResult alarmResult = getLatestAlarmResult(calculatedField.getId());
@ -291,7 +338,7 @@ public class AlarmRulesTest extends AbstractControllerTest {
assertion.accept(alarmResult); assertion.accept(alarmResult);
Alarm alarm = alarmResult.getAlarm(); Alarm alarm = alarmResult.getAlarm();
assertThat(alarm.getOriginator()).isEqualTo(deviceId); assertThat(alarm.getOriginator()).isEqualTo(originatorId);
assertThat(alarm.getType()).isEqualTo(calculatedField.getName()); assertThat(alarm.getType()).isEqualTo(calculatedField.getName());
}); });
} }
@ -303,8 +350,7 @@ public class AlarmRulesTest extends AbstractControllerTest {
} }
CalculatedFieldDebugEvent debugEvent = debugEvents.get(0); CalculatedFieldDebugEvent debugEvent = debugEvents.get(0);
if (debugEvent.getError() != null) { if (debugEvent.getError() != null) {
System.err.println("CF error: " + debugEvent.getError()); throw new RuntimeException(debugEvent.getError());
Assertions.fail();
} }
if (debugEvent.getId().equals(latestEventId)) { if (debugEvent.getId().equals(latestEventId)) {
return null; return null;
@ -381,6 +427,18 @@ public class AlarmRulesTest extends AbstractControllerTest {
return rule; return rule;
} }
private SimpleAlarmConditionExpression createSimpleExpression(String argument, StringOperation stringOperation, AlarmConditionValue<String> conditionValue) {
SimpleAlarmConditionExpression simpleExpression = new SimpleAlarmConditionExpression();
AlarmConditionFilter filter = new AlarmConditionFilter();
filter.setArgument(argument);
StringFilterPredicate predicate = new StringFilterPredicate();
predicate.setOperation(stringOperation);
predicate.setValue(conditionValue);
filter.setPredicate(predicate);
simpleExpression.setFilters(List.of(filter));
return simpleExpression;
}
private List<CalculatedFieldDebugEvent> getDebugEvents(CalculatedFieldId calculatedFieldId, int limit) { private List<CalculatedFieldDebugEvent> getDebugEvents(CalculatedFieldId calculatedFieldId, int limit) {
return eventDao.findLatestEvents(tenantId.getId(), calculatedFieldId.getId(), EventType.DEBUG_CALCULATED_FIELD, limit).stream() return eventDao.findLatestEvents(tenantId.getId(), calculatedFieldId.getId(), EventType.DEBUG_CALCULATED_FIELD, limit).stream()
.map(e -> (CalculatedFieldDebugEvent) e).toList(); .map(e -> (CalculatedFieldDebugEvent) e).toList();

4
common/data/src/main/java/org/thingsboard/server/common/data/alarm/rule/condition/AlarmConditionValue.java

@ -15,9 +15,13 @@
*/ */
package org.thingsboard.server.common.data.alarm.rule.condition; package org.thingsboard.server.common.data.alarm.rule.condition;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
@Data @Data
@AllArgsConstructor
@NoArgsConstructor
public class AlarmConditionValue<T> { public class AlarmConditionValue<T> {
private T staticValue; private T staticValue;

11
common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java

@ -25,6 +25,7 @@ import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasDebugSettings; import org.thingsboard.server.common.data.HasDebugSettings;
import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.HasTenantId;
@ -39,6 +40,9 @@ import org.thingsboard.server.common.data.validation.Length;
import org.thingsboard.server.common.data.validation.NoXss; import org.thingsboard.server.common.data.validation.NoXss;
import java.io.Serial; import java.io.Serial;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
@Schema @Schema
@Data @Data
@ -48,6 +52,13 @@ public class CalculatedField extends BaseData<CalculatedFieldId> implements HasN
@Serial @Serial
private static final long serialVersionUID = 4491966747773381420L; private static final long serialVersionUID = 4491966747773381420L;
public static final Set<EntityType> SUPPORTED_ENTITIES = Collections.unmodifiableSet(EnumSet.of(
EntityType.DEVICE, EntityType.ASSET, EntityType.DEVICE_PROFILE, EntityType.ASSET_PROFILE, EntityType.CUSTOMER
));
public static final Set<EntityType> SUPPORTED_REFERENCED_ENTITIES = Collections.unmodifiableSet(EnumSet.of(
EntityType.DEVICE, EntityType.ASSET, EntityType.CUSTOMER, EntityType.TENANT
));
private TenantId tenantId; private TenantId tenantId;
private EntityId entityId; private EntityId entityId;

Loading…
Cancel
Save