thingsboard-aplcache

Merge pull request #223 from thingsboard/feature/TB-70 TB-70:

7/26/2017 10:29:27 AM

Details

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 7f9c75a..67a076b 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": "<tb-led-indicator ctx='ctx'></tb-led-indicator>",
         "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 58a7c4b..0487ee3 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);
+    }
+
 }