Commit 351684a6cdefc028213ace04234b49e6dc13661d
1 parent
2cb71c15
TB-63: Update Alarms search query with AlarmSearchStatus parameter.
Showing
14 changed files
with
230 additions
and
43 deletions
... | ... | @@ -22,10 +22,7 @@ import org.springframework.security.access.prepost.PreAuthorize; |
22 | 22 | import org.springframework.web.bind.annotation.*; |
23 | 23 | import org.thingsboard.server.common.data.Customer; |
24 | 24 | import org.thingsboard.server.common.data.Event; |
25 | -import org.thingsboard.server.common.data.alarm.Alarm; | |
26 | -import org.thingsboard.server.common.data.alarm.AlarmId; | |
27 | -import org.thingsboard.server.common.data.alarm.AlarmQuery; | |
28 | -import org.thingsboard.server.common.data.alarm.AlarmStatus; | |
25 | +import org.thingsboard.server.common.data.alarm.*; | |
29 | 26 | import org.thingsboard.server.common.data.asset.Asset; |
30 | 27 | import org.thingsboard.server.common.data.id.*; |
31 | 28 | import org.thingsboard.server.common.data.page.TextPageData; |
... | ... | @@ -103,24 +100,31 @@ public class AlarmController extends BaseController { |
103 | 100 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
104 | 101 | @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) |
105 | 102 | @ResponseBody |
106 | - public TimePageData<Alarm> getAlarms( | |
103 | + public TimePageData<AlarmInfo> getAlarms( | |
107 | 104 | @PathVariable("entityType") String strEntityType, |
108 | 105 | @PathVariable("entityId") String strEntityId, |
106 | + @RequestParam(required = false) String searchStatus, | |
109 | 107 | @RequestParam(required = false) String status, |
110 | 108 | @RequestParam int limit, |
111 | 109 | @RequestParam(required = false) Long startTime, |
112 | 110 | @RequestParam(required = false) Long endTime, |
113 | 111 | @RequestParam(required = false, defaultValue = "false") boolean ascOrder, |
114 | - @RequestParam(required = false) String offset | |
112 | + @RequestParam(required = false) String offset, | |
113 | + @RequestParam(required = false) Boolean fetchOriginator | |
115 | 114 | ) throws ThingsboardException { |
116 | 115 | checkParameter("EntityId", strEntityId); |
117 | 116 | checkParameter("EntityType", strEntityType); |
118 | 117 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); |
118 | + AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); | |
119 | 119 | AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); |
120 | + if (alarmSearchStatus != null && alarmStatus != null) { | |
121 | + throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " + | |
122 | + "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | |
123 | + } | |
120 | 124 | checkEntityId(entityId); |
121 | 125 | try { |
122 | 126 | TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); |
123 | - return checkNotNull(alarmService.findAlarms(new AlarmQuery(entityId, pageLink, alarmStatus)).get()); | |
127 | + return checkNotNull(alarmService.findAlarms(new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); | |
124 | 128 | } catch (Exception e) { |
125 | 129 | throw handleException(e); |
126 | 130 | } | ... | ... |
... | ... | @@ -53,6 +53,21 @@ public class Alarm extends BaseData<AlarmId> implements HasName { |
53 | 53 | super(id); |
54 | 54 | } |
55 | 55 | |
56 | + public Alarm(Alarm alarm) { | |
57 | + super(alarm.getId()); | |
58 | + this.tenantId = alarm.getTenantId(); | |
59 | + this.type = alarm.getType(); | |
60 | + this.originator = alarm.getOriginator(); | |
61 | + this.severity = alarm.getSeverity(); | |
62 | + this.status = alarm.getStatus(); | |
63 | + this.startTs = alarm.getStartTs(); | |
64 | + this.endTs = alarm.getEndTs(); | |
65 | + this.ackTs = alarm.getAckTs(); | |
66 | + this.clearTs = alarm.getClearTs(); | |
67 | + this.details = alarm.getDetails(); | |
68 | + this.propagate = alarm.isPropagate(); | |
69 | + } | |
70 | + | |
56 | 71 | @Override |
57 | 72 | @JsonProperty(access = JsonProperty.Access.READ_ONLY) |
58 | 73 | public String getName() { | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.alarm; | |
17 | + | |
18 | +public class AlarmInfo extends Alarm { | |
19 | + | |
20 | + private static final long serialVersionUID = 2807343093519543363L; | |
21 | + | |
22 | + private String originatorName; | |
23 | + | |
24 | + public AlarmInfo() { | |
25 | + super(); | |
26 | + } | |
27 | + | |
28 | + public AlarmInfo(Alarm alarm) { | |
29 | + super(alarm); | |
30 | + } | |
31 | + | |
32 | + public String getOriginatorName() { | |
33 | + return originatorName; | |
34 | + } | |
35 | + | |
36 | + public void setOriginatorName(String originatorName) { | |
37 | + this.originatorName = originatorName; | |
38 | + } | |
39 | + | |
40 | + @Override | |
41 | + public boolean equals(Object o) { | |
42 | + if (this == o) return true; | |
43 | + if (o == null || getClass() != o.getClass()) return false; | |
44 | + if (!super.equals(o)) return false; | |
45 | + | |
46 | + AlarmInfo alarmInfo = (AlarmInfo) o; | |
47 | + | |
48 | + return originatorName != null ? originatorName.equals(alarmInfo.originatorName) : alarmInfo.originatorName == null; | |
49 | + | |
50 | + } | |
51 | + | |
52 | + @Override | |
53 | + public int hashCode() { | |
54 | + int result = super.hashCode(); | |
55 | + result = 31 * result + (originatorName != null ? originatorName.hashCode() : 0); | |
56 | + return result; | |
57 | + } | |
58 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmSearchStatus.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +package org.thingsboard.server.common.data.alarm; | |
18 | + | |
19 | +public enum AlarmSearchStatus { | |
20 | + | |
21 | + ANY, ACTIVE, CLEARED, ACK, UNACK | |
22 | + | |
23 | +} | ... | ... |
... | ... | @@ -30,4 +30,13 @@ public enum AlarmStatus { |
30 | 30 | return this == CLEARED_ACK || this == CLEARED_UNACK; |
31 | 31 | } |
32 | 32 | |
33 | + public AlarmSearchStatus getClearSearchStatus() { | |
34 | + return this.isCleared() ? AlarmSearchStatus.CLEARED : AlarmSearchStatus.ACTIVE; | |
35 | + } | |
36 | + | |
37 | + public AlarmSearchStatus getAckSearchStatus() { | |
38 | + return this.isAck() ? AlarmSearchStatus.ACK : AlarmSearchStatus.UNACK; | |
39 | + } | |
40 | + | |
41 | + | |
33 | 42 | } | ... | ... |
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | 19 | import org.thingsboard.server.common.data.alarm.Alarm; |
20 | +import org.thingsboard.server.common.data.alarm.AlarmInfo; | |
20 | 21 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
21 | 22 | import org.thingsboard.server.common.data.id.EntityId; |
22 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -37,5 +38,5 @@ public interface AlarmDao extends Dao<AlarmEntity> { |
37 | 38 | |
38 | 39 | AlarmEntity save(Alarm alarm); |
39 | 40 | |
40 | - ListenableFuture<List<Alarm>> findAlarms(AlarmQuery query); | |
41 | + ListenableFuture<List<AlarmInfo>> findAlarms(AlarmQuery query); | |
41 | 42 | } | ... | ... |
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; |
17 | 17 | |
18 | 18 | import com.datastax.driver.core.querybuilder.QueryBuilder; |
19 | 19 | import com.datastax.driver.core.querybuilder.Select; |
20 | +import com.google.common.base.Function; | |
20 | 21 | import com.google.common.util.concurrent.AsyncFunction; |
21 | 22 | import com.google.common.util.concurrent.Futures; |
22 | 23 | import com.google.common.util.concurrent.ListenableFuture; |
... | ... | @@ -25,7 +26,9 @@ import org.springframework.beans.factory.annotation.Autowired; |
25 | 26 | import org.springframework.stereotype.Component; |
26 | 27 | import org.thingsboard.server.common.data.EntityType; |
27 | 28 | import org.thingsboard.server.common.data.alarm.Alarm; |
29 | +import org.thingsboard.server.common.data.alarm.AlarmInfo; | |
28 | 30 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
31 | +import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; | |
29 | 32 | import org.thingsboard.server.common.data.id.EntityId; |
30 | 33 | import org.thingsboard.server.common.data.id.TenantId; |
31 | 34 | import org.thingsboard.server.common.data.relation.EntityRelation; |
... | ... | @@ -94,15 +97,25 @@ public class AlarmDaoImpl extends AbstractModelDao<AlarmEntity> implements Alarm |
94 | 97 | } |
95 | 98 | |
96 | 99 | @Override |
97 | - public ListenableFuture<List<Alarm>> findAlarms(AlarmQuery query) { | |
98 | - log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink()); | |
100 | + public ListenableFuture<List<AlarmInfo>> findAlarms(AlarmQuery query) { | |
101 | + log.trace("Try to find alarms by entity [{}], searchStatus [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getSearchStatus(), query.getStatus(), query.getPageLink()); | |
99 | 102 | EntityId affectedEntity = query.getAffectedEntityId(); |
100 | - String relationType = query.getStatus() == null ? BaseAlarmService.ALARM_RELATION : BaseAlarmService.ALARM_RELATION_PREFIX + query.getStatus().name(); | |
103 | + String searchStatusName; | |
104 | + if (query.getSearchStatus() == null && query.getStatus() == null) { | |
105 | + searchStatusName = AlarmSearchStatus.ANY.name(); | |
106 | + } else if (query.getSearchStatus() != null) { | |
107 | + searchStatusName = query.getSearchStatus().name(); | |
108 | + } else { | |
109 | + searchStatusName = query.getStatus().name(); | |
110 | + } | |
111 | + String relationType = BaseAlarmService.ALARM_RELATION_PREFIX + searchStatusName; | |
101 | 112 | ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink()); |
102 | - return Futures.transform(relations, (AsyncFunction<List<EntityRelation>, List<Alarm>>) input -> { | |
103 | - List<ListenableFuture<Alarm>> alarmFutures = new ArrayList<>(input.size()); | |
113 | + return Futures.transform(relations, (AsyncFunction<List<EntityRelation>, List<AlarmInfo>>) input -> { | |
114 | + List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size()); | |
104 | 115 | for (EntityRelation relation : input) { |
105 | - alarmFutures.add(findAlarmByIdAsync(relation.getTo().getId())); | |
116 | + alarmFutures.add(Futures.transform( | |
117 | + findAlarmByIdAsync(relation.getTo().getId()), (Function<Alarm, AlarmInfo>) | |
118 | + alarm1 -> new AlarmInfo(alarm1))); | |
106 | 119 | } |
107 | 120 | return Futures.successfulAsList(alarmFutures); |
108 | 121 | }); | ... | ... |
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.alarm; |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | 19 | import org.thingsboard.server.common.data.alarm.Alarm; |
20 | 20 | import org.thingsboard.server.common.data.alarm.AlarmId; |
21 | +import org.thingsboard.server.common.data.alarm.AlarmInfo; | |
21 | 22 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
22 | 23 | import org.thingsboard.server.common.data.page.TimePageData; |
23 | 24 | |
... | ... | @@ -34,6 +35,6 @@ public interface AlarmService { |
34 | 35 | |
35 | 36 | ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId); |
36 | 37 | |
37 | - ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query); | |
38 | + ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query); | |
38 | 39 | |
39 | 40 | } | ... | ... |
... | ... | @@ -17,22 +17,21 @@ package org.thingsboard.server.dao.alarm; |
17 | 17 | |
18 | 18 | |
19 | 19 | import com.google.common.base.Function; |
20 | +import com.google.common.util.concurrent.AsyncFunction; | |
20 | 21 | import com.google.common.util.concurrent.Futures; |
21 | 22 | import com.google.common.util.concurrent.ListenableFuture; |
22 | 23 | import lombok.extern.slf4j.Slf4j; |
23 | 24 | import org.springframework.beans.factory.annotation.Autowired; |
24 | 25 | import org.springframework.stereotype.Service; |
25 | 26 | import org.springframework.util.StringUtils; |
26 | -import org.thingsboard.server.common.data.alarm.Alarm; | |
27 | -import org.thingsboard.server.common.data.alarm.AlarmId; | |
28 | -import org.thingsboard.server.common.data.alarm.AlarmQuery; | |
29 | -import org.thingsboard.server.common.data.alarm.AlarmStatus; | |
27 | +import org.thingsboard.server.common.data.alarm.*; | |
30 | 28 | import org.thingsboard.server.common.data.id.EntityId; |
31 | 29 | import org.thingsboard.server.common.data.page.TimePageData; |
32 | 30 | import org.thingsboard.server.common.data.relation.EntityRelation; |
33 | 31 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
34 | 32 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
35 | 33 | import org.thingsboard.server.dao.entity.BaseEntityService; |
34 | +import org.thingsboard.server.dao.entity.EntityService; | |
36 | 35 | import org.thingsboard.server.dao.exception.DataValidationException; |
37 | 36 | import org.thingsboard.server.dao.model.*; |
38 | 37 | import org.thingsboard.server.dao.relation.EntityRelationsQuery; |
... | ... | @@ -45,6 +44,7 @@ import org.thingsboard.server.dao.tenant.TenantDao; |
45 | 44 | import javax.annotation.Nullable; |
46 | 45 | import javax.annotation.PostConstruct; |
47 | 46 | import javax.annotation.PreDestroy; |
47 | +import java.util.ArrayList; | |
48 | 48 | import java.util.List; |
49 | 49 | import java.util.concurrent.ExecutionException; |
50 | 50 | import java.util.concurrent.ExecutorService; |
... | ... | @@ -59,7 +59,6 @@ import static org.thingsboard.server.dao.service.Validator.*; |
59 | 59 | public class BaseAlarmService extends AbstractEntityService implements AlarmService { |
60 | 60 | |
61 | 61 | public static final String ALARM_RELATION_PREFIX = "ALARM_"; |
62 | - public static final String ALARM_RELATION = "ALARM_ANY"; | |
63 | 62 | |
64 | 63 | @Autowired |
65 | 64 | private AlarmDao alarmDao; |
... | ... | @@ -70,6 +69,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ |
70 | 69 | @Autowired |
71 | 70 | private RelationService relationService; |
72 | 71 | |
72 | + @Autowired | |
73 | + private EntityService entityService; | |
74 | + | |
73 | 75 | protected ExecutorService readResultsProcessingExecutor; |
74 | 76 | |
75 | 77 | @PostConstruct |
... | ... | @@ -116,11 +118,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ |
116 | 118 | query.setParameters(new RelationsSearchParameters(saved.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); |
117 | 119 | List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); |
118 | 120 | for (EntityId parentId : parentEntities) { |
119 | - createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); | |
120 | - createRelation(new EntityRelation(parentId, saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); | |
121 | + createAlarmRelation(parentId, saved.getId(), saved.getStatus(), true); | |
121 | 122 | } |
122 | - createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION, RelationTypeGroup.ALARM)); | |
123 | - createRelation(new EntityRelation(alarm.getOriginator(), saved.getId(), ALARM_RELATION_PREFIX + saved.getStatus().name(), RelationTypeGroup.ALARM)); | |
123 | + createAlarmRelation(alarm.getOriginator(), saved.getId(), saved.getStatus(), true); | |
124 | 124 | return saved; |
125 | 125 | } |
126 | 126 | |
... | ... | @@ -199,12 +199,27 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ |
199 | 199 | } |
200 | 200 | |
201 | 201 | @Override |
202 | - public ListenableFuture<TimePageData<Alarm>> findAlarms(AlarmQuery query) { | |
203 | - ListenableFuture<List<Alarm>> alarms = alarmDao.findAlarms(query); | |
204 | - return Futures.transform(alarms, new Function<List<Alarm>, TimePageData<Alarm>>() { | |
202 | + public ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query) { | |
203 | + ListenableFuture<List<AlarmInfo>> alarms = alarmDao.findAlarms(query); | |
204 | + if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { | |
205 | + alarms = Futures.transform(alarms, (AsyncFunction<List<AlarmInfo>, List<AlarmInfo>>) input -> { | |
206 | + List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size()); | |
207 | + for (AlarmInfo alarmInfo : input) { | |
208 | + alarmFutures.add(Futures.transform( | |
209 | + entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>) | |
210 | + originatorName -> { | |
211 | + alarmInfo.setOriginatorName(originatorName); | |
212 | + return alarmInfo; | |
213 | + } | |
214 | + )); | |
215 | + } | |
216 | + return Futures.successfulAsList(alarmFutures); | |
217 | + }); | |
218 | + } | |
219 | + return Futures.transform(alarms, new Function<List<AlarmInfo>, TimePageData<AlarmInfo>>() { | |
205 | 220 | @Nullable |
206 | 221 | @Override |
207 | - public TimePageData<Alarm> apply(@Nullable List<Alarm> alarms) { | |
222 | + public TimePageData<AlarmInfo> apply(@Nullable List<AlarmInfo> alarms) { | |
208 | 223 | return new TimePageData<>(alarms, query.getPageLink()); |
209 | 224 | } |
210 | 225 | }); |
... | ... | @@ -245,17 +260,45 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ |
245 | 260 | query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); |
246 | 261 | List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList()); |
247 | 262 | for (EntityId parentId : parentEntities) { |
248 | - deleteRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); | |
249 | - createRelation(new EntityRelation(parentId, alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); | |
250 | - } | |
251 | - deleteRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + oldStatus.name(), RelationTypeGroup.ALARM)); | |
252 | - createRelation(new EntityRelation(alarm.getOriginator(), alarm.getId(), ALARM_RELATION_PREFIX + newStatus.name(), RelationTypeGroup.ALARM)); | |
263 | + updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus); | |
264 | + } | |
265 | + updateAlarmRelation(alarm.getOriginator(), alarm.getId(), oldStatus, newStatus); | |
253 | 266 | } catch (ExecutionException | InterruptedException e) { |
254 | 267 | log.warn("[{}] Failed to update relations. Old status: [{}], New status: [{}]", alarm.getId(), oldStatus, newStatus); |
255 | 268 | throw new RuntimeException(e); |
256 | 269 | } |
257 | 270 | } |
258 | 271 | |
272 | + private void createAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus status, boolean createAnyRelation) { | |
273 | + try { | |
274 | + if (createAnyRelation) { | |
275 | + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + AlarmSearchStatus.ANY.name(), RelationTypeGroup.ALARM)); | |
276 | + } | |
277 | + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM)); | |
278 | + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM)); | |
279 | + createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM)); | |
280 | + } catch (ExecutionException | InterruptedException e) { | |
281 | + log.warn("[{}] Failed to create relation. Status: [{}]", alarmId, status); | |
282 | + throw new RuntimeException(e); | |
283 | + } | |
284 | + } | |
285 | + | |
286 | + private void deleteAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus status) { | |
287 | + try { | |
288 | + deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM)); | |
289 | + deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM)); | |
290 | + deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM)); | |
291 | + } catch (ExecutionException | InterruptedException e) { | |
292 | + log.warn("[{}] Failed to delete relation. Status: [{}]", alarmId, status); | |
293 | + throw new RuntimeException(e); | |
294 | + } | |
295 | + } | |
296 | + | |
297 | + private void updateAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus oldStatus, AlarmStatus newStatus) { | |
298 | + deleteAlarmRelation(entityId, alarmId, oldStatus); | |
299 | + createAlarmRelation(entityId, alarmId, newStatus, false); | |
300 | + } | |
301 | + | |
259 | 302 | private <T> ListenableFuture<T> getAndUpdate(AlarmId alarmId, Function<Alarm, T> function) { |
260 | 303 | validateId(alarmId, "Alarm id should be specified!"); |
261 | 304 | ListenableFuture<Alarm> entity = alarmDao.findAlarmByIdAsync(alarmId.getId()); | ... | ... |
... | ... | @@ -178,9 +178,14 @@ public class BaseRelationDao extends AbstractAsyncDao implements RelationDao { |
178 | 178 | eq(ModelConstants.RELATION_TYPE_GROUP_PROPERTY, typeGroup.name()), |
179 | 179 | eq(ModelConstants.RELATION_TYPE_PROPERTY, relationType), |
180 | 180 | eq(ModelConstants.RELATION_TO_TYPE_PROPERTY, childType.name())), |
181 | - Arrays.asList(QueryBuilder.asc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY), | |
182 | - QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), | |
183 | - QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY)), | |
181 | + Arrays.asList( | |
182 | + pageLink.isAscOrder() ? QueryBuilder.desc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY) : | |
183 | + QueryBuilder.asc(ModelConstants.RELATION_TYPE_GROUP_PROPERTY), | |
184 | + pageLink.isAscOrder() ? QueryBuilder.desc(ModelConstants.RELATION_TYPE_PROPERTY) : | |
185 | + QueryBuilder.asc(ModelConstants.RELATION_TYPE_PROPERTY), | |
186 | + pageLink.isAscOrder() ? QueryBuilder.desc(ModelConstants.RELATION_TO_TYPE_PROPERTY) : | |
187 | + QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY) | |
188 | + ), | |
184 | 189 | pageLink, ModelConstants.RELATION_TO_ID_PROPERTY); |
185 | 190 | return getFuture(executeAsyncRead(query), rs -> getEntityRelations(rs)); |
186 | 191 | } | ... | ... |
... | ... | @@ -22,10 +22,7 @@ import org.junit.Before; |
22 | 22 | import org.junit.Test; |
23 | 23 | import org.thingsboard.server.common.data.EntityType; |
24 | 24 | import org.thingsboard.server.common.data.Tenant; |
25 | -import org.thingsboard.server.common.data.alarm.Alarm; | |
26 | -import org.thingsboard.server.common.data.alarm.AlarmQuery; | |
27 | -import org.thingsboard.server.common.data.alarm.AlarmSeverity; | |
28 | -import org.thingsboard.server.common.data.alarm.AlarmStatus; | |
25 | +import org.thingsboard.server.common.data.alarm.*; | |
29 | 26 | import org.thingsboard.server.common.data.id.AssetId; |
30 | 27 | import org.thingsboard.server.common.data.id.DeviceId; |
31 | 28 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -117,7 +114,7 @@ public class AlarmServiceTest extends AbstractServiceTest { |
117 | 114 | Alarm created = alarmService.createOrUpdateAlarm(alarm); |
118 | 115 | |
119 | 116 | // Check child relation |
120 | - TimePageData<Alarm> alarms = alarmService.findAlarms(AlarmQuery.builder() | |
117 | + TimePageData<AlarmInfo> alarms = alarmService.findAlarms(AlarmQuery.builder() | |
121 | 118 | .affectedEntityId(childId) |
122 | 119 | .status(AlarmStatus.ACTIVE_UNACK).pageLink( |
123 | 120 | new TimePageLink(1, 0L, System.currentTimeMillis(), false) | ... | ... |
... | ... | @@ -91,7 +91,7 @@ function AlarmService($http, $q, $interval, $filter) { |
91 | 91 | return deferred.promise; |
92 | 92 | } |
93 | 93 | |
94 | - function getAlarms(entityType, entityId, pageLink, alarmStatus, ascOrder, config) { | |
94 | + function getAlarms(entityType, entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator, ascOrder, config) { | |
95 | 95 | var deferred = $q.defer(); |
96 | 96 | var url = '/api/alarm/' + entityType + '/' + entityId + '?limit=' + pageLink.limit; |
97 | 97 | |
... | ... | @@ -104,9 +104,15 @@ function AlarmService($http, $q, $interval, $filter) { |
104 | 104 | if (angular.isDefined(pageLink.idOffset)) { |
105 | 105 | url += '&offset=' + pageLink.idOffset; |
106 | 106 | } |
107 | + if (alarmSearchStatus) { | |
108 | + url += '&searchStatus=' + alarmSearchStatus; | |
109 | + } | |
107 | 110 | if (alarmStatus) { |
108 | 111 | url += '&status=' + alarmStatus; |
109 | 112 | } |
113 | + if (fetchOriginator) { | |
114 | + url += '&fetchOriginator=' + ((fetchOriginator===true) ? 'true' : 'false'); | |
115 | + } | |
110 | 116 | if (angular.isDefined(ascOrder) && ascOrder != null) { |
111 | 117 | url += '&ascOrder=' + (ascOrder ? 'true' : 'false'); |
112 | 118 | } |
... | ... | @@ -121,7 +127,8 @@ function AlarmService($http, $q, $interval, $filter) { |
121 | 127 | |
122 | 128 | function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) { |
123 | 129 | getAlarms(alarmsQuery.entityType, alarmsQuery.entityId, |
124 | - pageLink, alarmsQuery.alarmStatus, false, {ignoreLoading: true}).then( | |
130 | + pageLink, alarmsQuery.alarmSearchStatus, alarmsQuery.alarmStatus, | |
131 | + alarmsQuery.fetchOriginator, false, {ignoreLoading: true}).then( | |
125 | 132 | function success(alarms) { |
126 | 133 | if (!alarmsList) { |
127 | 134 | alarmsList = []; |
... | ... | @@ -171,7 +178,9 @@ function AlarmService($http, $q, $interval, $filter) { |
171 | 178 | var alarmsQuery = { |
172 | 179 | entityType: entityType, |
173 | 180 | entityId: entityId, |
181 | + alarmSearchStatus: null, | |
174 | 182 | alarmStatus: alarmStatus, |
183 | + fetchOriginator: false, | |
175 | 184 | interval: interval, |
176 | 185 | limit: limit, |
177 | 186 | onAlarms: onAlarms | ... | ... |
... | ... | @@ -65,6 +65,13 @@ export default angular.module('thingsboard.types', []) |
65 | 65 | clearedUnack: "CLEARED_UNACK", |
66 | 66 | clearedAck: "CLEARED_ACK" |
67 | 67 | }, |
68 | + alarmSearchStatus: { | |
69 | + any: "ANY", | |
70 | + active: "ACTIVE", | |
71 | + cleared: "CLEARED", | |
72 | + ack: "ACK", | |
73 | + unack: "UNACK" | |
74 | + }, | |
68 | 75 | aliasFilterType: { |
69 | 76 | entityList: { |
70 | 77 | value: 'entityList', | ... | ... |