@ -42,6 +42,8 @@ import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType;
import org.thingsboard.server.common.data.device.profile.AlarmRule ;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm ;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData ;
import org.thingsboard.server.common.data.device.profile.DurationAlarmConditionSpec ;
import org.thingsboard.server.common.data.device.profile.RepeatingAlarmConditionSpec ;
import org.thingsboard.server.common.data.id.CustomerId ;
import org.thingsboard.server.common.data.id.DeviceId ;
import org.thingsboard.server.common.data.id.DeviceProfileId ;
@ -64,12 +66,15 @@ import org.thingsboard.server.dao.model.sql.AttributeKvCompositeKey;
import org.thingsboard.server.dao.model.sql.AttributeKvEntity ;
import org.thingsboard.server.dao.timeseries.TimeseriesService ;
import java.math.BigDecimal ;
import java.math.RoundingMode ;
import java.util.Arrays ;
import java.util.Collections ;
import java.util.List ;
import java.util.Optional ;
import java.util.TreeMap ;
import java.util.UUID ;
import java.util.concurrent.TimeUnit ;
import static org.mockito.ArgumentMatchers.eq ;
import static org.mockito.Mockito.verify ;
@ -94,10 +99,10 @@ public class TbDeviceProfileNodeTest {
@Mock
private AttributesService attributesService ;
private TenantId tenantId = new TenantId ( UUID . randomUUID ( ) ) ;
private DeviceId deviceId = new DeviceId ( UUID . randomUUID ( ) ) ;
private CustomerId customerId = new CustomerId ( UUID . randomUUID ( ) ) ;
private DeviceProfileId deviceProfileId = new DeviceProfileId ( UUID . randomUUID ( ) ) ;
private final TenantId tenantId = new TenantId ( UUID . randomUUID ( ) ) ;
private final DeviceId deviceId = new DeviceId ( UUID . randomUUID ( ) ) ;
private final CustomerId customerId = new CustomerId ( UUID . randomUUID ( ) ) ;
private final DeviceProfileId deviceProfileId = new DeviceProfileId ( UUID . randomUUID ( ) ) ;
@Test
public void testRandomMessageType ( ) throws Exception {
@ -444,6 +449,642 @@ public class TbDeviceProfileNodeTest {
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testCurrentDeviceAttributeForDynamicDurationValue ( ) throws Exception {
init ( ) ;
DeviceProfile deviceProfile = new DeviceProfile ( ) ;
deviceProfile . setId ( deviceProfileId ) ;
DeviceProfileData deviceProfileData = new DeviceProfileData ( ) ;
AttributeKvCompositeKey compositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "greaterAttribute"
) ;
AttributeKvEntity attributeKvEntity = new AttributeKvEntity ( ) ;
attributeKvEntity . setId ( compositeKey ) ;
attributeKvEntity . setLongValue ( 30L ) ;
attributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvCompositeKey alarmDelayCompositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "alarm_delay"
) ;
AttributeKvEntity alarmDelayAttributeKvEntity = new AttributeKvEntity ( ) ;
alarmDelayAttributeKvEntity . setId ( alarmDelayCompositeKey ) ;
long alarmDelayInSeconds = 5L ;
alarmDelayAttributeKvEntity . setLongValue ( alarmDelayInSeconds ) ;
alarmDelayAttributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvEntry entry = attributeKvEntity . toData ( ) ;
AttributeKvEntry alarmDelayAttributeKvEntry = alarmDelayAttributeKvEntity . toData ( ) ;
ListenableFuture < List < AttributeKvEntry > > listListenableFuture =
Futures . immediateFuture ( Arrays . asList ( entry , alarmDelayAttributeKvEntry ) ) ;
AlarmConditionFilter highTempFilter = new AlarmConditionFilter ( ) ;
highTempFilter . setKey ( new AlarmConditionFilterKey ( AlarmConditionKeyType . TIME_SERIES , "temperature" ) ) ;
highTempFilter . setValueType ( EntityKeyValueType . NUMERIC ) ;
NumericFilterPredicate highTemperaturePredicate = new NumericFilterPredicate ( ) ;
highTemperaturePredicate . setOperation ( NumericFilterPredicate . NumericOperation . GREATER ) ;
highTemperaturePredicate . setValue ( new FilterPredicateValue < > (
0 . 0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "greaterAttribute" , false )
) ) ;
highTempFilter . setPredicate ( highTemperaturePredicate ) ;
AlarmCondition alarmCondition = new AlarmCondition ( ) ;
alarmCondition . setCondition ( Collections . singletonList ( highTempFilter ) ) ;
FilterPredicateValue < Long > filterPredicateValue = new FilterPredicateValue < > (
10L ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "alarm_delay" , false )
) ;
DurationAlarmConditionSpec durationSpec = new DurationAlarmConditionSpec ( ) ;
durationSpec . setUnit ( TimeUnit . SECONDS ) ;
durationSpec . setPredicate ( filterPredicateValue ) ;
alarmCondition . setSpec ( durationSpec ) ;
AlarmRule alarmRule = new AlarmRule ( ) ;
alarmRule . setCondition ( alarmCondition ) ;
DeviceProfileAlarm dpa = new DeviceProfileAlarm ( ) ;
dpa . setId ( "highTemperatureAlarmID" ) ;
dpa . setAlarmType ( "highTemperatureAlarm" ) ;
dpa . setCreateRules ( new TreeMap < > ( Collections . singletonMap ( AlarmSeverity . CRITICAL , alarmRule ) ) ) ;
deviceProfileData . setAlarms ( Collections . singletonList ( dpa ) ) ;
deviceProfile . setProfileData ( deviceProfileData ) ;
Mockito . when ( cache . get ( tenantId , deviceId ) ) . thenReturn ( deviceProfile ) ;
Mockito . when ( timeseriesService . findLatest ( tenantId , deviceId , Collections . singleton ( "temperature" ) ) )
. thenReturn ( Futures . immediateFuture ( Collections . emptyList ( ) ) ) ;
Mockito . when ( alarmService . findLatestByOriginatorAndType ( tenantId , deviceId , "highTemperatureAlarm" ) )
. thenReturn ( Futures . immediateFuture ( null ) ) ;
Mockito . when ( alarmService . createOrUpdateAlarm ( Mockito . any ( ) ) ) . thenAnswer ( AdditionalAnswers . returnsFirstArg ( ) ) ;
Mockito . when ( ctx . getAttributesService ( ) ) . thenReturn ( attributesService ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( deviceId ) , Mockito . anyString ( ) , Mockito . anySet ( ) ) )
. thenReturn ( listListenableFuture ) ;
TbMsg theMsg = TbMsg . newMsg ( "ALARM" , deviceId , new TbMsgMetaData ( ) , "" ) ;
Mockito . when ( ctx . newMsg ( Mockito . anyString ( ) , Mockito . anyString ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . anyString ( ) ) )
. thenReturn ( theMsg ) ;
ObjectNode data = mapper . createObjectNode ( ) ;
data . put ( "temperature" , 35 ) ;
TbMsg msg = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg ) ;
verify ( ctx ) . tellSuccess ( msg ) ;
int halfOfAlarmDelay = new BigDecimal ( alarmDelayInSeconds )
. multiply ( BigDecimal . valueOf ( 1000 ) )
. divide ( BigDecimal . valueOf ( 2 ) , 3 , RoundingMode . HALF_EVEN )
. intValueExact ( ) ;
Thread . sleep ( halfOfAlarmDelay ) ;
verify ( ctx , Mockito . never ( ) ) . tellNext ( theMsg , "Alarm Created" ) ;
Thread . sleep ( halfOfAlarmDelay ) ;
TbMsg msg2 = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg2 ) ;
verify ( ctx ) . tellSuccess ( msg2 ) ;
verify ( ctx ) . tellNext ( theMsg , "Alarm Created" ) ;
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testInheritTenantAttributeForDuration ( ) throws Exception {
init ( ) ;
DeviceProfile deviceProfile = new DeviceProfile ( ) ;
deviceProfile . setId ( deviceProfileId ) ;
DeviceProfileData deviceProfileData = new DeviceProfileData ( ) ;
Device device = new Device ( ) ;
device . setId ( deviceId ) ;
device . setCustomerId ( customerId ) ;
AttributeKvCompositeKey compositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "greaterAttribute"
) ;
AttributeKvEntity attributeKvEntity = new AttributeKvEntity ( ) ;
attributeKvEntity . setId ( compositeKey ) ;
attributeKvEntity . setLongValue ( 30L ) ;
attributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvCompositeKey alarmDelayCompositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "alarm_delay"
) ;
AttributeKvEntity alarmDelayAttributeKvEntity = new AttributeKvEntity ( ) ;
alarmDelayAttributeKvEntity . setId ( alarmDelayCompositeKey ) ;
long alarmDelayInSeconds = 5L ;
alarmDelayAttributeKvEntity . setLongValue ( alarmDelayInSeconds ) ;
alarmDelayAttributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvEntry entry = attributeKvEntity . toData ( ) ;
AttributeKvEntry alarmDelayAttributeKvEntry = alarmDelayAttributeKvEntity . toData ( ) ;
ListenableFuture < Optional < AttributeKvEntry > > optionalDurationAttribute =
Futures . immediateFuture ( Optional . of ( alarmDelayAttributeKvEntry ) ) ;
ListenableFuture < List < AttributeKvEntry > > listNoDurationAttribute =
Futures . immediateFuture ( Collections . singletonList ( entry ) ) ;
ListenableFuture < Optional < AttributeKvEntry > > emptyOptional =
Futures . immediateFuture ( Optional . empty ( ) ) ;
AlarmConditionFilter highTempFilter = new AlarmConditionFilter ( ) ;
highTempFilter . setKey ( new AlarmConditionFilterKey ( AlarmConditionKeyType . TIME_SERIES , "temperature" ) ) ;
highTempFilter . setValueType ( EntityKeyValueType . NUMERIC ) ;
NumericFilterPredicate highTemperaturePredicate = new NumericFilterPredicate ( ) ;
highTemperaturePredicate . setOperation ( NumericFilterPredicate . NumericOperation . GREATER ) ;
highTemperaturePredicate . setValue ( new FilterPredicateValue < > (
0 . 0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "greaterAttribute" , false )
) ) ;
highTempFilter . setPredicate ( highTemperaturePredicate ) ;
AlarmCondition alarmCondition = new AlarmCondition ( ) ;
alarmCondition . setCondition ( Collections . singletonList ( highTempFilter ) ) ;
FilterPredicateValue < Long > filterPredicateValue = new FilterPredicateValue < > (
10L ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "alarm_delay" , true )
) ;
DurationAlarmConditionSpec durationSpec = new DurationAlarmConditionSpec ( ) ;
durationSpec . setUnit ( TimeUnit . SECONDS ) ;
durationSpec . setPredicate ( filterPredicateValue ) ;
alarmCondition . setSpec ( durationSpec ) ;
AlarmRule alarmRule = new AlarmRule ( ) ;
alarmRule . setCondition ( alarmCondition ) ;
DeviceProfileAlarm dpa = new DeviceProfileAlarm ( ) ;
dpa . setId ( "highTemperatureAlarmID" ) ;
dpa . setAlarmType ( "highTemperatureAlarm" ) ;
dpa . setCreateRules ( new TreeMap < > ( Collections . singletonMap ( AlarmSeverity . CRITICAL , alarmRule ) ) ) ;
deviceProfileData . setAlarms ( Collections . singletonList ( dpa ) ) ;
deviceProfile . setProfileData ( deviceProfileData ) ;
Mockito . when ( cache . get ( tenantId , deviceId ) ) . thenReturn ( deviceProfile ) ;
Mockito . when ( timeseriesService . findLatest ( tenantId , deviceId , Collections . singleton ( "temperature" ) ) )
. thenReturn ( Futures . immediateFuture ( Collections . emptyList ( ) ) ) ;
Mockito . when ( alarmService . findLatestByOriginatorAndType ( tenantId , deviceId , "highTemperatureAlarm" ) )
. thenReturn ( Futures . immediateFuture ( null ) ) ;
Mockito . when ( alarmService . createOrUpdateAlarm ( Mockito . any ( ) ) ) . thenAnswer ( AdditionalAnswers . returnsFirstArg ( ) ) ;
Mockito . when ( ctx . getAttributesService ( ) ) . thenReturn ( attributesService ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( tenantId ) , Mockito . anyString ( ) , Mockito . anyString ( ) ) )
. thenReturn ( optionalDurationAttribute ) ;
Mockito . when ( ctx . getDeviceService ( ) . findDeviceById ( tenantId , deviceId ) )
. thenReturn ( device ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( customerId ) , eq ( DataConstants . SERVER_SCOPE ) , Mockito . anyString ( ) ) )
. thenReturn ( emptyOptional ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( deviceId ) , Mockito . anyString ( ) , Mockito . anySet ( ) ) )
. thenReturn ( listNoDurationAttribute ) ;
TbMsg theMsg = TbMsg . newMsg ( "ALARM" , deviceId , new TbMsgMetaData ( ) , "" ) ;
Mockito . when ( ctx . newMsg ( Mockito . anyString ( ) , Mockito . anyString ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . anyString ( ) ) )
. thenReturn ( theMsg ) ;
ObjectNode data = mapper . createObjectNode ( ) ;
data . put ( "temperature" , 150 ) ;
TbMsg msg = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg ) ;
verify ( ctx ) . tellSuccess ( msg ) ;
int halfOfAlarmDelay = new BigDecimal ( alarmDelayInSeconds )
. multiply ( BigDecimal . valueOf ( 1000 ) )
. divide ( BigDecimal . valueOf ( 2 ) , 3 , RoundingMode . HALF_EVEN )
. intValueExact ( ) ;
Thread . sleep ( halfOfAlarmDelay ) ;
verify ( ctx , Mockito . never ( ) ) . tellNext ( theMsg , "Alarm Created" ) ;
Thread . sleep ( halfOfAlarmDelay ) ;
TbMsg msg2 = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg2 ) ;
verify ( ctx ) . tellSuccess ( msg2 ) ;
verify ( ctx ) . tellNext ( theMsg , "Alarm Created" ) ;
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testCurrentDeviceAttributeForDynamicRepeatingValue ( ) throws Exception {
init ( ) ;
DeviceProfile deviceProfile = new DeviceProfile ( ) ;
deviceProfile . setId ( deviceProfileId ) ;
DeviceProfileData deviceProfileData = new DeviceProfileData ( ) ;
AttributeKvCompositeKey compositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "greaterAttribute"
) ;
AttributeKvEntity attributeKvEntity = new AttributeKvEntity ( ) ;
attributeKvEntity . setId ( compositeKey ) ;
attributeKvEntity . setLongValue ( 30L ) ;
attributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvCompositeKey alarmDelayCompositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "alarm_delay"
) ;
AttributeKvEntity alarmDelayAttributeKvEntity = new AttributeKvEntity ( ) ;
alarmDelayAttributeKvEntity . setId ( alarmDelayCompositeKey ) ;
long alarmRepeating = 2 ;
alarmDelayAttributeKvEntity . setLongValue ( alarmRepeating ) ;
alarmDelayAttributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvEntry entry = attributeKvEntity . toData ( ) ;
AttributeKvEntry alarmDelayAttributeKvEntry = alarmDelayAttributeKvEntity . toData ( ) ;
ListenableFuture < List < AttributeKvEntry > > listListenableFuture =
Futures . immediateFuture ( Arrays . asList ( entry , alarmDelayAttributeKvEntry ) ) ;
AlarmConditionFilter highTempFilter = new AlarmConditionFilter ( ) ;
highTempFilter . setKey ( new AlarmConditionFilterKey ( AlarmConditionKeyType . TIME_SERIES , "temperature" ) ) ;
highTempFilter . setValueType ( EntityKeyValueType . NUMERIC ) ;
NumericFilterPredicate highTemperaturePredicate = new NumericFilterPredicate ( ) ;
highTemperaturePredicate . setOperation ( NumericFilterPredicate . NumericOperation . GREATER ) ;
highTemperaturePredicate . setValue ( new FilterPredicateValue < > (
0 . 0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "greaterAttribute" , false )
) ) ;
highTempFilter . setPredicate ( highTemperaturePredicate ) ;
AlarmCondition alarmCondition = new AlarmCondition ( ) ;
alarmCondition . setCondition ( Collections . singletonList ( highTempFilter ) ) ;
FilterPredicateValue < Integer > filterPredicateValue = new FilterPredicateValue < > (
10 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "alarm_delay" , false )
) ;
RepeatingAlarmConditionSpec repeatingSpec = new RepeatingAlarmConditionSpec ( ) ;
repeatingSpec . setPredicate ( filterPredicateValue ) ;
alarmCondition . setSpec ( repeatingSpec ) ;
AlarmRule alarmRule = new AlarmRule ( ) ;
alarmRule . setCondition ( alarmCondition ) ;
DeviceProfileAlarm dpa = new DeviceProfileAlarm ( ) ;
dpa . setId ( "highTemperatureAlarmID" ) ;
dpa . setAlarmType ( "highTemperatureAlarm" ) ;
dpa . setCreateRules ( new TreeMap < > ( Collections . singletonMap ( AlarmSeverity . CRITICAL , alarmRule ) ) ) ;
deviceProfileData . setAlarms ( Collections . singletonList ( dpa ) ) ;
deviceProfile . setProfileData ( deviceProfileData ) ;
Mockito . when ( cache . get ( tenantId , deviceId ) ) . thenReturn ( deviceProfile ) ;
Mockito . when ( timeseriesService . findLatest ( tenantId , deviceId , Collections . singleton ( "temperature" ) ) )
. thenReturn ( Futures . immediateFuture ( Collections . emptyList ( ) ) ) ;
Mockito . when ( alarmService . findLatestByOriginatorAndType ( tenantId , deviceId , "highTemperatureAlarm" ) )
. thenReturn ( Futures . immediateFuture ( null ) ) ;
Mockito . when ( alarmService . createOrUpdateAlarm ( Mockito . any ( ) ) ) . thenAnswer ( AdditionalAnswers . returnsFirstArg ( ) ) ;
Mockito . when ( ctx . getAttributesService ( ) ) . thenReturn ( attributesService ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( deviceId ) , Mockito . anyString ( ) , Mockito . anySet ( ) ) )
. thenReturn ( listListenableFuture ) ;
TbMsg theMsg = TbMsg . newMsg ( "ALARM" , deviceId , new TbMsgMetaData ( ) , "" ) ;
Mockito . when ( ctx . newMsg ( Mockito . anyString ( ) , Mockito . anyString ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . anyString ( ) ) )
. thenReturn ( theMsg ) ;
ObjectNode data = mapper . createObjectNode ( ) ;
data . put ( "temperature" , 150 ) ;
TbMsg msg = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg ) ;
verify ( ctx ) . tellSuccess ( msg ) ;
verify ( ctx , Mockito . never ( ) ) . tellNext ( theMsg , "Alarm Created" ) ;
TbMsg msg2 = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg2 ) ;
verify ( ctx ) . tellSuccess ( msg2 ) ;
verify ( ctx ) . tellNext ( theMsg , "Alarm Created" ) ;
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testInheritTenantAttributeForRepeating ( ) throws Exception {
init ( ) ;
DeviceProfile deviceProfile = new DeviceProfile ( ) ;
deviceProfile . setId ( deviceProfileId ) ;
DeviceProfileData deviceProfileData = new DeviceProfileData ( ) ;
AttributeKvCompositeKey compositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "greaterAttribute"
) ;
Device device = new Device ( ) ;
device . setId ( deviceId ) ;
device . setCustomerId ( customerId ) ;
AttributeKvEntity attributeKvEntity = new AttributeKvEntity ( ) ;
attributeKvEntity . setId ( compositeKey ) ;
attributeKvEntity . setLongValue ( 30L ) ;
attributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvCompositeKey alarmDelayCompositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "alarm_delay"
) ;
AttributeKvEntity alarmDelayAttributeKvEntity = new AttributeKvEntity ( ) ;
alarmDelayAttributeKvEntity . setId ( alarmDelayCompositeKey ) ;
long repeatingCondition = 2 ;
alarmDelayAttributeKvEntity . setLongValue ( repeatingCondition ) ;
alarmDelayAttributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvEntry entry = attributeKvEntity . toData ( ) ;
AttributeKvEntry alarmDelayAttributeKvEntry = alarmDelayAttributeKvEntity . toData ( ) ;
ListenableFuture < Optional < AttributeKvEntry > > optionalDurationAttribute =
Futures . immediateFuture ( Optional . of ( alarmDelayAttributeKvEntry ) ) ;
ListenableFuture < List < AttributeKvEntry > > listNoDurationAttribute =
Futures . immediateFuture ( Collections . singletonList ( entry ) ) ;
ListenableFuture < Optional < AttributeKvEntry > > emptyOptional =
Futures . immediateFuture ( Optional . empty ( ) ) ;
AlarmConditionFilter highTempFilter = new AlarmConditionFilter ( ) ;
highTempFilter . setKey ( new AlarmConditionFilterKey ( AlarmConditionKeyType . TIME_SERIES , "temperature" ) ) ;
highTempFilter . setValueType ( EntityKeyValueType . NUMERIC ) ;
NumericFilterPredicate highTemperaturePredicate = new NumericFilterPredicate ( ) ;
highTemperaturePredicate . setOperation ( NumericFilterPredicate . NumericOperation . GREATER ) ;
highTemperaturePredicate . setValue ( new FilterPredicateValue < > (
0 . 0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "greaterAttribute" , false )
) ) ;
highTempFilter . setPredicate ( highTemperaturePredicate ) ;
AlarmCondition alarmCondition = new AlarmCondition ( ) ;
alarmCondition . setCondition ( Collections . singletonList ( highTempFilter ) ) ;
FilterPredicateValue < Integer > filterPredicateValue = new FilterPredicateValue < > (
10 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "alarm_delay" , true )
) ;
RepeatingAlarmConditionSpec repeatingSpec = new RepeatingAlarmConditionSpec ( ) ;
repeatingSpec . setPredicate ( filterPredicateValue ) ;
alarmCondition . setSpec ( repeatingSpec ) ;
AlarmRule alarmRule = new AlarmRule ( ) ;
alarmRule . setCondition ( alarmCondition ) ;
DeviceProfileAlarm dpa = new DeviceProfileAlarm ( ) ;
dpa . setId ( "highTemperatureAlarmID" ) ;
dpa . setAlarmType ( "highTemperatureAlarm" ) ;
dpa . setCreateRules ( new TreeMap < > ( Collections . singletonMap ( AlarmSeverity . CRITICAL , alarmRule ) ) ) ;
deviceProfileData . setAlarms ( Collections . singletonList ( dpa ) ) ;
deviceProfile . setProfileData ( deviceProfileData ) ;
Mockito . when ( cache . get ( tenantId , deviceId ) ) . thenReturn ( deviceProfile ) ;
Mockito . when ( timeseriesService . findLatest ( tenantId , deviceId , Collections . singleton ( "temperature" ) ) )
. thenReturn ( Futures . immediateFuture ( Collections . emptyList ( ) ) ) ;
Mockito . when ( alarmService . findLatestByOriginatorAndType ( tenantId , deviceId , "highTemperatureAlarm" ) )
. thenReturn ( Futures . immediateFuture ( null ) ) ;
Mockito . when ( alarmService . createOrUpdateAlarm ( Mockito . any ( ) ) ) . thenAnswer ( AdditionalAnswers . returnsFirstArg ( ) ) ;
Mockito . when ( ctx . getAttributesService ( ) ) . thenReturn ( attributesService ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( tenantId ) , Mockito . anyString ( ) , Mockito . anyString ( ) ) )
. thenReturn ( optionalDurationAttribute ) ;
Mockito . when ( ctx . getDeviceService ( ) . findDeviceById ( tenantId , deviceId ) )
. thenReturn ( device ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( customerId ) , eq ( DataConstants . SERVER_SCOPE ) , Mockito . anyString ( ) ) )
. thenReturn ( emptyOptional ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( deviceId ) , Mockito . anyString ( ) , Mockito . anySet ( ) ) )
. thenReturn ( listNoDurationAttribute ) ;
TbMsg theMsg = TbMsg . newMsg ( "ALARM" , deviceId , new TbMsgMetaData ( ) , "" ) ;
Mockito . when ( ctx . newMsg ( Mockito . anyString ( ) , Mockito . anyString ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . anyString ( ) ) )
. thenReturn ( theMsg ) ;
ObjectNode data = mapper . createObjectNode ( ) ;
data . put ( "temperature" , 150 ) ;
TbMsg msg = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg ) ;
verify ( ctx ) . tellSuccess ( msg ) ;
verify ( ctx , Mockito . never ( ) ) . tellNext ( theMsg , "Alarm Created" ) ;
TbMsg msg2 = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg2 ) ;
verify ( ctx ) . tellSuccess ( msg2 ) ;
verify ( ctx ) . tellNext ( theMsg , "Alarm Created" ) ;
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testCurrentDeviceAttributeForUseDefaultDurationWhenDynamicDurationValueIsNull ( ) throws Exception {
init ( ) ;
long alarmDelayInSeconds = 5 ;
DeviceProfile deviceProfile = new DeviceProfile ( ) ;
deviceProfile . setId ( deviceProfileId ) ;
DeviceProfileData deviceProfileData = new DeviceProfileData ( ) ;
Device device = new Device ( ) ;
device . setId ( deviceId ) ;
device . setCustomerId ( customerId ) ;
AttributeKvCompositeKey compositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "greaterAttribute"
) ;
AttributeKvEntity attributeKvEntity = new AttributeKvEntity ( ) ;
attributeKvEntity . setId ( compositeKey ) ;
attributeKvEntity . setLongValue ( 30L ) ;
attributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvEntry entry = attributeKvEntity . toData ( ) ;
ListenableFuture < List < AttributeKvEntry > > listListenableFuture =
Futures . immediateFuture ( Collections . singletonList ( entry ) ) ;
AlarmConditionFilter highTempFilter = new AlarmConditionFilter ( ) ;
highTempFilter . setKey ( new AlarmConditionFilterKey ( AlarmConditionKeyType . TIME_SERIES , "temperature" ) ) ;
highTempFilter . setValueType ( EntityKeyValueType . NUMERIC ) ;
NumericFilterPredicate highTemperaturePredicate = new NumericFilterPredicate ( ) ;
highTemperaturePredicate . setOperation ( NumericFilterPredicate . NumericOperation . GREATER ) ;
highTemperaturePredicate . setValue ( new FilterPredicateValue < > (
0 . 0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "greaterAttribute" )
) ) ;
highTempFilter . setPredicate ( highTemperaturePredicate ) ;
AlarmCondition alarmCondition = new AlarmCondition ( ) ;
alarmCondition . setCondition ( Collections . singletonList ( highTempFilter ) ) ;
FilterPredicateValue < Long > filterPredicateValue = new FilterPredicateValue < > (
alarmDelayInSeconds ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , null , false )
) ;
DurationAlarmConditionSpec durationSpec = new DurationAlarmConditionSpec ( ) ;
durationSpec . setUnit ( TimeUnit . SECONDS ) ;
durationSpec . setPredicate ( filterPredicateValue ) ;
alarmCondition . setSpec ( durationSpec ) ;
AlarmRule alarmRule = new AlarmRule ( ) ;
alarmRule . setCondition ( alarmCondition ) ;
DeviceProfileAlarm dpa = new DeviceProfileAlarm ( ) ;
dpa . setId ( "highTemperatureAlarmID" ) ;
dpa . setAlarmType ( "highTemperatureAlarm" ) ;
dpa . setCreateRules ( new TreeMap < > ( Collections . singletonMap ( AlarmSeverity . CRITICAL , alarmRule ) ) ) ;
deviceProfileData . setAlarms ( Collections . singletonList ( dpa ) ) ;
deviceProfile . setProfileData ( deviceProfileData ) ;
Mockito . when ( cache . get ( tenantId , deviceId ) ) . thenReturn ( deviceProfile ) ;
Mockito . when ( timeseriesService . findLatest ( tenantId , deviceId , Collections . singleton ( "temperature" ) ) )
. thenReturn ( Futures . immediateFuture ( Collections . emptyList ( ) ) ) ;
Mockito . when ( alarmService . findLatestByOriginatorAndType ( tenantId , deviceId , "highTemperatureAlarm" ) )
. thenReturn ( Futures . immediateFuture ( null ) ) ;
Mockito . when ( alarmService . createOrUpdateAlarm ( Mockito . any ( ) ) ) . thenAnswer ( AdditionalAnswers . returnsFirstArg ( ) ) ;
Mockito . when ( ctx . getAttributesService ( ) ) . thenReturn ( attributesService ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( deviceId ) , Mockito . anyString ( ) , Mockito . anySet ( ) ) )
. thenReturn ( listListenableFuture ) ;
TbMsg theMsg = TbMsg . newMsg ( "ALARM" , deviceId , new TbMsgMetaData ( ) , "" ) ;
Mockito . when ( ctx . newMsg ( Mockito . anyString ( ) , Mockito . anyString ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . anyString ( ) ) )
. thenReturn ( theMsg ) ;
ObjectNode data = mapper . createObjectNode ( ) ;
data . put ( "temperature" , 35 ) ;
TbMsg msg = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg ) ;
verify ( ctx ) . tellSuccess ( msg ) ;
int halfOfAlarmDelay = new BigDecimal ( alarmDelayInSeconds )
. multiply ( BigDecimal . valueOf ( 1000 ) )
. divide ( BigDecimal . valueOf ( 2 ) , 3 , RoundingMode . HALF_EVEN )
. intValueExact ( ) ;
Thread . sleep ( halfOfAlarmDelay ) ;
verify ( ctx , Mockito . never ( ) ) . tellNext ( theMsg , "Alarm Created" ) ;
Thread . sleep ( halfOfAlarmDelay ) ;
TbMsg msg2 = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg2 ) ;
verify ( ctx ) . tellSuccess ( msg2 ) ;
verify ( ctx ) . tellNext ( theMsg , "Alarm Created" ) ;
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testCurrentDeviceAttributeForUseDefaultRepeatingWhenDynamicDurationValueIsNull ( ) throws Exception {
init ( ) ;
DeviceProfile deviceProfile = new DeviceProfile ( ) ;
deviceProfile . setId ( deviceProfileId ) ;
DeviceProfileData deviceProfileData = new DeviceProfileData ( ) ;
Device device = new Device ( ) ;
device . setId ( deviceId ) ;
device . setCustomerId ( customerId ) ;
AttributeKvCompositeKey compositeKey = new AttributeKvCompositeKey (
EntityType . TENANT , deviceId . getId ( ) , "SERVER_SCOPE" , "greaterAttribute"
) ;
AttributeKvEntity attributeKvEntity = new AttributeKvEntity ( ) ;
attributeKvEntity . setId ( compositeKey ) ;
attributeKvEntity . setLongValue ( 30L ) ;
attributeKvEntity . setLastUpdateTs ( 0L ) ;
AttributeKvEntry entry = attributeKvEntity . toData ( ) ;
ListenableFuture < List < AttributeKvEntry > > listListenableFuture =
Futures . immediateFuture ( Collections . singletonList ( entry ) ) ;
AlarmConditionFilter highTempFilter = new AlarmConditionFilter ( ) ;
highTempFilter . setKey ( new AlarmConditionFilterKey ( AlarmConditionKeyType . TIME_SERIES , "temperature" ) ) ;
highTempFilter . setValueType ( EntityKeyValueType . NUMERIC ) ;
NumericFilterPredicate highTemperaturePredicate = new NumericFilterPredicate ( ) ;
highTemperaturePredicate . setOperation ( NumericFilterPredicate . NumericOperation . GREATER ) ;
highTemperaturePredicate . setValue ( new FilterPredicateValue < > (
0 . 0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "greaterAttribute" )
) ) ;
highTempFilter . setPredicate ( highTemperaturePredicate ) ;
AlarmCondition alarmCondition = new AlarmCondition ( ) ;
alarmCondition . setCondition ( Collections . singletonList ( highTempFilter ) ) ;
RepeatingAlarmConditionSpec repeating = new RepeatingAlarmConditionSpec ( ) ;
repeating . setPredicate ( new FilterPredicateValue < > (
0 ,
null ,
new DynamicValue < > ( DynamicValueSourceType . CURRENT_DEVICE , "alarm_rule" , false )
) ) ;
alarmCondition . setSpec ( repeating ) ;
AlarmRule alarmRule = new AlarmRule ( ) ;
alarmRule . setCondition ( alarmCondition ) ;
DeviceProfileAlarm dpa = new DeviceProfileAlarm ( ) ;
dpa . setId ( "highTemperatureAlarmID" ) ;
dpa . setAlarmType ( "highTemperatureAlarm" ) ;
dpa . setCreateRules ( new TreeMap < > ( Collections . singletonMap ( AlarmSeverity . CRITICAL , alarmRule ) ) ) ;
deviceProfileData . setAlarms ( Collections . singletonList ( dpa ) ) ;
deviceProfile . setProfileData ( deviceProfileData ) ;
Mockito . when ( cache . get ( tenantId , deviceId ) ) . thenReturn ( deviceProfile ) ;
Mockito . when ( timeseriesService . findLatest ( tenantId , deviceId , Collections . singleton ( "temperature" ) ) )
. thenReturn ( Futures . immediateFuture ( Collections . emptyList ( ) ) ) ;
Mockito . when ( alarmService . findLatestByOriginatorAndType ( tenantId , deviceId , "highTemperatureAlarm" ) )
. thenReturn ( Futures . immediateFuture ( null ) ) ;
Mockito . when ( alarmService . createOrUpdateAlarm ( Mockito . any ( ) ) ) . thenAnswer ( AdditionalAnswers . returnsFirstArg ( ) ) ;
Mockito . when ( ctx . getAttributesService ( ) ) . thenReturn ( attributesService ) ;
Mockito . when ( attributesService . find ( eq ( tenantId ) , eq ( deviceId ) , Mockito . anyString ( ) , Mockito . anySet ( ) ) )
. thenReturn ( listListenableFuture ) ;
TbMsg theMsg = TbMsg . newMsg ( "ALARM" , deviceId , new TbMsgMetaData ( ) , "" ) ;
Mockito . when ( ctx . newMsg ( Mockito . anyString ( ) , Mockito . anyString ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . any ( ) , Mockito . anyString ( ) ) )
. thenReturn ( theMsg ) ;
ObjectNode data = mapper . createObjectNode ( ) ;
data . put ( "temperature" , 35 ) ;
TbMsg msg = TbMsg . newMsg ( SessionMsgType . POST_TELEMETRY_REQUEST . name ( ) , deviceId , new TbMsgMetaData ( ) ,
TbMsgDataType . JSON , mapper . writeValueAsString ( data ) , null , null ) ;
node . onMsg ( ctx , msg ) ;
verify ( ctx ) . tellSuccess ( msg ) ;
verify ( ctx ) . tellNext ( theMsg , "Alarm Created" ) ;
verify ( ctx , Mockito . never ( ) ) . tellFailure ( Mockito . any ( ) , Mockito . any ( ) ) ;
}
@Test
public void testCurrentCustomersAttributeForDynamicValue ( ) throws Exception {
init ( ) ;