Commit c003b20bbe4227d6009dfa156022a71d33ba2cd7
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
2 changed files
with
91 additions
and
23 deletions
... | ... | @@ -96,9 +96,9 @@ |
96 | 96 | "templateHtml": "<tb-led-indicator ctx='ctx'></tb-led-indicator>", |
97 | 97 | "templateCss": "", |
98 | 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 | 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 | 43 | } |
44 | 44 | |
45 | 45 | /*@ngInject*/ |
46 | -function LedIndicatorController($element, $scope, $timeout) { | |
46 | +function LedIndicatorController($element, $scope, $timeout, utils, types) { | |
47 | 47 | let vm = this; |
48 | 48 | |
49 | 49 | vm.showTitle = false; |
50 | 50 | vm.value = false; |
51 | 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 | 63 | var led = angular.element('.led', $element), |
54 | 64 | ledContainer = angular.element('#led-container', $element), |
55 | 65 | textMeasure = angular.element('#text-measure', $element), |
... | ... | @@ -66,8 +76,11 @@ function LedIndicatorController($element, $scope, $timeout) { |
66 | 76 | |
67 | 77 | $scope.$on('$destroy', () => { |
68 | 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 | 93 | |
81 | 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 | 98 | vm.ledColor = tinycolor(origColor).brighten(30).toHexString(); |
84 | 99 | vm.ledMiddleColor = tinycolor(origColor).toHexString(); |
85 | 100 | vm.disabledColor = tinycolor(origColor).darken(40).toHexString(); |
... | ... | @@ -101,19 +116,15 @@ function LedIndicatorController($element, $scope, $timeout) { |
101 | 116 | if (vm.ctx.settings.requestTimeout) { |
102 | 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 | 123 | if (!rpcEnabled) { |
113 | 124 | onError('Target device is not set!'); |
114 | 125 | } else { |
115 | 126 | if (!vm.isSimulated) { |
116 | - rpcRequestValue(); | |
127 | + rpcCheckStatus(); | |
117 | 128 | } |
118 | 129 | } |
119 | 130 | } |
... | ... | @@ -173,29 +184,86 @@ function LedIndicatorController($element, $scope, $timeout) { |
173 | 184 | return textMeasure.width(); |
174 | 185 | } |
175 | 186 | |
176 | - function rpcRequestValue() { | |
187 | + function rpcCheckStatus() { | |
177 | 188 | if (vm.destroyed) { |
178 | 189 | return; |
179 | 190 | } |
180 | 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 | 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 | 211 | var errorText = vm.ctx.defaultSubscription.rpcErrorText; |
192 | 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 | } | ... | ... |