Merge remote-tracking branch 'klimov/feature/notification-system' into feature/notification-system
This commit is contained in:
commit
10e34cc1ad
@ -19,18 +19,27 @@ import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmComment;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
|
||||
import org.thingsboard.server.common.data.notification.info.AlarmCommentNotificationInfo;
|
||||
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
|
||||
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmCommentNotificationRuleTriggerConfig;
|
||||
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
|
||||
import org.thingsboard.server.common.msg.TbMsg;
|
||||
|
||||
import static org.apache.commons.collections.CollectionUtils.isEmpty;
|
||||
|
||||
@Service
|
||||
public class AlarmCommentTriggerProcessor implements NotificationRuleTriggerProcessor<TbMsg, AlarmCommentNotificationRuleTriggerConfig> {
|
||||
|
||||
@Override
|
||||
public boolean matchesFilter(TbMsg ruleEngineMsg, AlarmCommentNotificationRuleTriggerConfig triggerConfig) {
|
||||
return ruleEngineMsg.getMetaData().getValue("comment") != null;
|
||||
if (ruleEngineMsg.getMetaData().getValue("comment") == null) {
|
||||
return false;
|
||||
}
|
||||
Alarm alarm = JacksonUtil.fromString(ruleEngineMsg.getData(), Alarm.class);
|
||||
return (isEmpty(triggerConfig.getAlarmTypes()) || triggerConfig.getAlarmTypes().contains(alarm.getType())) &&
|
||||
(isEmpty(triggerConfig.getAlarmSeverities()) || triggerConfig.getAlarmSeverities().contains(alarm.getSeverity())) &&
|
||||
(isEmpty(triggerConfig.getAlarmStatuses()) || AlarmStatusFilter.from(triggerConfig.getAlarmStatuses()).matches(alarm));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -39,8 +48,11 @@ public class AlarmCommentTriggerProcessor implements NotificationRuleTriggerProc
|
||||
Alarm alarm = JacksonUtil.fromString(ruleEngineMsg.getData(), Alarm.class);
|
||||
return AlarmCommentNotificationInfo.builder()
|
||||
.comment(comment.getComment().get("text").asText())
|
||||
.alarmId(alarm.getUuidId())
|
||||
.alarmType(alarm.getType())
|
||||
.alarmId(comment.getAlarmId().getId())
|
||||
.alarmOriginator(alarm.getOriginator())
|
||||
.alarmSeverity(alarm.getSeverity())
|
||||
.alarmStatus(alarm.getStatus())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@ package org.thingsboard.server.service.notification.rule.trigger;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
|
||||
import org.thingsboard.server.common.data.notification.info.AlarmNotificationInfo;
|
||||
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
|
||||
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig;
|
||||
@ -27,14 +27,17 @@ import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotific
|
||||
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
|
||||
import org.thingsboard.server.service.notification.rule.trigger.AlarmTriggerProcessor.AlarmTriggerObject;
|
||||
|
||||
import static org.apache.commons.collections.CollectionUtils.isEmpty;
|
||||
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
|
||||
|
||||
@Service
|
||||
public class AlarmTriggerProcessor implements NotificationRuleTriggerProcessor<AlarmTriggerObject, AlarmNotificationRuleTriggerConfig> {
|
||||
|
||||
@Override
|
||||
public boolean matchesFilter(AlarmTriggerObject triggerObject, AlarmNotificationRuleTriggerConfig triggerConfig) {
|
||||
Alarm alarm = triggerObject.getAlarm();
|
||||
return (CollectionUtils.isEmpty(triggerConfig.getAlarmTypes()) || triggerConfig.getAlarmTypes().contains(alarm.getType())) &&
|
||||
(CollectionUtils.isEmpty(triggerConfig.getAlarmSeverities()) || triggerConfig.getAlarmSeverities().contains(alarm.getSeverity()));
|
||||
return (isEmpty(triggerConfig.getAlarmTypes()) || triggerConfig.getAlarmTypes().contains(alarm.getType())) &&
|
||||
(isEmpty(triggerConfig.getAlarmSeverities()) || triggerConfig.getAlarmSeverities().contains(alarm.getSeverity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,8 +48,8 @@ public class AlarmTriggerProcessor implements NotificationRuleTriggerProcessor<A
|
||||
Alarm alarm = triggerObject.getAlarm();
|
||||
ClearRule clearRule = triggerConfig.getClearRule();
|
||||
if (clearRule != null) {
|
||||
if (clearRule.getAlarmStatus() != null) {
|
||||
return clearRule.getAlarmStatus().equals(alarm.getStatus());
|
||||
if (isNotEmpty(clearRule.getAlarmStatuses())) {
|
||||
return AlarmStatusFilter.from(clearRule.getAlarmStatuses()).matches(alarm);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -59,8 +59,7 @@ public class EntityActionTriggerProcessor implements NotificationRuleTriggerProc
|
||||
msgType.equals(DataConstants.ENTITY_UPDATED) ? ActionType.UPDATED :
|
||||
msgType.equals(DataConstants.ENTITY_DELETED) ? ActionType.DELETED : null;
|
||||
return EntityActionNotificationInfo.builder()
|
||||
.entityType(entityId.getEntityType())
|
||||
.entityId(entityId.getId())
|
||||
.entityId(entityId)
|
||||
.entityName(ruleEngineMsg.getMetaData().getValue("entityName"))
|
||||
.actionType(actionType)
|
||||
.originatorUserId(UUID.fromString(ruleEngineMsg.getMetaData().getValue("userId")))
|
||||
|
||||
@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatus;
|
||||
import org.thingsboard.server.common.data.device.profile.AlarmCondition;
|
||||
@ -234,7 +235,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
||||
});
|
||||
|
||||
clients.values().forEach(wsClient -> wsClient.registerWaitForUpdate());
|
||||
alarmSubscriptionService.ackAlarm(tenantId, alarm.getId(), System.currentTimeMillis());
|
||||
alarmSubscriptionService.acknowledgeAlarm(tenantId, alarm.getId(), System.currentTimeMillis());
|
||||
AlarmStatus expectedStatus = AlarmStatus.ACTIVE_ACK;
|
||||
AlarmSeverity expectedSeverity = AlarmSeverity.CRITICAL;
|
||||
clients.values().forEach(wsClient -> {
|
||||
@ -270,7 +271,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
||||
triggerConfig.setAlarmSeverities(null);
|
||||
|
||||
AlarmNotificationRuleTriggerConfig.ClearRule clearRule = new AlarmNotificationRuleTriggerConfig.ClearRule();
|
||||
clearRule.setAlarmStatus(AlarmStatus.CLEARED_UNACK);
|
||||
clearRule.setAlarmStatuses(Set.of(AlarmSearchStatus.CLEARED, AlarmSearchStatus.UNACK));
|
||||
triggerConfig.setClearRule(clearRule);
|
||||
notificationRule.setTriggerConfig(triggerConfig);
|
||||
|
||||
@ -308,7 +309,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
||||
assertThat(scheduledNotificationRequest).extracting(NotificationRequest::getInfo).isEqualTo(notification.getInfo());
|
||||
|
||||
getWsClient().registerWaitForUpdate();
|
||||
alarmSubscriptionService.clearAlarm(tenantId, alarm.getId(), null, System.currentTimeMillis());
|
||||
alarmSubscriptionService.clearAlarm(tenantId, alarm.getId(), System.currentTimeMillis(), null);
|
||||
getWsClient().waitForUpdate(true);
|
||||
notification = getWsClient().getLastDataUpdate().getNotifications().iterator().next();
|
||||
assertThat(notification.getSubject()).isEqualTo("CRITICAL alarm '" + alarmType + "' is CLEARED_UNACK");
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.common.data.alarm;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AlarmStatusFilter {
|
||||
@ -94,19 +94,19 @@ public class AlarmStatusFilter {
|
||||
}
|
||||
|
||||
|
||||
public static AlarmStatusFilter fromList(List<AlarmSearchStatus> list) {
|
||||
if (list == null || list.isEmpty() || list.contains(AlarmSearchStatus.ANY)) {
|
||||
public static AlarmStatusFilter from(Collection<AlarmSearchStatus> statuses) {
|
||||
if (statuses == null || statuses.isEmpty() || statuses.contains(AlarmSearchStatus.ANY)) {
|
||||
return EMPTY;
|
||||
}
|
||||
boolean clearFilter = list.contains(AlarmSearchStatus.CLEARED);
|
||||
boolean activeFilter = list.contains(AlarmSearchStatus.ACTIVE);
|
||||
boolean clearFilter = statuses.contains(AlarmSearchStatus.CLEARED);
|
||||
boolean activeFilter = statuses.contains(AlarmSearchStatus.ACTIVE);
|
||||
Optional<Boolean> clear = Optional.empty();
|
||||
if (clearFilter && !activeFilter || !clearFilter && activeFilter) {
|
||||
clear = Optional.of(clearFilter);
|
||||
}
|
||||
|
||||
boolean ackFilter = list.contains(AlarmSearchStatus.ACK);
|
||||
boolean unackFilter = list.contains(AlarmSearchStatus.UNACK);
|
||||
boolean ackFilter = statuses.contains(AlarmSearchStatus.ACK);
|
||||
boolean unackFilter = statuses.contains(AlarmSearchStatus.UNACK);
|
||||
Optional<Boolean> ack = Optional.empty();
|
||||
if (ackFilter && !unackFilter || !ackFilter && unackFilter) {
|
||||
ack = Optional.of(ackFilter);
|
||||
@ -114,5 +114,9 @@ public class AlarmStatusFilter {
|
||||
return new AlarmStatusFilter(clear, ack);
|
||||
}
|
||||
|
||||
public boolean matches(Alarm alarm) {
|
||||
return ackFilter.map(ackFilter -> ackFilter.equals(alarm.isAcknowledged())).orElse(true) &&
|
||||
clearFilter.map(clearedFilter -> clearedFilter.equals(alarm.isCleared())).orElse(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,9 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatus;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@ -32,14 +35,26 @@ public class AlarmCommentNotificationInfo implements NotificationInfo {
|
||||
private String comment;
|
||||
private String alarmType;
|
||||
private UUID alarmId;
|
||||
private EntityId alarmOriginator;
|
||||
private AlarmSeverity alarmSeverity;
|
||||
private AlarmStatus alarmStatus;
|
||||
|
||||
@Override
|
||||
public Map<String, String> getTemplateData() {
|
||||
return Map.of(
|
||||
"comment", comment,
|
||||
"alarmType", alarmType,
|
||||
"alarmId", alarmId.toString()
|
||||
"alarmId", alarmId.toString(),
|
||||
"alarmSeverity", alarmSeverity.toString(),
|
||||
"alarmStatus", alarmStatus.toString(),
|
||||
"alarmOriginatorEntityType", alarmOriginator.getEntityType().toString(),
|
||||
"alarmOriginatorId", alarmOriginator.getId().toString()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityId getStateEntityId() {
|
||||
return alarmOriginator;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -57,4 +57,9 @@ public class AlarmNotificationInfo implements RuleOriginatedNotificationInfo {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityId getStateEntityId() {
|
||||
return alarmOriginator;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.DeviceId;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@ -49,4 +51,9 @@ public class DeviceInactivityNotificationInfo implements RuleOriginatedNotificat
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityId getStateEntityId() {
|
||||
return new DeviceId(deviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,9 +19,9 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.audit.ActionType;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@ -32,8 +32,7 @@ import java.util.UUID;
|
||||
@Builder
|
||||
public class EntityActionNotificationInfo implements RuleOriginatedNotificationInfo {
|
||||
|
||||
private EntityType entityType;
|
||||
private UUID entityId;
|
||||
private EntityId entityId;
|
||||
private String entityName;
|
||||
private ActionType actionType;
|
||||
private UUID originatorUserId;
|
||||
@ -48,7 +47,7 @@ public class EntityActionNotificationInfo implements RuleOriginatedNotificationI
|
||||
@Override
|
||||
public Map<String, String> getTemplateData() {
|
||||
return Map.of(
|
||||
"entityType", entityType.name(),
|
||||
"entityType", entityId.getEntityType().name(),
|
||||
"entityId", entityId.toString(),
|
||||
"entityName", entityName,
|
||||
"actionType", actionType.name().toLowerCase(),
|
||||
@ -57,4 +56,9 @@ public class EntityActionNotificationInfo implements RuleOriginatedNotificationI
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityId getStateEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.notification.info;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ -28,4 +29,8 @@ public interface NotificationInfo {
|
||||
@JsonIgnore
|
||||
Map<String, String> getTemplateData();
|
||||
|
||||
default EntityId getStateEntityId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -53,4 +53,9 @@ public class RuleEngineComponentLifecycleEventNotificationInfo implements Notifi
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityId getStateEntityId() {
|
||||
return ruleChainId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -43,4 +43,9 @@ public class RuleEngineOriginatedNotificationInfo implements NotificationInfo {
|
||||
return templateData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityId getStateEntityId() {
|
||||
return msgOriginator;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -16,10 +16,18 @@
|
||||
package org.thingsboard.server.common.data.notification.rule.trigger;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
public class AlarmCommentNotificationRuleTriggerConfig implements NotificationRuleTriggerConfig {
|
||||
|
||||
private Set<String> alarmTypes;
|
||||
private Set<AlarmSeverity> alarmSeverities;
|
||||
private Set<AlarmSearchStatus> alarmStatuses;
|
||||
|
||||
@Override
|
||||
public NotificationRuleTriggerType getTriggerType() {
|
||||
return NotificationRuleTriggerType.ALARM_COMMENT;
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
package org.thingsboard.server.common.data.notification.rule.trigger;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatus;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@ -35,7 +35,7 @@ public class AlarmNotificationRuleTriggerConfig implements NotificationRuleTrigg
|
||||
|
||||
@Data
|
||||
public static class ClearRule {
|
||||
private AlarmStatus alarmStatus;
|
||||
private Set<AlarmSearchStatus> alarmStatuses;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,12 +19,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.thingsboard.server.common.data.DataConstants;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatus;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
@ -41,11 +38,9 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Repository
|
||||
@ -248,7 +243,7 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository {
|
||||
wherePart.append("a.severity in (:alarmSeverities)");
|
||||
}
|
||||
|
||||
AlarmStatusFilter asf = AlarmStatusFilter.fromList(pageLink.getStatusList());
|
||||
AlarmStatusFilter asf = AlarmStatusFilter.from(pageLink.getStatusList());
|
||||
if (asf.hasAnyFilter()) {
|
||||
if (asf.hasAckFilter()) {
|
||||
addAndIfNeeded(wherePart, addAnd);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user