thingsboard-memoizeit
Changes
extensions/extension-kafka/src/main/java/org/thingsboard/server/extensions/kafka/plugin/KafkaMsgHandler.java 4(+3 -1)
extensions-api/src/main/java/org/thingsboard/server/extensions/api/device/DeviceAttributes.java 9(+9 -0)
extensions-core/src/main/java/org/thingsboard/server/extensions/core/action/template/AbstractTemplatePluginAction.java 3(+3 -0)
transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionCtx.java 1(+1 -0)
ui/src/app/api/alarm.service.js 189(+189 -0)
ui/src/app/api/datasource.service.js 2(+1 -1)
ui/src/app/app.js 2(+2 -0)
ui/src/app/common/types.constant.js 6(+6 -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 7d29d57..7a2c273 100644
--- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java
@@ -72,7 +72,7 @@ public class AlarmController extends BaseController {
}
}
- @PreAuthorize("hasAuthority('TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
@@ -86,7 +86,7 @@ public class AlarmController extends BaseController {
}
}
- @PreAuthorize("hasAuthority('TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
diff --git a/extensions/extension-kafka/src/main/java/org/thingsboard/server/extensions/kafka/plugin/KafkaMsgHandler.java b/extensions/extension-kafka/src/main/java/org/thingsboard/server/extensions/kafka/plugin/KafkaMsgHandler.java
index bde0a6f..87f890a 100644
--- a/extensions/extension-kafka/src/main/java/org/thingsboard/server/extensions/kafka/plugin/KafkaMsgHandler.java
+++ b/extensions/extension-kafka/src/main/java/org/thingsboard/server/extensions/kafka/plugin/KafkaMsgHandler.java
@@ -16,6 +16,7 @@
package org.thingsboard.server.extensions.kafka.plugin;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.thingsboard.server.common.data.id.RuleId;
@@ -30,6 +31,7 @@ import org.thingsboard.server.extensions.kafka.action.KafkaActionMsg;
import org.thingsboard.server.extensions.kafka.action.KafkaActionPayload;
@RequiredArgsConstructor
+@Slf4j
public class KafkaMsgHandler implements RuleMsgHandler {
private final Producer<?, String> producer;
@@ -40,7 +42,7 @@ public class KafkaMsgHandler implements RuleMsgHandler {
throw new RuleException("Unsupported message type " + msg.getClass().getName() + "!");
}
KafkaActionPayload payload = ((KafkaActionMsg) msg).getPayload();
-
+ log.debug("Processing kafka payload: {}", payload);
try {
producer.send(new ProducerRecord<>(payload.getTopic(), payload.getMsgBody()),
(metadata, e) -> {
diff --git a/extensions-api/src/main/java/org/thingsboard/server/extensions/api/device/DeviceAttributes.java b/extensions-api/src/main/java/org/thingsboard/server/extensions/api/device/DeviceAttributes.java
index 8628d0c..2cfeefb 100644
--- a/extensions-api/src/main/java/org/thingsboard/server/extensions/api/device/DeviceAttributes.java
+++ b/extensions-api/src/main/java/org/thingsboard/server/extensions/api/device/DeviceAttributes.java
@@ -91,4 +91,13 @@ public class DeviceAttributes {
}
return map;
}
+
+ @Override
+ public String toString() {
+ return "DeviceAttributes{" +
+ "clientSideAttributesMap=" + clientSideAttributesMap +
+ ", serverPrivateAttributesMap=" + serverPrivateAttributesMap +
+ ", serverPublicAttributesMap=" + serverPublicAttributesMap +
+ '}';
+ }
}
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/action/template/AbstractTemplatePluginAction.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/action/template/AbstractTemplatePluginAction.java
index 9360af1..12958f5 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/action/template/AbstractTemplatePluginAction.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/action/template/AbstractTemplatePluginAction.java
@@ -15,6 +15,7 @@
*/
package org.thingsboard.server.extensions.core.action.template;
+import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.runtime.parser.ParseException;
@@ -35,6 +36,7 @@ import java.util.Optional;
/**
* @author Andrew Shvayka
*/
+@Slf4j
public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfiguration> extends SimpleRuleLifecycleComponent implements PluginAction<T> {
protected T configuration;
protected Template template;
@@ -69,6 +71,7 @@ public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfi
}
protected String getMsgBody(RuleContext ctx, ToDeviceActorMsg msg) {
+ log.trace("Creating context for: {} and payload {}", ctx.getDeviceAttributes(), msg.getPayload());
VelocityContext context = VelocityUtils.createContext(ctx.getDeviceAttributes(), msg.getPayload());
return VelocityUtils.merge(template, context);
}
diff --git a/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionCtx.java b/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionCtx.java
index a78319a..d6a953a 100644
--- a/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionCtx.java
+++ b/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionCtx.java
@@ -78,6 +78,7 @@ public class GatewaySessionCtx {
Device newDevice = new Device();
newDevice.setTenantId(gateway.getTenantId());
newDevice.setName(deviceName);
+ newDevice.setType("default");
return deviceService.saveDevice(newDevice);
});
GatewayDeviceSessionCtx ctx = new GatewayDeviceSessionCtx(this, device);
ui/src/app/api/alarm.service.js 189(+189 -0)
diff --git a/ui/src/app/api/alarm.service.js b/ui/src/app/api/alarm.service.js
new file mode 100644
index 0000000..d9ab4ff
--- /dev/null
+++ b/ui/src/app/api/alarm.service.js
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+export default angular.module('thingsboard.api.alarm', [])
+ .factory('alarmService', AlarmService)
+ .name;
+
+/*@ngInject*/
+function AlarmService($http, $q, $interval, $filter) {
+ var service = {
+ getAlarm: getAlarm,
+ saveAlarm: saveAlarm,
+ ackAlarm: ackAlarm,
+ clearAlarm: clearAlarm,
+ getAlarms: getAlarms,
+ pollAlarms: pollAlarms,
+ cancelPollAlarms: cancelPollAlarms
+ }
+
+ return service;
+
+ function getAlarm(alarmId, ignoreErrors, config) {
+ var deferred = $q.defer();
+ var url = '/api/alarm/' + alarmId;
+ if (!config) {
+ config = {};
+ }
+ config = Object.assign(config, { ignoreErrors: ignoreErrors });
+ $http.get(url, config).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function saveAlarm(alarm, ignoreErrors, config) {
+ var deferred = $q.defer();
+ var url = '/api/alarm';
+ if (!config) {
+ config = {};
+ }
+ config = Object.assign(config, { ignoreErrors: ignoreErrors });
+ $http.post(url, alarm, config).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function ackAlarm(alarmId, ignoreErrors, config) {
+ var deferred = $q.defer();
+ var url = '/api/alarm/' + alarmId + '/ack';
+ if (!config) {
+ config = {};
+ }
+ config = Object.assign(config, { ignoreErrors: ignoreErrors });
+ $http.post(url, null, config).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function clearAlarm(alarmId, ignoreErrors, config) {
+ var deferred = $q.defer();
+ var url = '/api/alarm/' + alarmId + '/clear';
+ if (!config) {
+ config = {};
+ }
+ config = Object.assign(config, { ignoreErrors: ignoreErrors });
+ $http.post(url, null, config).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function getAlarms(entityType, entityId, pageLink, alarmStatus, ascOrder, config) {
+ var deferred = $q.defer();
+ var url = '/api/alarm/' + entityType + '/' + entityId + '?limit=' + pageLink.limit;
+
+ if (angular.isDefined(pageLink.startTime)) {
+ url += '&startTime=' + pageLink.startTime;
+ }
+ if (angular.isDefined(pageLink.endTime)) {
+ url += '&endTime=' + pageLink.endTime;
+ }
+ if (angular.isDefined(pageLink.idOffset)) {
+ url += '&offset=' + pageLink.idOffset;
+ }
+ if (alarmStatus) {
+ url += '&status=' + alarmStatus;
+ }
+ if (angular.isDefined(ascOrder) && ascOrder != null) {
+ url += '&ascOrder=' + (ascOrder ? 'true' : 'false');
+ }
+
+ $http.get(url, config).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) {
+ getAlarms(alarmsQuery.entityType, alarmsQuery.entityId,
+ pageLink, alarmsQuery.alarmStatus, false, {ignoreLoading: true}).then(
+ function success(alarms) {
+ if (!alarmsList) {
+ alarmsList = [];
+ }
+ alarmsList = alarmsList.concat(alarms.data);
+ if (alarms.hasNext && !alarmsQuery.limit) {
+ fetchAlarms(alarmsQuery, alarms.nextPageLink, deferred, alarmsList);
+ } else {
+ alarmsList = $filter('orderBy')(alarmsList, ['-createdTime']);
+ deferred.resolve(alarmsList);
+ }
+ },
+ function fail() {
+ deferred.reject();
+ }
+ );
+ }
+
+ function getAlarmsByQuery(alarmsQuery) {
+ var deferred = $q.defer();
+ var time = Date.now();
+ var pageLink;
+ if (alarmsQuery.limit) {
+ pageLink = {
+ limit: alarmsQuery.limit
+ };
+ } else {
+ pageLink = {
+ limit: 100,
+ startTime: time - alarmsQuery.interval
+ };
+ }
+ fetchAlarms(alarmsQuery, pageLink, deferred);
+ return deferred.promise;
+ }
+
+ function onPollAlarms(alarmsQuery) {
+ getAlarmsByQuery(alarmsQuery).then(
+ function success(alarms) {
+ alarmsQuery.onAlarms(alarms);
+ },
+ function fail() {}
+ );
+ }
+
+ function pollAlarms(entityType, entityId, alarmStatus, interval, limit, pollingInterval, onAlarms) {
+ var alarmsQuery = {
+ entityType: entityType,
+ entityId: entityId,
+ alarmStatus: alarmStatus,
+ interval: interval,
+ limit: limit,
+ onAlarms: onAlarms
+ };
+ onPollAlarms(alarmsQuery);
+ return $interval(onPollAlarms, pollingInterval, 0, false, alarmsQuery);
+ }
+
+ function cancelPollAlarms(pollPromise) {
+ if (angular.isDefined(pollPromise)) {
+ $interval.cancel(pollPromise);
+ }
+ }
+
+}
ui/src/app/api/datasource.service.js 2(+1 -1)
diff --git a/ui/src/app/api/datasource.service.js b/ui/src/app/api/datasource.service.js
index 27da468..bfa3184 100644
--- a/ui/src/app/api/datasource.service.js
+++ b/ui/src/app/api/datasource.service.js
@@ -595,8 +595,8 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
}
series = [time, value];
data.push(series);
- update = true;
}
+ update = true;
}
if (update) {
datasourceData[datasourceKey].data = data;
ui/src/app/app.js 2(+2 -0)
diff --git a/ui/src/app/app.js b/ui/src/app/app.js
index f67be33..9ba34b4 100644
--- a/ui/src/app/app.js
+++ b/ui/src/app/app.js
@@ -67,6 +67,7 @@ import thingsboardApiEntityRelation from './api/entity-relation.service';
import thingsboardApiAsset from './api/asset.service';
import thingsboardApiAttribute from './api/attribute.service';
import thingsboardApiEntity from './api/entity.service';
+import thingsboardApiAlarm from './api/alarm.service';
import 'typeface-roboto';
import 'font-awesome/css/font-awesome.min.css';
@@ -124,6 +125,7 @@ angular.module('thingsboard', [
thingsboardApiAsset,
thingsboardApiAttribute,
thingsboardApiEntity,
+ thingsboardApiAlarm,
uiRouter])
.config(AppConfig)
.factory('globalInterceptor', GlobalInterceptor)
ui/src/app/common/types.constant.js 6(+6 -0)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 47ac7a0..44e59a2 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -59,6 +59,12 @@ export default angular.module('thingsboard.types', [])
name: "aggregation.none"
}
},
+ alarmStatus: {
+ activeUnack: "ACTIVE_UNACK",
+ activeAck: "ACTIVE_ACK",
+ clearedUnack: "CLEARED_UNACK",
+ clearedAck: "CLEARED_ACK"
+ },
position: {
top: {
value: "top",
diff --git a/ui/src/app/dashboard/dashboard.controller.js b/ui/src/app/dashboard/dashboard.controller.js
index ecf072d..ac14f79 100644
--- a/ui/src/app/dashboard/dashboard.controller.js
+++ b/ui/src/app/dashboard/dashboard.controller.js
@@ -138,10 +138,10 @@ export default function DashboardController(types, dashboardUtils, widgetService
}
vm.mainLayoutHeight = function() {
- if (vm.isEditingWidget && vm.editingLayoutCtx.id === 'main') {
+ if (!vm.isEditingWidget || vm.editingLayoutCtx.id === 'main') {
return '100%';
} else {
- return 'auto';
+ return '0px';
}
}
@@ -154,10 +154,10 @@ export default function DashboardController(types, dashboardUtils, widgetService
}
vm.rightLayoutHeight = function() {
- if (vm.isEditingWidget && vm.editingLayoutCtx.id === 'right') {
+ if (!vm.isEditingWidget || vm.editingLayoutCtx.id === 'right') {
return '100%';
} else {
- return 'auto';
+ return '0px';
}
}
@@ -369,7 +369,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
}
}
- function openDashboardState(state) {
+ function openDashboardState(state, openRightLayout) {
var layoutsData = dashboardUtils.getStateLayoutsData(vm.dashboard, state);
if (layoutsData) {
vm.dashboardCtx.state = state;
@@ -387,7 +387,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
layoutVisibilityChanged = !vm.isMobile;
}
}
- vm.isRightLayoutOpened = false;
+ vm.isRightLayoutOpened = openRightLayout ? true : false;
updateLayouts(layoutVisibilityChanged);
}
diff --git a/ui/src/app/dashboard/states/default-state-controller.js b/ui/src/app/dashboard/states/default-state-controller.js
index 782f59e..76ea9b8 100644
--- a/ui/src/app/dashboard/states/default-state-controller.js
+++ b/ui/src/app/dashboard/states/default-state-controller.js
@@ -26,12 +26,13 @@ export default function DefaultStateController($scope, $location, $state, $state
vm.navigatePrevState = navigatePrevState;
vm.getStateId = getStateId;
vm.getStateParams = getStateParams;
+ vm.getStateParamsByStateId = getStateParamsByStateId;
vm.getStateName = getStateName;
vm.displayStateSelection = displayStateSelection;
- function openState(id, params) {
+ function openState(id, params, openRightLayout) {
if (vm.states && vm.states[id]) {
if (!params) {
params = {};
@@ -42,11 +43,11 @@ export default function DefaultStateController($scope, $location, $state, $state
}
//append new state
vm.stateObject[0] = newState;
- gotoState(vm.stateObject[0].id, true);
+ gotoState(vm.stateObject[0].id, true, openRightLayout);
}
}
- function updateState(id, params) {
+ function updateState(id, params, openRightLayout) {
if (vm.states && vm.states[id]) {
if (!params) {
params = {};
@@ -57,7 +58,7 @@ export default function DefaultStateController($scope, $location, $state, $state
}
//replace with new state
vm.stateObject[0] = newState;
- gotoState(vm.stateObject[0].id, true);
+ gotoState(vm.stateObject[0].id, true, openRightLayout);
}
}
@@ -76,6 +77,24 @@ export default function DefaultStateController($scope, $location, $state, $state
return vm.stateObject[vm.stateObject.length-1].params;
}
+ function getStateParamsByStateId(stateId) {
+ var stateObj = getStateObjById(stateId);
+ if (stateObj) {
+ return stateObj.params;
+ } else {
+ return null;
+ }
+ }
+
+ function getStateObjById(id) {
+ for (var i=0; i < vm.stateObject.length; i++) {
+ if (vm.stateObject[i].id === id) {
+ return vm.stateObject[i];
+ }
+ }
+ return null;
+ }
+
function getStateName(id, state) {
var result = '';
var translationId = types.translate.dashboardStatePrefix + id;
@@ -161,9 +180,9 @@ export default function DefaultStateController($scope, $location, $state, $state
}, true);
}
- function gotoState(stateId, update) {
+ function gotoState(stateId, update, openRightLayout) {
if (vm.dashboardCtrl.dashboardCtx.state != stateId) {
- vm.dashboardCtrl.openDashboardState(stateId);
+ vm.dashboardCtrl.openDashboardState(stateId, openRightLayout);
if (update) {
updateLocation();
}
diff --git a/ui/src/app/dashboard/states/entity-state-controller.js b/ui/src/app/dashboard/states/entity-state-controller.js
index 8ee9285..51cf67d 100644
--- a/ui/src/app/dashboard/states/entity-state-controller.js
+++ b/ui/src/app/dashboard/states/entity-state-controller.js
@@ -28,12 +28,13 @@ export default function EntityStateController($scope, $location, $state, $stateP
vm.navigatePrevState = navigatePrevState;
vm.getStateId = getStateId;
vm.getStateParams = getStateParams;
+ vm.getStateParamsByStateId = getStateParamsByStateId;
vm.getStateName = getStateName;
vm.selectedStateIndex = -1;
- function openState(id, params) {
+ function openState(id, params, openRightLayout) {
if (vm.states && vm.states[id]) {
resolveEntity(params).then(
function success(entityName) {
@@ -45,13 +46,13 @@ export default function EntityStateController($scope, $location, $state, $stateP
//append new state
vm.stateObject.push(newState);
vm.selectedStateIndex = vm.stateObject.length-1;
- gotoState(vm.stateObject[vm.stateObject.length-1].id, true);
+ gotoState(vm.stateObject[vm.stateObject.length-1].id, true, openRightLayout);
}
);
}
}
- function updateState(id, params) {
+ function updateState(id, params, openRightLayout) {
if (vm.states && vm.states[id]) {
resolveEntity(params).then(
function success(entityName) {
@@ -62,7 +63,7 @@ export default function EntityStateController($scope, $location, $state, $stateP
}
//replace with new state
vm.stateObject[vm.stateObject.length - 1] = newState;
- gotoState(vm.stateObject[vm.stateObject.length - 1].id, true);
+ gotoState(vm.stateObject[vm.stateObject.length - 1].id, true, openRightLayout);
}
);
}
@@ -84,6 +85,24 @@ export default function EntityStateController($scope, $location, $state, $stateP
return vm.stateObject[vm.stateObject.length-1].params;
}
+ function getStateParamsByStateId(stateId) {
+ var stateObj = getStateObjById(stateId);
+ if (stateObj) {
+ return stateObj.params;
+ } else {
+ return null;
+ }
+ }
+
+ function getStateObjById(id) {
+ for (var i=0; i < vm.stateObject.length; i++) {
+ if (vm.stateObject[i].id === id) {
+ return vm.stateObject[i];
+ }
+ }
+ return null;
+ }
+
function getStateName(index) {
var result = '';
if (vm.stateObject[index]) {
@@ -223,9 +242,9 @@ export default function EntityStateController($scope, $location, $state, $stateP
});
}
- function gotoState(stateId, update) {
+ function gotoState(stateId, update, openRightLayout) {
if (vm.dashboardCtrl.dashboardCtx.state != stateId) {
- vm.dashboardCtrl.openDashboardState(stateId);
+ vm.dashboardCtrl.openDashboardState(stateId, openRightLayout);
if (update) {
updateLocation();
}
diff --git a/ui/src/app/dashboard/states/states-component.directive.js b/ui/src/app/dashboard/states/states-component.directive.js
index fb5e77c..538c3e9 100644
--- a/ui/src/app/dashboard/states/states-component.directive.js
+++ b/ui/src/app/dashboard/states/states-component.directive.js
@@ -29,15 +29,15 @@ export default function StatesComponent($compile, $templateCache, $controller, s
var stateController = scope.dashboardCtrl.dashboardCtx.stateController;
- stateController.openState = function(id, params) {
+ stateController.openState = function(id, params, openRightLayout) {
if (scope.statesController) {
- scope.statesController.openState(id, params);
+ scope.statesController.openState(id, params, openRightLayout);
}
}
- stateController.updateState = function(id, params) {
+ stateController.updateState = function(id, params, openRightLayout) {
if (scope.statesController) {
- scope.statesController.updateState(id, params);
+ scope.statesController.updateState(id, params, openRightLayout);
}
}
@@ -62,6 +62,14 @@ export default function StatesComponent($compile, $templateCache, $controller, s
return {};
}
}
+
+ stateController.getStateParamsByStateId = function(id) {
+ if (scope.statesController) {
+ return scope.statesController.getStateParamsByStateId(id);
+ } else {
+ return null;
+ }
+ }
}
scope.$on('$destroy', function callOnDestroyHook() {