diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 7a2c273002..19774bbf42 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -22,10 +22,7 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Event; -import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmId; -import org.thingsboard.server.common.data.alarm.AlarmQuery; -import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.alarm.*; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.*; import org.thingsboard.server.common.data.page.TextPageData; @@ -103,24 +100,31 @@ public class AlarmController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody - public TimePageData getAlarms( + public TimePageData getAlarms( @PathVariable("entityType") String strEntityType, @PathVariable("entityId") String strEntityId, + @RequestParam(required = false) String searchStatus, @RequestParam(required = false) String status, @RequestParam int limit, @RequestParam(required = false) Long startTime, @RequestParam(required = false) Long endTime, @RequestParam(required = false, defaultValue = "false") boolean ascOrder, - @RequestParam(required = false) String offset + @RequestParam(required = false) String offset, + @RequestParam(required = false) Boolean fetchOriginator ) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); + AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); + if (alarmSearchStatus != null && alarmStatus != null) { + throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " + + "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } checkEntityId(entityId); try { TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); - return checkNotNull(alarmService.findAlarms(new AlarmQuery(entityId, pageLink, alarmStatus)).get()); + return checkNotNull(alarmService.findAlarms(new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); } catch (Exception e) { throw handleException(e); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java index 09695e5ee8..9c6f998a3f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java @@ -53,6 +53,21 @@ public class Alarm extends BaseData implements HasName { super(id); } + public Alarm(Alarm alarm) { + super(alarm.getId()); + this.tenantId = alarm.getTenantId(); + this.type = alarm.getType(); + this.originator = alarm.getOriginator(); + this.severity = alarm.getSeverity(); + this.status = alarm.getStatus(); + this.startTs = alarm.getStartTs(); + this.endTs = alarm.getEndTs(); + this.ackTs = alarm.getAckTs(); + this.clearTs = alarm.getClearTs(); + this.details = alarm.getDetails(); + this.propagate = alarm.isPropagate(); + } + @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java new file mode 100644 index 0000000000..ef24f1c2c0 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java @@ -0,0 +1,58 @@ +/** + * Copyright © 2016-2017 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.alarm; + +public class AlarmInfo extends Alarm { + + private static final long serialVersionUID = 2807343093519543363L; + + private String originatorName; + + public AlarmInfo() { + super(); + } + + public AlarmInfo(Alarm alarm) { + super(alarm); + } + + public String getOriginatorName() { + return originatorName; + } + + public void setOriginatorName(String originatorName) { + this.originatorName = originatorName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + AlarmInfo alarmInfo = (AlarmInfo) o; + + return originatorName != null ? originatorName.equals(alarmInfo.originatorName) : alarmInfo.originatorName == null; + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (originatorName != null ? originatorName.hashCode() : 0); + return result; + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmQuery.java index 00ca6c34ab..55019c8e33 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmQuery.java @@ -32,6 +32,8 @@ public class AlarmQuery { private EntityId affectedEntityId; private TimePageLink pageLink; + private AlarmSearchStatus searchStatus; private AlarmStatus status; + private Boolean fetchOriginator; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmSearchStatus.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmSearchStatus.java new file mode 100644 index 0000000000..c09b1fd37e --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmSearchStatus.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2017 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thingsboard.server.common.data.alarm; + +public enum AlarmSearchStatus { + + ANY, ACTIVE, CLEARED, ACK, UNACK + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmStatus.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmStatus.java index 0f1b346f2c..a8704b2f58 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmStatus.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmStatus.java @@ -30,4 +30,13 @@ public enum AlarmStatus { return this == CLEARED_ACK || this == CLEARED_UNACK; } + public AlarmSearchStatus getClearSearchStatus() { + return this.isCleared() ? AlarmSearchStatus.CLEARED : AlarmSearchStatus.ACTIVE; + } + + public AlarmSearchStatus getAckSearchStatus() { + return this.isAck() ? AlarmSearchStatus.ACK : AlarmSearchStatus.UNACK; + } + + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java index 9fdd92e4cf..289d5c9e59 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; @@ -37,5 +38,5 @@ public interface AlarmDao extends Dao { AlarmEntity save(Alarm alarm); - ListenableFuture> findAlarms(AlarmQuery query); + ListenableFuture> findAlarms(AlarmQuery query); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java index 1362e6b3a9..72fbae5e6f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDaoImpl.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Select; +import com.google.common.base.Function; import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -25,7 +26,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; +import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -94,15 +97,25 @@ public class AlarmDaoImpl extends AbstractModelDao implements Alarm } @Override - public ListenableFuture> findAlarms(AlarmQuery query) { - log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink()); + public ListenableFuture> findAlarms(AlarmQuery query) { + log.trace("Try to find alarms by entity [{}], searchStatus [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getSearchStatus(), query.getStatus(), query.getPageLink()); EntityId affectedEntity = query.getAffectedEntityId(); - String relationType = query.getStatus() == null ? BaseAlarmService.ALARM_RELATION : BaseAlarmService.ALARM_RELATION_PREFIX + query.getStatus().name(); + String searchStatusName; + if (query.getSearchStatus() == null && query.getStatus() == null) { + searchStatusName = AlarmSearchStatus.ANY.name(); + } else if (query.getSearchStatus() != null) { + searchStatusName = query.getSearchStatus().name(); + } else { + searchStatusName = query.getStatus().name(); + } + String relationType = BaseAlarmService.ALARM_RELATION_PREFIX + searchStatusName; ListenableFuture> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink()); - return Futures.transform(relations, (AsyncFunction, List>) input -> { - List> alarmFutures = new ArrayList<>(input.size()); + return Futures.transform(relations, (AsyncFunction, List>) input -> { + List> alarmFutures = new ArrayList<>(input.size()); for (EntityRelation relation : input) { - alarmFutures.add(findAlarmByIdAsync(relation.getTo().getId())); + alarmFutures.add(Futures.transform( + findAlarmByIdAsync(relation.getTo().getId()), (Function) + alarm1 -> new AlarmInfo(alarm1))); } return Futures.successfulAsList(alarmFutures); }); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java index 5399d9dd7f..fb8a80d611 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.alarm; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmId; +import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.page.TimePageData; @@ -34,6 +35,6 @@ public interface AlarmService { ListenableFuture findAlarmByIdAsync(AlarmId alarmId); - ListenableFuture> findAlarms(AlarmQuery query); + ListenableFuture> findAlarms(AlarmQuery query); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index 3981f64701..d152d96767 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -17,22 +17,21 @@ package org.thingsboard.server.dao.alarm; import com.google.common.base.Function; +import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmId; -import org.thingsboard.server.common.data.alarm.AlarmQuery; -import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.alarm.*; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.entity.BaseEntityService; +import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.model.*; import org.thingsboard.server.dao.relation.EntityRelationsQuery; @@ -45,6 +44,7 @@ import org.thingsboard.server.dao.tenant.TenantDao; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -59,7 +59,6 @@ import static org.thingsboard.server.dao.service.Validator.*; public class BaseAlarmService extends AbstractEntityService implements AlarmService { public static final String ALARM_RELATION_PREFIX = "ALARM_"; - public static final String ALARM_RELATION = "ALARM_ANY"; @Autowired private AlarmDao alarmDao; @@ -70,6 +69,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @Autowired private RelationService relationService; + @Autowired + private EntityService entityService; + protected ExecutorService readResultsProcessingExecutor; @PostConstruct @@ -116,11 +118,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ query.setParameters(new RelationsSearchParameters(saved.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); List parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); for (EntityId parentId : parentEntities) { - createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); - createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); + createAlarmRelation(parentId, saved.getId(), saved.getStatus(), true); } - createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); - createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); + createAlarmRelation(alarm.getOriginator(), saved.getId(), saved.getStatus(), true); return saved; } @@ -199,12 +199,27 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ } @Override - public ListenableFuture> findAlarms(AlarmQuery query) { - ListenableFuture> alarms = alarmDao.findAlarms(query); - return Futures.transform(alarms, new Function, TimePageData>() { + public ListenableFuture> findAlarms(AlarmQuery query) { + ListenableFuture> alarms = alarmDao.findAlarms(query); + if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { + alarms = Futures.transform(alarms, (AsyncFunction, List>) input -> { + List> alarmFutures = new ArrayList<>(input.size()); + for (AlarmInfo alarmInfo : input) { + alarmFutures.add(Futures.transform( + entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function) + originatorName -> { + alarmInfo.setOriginatorName(originatorName); + return alarmInfo; + } + )); + } + return Futures.successfulAsList(alarmFutures); + }); + } + return Futures.transform(alarms, new Function, TimePageData>() { @Nullable @Override - public TimePageData apply(@Nullable List alarms) { + public TimePageData apply(@Nullable List alarms) { return new TimePageData<>(alarms, query.getPageLink()); } }); @@ -245,17 +260,45 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); List parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); for (EntityId parentId : parentEntities) { - deleteRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); - createRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); - } - deleteRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); - createRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); + updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus); + } + updateAlarmRelation(alarm.getOriginator(), alarm.getId(), oldStatus, newStatus); } catch (ExecutionException | InterruptedException e) { log.warn("[{}] Failed to update relations. Old status: [{}], New status: [{}]", alarm.getId(), oldStatus, newStatus); throw new RuntimeException(e); } } + private void createAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus status, boolean createAnyRelation) { + try { + if (createAnyRelation) { + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + AlarmSearchStatus.ANY.name(), RelationTypeGroup.ALARM)); + } + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM)); + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM)); + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM)); + } catch (ExecutionException | InterruptedException e) { + log.warn("[{}] Failed to create relation. Status: [{}]", alarmId, status); + throw new RuntimeException(e); + } + } + + private void deleteAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus status) { + try { + deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM)); + deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM)); + deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM)); + } catch (ExecutionException | InterruptedException e) { + log.warn("[{}] Failed to delete relation. Status: [{}]", alarmId, status); + throw new RuntimeException(e); + } + } + + private void updateAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus oldStatus, AlarmStatus newStatus) { + deleteAlarmRelation(entityId, alarmId, oldStatus); + createAlarmRelation(entityId, alarmId, newStatus, false); + } + private ListenableFuture getAndUpdate(AlarmId alarmId, Function function) { validateId(alarmId, "Alarm id should be specified!"); ListenableFuture entity = alarmDao.findAlarmByIdAsync(alarmId.getId()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java index 9fc2382d8d..77f79e1bc4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationDao.java @@ -178,9 +178,14 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { eq(ModelConstants.RELATION_TYPE_GROUP_PROPERTY, typeGroup.name()), eq(ModelConstants.RELATION_TYPE_PROPERTY, relationType), eq(ModelConstants.RELATION_TO_TYPE_PROPERTY, childType.name())), - Arrays.asList(QueryBuilder.asc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY), - QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), - QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY)), + Arrays.asList( + pageLink.isAscOrder() ? QueryBuilder.desc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY) : + QueryBuilder.asc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY), + pageLink.isAscOrder() ? QueryBuilder.desc(ModelConstants.RELATION_TYPE_PROPERTY) : + QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), + pageLink.isAscOrder() ? QueryBuilder.desc(ModelConstants.RELATION_TO_TYPE_PROPERTY) : + QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY) + ), pageLink, ModelConstants.RELATION_TO_ID_PROPERTY); return getFuture(executeAsyncRead(query), rs -> getEntityRelations(rs)); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AlarmServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AlarmServiceTest.java index 3b72574302..b22df63e3f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/AlarmServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/AlarmServiceTest.java @@ -22,10 +22,7 @@ import org.junit.Before; import org.junit.Test; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmQuery; -import org.thingsboard.server.common.data.alarm.AlarmSeverity; -import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.alarm.*; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -117,7 +114,7 @@ public class AlarmServiceTest extends AbstractServiceTest { Alarm created = alarmService.createOrUpdateAlarm(alarm); // Check child relation - TimePageData alarms = alarmService.findAlarms(AlarmQuery.builder() + TimePageData alarms = alarmService.findAlarms(AlarmQuery.builder() .affectedEntityId(childId) .status(AlarmStatus.ACTIVE_UNACK).pageLink( new TimePageLink(1, 0L, System.currentTimeMillis(), false) diff --git a/ui/src/app/api/alarm.service.js b/ui/src/app/api/alarm.service.js index d9ab4ff338..ca892f292b 100644 --- a/ui/src/app/api/alarm.service.js +++ b/ui/src/app/api/alarm.service.js @@ -91,7 +91,7 @@ function AlarmService($http, $q, $interval, $filter) { return deferred.promise; } - function getAlarms(entityType, entityId, pageLink, alarmStatus, ascOrder, config) { + function getAlarms(entityType, entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator, ascOrder, config) { var deferred = $q.defer(); var url = '/api/alarm/' + entityType + '/' + entityId + '?limit=' + pageLink.limit; @@ -104,9 +104,15 @@ function AlarmService($http, $q, $interval, $filter) { if (angular.isDefined(pageLink.idOffset)) { url += '&offset=' + pageLink.idOffset; } + if (alarmSearchStatus) { + url += '&searchStatus=' + alarmSearchStatus; + } if (alarmStatus) { url += '&status=' + alarmStatus; } + if (fetchOriginator) { + url += '&fetchOriginator=' + ((fetchOriginator===true) ? 'true' : 'false'); + } if (angular.isDefined(ascOrder) && ascOrder != null) { url += '&ascOrder=' + (ascOrder ? 'true' : 'false'); } @@ -121,7 +127,8 @@ function AlarmService($http, $q, $interval, $filter) { function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) { getAlarms(alarmsQuery.entityType, alarmsQuery.entityId, - pageLink, alarmsQuery.alarmStatus, false, {ignoreLoading: true}).then( + pageLink, alarmsQuery.alarmSearchStatus, alarmsQuery.alarmStatus, + alarmsQuery.fetchOriginator, false, {ignoreLoading: true}).then( function success(alarms) { if (!alarmsList) { alarmsList = []; @@ -171,7 +178,9 @@ function AlarmService($http, $q, $interval, $filter) { var alarmsQuery = { entityType: entityType, entityId: entityId, + alarmSearchStatus: null, alarmStatus: alarmStatus, + fetchOriginator: false, interval: interval, limit: limit, onAlarms: onAlarms diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index fe3f73ca88..20760937a3 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -65,6 +65,13 @@ export default angular.module('thingsboard.types', []) clearedUnack: "CLEARED_UNACK", clearedAck: "CLEARED_ACK" }, + alarmSearchStatus: { + any: "ANY", + active: "ACTIVE", + cleared: "CLEARED", + ack: "ACK", + unack: "UNACK" + }, aliasFilterType: { entityList: { value: 'entityList',