Commit c003b20bbe4227d6009dfa156022a71d33ba2cd7

Authored by Andrew Shvayka
2 parents 8161956d 1430fe27

Merge branch 'master' of github.com:thingsboard/thingsboard

@@ -96,9 +96,9 @@ @@ -96,9 +96,9 @@
96 "templateHtml": "<tb-led-indicator ctx='ctx'></tb-led-indicator>", 96 "templateHtml": "<tb-led-indicator ctx='ctx'></tb-led-indicator>",
97 "templateCss": "", 97 "templateCss": "",
98 "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", 98 "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",
99 - "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}", 99 + "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}",
100 "dataKeySettingsSchema": "{}\n", 100 "dataKeySettingsSchema": "{}\n",
101 - "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}" 101 + "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}"
102 } 102 }
103 } 103 }
104 ] 104 ]
@@ -43,13 +43,23 @@ function LedIndicator() { @@ -43,13 +43,23 @@ function LedIndicator() {
43 } 43 }
44 44
45 /*@ngInject*/ 45 /*@ngInject*/
46 -function LedIndicatorController($element, $scope, $timeout) { 46 +function LedIndicatorController($element, $scope, $timeout, utils, types) {
47 let vm = this; 47 let vm = this;
48 48
49 vm.showTitle = false; 49 vm.showTitle = false;
50 vm.value = false; 50 vm.value = false;
51 vm.error = ''; 51 vm.error = '';
52 52
  53 + const checkStatusPollingInterval = 10000;
  54 +
  55 + vm.subscriptionOptions = {
  56 + callbacks: {
  57 + onDataUpdated: onDataUpdated,
  58 + onDataUpdateError: onDataUpdateError,
  59 + dataLoading: () => {}
  60 + }
  61 + };
  62 +
53 var led = angular.element('.led', $element), 63 var led = angular.element('.led', $element),
54 ledContainer = angular.element('#led-container', $element), 64 ledContainer = angular.element('#led-container', $element),
55 textMeasure = angular.element('#text-measure', $element), 65 textMeasure = angular.element('#text-measure', $element),
@@ -66,8 +76,11 @@ function LedIndicatorController($element, $scope, $timeout) { @@ -66,8 +76,11 @@ function LedIndicatorController($element, $scope, $timeout) {
66 76
67 $scope.$on('$destroy', () => { 77 $scope.$on('$destroy', () => {
68 vm.destroyed = true; 78 vm.destroyed = true;
69 - if (vm.requestValueTimeoutHandle) {  
70 - $timeout.cancel(vm.requestValueTimeoutHandle); 79 + if (vm.checkStatusTimeoutHandle) {
  80 + $timeout.cancel(vm.checkStatusTimeoutHandle);
  81 + }
  82 + if (vm.subscription) {
  83 + vm.ctx.subscriptionApi.removeSubscription(vm.subscription.id);
71 } 84 }
72 }); 85 });
73 86
@@ -80,6 +93,8 @@ function LedIndicatorController($element, $scope, $timeout) { @@ -80,6 +93,8 @@ function LedIndicatorController($element, $scope, $timeout) {
80 93
81 var origColor = angular.isDefined(vm.ctx.settings.ledColor) ? vm.ctx.settings.ledColor : 'green'; 94 var origColor = angular.isDefined(vm.ctx.settings.ledColor) ? vm.ctx.settings.ledColor : 'green';
82 95
  96 + vm.valueAttribute = angular.isDefined(vm.ctx.settings.valueAttribute) ? vm.ctx.settings.valueAttribute : 'value';
  97 +
83 vm.ledColor = tinycolor(origColor).brighten(30).toHexString(); 98 vm.ledColor = tinycolor(origColor).brighten(30).toHexString();
84 vm.ledMiddleColor = tinycolor(origColor).toHexString(); 99 vm.ledMiddleColor = tinycolor(origColor).toHexString();
85 vm.disabledColor = tinycolor(origColor).darken(40).toHexString(); 100 vm.disabledColor = tinycolor(origColor).darken(40).toHexString();
@@ -101,19 +116,15 @@ function LedIndicatorController($element, $scope, $timeout) { @@ -101,19 +116,15 @@ function LedIndicatorController($element, $scope, $timeout) {
101 if (vm.ctx.settings.requestTimeout) { 116 if (vm.ctx.settings.requestTimeout) {
102 vm.requestTimeout = vm.ctx.settings.requestTimeout; 117 vm.requestTimeout = vm.ctx.settings.requestTimeout;
103 } 118 }
104 - vm.valuePollingInterval = 500;  
105 - if (vm.ctx.settings.valuePollingInterval) {  
106 - vm.valuePollingInterval = vm.ctx.settings.valuePollingInterval;  
107 - }  
108 - vm.getValueMethod = 'getValue';  
109 - if (vm.ctx.settings.getValueMethod && vm.ctx.settings.getValueMethod.length) {  
110 - vm.getValueMethod = vm.ctx.settings.getValueMethod; 119 + vm.checkStatusMethod = 'checkStatus';
  120 + if (vm.ctx.settings.checkStatusMethod && vm.ctx.settings.checkStatusMethod.length) {
  121 + vm.checkStatusMethod = vm.ctx.settings.checkStatusMethod;
111 } 122 }
112 if (!rpcEnabled) { 123 if (!rpcEnabled) {
113 onError('Target device is not set!'); 124 onError('Target device is not set!');
114 } else { 125 } else {
115 if (!vm.isSimulated) { 126 if (!vm.isSimulated) {
116 - rpcRequestValue(); 127 + rpcCheckStatus();
117 } 128 }
118 } 129 }
119 } 130 }
@@ -173,29 +184,86 @@ function LedIndicatorController($element, $scope, $timeout) { @@ -173,29 +184,86 @@ function LedIndicatorController($element, $scope, $timeout) {
173 return textMeasure.width(); 184 return textMeasure.width();
174 } 185 }
175 186
176 - function rpcRequestValue() { 187 + function rpcCheckStatus() {
177 if (vm.destroyed) { 188 if (vm.destroyed) {
178 return; 189 return;
179 } 190 }
180 vm.error = ''; 191 vm.error = '';
181 - vm.ctx.controlApi.sendTwoWayCommand(vm.getValueMethod, null, vm.requestTimeout).then( 192 + vm.ctx.controlApi.sendTwoWayCommand(vm.checkStatusMethod, null, vm.requestTimeout).then(
182 (responseBody) => { 193 (responseBody) => {
183 - var newValue = responseBody ? true : false;  
184 - setValue(newValue);  
185 - if (vm.requestValueTimeoutHandle) {  
186 - $timeout.cancel(vm.requestValueTimeoutHandle); 194 + var status = responseBody ? true : false;
  195 + if (status) {
  196 + if (vm.checkStatusTimeoutHandle) {
  197 + $timeout.cancel(vm.checkStatusTimeoutHandle);
  198 + vm.checkStatusTimeoutHandle = null;
  199 + }
  200 + subscribeForValue();
  201 + } else {
  202 + var errorText = 'Unknown device status!';
  203 + onError(errorText);
  204 + if (vm.checkStatusTimeoutHandle) {
  205 + $timeout.cancel(vm.checkStatusTimeoutHandle);
  206 + }
  207 + vm.checkStatusTimeoutHandle = $timeout(rpcCheckStatus, checkStatusPollingInterval);
187 } 208 }
188 - vm.requestValueTimeoutHandle = $timeout(rpcRequestValue, vm.valuePollingInterval);  
189 }, 209 },
190 () => { 210 () => {
191 var errorText = vm.ctx.defaultSubscription.rpcErrorText; 211 var errorText = vm.ctx.defaultSubscription.rpcErrorText;
192 onError(errorText); 212 onError(errorText);
193 - if (vm.requestValueTimeoutHandle) {  
194 - $timeout.cancel(vm.requestValueTimeoutHandle); 213 + if (vm.checkStatusTimeoutHandle) {
  214 + $timeout.cancel(vm.checkStatusTimeoutHandle);
195 } 215 }
196 - vm.requestValueTimeoutHandle = $timeout(rpcRequestValue, vm.valuePollingInterval); 216 + vm.checkStatusTimeoutHandle = $timeout(rpcCheckStatus, checkStatusPollingInterval);
  217 + }
  218 + );
  219 + }
  220 +
  221 + function subscribeForValue() {
  222 + var subscriptionsInfo = [{
  223 + type: types.datasourceType.entity,
  224 + entityType: types.entityType.device,
  225 + entityId: vm.ctx.defaultSubscription.targetDeviceId,
  226 + attributes: [
  227 + {name: vm.valueAttribute}
  228 + ]
  229 + }];
  230 + vm.ctx.subscriptionApi.createSubscriptionFromInfo (
  231 + types.widgetType.latest.value, subscriptionsInfo, vm.subscriptionOptions, false, true).then(
  232 + function(subscription) {
  233 + vm.subscription = subscription;
197 } 234 }
198 ); 235 );
199 } 236 }
200 237
  238 + function onDataUpdated(subscription, apply) {
  239 + var value = false;
  240 + var data = subscription.data;
  241 + if (data.length) {
  242 + var keyData = data[0];
  243 + if (keyData && keyData.data && keyData.data[0]) {
  244 + var attrValue = keyData.data[0][1];
  245 + if (attrValue) {
  246 + var parsed = null;
  247 + try {
  248 + parsed = angular.fromJson(attrValue);
  249 + } catch (e){/**/}
  250 + value = parsed ? true : false;
  251 + }
  252 + }
  253 + }
  254 + setValue(value);
  255 + if (apply) {
  256 + $scope.$digest();
  257 + }
  258 + }
  259 +
  260 + function onDataUpdateError(subscription, e) {
  261 + var exceptionData = utils.parseException(e);
  262 + var errorText = exceptionData.name;
  263 + if (exceptionData.message) {
  264 + errorText += ': ' + exceptionData.message;
  265 + }
  266 + onError(errorText);
  267 + }
  268 +
201 } 269 }