Commit 87683218b556558fbb81e2faf0898de5e55fb879

Authored by Igor Kulikov
1 parent 69a0b74c

TB-63: Find highest alarm severity for specified entity.

... ... @@ -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 16 package org.thingsboard.server.dao.alarm;
17 17
18 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 21 import org.thingsboard.server.common.data.page.TimePageData;
24 22
25 23 /**
... ... @@ -39,4 +37,7 @@ public interface AlarmService {
39 37
40 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 27 import org.thingsboard.server.common.data.alarm.*;
28 28 import org.thingsboard.server.common.data.id.EntityId;
29 29 import org.thingsboard.server.common.data.page.TimePageData;
  30 +import org.thingsboard.server.common.data.page.TimePageLink;
30 31 import org.thingsboard.server.common.data.relation.EntityRelation;
31 32 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
32 33 import org.thingsboard.server.dao.entity.AbstractEntityService;
... ... @@ -46,6 +47,7 @@ import javax.annotation.PostConstruct;
46 47 import javax.annotation.PreDestroy;
47 48 import java.util.ArrayList;
48 49 import java.util.List;
  50 +import java.util.UUID;
49 51 import java.util.concurrent.ExecutionException;
50 52 import java.util.concurrent.ExecutorService;
51 53 import java.util.concurrent.Executors;
... ... @@ -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 287 private void deleteRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException {
246 288 log.debug("Deleting Alarm relation: {}", alarmRelation);
247 289 relationService.deleteRelation(alarmRelation).get();
... ...
... ... @@ -48,6 +48,7 @@ function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) {
48 48 ackAlarm: ackAlarm,
49 49 clearAlarm: clearAlarm,
50 50 getAlarms: getAlarms,
  51 + getHighestAlarmSeverity: getHighestAlarmSeverity,
51 52 pollAlarms: pollAlarms,
52 53 cancelPollAlarms: cancelPollAlarms,
53 54 subscribeForAlarms: subscribeForAlarms,
... ... @@ -165,6 +166,23 @@ function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) {
165 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 186 function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) {
169 187 getAlarms(alarmsQuery.entityType, alarmsQuery.entityId,
170 188 pageLink, alarmsQuery.alarmSearchStatus, alarmsQuery.alarmStatus,
... ...