@ -51,6 +51,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.EntitySearchDirection ;
import org.thingsboard.server.common.data.relation.RelationPathLevel ;
import org.thingsboard.server.common.data.relation.RelationTypeGroup ;
import org.thingsboard.server.common.data.rule.RuleChain ;
import org.thingsboard.server.common.data.security.Authority ;
import org.thingsboard.server.controller.AbstractControllerTest ;
import org.thingsboard.server.dao.service.DaoSqlTest ;
@ -87,6 +88,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
updateDefaultTenantProfileConfig ( tenantProfileConfig - > {
tenantProfileConfig . setMinAllowedDeduplicationIntervalInSecForCF ( 1 ) ;
tenantProfileConfig . setMinAllowedScheduledUpdateIntervalInSecForCF ( 1 ) ;
} ) ;
Tenant tenant = new Tenant ( ) ;
@ -177,7 +179,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
Asset asset2 = createAsset ( "Asset 2" , assetProfile . getId ( ) ) ;
await ( ) . alias ( "add entity to profile with no related entities and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "add entity to profile with no related entities and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ObjectNode occupancy = getLatestTelemetry ( asset2 . getId ( ) , "freeSpaces" , "occupiedSpaces" , "totalSpaces" ) ;
@ -190,7 +192,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
createEntityRelation ( asset2 . getId ( ) , device3 . getId ( ) , "Contains" ) ;
createEntityRelation ( asset2 . getId ( ) , device4 . getId ( ) , "Contains" ) ;
await ( ) . alias ( "create relations and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create relations and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
@ -202,7 +204,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
postTelemetry ( device3 . getId ( ) , "{\"occupied\":false}" ) ;
await ( ) . alias ( "update telemetry and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "update telemetry and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
@ -224,7 +226,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
createOccupancyCF ( assetProfile . getId ( ) ) ;
await ( ) . alias ( "create CF and perform initial aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create CF and perform initial aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
@ -246,7 +248,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
postTelemetry ( device3 . getId ( ) , "{\"occupied\":true}" ) ;
await ( ) . alias ( "change profile and no aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "change profile and no aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
@ -268,7 +270,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
createOccupancyCF ( asset2 . getId ( ) ) ;
await ( ) . alias ( "create CF and perform aggregation with default values" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create CF and perform aggregation with default values" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
@ -299,6 +301,45 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
} ) ;
}
@Test
public void testCreateCfAndRelationToRuleChain_checkAggregation ( ) throws Exception {
Asset asset2 = createAsset ( "Asset 2" , assetProfile . getId ( ) ) ;
Device device3 = createDevice ( "Device 3" , "1234567890333" ) ;
postTelemetry ( device3 . getId ( ) , "{\"occupied\":true}" ) ;
RuleChain ruleChain = new RuleChain ( ) ;
ruleChain . setName ( "RuleChain" ) ;
ruleChain = doPost ( "/api/ruleChain" , ruleChain , RuleChain . class ) ;
postTelemetry ( ruleChain . getId ( ) , "{\"occupied\":true}" ) ;
createEntityRelation ( asset2 . getId ( ) , device3 . getId ( ) , "Contains" ) ;
createEntityRelation ( asset2 . getId ( ) , ruleChain . getId ( ) , "Contains" ) ;
createOccupancyCF ( asset2 . getId ( ) ) ;
await ( ) . alias ( "create CF and perform initial aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
"freeSpaces" , "0" ,
"occupiedSpaces" , "1" ,
"totalSpaces" , "1"
) ) ;
} ) ;
postTelemetry ( ruleChain . getId ( ) , "{\"occupied\":true}" ) ;
await ( ) . alias ( "update telemetry on rule chain and no aggregation performed" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
"freeSpaces" , "0" ,
"occupiedSpaces" , "1" ,
"totalSpaces" , "1"
) ) ;
} ) ;
}
@Test
public void testDeleteCf_checkNoAggregation ( ) throws Exception {
CalculatedField cf = createOccupancyCF ( asset . getId ( ) ) ;
@ -309,7 +350,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
postTelemetry ( device1 . getId ( ) , "{\"occupied\":false}" ) ;
await ( ) . alias ( "delete cf and update telemetry and no aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "delete cf and update telemetry and no aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
@ -364,7 +405,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
createOccupancyCF ( asset2 . getId ( ) ) ;
await ( ) . alias ( "create CF and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create CF and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
@ -402,7 +443,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
createOccupancyCFWithAttr ( asset2 . getId ( ) ) ;
await ( ) . alias ( "create CF and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create CF and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset2 . getId ( ) , Map . of (
@ -437,7 +478,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
createEntityRelation ( asset . getId ( ) , device3 . getId ( ) , "Contains" ) ;
await ( ) . alias ( "create relation and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create relation and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
@ -455,7 +496,25 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
deleteEntityRelation ( new EntityRelation ( asset . getId ( ) , device1 . getId ( ) , "Contains" , RelationTypeGroup . COMMON ) ) ;
await ( ) . alias ( "create relation and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create relation and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
"freeSpaces" , "1" ,
"occupiedSpaces" , "0" ,
"totalSpaces" , "1"
) ) ;
} ) ;
}
@Test
public void testDeleteEntityByRelation_checkAggregation ( ) throws Exception {
createOccupancyCF ( asset . getId ( ) ) ;
checkInitialCalculation ( ) ;
doDelete ( "/api/device/" + device1 . getId ( ) ) . andExpect ( status ( ) . isOk ( ) ) ;
await ( ) . alias ( "create relation and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
@ -479,7 +538,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
configuration . setRelation ( new RelationPathLevel ( EntitySearchDirection . FROM , "Has" ) ) ;
saveCalculatedField ( cf ) ;
await ( ) . alias ( "update relation path and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "update relation path and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
@ -505,7 +564,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
configuration . setArguments ( Map . of ( "oc" , argument ) ) ;
saveCalculatedField ( cf ) ;
await ( ) . alias ( "update arguments and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "update arguments and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of (
@ -560,7 +619,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
postTelemetry ( device2 . getId ( ) , "{\"temperature\":19.6}" ) ;
CalculatedField cf = createAvgTemperatureCF ( asset . getId ( ) ) ;
await ( ) . alias ( "create avg temp cf and perform initial aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create avg temp cf and perform initial aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of ( "avgTemperature" , "24" ) ) ;
@ -573,7 +632,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
configuration . setOutput ( output ) ;
saveCalculatedField ( cf ) ;
await ( ) . alias ( "update output and perform aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "update output and perform aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ArrayNode avgTemperature = getServerAttributes ( asset . getId ( ) , "avgTemperature" ) ;
@ -589,7 +648,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
postTelemetry ( device2 . getId ( ) , "{\"temperature\":19.6}" ) ;
CalculatedField cf = createAvgTemperatureCF ( asset . getId ( ) ) ;
await ( ) . alias ( "create avg temp cf and perform initial aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create avg temp cf and perform initial aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of ( "avgTemperature" , "24" ) ) ;
@ -607,7 +666,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
postTelemetry ( device2 . getId ( ) , "{\"temperature\":32.1}" ) ;
await ( ) . alias ( "update telemetry and perform aggregation" ) . atMost ( 2 * deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "update telemetry and perform aggregation" ) . atMost ( 2 * deduplicationInterval + 10 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
verifyTelemetry ( asset . getId ( ) , Map . of ( "avgTemperature" , "28" ) ) ;
@ -615,7 +674,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
}
private void checkInitialCalculation ( ) {
await ( ) . alias ( "create CF and perform initial aggregation" ) . atMost ( deduplicationInterval , TimeUnit . SECONDS )
await ( ) . alias ( "create CF and perform initial aggregation" ) . atMost ( deduplicationInterval * 2 , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( this : : checkInitialCalculationValues ) ;
}
@ -743,6 +802,7 @@ public class RelatedEntitiesAggregationCalculatedFieldTest extends AbstractContr
configuration . setRelation ( relation ) ;
configuration . setArguments ( inputs ) ;
configuration . setDeduplicationIntervalInSec ( deduplicationInterval ) ;
configuration . setScheduledUpdateInterval ( 10 ) ;
configuration . setMetrics ( metrics ) ;
configuration . setOutput ( output ) ;