@ -799,23 +799,22 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
doPost ( "/api/calculatedField" , cf , CalculatedField . class ) ;
// --- Assert initial evaluation (ENTERED / OUTSIDE) ---
// --- Assert initial evaluation ---
await ( ) . alias ( "initial geofencing evaluation" )
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ArrayNode attrs = getServerAttributes ( device . getId ( ) ,
"allowedZonesEvent" , "allowedZonesStatus" , "restrictedZonesStatus" , "restrictedZonesEvent" ) ;
// --- no restrictedZonesEvent as no transition happened yet
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 3 ) ;
// --- no transition events as no transitions happened yet
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 2 ) ;
Map < String , String > m = kv ( attrs ) ;
assertThat ( m ) . containsEntry ( "allowedZonesEvent" , "ENTERED" )
. containsEntry ( "allowedZonesStatus" , "INSIDE" )
assertThat ( m ) . containsEntry ( "allowedZonesStatus" , "INSIDE" )
. containsEntry ( "restrictedZonesStatus" , "OUTSIDE" ) ;
} ) ;
// --- delete attributes reported in previous evaluation
doDelete ( "/api/plugins/telemetry/DEVICE/" + device . getUuidId ( ) + "/SERVER_SCOPE?keys=allowedZonesEvent,allowedZones Status,restrictedZonesStatus" , String . class ) ;
doDelete ( "/api/plugins/telemetry/DEVICE/" + device . getUuidId ( ) + "/SERVER_SCOPE?keys=allowedZonesStatus,restrictedZonesStatus" , String . class ) ;
// --- Update restrictedZone by 'restrictedZone' attribute update
doPost ( "/api/plugins/telemetry/DEVICE/" + device . getUuidId ( ) + "/attributes/" + DataConstants . SERVER_SCOPE ,
@ -909,17 +908,16 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
doPost ( "/api/calculatedField" , cf , CalculatedField . class ) ;
// --- Assert initial evaluation (ENTERED / OUTSIDE) ---
// --- Assert initial evaluation ---
await ( ) . alias ( "initial geofencing evaluation" )
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ArrayNode attrs = getServerAttributes ( device . getId ( ) ,
"allowedZonesEvent" , "allowedZonesStatus" , "restrictedZonesStatus" ) ;
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 3 ) ;
"allowedZonesEvent" , "allowedZonesStatus" , "restrictedZonesStatus" , "restrictedZonesEvent" ) ;
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 2 ) ;
Map < String , String > m = kv ( attrs ) ;
assertThat ( m ) . containsEntry ( "allowedZonesEvent" , "ENTERED" )
. containsEntry ( "allowedZonesStatus" , "INSIDE" )
assertThat ( m ) . containsEntry ( "allowedZonesStatus" , "INSIDE" )
. containsEntry ( "restrictedZonesStatus" , "OUTSIDE" ) ;
} ) ;
@ -1014,16 +1012,15 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
var geofencingConfiguration = ( GeofencingCalculatedFieldConfiguration ) configuration ;
assertThat ( geofencingConfiguration . isScheduledUpdateEnabled ( ) ) . isTrue ( ) ;
// --- Assert initial evaluation (ENTERED) ---
// --- Assert initial evaluation ---
await ( ) . alias ( "initial geofencing evaluation" )
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ArrayNode attrs = getServerAttributes ( device . getId ( ) , "allowedZonesEvent" , "allowedZonesStatus" ) ;
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 2 ) ;
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 1 ) ;
Map < String , String > m = kv ( attrs ) ;
assertThat ( m ) . containsEntry ( "allowedZonesEvent" , "ENTERED" )
. containsEntry ( "allowedZonesStatus" , "INSIDE" ) ;
assertThat ( m ) . containsEntry ( "allowedZonesStatus" , "INSIDE" ) ;
} ) ;
// --- Move device OUTSIDE Zone A (expect LEFT) ---
@ -1057,11 +1054,11 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
awaitForCalculatedFieldEntityMessageProcessorToRegisterCfStateAsReadyToRefreshDynamicArguments ( device . getId ( ) , savedCalculatedField . getId ( ) , minAllowedScheduledUpdateIntervalInSecForCF ) ;
// --- Same coordinates as before, but now we expect ENTERED since a new zone is registered ---
// --- Same coordinates as before, but now we expect INSIDE group status since a new zone is registered ---
doPost ( "/api/plugins/telemetry/DEVICE/" + device . getUuidId ( ) + "/timeseries/unusedScope" ,
JacksonUtil . toJsonNode ( "{\"latitude\":50.4760,\"longitude\":30.5110}" ) ) . andExpect ( status ( ) . isOk ( ) ) ;
// --- Assert dynamic refresh picks up new relation and flips event back to ENTERED on the next telemetry update ---
// --- Assert dynamic refresh picks up a new relation and flips status back to INSIDE on the next telemetry update ---
await ( ) . alias ( "dynamic refresh rebinds allowedZones" )
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( 1 , TimeUnit . SECONDS )
@ -1069,7 +1066,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
ArrayNode attrs = getServerAttributes ( device . getId ( ) , "allowedZonesEvent" , "allowedZonesStatus" ) ;
assertThat ( attrs ) . isNotNull ( ) . isNotEmpty ( ) . hasSize ( 2 ) ;
Map < String , String > m = kv ( attrs ) ;
assertThat ( m ) . containsEntry ( "allowedZonesEvent" , "ENTERED" )
assertThat ( m ) . containsEntry ( "allowedZonesEvent" , "LEFT" ) // attribute from previous eval with outdated ts.
. containsEntry ( "allowedZonesStatus" , "INSIDE" ) ;
} ) ;
}
@ -1089,7 +1086,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
// Telemetry on device
doPost ( "/api/plugins/telemetry/DEVICE/" + device . getUuidId ( ) + "/timeseries/unusedScope" ,
JacksonUtil . toJsonNode ( "{\"temperature\":12.5}" ) ) . andExpect ( status ( ) . isOk ( ) ) ;
JacksonUtil . toJsonNode ( "{\"temperature\":12.5, \"humidity\":85 }" ) ) . andExpect ( status ( ) . isOk ( ) ) ;
// --- Build CF: PROPAGATION with expression ---
CalculatedField cf = new CalculatedField ( ) ;
@ -1102,11 +1099,14 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
cfg . setRelation ( new RelationPathLevel ( EntitySearchDirection . TO , EntityRelation . CONTAINS_TYPE ) ) ;
cfg . setApplyExpressionToResolvedArguments ( true ) ;
Argument arg = new Argument ( ) ;
arg . setRefEntityKey ( new ReferencedEntityKey ( "temperature" , ArgumentType . TS_LATEST , null ) ) ;
cfg . setArguments ( Map . of ( "t" , arg ) ) ;
Argument arg1 = new Argument ( ) ;
arg1 . setRefEntityKey ( new ReferencedEntityKey ( "temperature" , ArgumentType . TS_LATEST , null ) ) ;
cfg . setExpression ( "{\"testResult\": t * 2}" ) ;
Argument arg2 = new Argument ( ) ;
arg2 . setRefEntityKey ( new ReferencedEntityKey ( "humidity" , ArgumentType . TS_LATEST , null ) ) ;
cfg . setArguments ( Map . of ( "t" , arg1 , "h" , arg2 ) ) ;
cfg . setExpression ( "return { testResult: (t + h) / 2};" ) ;
AttributesOutput output = new AttributesOutput ( ) ;
output . setScope ( AttributeScope . SERVER_SCOPE ) ;
@ -1125,8 +1125,8 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
ArrayNode attrs2 = getServerAttributes ( asset2 . getId ( ) , "testResult" ) ;
assertThat ( attrs1 ) . isNotNull ( ) ;
assertThat ( attrs2 ) . isNotNull ( ) ;
assertThat ( attrs1 . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 25 . 0 ) ;
assertThat ( attrs2 . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 25 . 0 ) ;
assertThat ( attrs1 . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 48 . 75 ) ;
assertThat ( attrs2 . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 48 . 75 ) ;
} ) ;
String deleteUrl = String . format ( "/api/v2/relation?fromId=%s&fromType=%s&relationType=%s&toId=%s&toType=%s" ,
@ -1148,7 +1148,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
ArrayNode attrs2 = getServerAttributes ( asset2 . getId ( ) , "testResult" ) ;
assertThat ( attrs1 ) . isNullOrEmpty ( ) ;
assertThat ( attrs2 ) . isNotNull ( ) ;
assertThat ( attrs2 . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 50 ) ;
assertThat ( attrs2 . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 55 ) ;
} ) ;
}
@ -1167,7 +1167,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
// Telemetry on device
long ts = System . currentTimeMillis ( ) - 300000L ;
postTelemetry ( device . getId ( ) , String . format ( "{\"ts\": %s, \"values\": {\"temperature\":12.5}}" , ts ) ) ;
postTelemetry ( device . getId ( ) , String . format ( "{\"ts\": %s, \"values\": {\"temperature\":12.5, \"humidity\":85 }}" , ts ) ) ;
// --- Build CF: PROPAGATION without expression ---
CalculatedField cf = new CalculatedField ( ) ;
@ -1180,9 +1180,12 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
cfg . setRelation ( new RelationPathLevel ( EntitySearchDirection . TO , EntityRelation . CONTAINS_TYPE ) ) ;
cfg . setApplyExpressionToResolvedArguments ( false ) ; // arguments-only mode
Argument arg = new Argument ( ) ;
arg . setRefEntityKey ( new ReferencedEntityKey ( "temperature" , ArgumentType . TS_LATEST , null ) ) ;
cfg . setArguments ( Map . of ( "temperatureComputed" , arg ) ) ;
Argument arg1 = new Argument ( ) ;
arg1 . setRefEntityKey ( new ReferencedEntityKey ( "temperature" , ArgumentType . TS_LATEST , null ) ) ;
Argument arg2 = new Argument ( ) ;
arg2 . setRefEntityKey ( new ReferencedEntityKey ( "humidity" , ArgumentType . TS_LATEST , null ) ) ;
cfg . setArguments ( Map . of ( "temperatureComputed" , arg1 , "humidityComputed" , arg2 ) ) ;
TimeSeriesOutput output = new TimeSeriesOutput ( ) ;
output . setStrategy ( new TimeSeriesImmediateOutputStrategy ( 0 , true , true , true , true ) ) ;
@ -1197,14 +1200,18 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ObjectNode telemetry1 = getLatestTelemetry ( asset1 . getId ( ) , "temperatureComputed" ) ;
ObjectNode telemetry2 = getLatestTelemetry ( asset2 . getId ( ) , "temperatureComputed" ) ;
ObjectNode telemetry1 = getLatestTelemetry ( asset1 . getId ( ) , "temperatureComputed,humidityComputed " ) ;
ObjectNode telemetry2 = getLatestTelemetry ( asset2 . getId ( ) , "temperatureComputed,humidityComputed " ) ;
assertThat ( telemetry1 ) . isNotNull ( ) ;
assertThat ( telemetry2 ) . isNotNull ( ) ;
assertThat ( telemetry1 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( ts ) ) ;
assertThat ( telemetry1 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 12 . 5 ) ;
assertThat ( telemetry1 . get ( "humidityComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( ts ) ) ;
assertThat ( telemetry1 . get ( "humidityComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 85 ) ;
assertThat ( telemetry2 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( ts ) ) ;
assertThat ( telemetry2 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 12 . 5 ) ;
assertThat ( telemetry2 . get ( "humidityComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( ts ) ) ;
assertThat ( telemetry2 . get ( "humidityComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 85 ) ;
} ) ;
String deleteUrl = String . format ( "/api/v2/relation?fromId=%s&fromType=%s&relationType=%s&toId=%s&toType=%s" ,
@ -1212,10 +1219,10 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
EntityRelation . CONTAINS_TYPE , device . getId ( ) . getId ( ) , EntityType . DEVICE
) ;
doDelete ( deleteUrl ) . andExpect ( status ( ) . isOk ( ) ) ;
doDelete ( "/api/plugins/telemetry/ASSET/" + asset1 . getId ( ) + "/timeseries/delete?keys=temperatureComputed&deleteAllDataForKeys=true" ) . andExpect ( status ( ) . isOk ( ) ) ;
doDelete ( "/api/plugins/telemetry/ASSET/" + asset1 . getId ( ) + "/timeseries/delete?keys=temperatureComputed,humidityComputed &deleteAllDataForKeys=true" ) . andExpect ( status ( ) . isOk ( ) ) ;
// Update telemetry on device
long newTs = System . currentTimeMillis ( ) - 300000L ;
// Update telemetry on the device
long newTs = ts + 300000L ;
postTelemetry ( device . getId ( ) , String . format ( "{\"ts\": %s, \"values\": {\"temperature\":25}}" , newTs ) ) ;
// --- Assert propagated calculation (arguments-only mode after update) ---
@ -1223,14 +1230,37 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ObjectNode telemetry1 = getLatestTelemetry ( asset1 . getId ( ) , "temperatureComputed" ) ;
ObjectNode telemetry2 = getLatestTelemetry ( asset2 . getId ( ) , "temperatureComputed" ) ;
ObjectNode telemetry1 = getLatestTelemetry ( asset1 . getId ( ) , "temperatureComputed,humidityComputed " ) ;
ObjectNode telemetry2 = getLatestTelemetry ( asset2 . getId ( ) , "temperatureComputed,humidityComputed " ) ;
assertThat ( telemetry1 ) . isNotNull ( ) ;
assertThat ( telemetry2 ) . isNotNull ( ) ;
assertThat ( telemetry1 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "value" ) ) . isEqualTo ( NullNode . instance ) ;
assertThat ( telemetry1 . get ( "humidityComputed" ) . get ( 0 ) . get ( "value" ) ) . isEqualTo ( NullNode . instance ) ;
assertThat ( telemetry2 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( newTs ) ) ;
assertThat ( telemetry2 . get ( "temperatureComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 25 ) ;
// TS for humidity is not updated -> expected
assertThat ( telemetry2 . get ( "humidityComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( ts ) ) ;
assertThat ( telemetry2 . get ( "humidityComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 85 ) ;
} ) ;
Asset asset3 = createAsset ( "Propagated Asset 3" , null ) ;
EntityRelation rel3 = new EntityRelation ( asset3 . getId ( ) , device . getId ( ) , EntityRelation . CONTAINS_TYPE ) ;
doPost ( "/api/relation" , rel3 ) . andExpect ( status ( ) . isOk ( ) ) ;
// --- Assert propagated calculation (arguments-only mode after update) ---
await ( ) . alias ( "propagation args-only to new entity after relation creation" )
. atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ObjectNode telemetry = getLatestTelemetry ( asset3 . getId ( ) , "temperatureComputed,humidityComputed" ) ;
assertThat ( telemetry ) . isNotNull ( ) ;
assertThat ( telemetry . get ( "temperatureComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( newTs ) ) ;
assertThat ( telemetry . get ( "temperatureComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 25 ) ;
assertThat ( telemetry . get ( "humidityComputed" ) . get ( 0 ) . get ( "ts" ) . asText ( ) ) . isEqualTo ( Long . toString ( newTs ) ) ;
assertThat ( telemetry . get ( "humidityComputed" ) . get ( 0 ) . get ( "value" ) . asDouble ( ) ) . isEqualTo ( 85 ) ;
} ) ;
}
@Test
@ -1282,6 +1312,83 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
} ) ;
}
@Test
public void testCalculatedFieldWhenBatchOfTelemetrySent ( ) throws Exception {
Device testDevice = createDevice ( "Test device" , "1234567890" ) ;
long now = System . currentTimeMillis ( ) ;
doPost ( "/api/plugins/telemetry/DEVICE/" + testDevice . getUuidId ( ) + "/timeseries/" + DataConstants . SERVER_SCOPE , JacksonUtil . toJsonNode ( String . format ( "{\"ts\": %s, \"values\": {\"a\":5, \"b\":10}}" , now - TimeUnit . MINUTES . toMillis ( 3 ) ) ) ) ;
doPost ( "/api/plugins/telemetry/DEVICE/" + testDevice . getUuidId ( ) + "/timeseries/" + DataConstants . SERVER_SCOPE , JacksonUtil . toJsonNode ( String . format ( "{\"ts\": %s, \"values\": {\"b\":20}}" , now - TimeUnit . MINUTES . toMillis ( 1 ) ) ) ) ;
CalculatedField calculatedField = new CalculatedField ( ) ;
calculatedField . setEntityId ( testDevice . getId ( ) ) ;
calculatedField . setType ( CalculatedFieldType . SCRIPT ) ;
calculatedField . setName ( "Script CF" ) ;
calculatedField . setDebugSettings ( DebugSettings . all ( ) ) ;
ScriptCalculatedFieldConfiguration config = new ScriptCalculatedFieldConfiguration ( ) ;
ReferencedEntityKey refEntityKeyA = new ReferencedEntityKey ( "a" , ArgumentType . TS_LATEST , null ) ;
Argument argumentA = new Argument ( ) ;
argumentA . setRefEntityKey ( refEntityKeyA ) ;
Argument argumentB = new Argument ( ) ;
ReferencedEntityKey refEntityKeyB = new ReferencedEntityKey ( "b" , ArgumentType . TS_ROLLING , null ) ;
argumentB . setTimeWindow ( TimeUnit . MINUTES . toMillis ( 10 ) ) ;
argumentB . setLimit ( 1000 ) ;
argumentB . setRefEntityKey ( refEntityKeyB ) ;
config . setArguments ( Map . of ( "a" , argumentA , "b" , argumentB ) ) ;
config . setExpression ( "" "
return {
"latestA" : a ,
"avgB" : b . avg
} ;
"" " ) ;
config . setOutput ( new TimeSeriesOutput ( ) ) ;
calculatedField . setConfiguration ( config ) ;
doPost ( "/api/calculatedField" , calculatedField , CalculatedField . class ) ;
await ( ) . alias ( "create CF -> perform initial calculation" ) . atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ObjectNode result = getLatestTelemetry ( testDevice . getId ( ) , "latestA" , "avgB" ) ;
assertThat ( result ) . isNotNull ( ) ;
assertThat ( result . get ( "latestA" ) . get ( 0 ) . get ( "value" ) . asText ( ) ) . isEqualTo ( "5" ) ;
assertThat ( result . get ( "avgB" ) . get ( 0 ) . get ( "value" ) . asText ( ) ) . isEqualTo ( "15.0" ) ;
} ) ;
doPost ( "/api/plugins/telemetry/DEVICE/" + testDevice . getUuidId ( ) + "/timeseries/" + DataConstants . SERVER_SCOPE , JacksonUtil . toJsonNode ( String . format ( "" "
[ {
"ts" : % s ,
"values" : {
"a" : 6 ,
"b" : 100
}
} , {
"ts" : % s ,
"values" : {
"a" : 7 ,
"b" : 200
}
} , {
"ts" : % s ,
"values" : {
"a" : 8 ,
"b" : 300
}
} ] "" " , now - TimeUnit . MINUTES . toMillis ( 2 ) , now , now - TimeUnit . MINUTES . toMillis ( 5 ) ) ) ) ;
await ( ) . alias ( "update telemetry -> recalculate state" ) . atMost ( TIMEOUT , TimeUnit . SECONDS )
. pollInterval ( POLL_INTERVAL , TimeUnit . SECONDS )
. untilAsserted ( ( ) - > {
ObjectNode result = getLatestTelemetry ( testDevice . getId ( ) , "latestA" , "avgB" ) ;
assertThat ( result ) . isNotNull ( ) ;
assertThat ( result . get ( "latestA" ) . get ( 0 ) . get ( "value" ) . asText ( ) ) . isEqualTo ( "7" ) ;
assertThat ( result . get ( "avgB" ) . get ( 0 ) . get ( "value" ) . asText ( ) ) . isEqualTo ( "126.0" ) ;
} ) ;
}
@Test
public void testSimpleCalculatedFieldWhenSkipRuleEngineOutputProcessing ( ) throws Exception {
Device testDevice = createDevice ( "Test device" , "1234567890" ) ;