Commit 776737519d5a8fb6d7b4834b66aa7289603689c2

Authored by Volodymyr Babak
2 parents 2349af5d ec39c15e

Merge remote-tracking branch 'upstream/master' into dao-refactoring-vs

... ... @@ -72,7 +72,7 @@ public class AlarmController extends BaseController {
72 72 }
73 73 }
74 74
75   - @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  75 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
76 76 @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
77 77 @ResponseStatus(value = HttpStatus.OK)
78 78 public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
... ... @@ -86,7 +86,7 @@ public class AlarmController extends BaseController {
86 86 }
87 87 }
88 88
89   - @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  89 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
90 90 @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST)
91 91 @ResponseStatus(value = HttpStatus.OK)
92 92 public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
... ...
... ... @@ -91,4 +91,13 @@ public class DeviceAttributes {
91 91 }
92 92 return map;
93 93 }
  94 +
  95 + @Override
  96 + public String toString() {
  97 + return "DeviceAttributes{" +
  98 + "clientSideAttributesMap=" + clientSideAttributesMap +
  99 + ", serverPrivateAttributesMap=" + serverPrivateAttributesMap +
  100 + ", serverPublicAttributesMap=" + serverPublicAttributesMap +
  101 + '}';
  102 + }
94 103 }
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.extensions.core.action.template;
17 17
  18 +import lombok.extern.slf4j.Slf4j;
18 19 import org.apache.velocity.Template;
19 20 import org.apache.velocity.VelocityContext;
20 21 import org.apache.velocity.runtime.parser.ParseException;
... ... @@ -35,6 +36,7 @@ import java.util.Optional;
35 36 /**
36 37 * @author Andrew Shvayka
37 38 */
  39 +@Slf4j
38 40 public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfiguration> extends SimpleRuleLifecycleComponent implements PluginAction<T> {
39 41 protected T configuration;
40 42 protected Template template;
... ... @@ -69,6 +71,7 @@ public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfi
69 71 }
70 72
71 73 protected String getMsgBody(RuleContext ctx, ToDeviceActorMsg msg) {
  74 + log.trace("Creating context for: {} and payload {}", ctx.getDeviceAttributes(), msg.getPayload());
72 75 VelocityContext context = VelocityUtils.createContext(ctx.getDeviceAttributes(), msg.getPayload());
73 76 return VelocityUtils.merge(template, context);
74 77 }
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.extensions.kafka.plugin;
17 17
18 18 import lombok.RequiredArgsConstructor;
  19 +import lombok.extern.slf4j.Slf4j;
19 20 import org.apache.kafka.clients.producer.Producer;
20 21 import org.apache.kafka.clients.producer.ProducerRecord;
21 22 import org.thingsboard.server.common.data.id.RuleId;
... ... @@ -30,6 +31,7 @@ import org.thingsboard.server.extensions.kafka.action.KafkaActionMsg;
30 31 import org.thingsboard.server.extensions.kafka.action.KafkaActionPayload;
31 32
32 33 @RequiredArgsConstructor
  34 +@Slf4j
33 35 public class KafkaMsgHandler implements RuleMsgHandler {
34 36
35 37 private final Producer<?, String> producer;
... ... @@ -40,7 +42,7 @@ public class KafkaMsgHandler implements RuleMsgHandler {
40 42 throw new RuleException("Unsupported message type " + msg.getClass().getName() + "!");
41 43 }
42 44 KafkaActionPayload payload = ((KafkaActionMsg) msg).getPayload();
43   -
  45 + log.debug("Processing kafka payload: {}", payload);
44 46 try {
45 47 producer.send(new ProducerRecord<>(payload.getTopic(), payload.getMsgBody()),
46 48 (metadata, e) -> {
... ...
... ... @@ -78,6 +78,7 @@ public class GatewaySessionCtx {
78 78 Device newDevice = new Device();
79 79 newDevice.setTenantId(gateway.getTenantId());
80 80 newDevice.setName(deviceName);
  81 + newDevice.setType("default");
81 82 return deviceService.saveDevice(newDevice);
82 83 });
83 84 GatewayDeviceSessionCtx ctx = new GatewayDeviceSessionCtx(this, device);
... ...
  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 +export default angular.module('thingsboard.api.alarm', [])
  17 + .factory('alarmService', AlarmService)
  18 + .name;
  19 +
  20 +/*@ngInject*/
  21 +function AlarmService($http, $q, $interval, $filter) {
  22 + var service = {
  23 + getAlarm: getAlarm,
  24 + saveAlarm: saveAlarm,
  25 + ackAlarm: ackAlarm,
  26 + clearAlarm: clearAlarm,
  27 + getAlarms: getAlarms,
  28 + pollAlarms: pollAlarms,
  29 + cancelPollAlarms: cancelPollAlarms
  30 + }
  31 +
  32 + return service;
  33 +
  34 + function getAlarm(alarmId, ignoreErrors, config) {
  35 + var deferred = $q.defer();
  36 + var url = '/api/alarm/' + alarmId;
  37 + if (!config) {
  38 + config = {};
  39 + }
  40 + config = Object.assign(config, { ignoreErrors: ignoreErrors });
  41 + $http.get(url, config).then(function success(response) {
  42 + deferred.resolve(response.data);
  43 + }, function fail() {
  44 + deferred.reject();
  45 + });
  46 + return deferred.promise;
  47 + }
  48 +
  49 + function saveAlarm(alarm, ignoreErrors, config) {
  50 + var deferred = $q.defer();
  51 + var url = '/api/alarm';
  52 + if (!config) {
  53 + config = {};
  54 + }
  55 + config = Object.assign(config, { ignoreErrors: ignoreErrors });
  56 + $http.post(url, alarm, config).then(function success(response) {
  57 + deferred.resolve(response.data);
  58 + }, function fail() {
  59 + deferred.reject();
  60 + });
  61 + return deferred.promise;
  62 + }
  63 +
  64 + function ackAlarm(alarmId, ignoreErrors, config) {
  65 + var deferred = $q.defer();
  66 + var url = '/api/alarm/' + alarmId + '/ack';
  67 + if (!config) {
  68 + config = {};
  69 + }
  70 + config = Object.assign(config, { ignoreErrors: ignoreErrors });
  71 + $http.post(url, null, config).then(function success(response) {
  72 + deferred.resolve(response.data);
  73 + }, function fail() {
  74 + deferred.reject();
  75 + });
  76 + return deferred.promise;
  77 + }
  78 +
  79 + function clearAlarm(alarmId, ignoreErrors, config) {
  80 + var deferred = $q.defer();
  81 + var url = '/api/alarm/' + alarmId + '/clear';
  82 + if (!config) {
  83 + config = {};
  84 + }
  85 + config = Object.assign(config, { ignoreErrors: ignoreErrors });
  86 + $http.post(url, null, config).then(function success(response) {
  87 + deferred.resolve(response.data);
  88 + }, function fail() {
  89 + deferred.reject();
  90 + });
  91 + return deferred.promise;
  92 + }
  93 +
  94 + function getAlarms(entityType, entityId, pageLink, alarmStatus, ascOrder, config) {
  95 + var deferred = $q.defer();
  96 + var url = '/api/alarm/' + entityType + '/' + entityId + '?limit=' + pageLink.limit;
  97 +
  98 + if (angular.isDefined(pageLink.startTime)) {
  99 + url += '&startTime=' + pageLink.startTime;
  100 + }
  101 + if (angular.isDefined(pageLink.endTime)) {
  102 + url += '&endTime=' + pageLink.endTime;
  103 + }
  104 + if (angular.isDefined(pageLink.idOffset)) {
  105 + url += '&offset=' + pageLink.idOffset;
  106 + }
  107 + if (alarmStatus) {
  108 + url += '&status=' + alarmStatus;
  109 + }
  110 + if (angular.isDefined(ascOrder) && ascOrder != null) {
  111 + url += '&ascOrder=' + (ascOrder ? 'true' : 'false');
  112 + }
  113 +
  114 + $http.get(url, config).then(function success(response) {
  115 + deferred.resolve(response.data);
  116 + }, function fail() {
  117 + deferred.reject();
  118 + });
  119 + return deferred.promise;
  120 + }
  121 +
  122 + function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) {
  123 + getAlarms(alarmsQuery.entityType, alarmsQuery.entityId,
  124 + pageLink, alarmsQuery.alarmStatus, false, {ignoreLoading: true}).then(
  125 + function success(alarms) {
  126 + if (!alarmsList) {
  127 + alarmsList = [];
  128 + }
  129 + alarmsList = alarmsList.concat(alarms.data);
  130 + if (alarms.hasNext && !alarmsQuery.limit) {
  131 + fetchAlarms(alarmsQuery, alarms.nextPageLink, deferred, alarmsList);
  132 + } else {
  133 + alarmsList = $filter('orderBy')(alarmsList, ['-createdTime']);
  134 + deferred.resolve(alarmsList);
  135 + }
  136 + },
  137 + function fail() {
  138 + deferred.reject();
  139 + }
  140 + );
  141 + }
  142 +
  143 + function getAlarmsByQuery(alarmsQuery) {
  144 + var deferred = $q.defer();
  145 + var time = Date.now();
  146 + var pageLink;
  147 + if (alarmsQuery.limit) {
  148 + pageLink = {
  149 + limit: alarmsQuery.limit
  150 + };
  151 + } else {
  152 + pageLink = {
  153 + limit: 100,
  154 + startTime: time - alarmsQuery.interval
  155 + };
  156 + }
  157 + fetchAlarms(alarmsQuery, pageLink, deferred);
  158 + return deferred.promise;
  159 + }
  160 +
  161 + function onPollAlarms(alarmsQuery) {
  162 + getAlarmsByQuery(alarmsQuery).then(
  163 + function success(alarms) {
  164 + alarmsQuery.onAlarms(alarms);
  165 + },
  166 + function fail() {}
  167 + );
  168 + }
  169 +
  170 + function pollAlarms(entityType, entityId, alarmStatus, interval, limit, pollingInterval, onAlarms) {
  171 + var alarmsQuery = {
  172 + entityType: entityType,
  173 + entityId: entityId,
  174 + alarmStatus: alarmStatus,
  175 + interval: interval,
  176 + limit: limit,
  177 + onAlarms: onAlarms
  178 + };
  179 + onPollAlarms(alarmsQuery);
  180 + return $interval(onPollAlarms, pollingInterval, 0, false, alarmsQuery);
  181 + }
  182 +
  183 + function cancelPollAlarms(pollPromise) {
  184 + if (angular.isDefined(pollPromise)) {
  185 + $interval.cancel(pollPromise);
  186 + }
  187 + }
  188 +
  189 +}
... ...
... ... @@ -595,8 +595,8 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
595 595 }
596 596 series = [time, value];
597 597 data.push(series);
598   - update = true;
599 598 }
  599 + update = true;
600 600 }
601 601 if (update) {
602 602 datasourceData[datasourceKey].data = data;
... ...
... ... @@ -67,6 +67,7 @@ import thingsboardApiEntityRelation from './api/entity-relation.service';
67 67 import thingsboardApiAsset from './api/asset.service';
68 68 import thingsboardApiAttribute from './api/attribute.service';
69 69 import thingsboardApiEntity from './api/entity.service';
  70 +import thingsboardApiAlarm from './api/alarm.service';
70 71
71 72 import 'typeface-roboto';
72 73 import 'font-awesome/css/font-awesome.min.css';
... ... @@ -124,6 +125,7 @@ angular.module('thingsboard', [
124 125 thingsboardApiAsset,
125 126 thingsboardApiAttribute,
126 127 thingsboardApiEntity,
  128 + thingsboardApiAlarm,
127 129 uiRouter])
128 130 .config(AppConfig)
129 131 .factory('globalInterceptor', GlobalInterceptor)
... ...
... ... @@ -59,6 +59,12 @@ export default angular.module('thingsboard.types', [])
59 59 name: "aggregation.none"
60 60 }
61 61 },
  62 + alarmStatus: {
  63 + activeUnack: "ACTIVE_UNACK",
  64 + activeAck: "ACTIVE_ACK",
  65 + clearedUnack: "CLEARED_UNACK",
  66 + clearedAck: "CLEARED_ACK"
  67 + },
62 68 position: {
63 69 top: {
64 70 value: "top",
... ...
... ... @@ -138,10 +138,10 @@ export default function DashboardController(types, dashboardUtils, widgetService
138 138 }
139 139
140 140 vm.mainLayoutHeight = function() {
141   - if (vm.isEditingWidget && vm.editingLayoutCtx.id === 'main') {
  141 + if (!vm.isEditingWidget || vm.editingLayoutCtx.id === 'main') {
142 142 return '100%';
143 143 } else {
144   - return 'auto';
  144 + return '0px';
145 145 }
146 146 }
147 147
... ... @@ -154,10 +154,10 @@ export default function DashboardController(types, dashboardUtils, widgetService
154 154 }
155 155
156 156 vm.rightLayoutHeight = function() {
157   - if (vm.isEditingWidget && vm.editingLayoutCtx.id === 'right') {
  157 + if (!vm.isEditingWidget || vm.editingLayoutCtx.id === 'right') {
158 158 return '100%';
159 159 } else {
160   - return 'auto';
  160 + return '0px';
161 161 }
162 162 }
163 163
... ... @@ -369,7 +369,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
369 369 }
370 370 }
371 371
372   - function openDashboardState(state) {
  372 + function openDashboardState(state, openRightLayout) {
373 373 var layoutsData = dashboardUtils.getStateLayoutsData(vm.dashboard, state);
374 374 if (layoutsData) {
375 375 vm.dashboardCtx.state = state;
... ... @@ -387,7 +387,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
387 387 layoutVisibilityChanged = !vm.isMobile;
388 388 }
389 389 }
390   - vm.isRightLayoutOpened = false;
  390 + vm.isRightLayoutOpened = openRightLayout ? true : false;
391 391 updateLayouts(layoutVisibilityChanged);
392 392 }
393 393
... ...
... ... @@ -26,12 +26,13 @@ export default function DefaultStateController($scope, $location, $state, $state
26 26 vm.navigatePrevState = navigatePrevState;
27 27 vm.getStateId = getStateId;
28 28 vm.getStateParams = getStateParams;
  29 + vm.getStateParamsByStateId = getStateParamsByStateId;
29 30
30 31 vm.getStateName = getStateName;
31 32
32 33 vm.displayStateSelection = displayStateSelection;
33 34
34   - function openState(id, params) {
  35 + function openState(id, params, openRightLayout) {
35 36 if (vm.states && vm.states[id]) {
36 37 if (!params) {
37 38 params = {};
... ... @@ -42,11 +43,11 @@ export default function DefaultStateController($scope, $location, $state, $state
42 43 }
43 44 //append new state
44 45 vm.stateObject[0] = newState;
45   - gotoState(vm.stateObject[0].id, true);
  46 + gotoState(vm.stateObject[0].id, true, openRightLayout);
46 47 }
47 48 }
48 49
49   - function updateState(id, params) {
  50 + function updateState(id, params, openRightLayout) {
50 51 if (vm.states && vm.states[id]) {
51 52 if (!params) {
52 53 params = {};
... ... @@ -57,7 +58,7 @@ export default function DefaultStateController($scope, $location, $state, $state
57 58 }
58 59 //replace with new state
59 60 vm.stateObject[0] = newState;
60   - gotoState(vm.stateObject[0].id, true);
  61 + gotoState(vm.stateObject[0].id, true, openRightLayout);
61 62 }
62 63 }
63 64
... ... @@ -76,6 +77,24 @@ export default function DefaultStateController($scope, $location, $state, $state
76 77 return vm.stateObject[vm.stateObject.length-1].params;
77 78 }
78 79
  80 + function getStateParamsByStateId(stateId) {
  81 + var stateObj = getStateObjById(stateId);
  82 + if (stateObj) {
  83 + return stateObj.params;
  84 + } else {
  85 + return null;
  86 + }
  87 + }
  88 +
  89 + function getStateObjById(id) {
  90 + for (var i=0; i < vm.stateObject.length; i++) {
  91 + if (vm.stateObject[i].id === id) {
  92 + return vm.stateObject[i];
  93 + }
  94 + }
  95 + return null;
  96 + }
  97 +
79 98 function getStateName(id, state) {
80 99 var result = '';
81 100 var translationId = types.translate.dashboardStatePrefix + id;
... ... @@ -161,9 +180,9 @@ export default function DefaultStateController($scope, $location, $state, $state
161 180 }, true);
162 181 }
163 182
164   - function gotoState(stateId, update) {
  183 + function gotoState(stateId, update, openRightLayout) {
165 184 if (vm.dashboardCtrl.dashboardCtx.state != stateId) {
166   - vm.dashboardCtrl.openDashboardState(stateId);
  185 + vm.dashboardCtrl.openDashboardState(stateId, openRightLayout);
167 186 if (update) {
168 187 updateLocation();
169 188 }
... ...
... ... @@ -28,12 +28,13 @@ export default function EntityStateController($scope, $location, $state, $stateP
28 28 vm.navigatePrevState = navigatePrevState;
29 29 vm.getStateId = getStateId;
30 30 vm.getStateParams = getStateParams;
  31 + vm.getStateParamsByStateId = getStateParamsByStateId;
31 32
32 33 vm.getStateName = getStateName;
33 34
34 35 vm.selectedStateIndex = -1;
35 36
36   - function openState(id, params) {
  37 + function openState(id, params, openRightLayout) {
37 38 if (vm.states && vm.states[id]) {
38 39 resolveEntity(params).then(
39 40 function success(entityName) {
... ... @@ -45,13 +46,13 @@ export default function EntityStateController($scope, $location, $state, $stateP
45 46 //append new state
46 47 vm.stateObject.push(newState);
47 48 vm.selectedStateIndex = vm.stateObject.length-1;
48   - gotoState(vm.stateObject[vm.stateObject.length-1].id, true);
  49 + gotoState(vm.stateObject[vm.stateObject.length-1].id, true, openRightLayout);
49 50 }
50 51 );
51 52 }
52 53 }
53 54
54   - function updateState(id, params) {
  55 + function updateState(id, params, openRightLayout) {
55 56 if (vm.states && vm.states[id]) {
56 57 resolveEntity(params).then(
57 58 function success(entityName) {
... ... @@ -62,7 +63,7 @@ export default function EntityStateController($scope, $location, $state, $stateP
62 63 }
63 64 //replace with new state
64 65 vm.stateObject[vm.stateObject.length - 1] = newState;
65   - gotoState(vm.stateObject[vm.stateObject.length - 1].id, true);
  66 + gotoState(vm.stateObject[vm.stateObject.length - 1].id, true, openRightLayout);
66 67 }
67 68 );
68 69 }
... ... @@ -84,6 +85,24 @@ export default function EntityStateController($scope, $location, $state, $stateP
84 85 return vm.stateObject[vm.stateObject.length-1].params;
85 86 }
86 87
  88 + function getStateParamsByStateId(stateId) {
  89 + var stateObj = getStateObjById(stateId);
  90 + if (stateObj) {
  91 + return stateObj.params;
  92 + } else {
  93 + return null;
  94 + }
  95 + }
  96 +
  97 + function getStateObjById(id) {
  98 + for (var i=0; i < vm.stateObject.length; i++) {
  99 + if (vm.stateObject[i].id === id) {
  100 + return vm.stateObject[i];
  101 + }
  102 + }
  103 + return null;
  104 + }
  105 +
87 106 function getStateName(index) {
88 107 var result = '';
89 108 if (vm.stateObject[index]) {
... ... @@ -223,9 +242,9 @@ export default function EntityStateController($scope, $location, $state, $stateP
223 242 });
224 243 }
225 244
226   - function gotoState(stateId, update) {
  245 + function gotoState(stateId, update, openRightLayout) {
227 246 if (vm.dashboardCtrl.dashboardCtx.state != stateId) {
228   - vm.dashboardCtrl.openDashboardState(stateId);
  247 + vm.dashboardCtrl.openDashboardState(stateId, openRightLayout);
229 248 if (update) {
230 249 updateLocation();
231 250 }
... ...
... ... @@ -29,15 +29,15 @@ export default function StatesComponent($compile, $templateCache, $controller, s
29 29
30 30 var stateController = scope.dashboardCtrl.dashboardCtx.stateController;
31 31
32   - stateController.openState = function(id, params) {
  32 + stateController.openState = function(id, params, openRightLayout) {
33 33 if (scope.statesController) {
34   - scope.statesController.openState(id, params);
  34 + scope.statesController.openState(id, params, openRightLayout);
35 35 }
36 36 }
37 37
38   - stateController.updateState = function(id, params) {
  38 + stateController.updateState = function(id, params, openRightLayout) {
39 39 if (scope.statesController) {
40   - scope.statesController.updateState(id, params);
  40 + scope.statesController.updateState(id, params, openRightLayout);
41 41 }
42 42 }
43 43
... ... @@ -62,6 +62,14 @@ export default function StatesComponent($compile, $templateCache, $controller, s
62 62 return {};
63 63 }
64 64 }
  65 +
  66 + stateController.getStateParamsByStateId = function(id) {
  67 + if (scope.statesController) {
  68 + return scope.statesController.getStateParamsByStateId(id);
  69 + } else {
  70 + return null;
  71 + }
  72 + }
65 73 }
66 74
67 75 scope.$on('$destroy', function callOnDestroyHook() {
... ...