thingsboard-memoizeit
Changes
common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmSearchStatus.java 23(+23 -0)
ui/src/app/api/alarm.service.js 13(+11 -2)
ui/src/app/common/types.constant.js 7(+7 -0)
Details
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 7a2c273..19774bb 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<Alarm> getAlarms(
+ public TimePageData<AlarmInfo> 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 09695e5..9c6f998 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<AlarmId> 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 0000000..ef24f1c
--- /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 00ca6c3..55019c8 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 0000000..c09b1fd
--- /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 0f1b346..a8704b2 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 9fdd92e..289d5c9 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> {
AlarmEntity save(Alarm alarm);
- ListenableFuture<List<Alarm>> findAlarms(AlarmQuery query);
+ ListenableFuture<List<AlarmInfo>> 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 1362e6b..72fbae5 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<AlarmEntity> implements Alarm
}
@Override
- public ListenableFuture<List<Alarm>> findAlarms(AlarmQuery query) {
- log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink());
+ public ListenableFuture<List<AlarmInfo>> 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<List<EntityRelation>> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink());
- return Futures.transform(relations, (AsyncFunction<List<EntityRelation>, List<Alarm>>) input -> {
- List<ListenableFuture<Alarm>> alarmFutures = new ArrayList<>(input.size());
+ return Futures.transform(relations, (AsyncFunction<List<EntityRelation>, List<AlarmInfo>>) input -> {
+ List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size());
for (EntityRelation relation : input) {
- alarmFutures.add(findAlarmByIdAsync(relation.getTo().getId()));
+ alarmFutures.add(Futures.transform(
+ findAlarmByIdAsync(relation.getTo().getId()), (Function<Alarm, AlarmInfo>)
+ 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 5399d9d..fb8a80d 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<Alarm> findAlarmByIdAsync(AlarmId alarmId);
- ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query);
+ ListenableFuture<TimePageData<AlarmInfo>> 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 3981f64..d152d96 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<EntityId> 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<TimePageData<Alarm>> findAlarms(AlarmQuery query) {
- ListenableFuture<List<Alarm>> alarms = alarmDao.findAlarms(query);
- return Futures.transform(alarms, new Function<List<Alarm>, TimePageData<Alarm>>() {
+ public ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query) {
+ ListenableFuture<List<AlarmInfo>> alarms = alarmDao.findAlarms(query);
+ if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) {
+ alarms = Futures.transform(alarms, (AsyncFunction<List<AlarmInfo>, List<AlarmInfo>>) input -> {
+ List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size());
+ for (AlarmInfo alarmInfo : input) {
+ alarmFutures.add(Futures.transform(
+ entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>)
+ originatorName -> {
+ alarmInfo.setOriginatorName(originatorName);
+ return alarmInfo;
+ }
+ ));
+ }
+ return Futures.successfulAsList(alarmFutures);
+ });
+ }
+ return Futures.transform(alarms, new Function<List<AlarmInfo>, TimePageData<AlarmInfo>>() {
@Nullable
@Override
- public TimePageData<Alarm> apply(@Nullable List<Alarm> alarms) {
+ public TimePageData<AlarmInfo> apply(@Nullable List<AlarmInfo> 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<EntityId> 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 <T> ListenableFuture<T> getAndUpdate(AlarmId alarmId, Function<Alarm, T> function) {
validateId(alarmId, "Alarm id should be specified!");
ListenableFuture<Alarm> 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 9fc2382..77f79e1 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 3b72574..b22df63 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<Alarm> alarms = alarmService.findAlarms(AlarmQuery.builder()
+ TimePageData<AlarmInfo> alarms = alarmService.findAlarms(AlarmQuery.builder()
.affectedEntityId(childId)
.status(AlarmStatus.ACTIVE_UNACK).pageLink(
new TimePageLink(1, 0L, System.currentTimeMillis(), false)
ui/src/app/api/alarm.service.js 13(+11 -2)
diff --git a/ui/src/app/api/alarm.service.js b/ui/src/app/api/alarm.service.js
index d9ab4ff..ca892f2 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
ui/src/app/common/types.constant.js 7(+7 -0)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index fe3f73c..2076093 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',