diff --git a/application/src/main/data/json/system/widget_bundles/control_widgets.json b/application/src/main/data/json/system/widget_bundles/control_widgets.json index 7f9c75a4e8..67a076bd46 100644 --- a/application/src/main/data/json/system/widget_bundles/control_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/control_widgets.json @@ -96,9 +96,9 @@ "templateHtml": "", "templateCss": "", "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n", - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"LED title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"ledColor\": {\n \"title\": \"LED Color\",\n \"type\": \"string\",\n \"default\": \"green\"\n },\n \"getValueMethod\": {\n \"title\": \"Get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"valuePollingInterval\": {\n \"title\": \"Value polling interval (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"getValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"getValueMethod\",\n \"valuePollingInterval\",\n \"requestTimeout\"\n ]\n}", + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"LED title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"ledColor\": {\n \"title\": \"LED Color\",\n \"type\": \"string\",\n \"default\": \"green\"\n },\n \"scheckStatusMethod\": {\n \"title\": \"Check device status method\",\n \"type\": \"string\",\n \"default\": \"checkStatus\"\n },\n \"valueAttribute\": {\n \"title\": \"Device attribute containing led status value\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"scheckStatusMethod\", \"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"scheckStatusMethod\",\n \"valueAttribute\",\n \"requestTimeout\"\n ]\n}", "dataKeySettingsSchema": "{}\n", - "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"getValueMethod\":\"getValue\",\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"valuePollingInterval\":500},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" + "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"scheckStatusMethod\":\"checkStatus\",\"valueAttribute\":\"value\"},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" } } ] diff --git a/ui/src/app/widget/lib/rpc/led-indicator.directive.js b/ui/src/app/widget/lib/rpc/led-indicator.directive.js index 58a7c4b64a..0487ee3501 100644 --- a/ui/src/app/widget/lib/rpc/led-indicator.directive.js +++ b/ui/src/app/widget/lib/rpc/led-indicator.directive.js @@ -43,13 +43,23 @@ function LedIndicator() { } /*@ngInject*/ -function LedIndicatorController($element, $scope, $timeout) { +function LedIndicatorController($element, $scope, $timeout, utils, types) { let vm = this; vm.showTitle = false; vm.value = false; vm.error = ''; + const checkStatusPollingInterval = 10000; + + vm.subscriptionOptions = { + callbacks: { + onDataUpdated: onDataUpdated, + onDataUpdateError: onDataUpdateError, + dataLoading: () => {} + } + }; + var led = angular.element('.led', $element), ledContainer = angular.element('#led-container', $element), textMeasure = angular.element('#text-measure', $element), @@ -66,8 +76,11 @@ function LedIndicatorController($element, $scope, $timeout) { $scope.$on('$destroy', () => { vm.destroyed = true; - if (vm.requestValueTimeoutHandle) { - $timeout.cancel(vm.requestValueTimeoutHandle); + if (vm.checkStatusTimeoutHandle) { + $timeout.cancel(vm.checkStatusTimeoutHandle); + } + if (vm.subscription) { + vm.ctx.subscriptionApi.removeSubscription(vm.subscription.id); } }); @@ -80,6 +93,8 @@ function LedIndicatorController($element, $scope, $timeout) { var origColor = angular.isDefined(vm.ctx.settings.ledColor) ? vm.ctx.settings.ledColor : 'green'; + vm.valueAttribute = angular.isDefined(vm.ctx.settings.valueAttribute) ? vm.ctx.settings.valueAttribute : 'value'; + vm.ledColor = tinycolor(origColor).brighten(30).toHexString(); vm.ledMiddleColor = tinycolor(origColor).toHexString(); vm.disabledColor = tinycolor(origColor).darken(40).toHexString(); @@ -101,19 +116,15 @@ function LedIndicatorController($element, $scope, $timeout) { if (vm.ctx.settings.requestTimeout) { vm.requestTimeout = vm.ctx.settings.requestTimeout; } - vm.valuePollingInterval = 500; - if (vm.ctx.settings.valuePollingInterval) { - vm.valuePollingInterval = vm.ctx.settings.valuePollingInterval; - } - vm.getValueMethod = 'getValue'; - if (vm.ctx.settings.getValueMethod && vm.ctx.settings.getValueMethod.length) { - vm.getValueMethod = vm.ctx.settings.getValueMethod; + vm.checkStatusMethod = 'checkStatus'; + if (vm.ctx.settings.checkStatusMethod && vm.ctx.settings.checkStatusMethod.length) { + vm.checkStatusMethod = vm.ctx.settings.checkStatusMethod; } if (!rpcEnabled) { onError('Target device is not set!'); } else { if (!vm.isSimulated) { - rpcRequestValue(); + rpcCheckStatus(); } } } @@ -173,29 +184,86 @@ function LedIndicatorController($element, $scope, $timeout) { return textMeasure.width(); } - function rpcRequestValue() { + function rpcCheckStatus() { if (vm.destroyed) { return; } vm.error = ''; - vm.ctx.controlApi.sendTwoWayCommand(vm.getValueMethod, null, vm.requestTimeout).then( + vm.ctx.controlApi.sendTwoWayCommand(vm.checkStatusMethod, null, vm.requestTimeout).then( (responseBody) => { - var newValue = responseBody ? true : false; - setValue(newValue); - if (vm.requestValueTimeoutHandle) { - $timeout.cancel(vm.requestValueTimeoutHandle); + var status = responseBody ? true : false; + if (status) { + if (vm.checkStatusTimeoutHandle) { + $timeout.cancel(vm.checkStatusTimeoutHandle); + vm.checkStatusTimeoutHandle = null; + } + subscribeForValue(); + } else { + var errorText = 'Unknown device status!'; + onError(errorText); + if (vm.checkStatusTimeoutHandle) { + $timeout.cancel(vm.checkStatusTimeoutHandle); + } + vm.checkStatusTimeoutHandle = $timeout(rpcCheckStatus, checkStatusPollingInterval); } - vm.requestValueTimeoutHandle = $timeout(rpcRequestValue, vm.valuePollingInterval); }, () => { var errorText = vm.ctx.defaultSubscription.rpcErrorText; onError(errorText); - if (vm.requestValueTimeoutHandle) { - $timeout.cancel(vm.requestValueTimeoutHandle); + if (vm.checkStatusTimeoutHandle) { + $timeout.cancel(vm.checkStatusTimeoutHandle); } - vm.requestValueTimeoutHandle = $timeout(rpcRequestValue, vm.valuePollingInterval); + vm.checkStatusTimeoutHandle = $timeout(rpcCheckStatus, checkStatusPollingInterval); } ); } + function subscribeForValue() { + var subscriptionsInfo = [{ + type: types.datasourceType.entity, + entityType: types.entityType.device, + entityId: vm.ctx.defaultSubscription.targetDeviceId, + attributes: [ + {name: vm.valueAttribute} + ] + }]; + vm.ctx.subscriptionApi.createSubscriptionFromInfo ( + types.widgetType.latest.value, subscriptionsInfo, vm.subscriptionOptions, false, true).then( + function(subscription) { + vm.subscription = subscription; + } + ); + } + + function onDataUpdated(subscription, apply) { + var value = false; + var data = subscription.data; + if (data.length) { + var keyData = data[0]; + if (keyData && keyData.data && keyData.data[0]) { + var attrValue = keyData.data[0][1]; + if (attrValue) { + var parsed = null; + try { + parsed = angular.fromJson(attrValue); + } catch (e){/**/} + value = parsed ? true : false; + } + } + } + setValue(value); + if (apply) { + $scope.$digest(); + } + } + + function onDataUpdateError(subscription, e) { + var exceptionData = utils.parseException(e); + var errorText = exceptionData.name; + if (exceptionData.message) { + errorText += ': ' + exceptionData.message; + } + onError(errorText); + } + }