Commit 87683218b556558fbb81e2faf0898de5e55fb879
1 parent
69a0b74c
TB-63: Find highest alarm severity for specified entity.
Showing
4 changed files
with
91 additions
and
4 deletions
@@ -143,4 +143,30 @@ public class AlarmController extends BaseController { | @@ -143,4 +143,30 @@ public class AlarmController extends BaseController { | ||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
147 | + @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) | ||
148 | + @ResponseBody | ||
149 | + public AlarmSeverity getHighestAlarmSeverity( | ||
150 | + @PathVariable("entityType") String strEntityType, | ||
151 | + @PathVariable("entityId") String strEntityId, | ||
152 | + @RequestParam(required = false) String searchStatus, | ||
153 | + @RequestParam(required = false) String status | ||
154 | + ) throws ThingsboardException { | ||
155 | + checkParameter("EntityId", strEntityId); | ||
156 | + checkParameter("EntityType", strEntityType); | ||
157 | + EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); | ||
158 | + AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); | ||
159 | + AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); | ||
160 | + if (alarmSearchStatus != null && alarmStatus != null) { | ||
161 | + throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " + | ||
162 | + "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | ||
163 | + } | ||
164 | + checkEntityId(entityId); | ||
165 | + try { | ||
166 | + return alarmService.findHighestAlarmSeverity(entityId, alarmSearchStatus, alarmStatus); | ||
167 | + } catch (Exception e) { | ||
168 | + throw handleException(e); | ||
169 | + } | ||
170 | + } | ||
171 | + | ||
146 | } | 172 | } |
@@ -16,10 +16,8 @@ | @@ -16,10 +16,8 @@ | ||
16 | package org.thingsboard.server.dao.alarm; | 16 | package org.thingsboard.server.dao.alarm; |
17 | 17 | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | -import org.thingsboard.server.common.data.alarm.Alarm; | ||
20 | -import org.thingsboard.server.common.data.alarm.AlarmId; | ||
21 | -import org.thingsboard.server.common.data.alarm.AlarmInfo; | ||
22 | -import org.thingsboard.server.common.data.alarm.AlarmQuery; | 19 | +import org.thingsboard.server.common.data.alarm.*; |
20 | +import org.thingsboard.server.common.data.id.EntityId; | ||
23 | import org.thingsboard.server.common.data.page.TimePageData; | 21 | import org.thingsboard.server.common.data.page.TimePageData; |
24 | 22 | ||
25 | /** | 23 | /** |
@@ -39,4 +37,7 @@ public interface AlarmService { | @@ -39,4 +37,7 @@ public interface AlarmService { | ||
39 | 37 | ||
40 | ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query); | 38 | ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query); |
41 | 39 | ||
40 | + AlarmSeverity findHighestAlarmSeverity(EntityId entityId, AlarmSearchStatus alarmSearchStatus, | ||
41 | + AlarmStatus alarmStatus); | ||
42 | + | ||
42 | } | 43 | } |
@@ -27,6 +27,7 @@ import org.springframework.util.StringUtils; | @@ -27,6 +27,7 @@ import org.springframework.util.StringUtils; | ||
27 | import org.thingsboard.server.common.data.alarm.*; | 27 | import org.thingsboard.server.common.data.alarm.*; |
28 | import org.thingsboard.server.common.data.id.EntityId; | 28 | import org.thingsboard.server.common.data.id.EntityId; |
29 | import org.thingsboard.server.common.data.page.TimePageData; | 29 | import org.thingsboard.server.common.data.page.TimePageData; |
30 | +import org.thingsboard.server.common.data.page.TimePageLink; | ||
30 | import org.thingsboard.server.common.data.relation.EntityRelation; | 31 | import org.thingsboard.server.common.data.relation.EntityRelation; |
31 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 32 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
32 | import org.thingsboard.server.dao.entity.AbstractEntityService; | 33 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
@@ -46,6 +47,7 @@ import javax.annotation.PostConstruct; | @@ -46,6 +47,7 @@ import javax.annotation.PostConstruct; | ||
46 | import javax.annotation.PreDestroy; | 47 | import javax.annotation.PreDestroy; |
47 | import java.util.ArrayList; | 48 | import java.util.ArrayList; |
48 | import java.util.List; | 49 | import java.util.List; |
50 | +import java.util.UUID; | ||
49 | import java.util.concurrent.ExecutionException; | 51 | import java.util.concurrent.ExecutionException; |
50 | import java.util.concurrent.ExecutorService; | 52 | import java.util.concurrent.ExecutorService; |
51 | import java.util.concurrent.Executors; | 53 | import java.util.concurrent.Executors; |
@@ -242,6 +244,46 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -242,6 +244,46 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
242 | }); | 244 | }); |
243 | } | 245 | } |
244 | 246 | ||
247 | + @Override | ||
248 | + public AlarmSeverity findHighestAlarmSeverity(EntityId entityId, AlarmSearchStatus alarmSearchStatus, | ||
249 | + AlarmStatus alarmStatus) { | ||
250 | + TimePageLink nextPageLink = new TimePageLink(100); | ||
251 | + boolean hasNext = true; | ||
252 | + AlarmSeverity highestSeverity = null; | ||
253 | + AlarmQuery query; | ||
254 | + while (hasNext) { | ||
255 | + query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false); | ||
256 | + List<AlarmInfo> alarms; | ||
257 | + try { | ||
258 | + alarms = alarmDao.findAlarms(query).get(); | ||
259 | + } catch (ExecutionException | InterruptedException e) { | ||
260 | + log.warn("Failed to find highest alarm severity. EntityId: [{}], AlarmSearchStatus: [{}], AlarmStatus: [{}]", | ||
261 | + entityId, alarmSearchStatus, alarmStatus); | ||
262 | + throw new RuntimeException(e); | ||
263 | + } | ||
264 | + hasNext = alarms.size() == nextPageLink.getLimit(); | ||
265 | + if (hasNext) { | ||
266 | + nextPageLink = new TimePageData<>(alarms, nextPageLink).getNextPageLink(); | ||
267 | + } | ||
268 | + if (alarms.isEmpty()) { | ||
269 | + continue; | ||
270 | + } else { | ||
271 | + List<AlarmInfo> sorted = new ArrayList(alarms); | ||
272 | + sorted.sort((p1, p2) -> p1.getSeverity().compareTo(p2.getSeverity())); | ||
273 | + AlarmSeverity severity = sorted.get(0).getSeverity(); | ||
274 | + if (severity == AlarmSeverity.CRITICAL) { | ||
275 | + highestSeverity = severity; | ||
276 | + break; | ||
277 | + } else if (highestSeverity == null) { | ||
278 | + highestSeverity = severity; | ||
279 | + } else { | ||
280 | + highestSeverity = highestSeverity.compareTo(severity) < 0 ? highestSeverity : severity; | ||
281 | + } | ||
282 | + } | ||
283 | + } | ||
284 | + return highestSeverity; | ||
285 | + } | ||
286 | + | ||
245 | private void deleteRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException { | 287 | private void deleteRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException { |
246 | log.debug("Deleting Alarm relation: {}", alarmRelation); | 288 | log.debug("Deleting Alarm relation: {}", alarmRelation); |
247 | relationService.deleteRelation(alarmRelation).get(); | 289 | relationService.deleteRelation(alarmRelation).get(); |
@@ -48,6 +48,7 @@ function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) { | @@ -48,6 +48,7 @@ function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) { | ||
48 | ackAlarm: ackAlarm, | 48 | ackAlarm: ackAlarm, |
49 | clearAlarm: clearAlarm, | 49 | clearAlarm: clearAlarm, |
50 | getAlarms: getAlarms, | 50 | getAlarms: getAlarms, |
51 | + getHighestAlarmSeverity: getHighestAlarmSeverity, | ||
51 | pollAlarms: pollAlarms, | 52 | pollAlarms: pollAlarms, |
52 | cancelPollAlarms: cancelPollAlarms, | 53 | cancelPollAlarms: cancelPollAlarms, |
53 | subscribeForAlarms: subscribeForAlarms, | 54 | subscribeForAlarms: subscribeForAlarms, |
@@ -165,6 +166,23 @@ function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) { | @@ -165,6 +166,23 @@ function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) { | ||
165 | return deferred.promise; | 166 | return deferred.promise; |
166 | } | 167 | } |
167 | 168 | ||
169 | + function getHighestAlarmSeverity(entityType, entityId, alarmSearchStatus, alarmStatus, config) { | ||
170 | + var deferred = $q.defer(); | ||
171 | + var url = '/api/alarm/highestSeverity/' + entityType + '/' + entityId; | ||
172 | + | ||
173 | + if (alarmSearchStatus) { | ||
174 | + url += '?searchStatus=' + alarmSearchStatus; | ||
175 | + } else if (alarmStatus) { | ||
176 | + url += '?status=' + alarmStatus; | ||
177 | + } | ||
178 | + $http.get(url, config).then(function success(response) { | ||
179 | + deferred.resolve(response.data); | ||
180 | + }, function fail() { | ||
181 | + deferred.reject(); | ||
182 | + }); | ||
183 | + return deferred.promise; | ||
184 | + } | ||
185 | + | ||
168 | function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) { | 186 | function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) { |
169 | getAlarms(alarmsQuery.entityType, alarmsQuery.entityId, | 187 | getAlarms(alarmsQuery.entityType, alarmsQuery.entityId, |
170 | pageLink, alarmsQuery.alarmSearchStatus, alarmsQuery.alarmStatus, | 188 | pageLink, alarmsQuery.alarmSearchStatus, alarmsQuery.alarmStatus, |