Commit c1e77ccad33e39408e1b228dc6efd76c3a473ff6
1 parent
28853c7d
UI: Improved configuration of RPC control widgets
Showing
5 changed files
with
258 additions
and
19 deletions
... | ... | @@ -64,7 +64,7 @@ |
64 | 64 | "templateHtml": "<tb-switch ctx='ctx'></tb-switch>", |
65 | 65 | "templateCss": "", |
66 | 66 | "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", |
67 | - "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\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showOnOffLabels\": {\n \"title\": \"Show on/off labels\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"getValueMethod\": {\n \"title\": \"Get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"Set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n \"showOnOffLabels\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"requestTimeout\"\n ]\n}", | |
67 | + "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\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showOnOffLabels\": {\n \"title\": \"Show on/off labels\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve on/off value using method\",\n \"type\": \"string\",\n \"default\": \"rpc\"\n },\n \"valueKey\": {\n \"title\": \"Attribute/Timeseries value key (only when subscribe for attribute/timeseries method)\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"getValueMethod\": {\n \"title\": \"RPC get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"RPC set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"convertValueFunction\": {\n \"title\": \"Convert value function, f(value), returns payload used by RPC set value method\",\n \"type\": \"string\",\n \"default\": \"return value;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n \"showOnOffLabels\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"none\",\n \"label\": \"Don't retrieve\"\n },\n {\n \"value\": \"rpc\",\n \"label\": \"Call RPC get value method\"\n },\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueKey\",\n \"getValueMethod\",\n \"setValueMethod\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"convertValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", | |
68 | 68 | "dataKeySettingsSchema": "{}\n", |
69 | 69 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"showOnOffLabels\":true,\"title\":\"Switch control\"},\"title\":\"Switch Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
70 | 70 | } |
... | ... | @@ -80,9 +80,9 @@ |
80 | 80 | "templateHtml": "<tb-round-switch ctx='ctx'></tb-round-switch>", |
81 | 81 | "templateCss": "", |
82 | 82 | "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", |
83 | - "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\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"getValueMethod\": {\n \"title\": \"Get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"Set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"requestTimeout\"\n ]\n}", | |
83 | + "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\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve on/off value using method\",\n \"type\": \"string\",\n \"default\": \"rpc\"\n },\n \"valueKey\": {\n \"title\": \"Attribute/Timeseries value key (only when subscribe for attribute/timeseries method)\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"getValueMethod\": {\n \"title\": \"RPC get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"RPC set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"convertValueFunction\": {\n \"title\": \"Convert value function, f(value), returns payload used by RPC set value method\",\n \"type\": \"string\",\n \"default\": \"return value;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"none\",\n \"label\": \"Don't retrieve\"\n },\n {\n \"value\": \"rpc\",\n \"label\": \"Call RPC get value method\"\n },\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueKey\",\n \"getValueMethod\",\n \"setValueMethod\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"convertValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", | |
84 | 84 | "dataKeySettingsSchema": "{}\n", |
85 | - "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"showOnOffLabels\":true,\"title\":\"Round switch\"},\"title\":\"Round switch\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" | |
85 | + "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"title\":\"Round switch\",\"retrieveValueMethod\":\"rpc\",\"valueKey\":\"value\",\"parseValueFunction\":\"return data ? true : false;\",\"convertValueFunction\":\"return value;\"},\"title\":\"Round switch\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" | |
86 | 86 | } |
87 | 87 | }, |
88 | 88 | { |
... | ... | @@ -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 \"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}", | |
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\": \"RPC check device status method\",\n \"type\": \"string\",\n \"default\": \"checkStatus\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve led status value using method\",\n \"type\": \"string\",\n \"default\": \"attribute\"\n },\n \"valueAttribute\": {\n \"title\": \"Device attribute/timeseries containing led status value\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse led status value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\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 {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueAttribute\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\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,\"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}" | |
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\",\"retrieveValueMethod\":\"attribute\",\"parseValueFunction\":\"return data ? true : false;\"},\"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 | ] | ... | ... |
... | ... | @@ -70,7 +70,7 @@ public class ThingsboardInstallService { |
70 | 70 | |
71 | 71 | switch (upgradeFromVersion) { |
72 | 72 | case "1.2.3": |
73 | - log.info("Upgrading ThingsBoard from version {} to 1.3.0 ...", upgradeFromVersion); | |
73 | + log.info("Upgrading ThingsBoard from version 1.2.3 to 1.3.0 ..."); | |
74 | 74 | |
75 | 75 | databaseUpgradeService.upgradeDatabase(upgradeFromVersion); |
76 | 76 | |
... | ... | @@ -84,6 +84,21 @@ public class ThingsboardInstallService { |
84 | 84 | systemDataLoaderService.deleteSystemWidgetBundle("gpio_widgets"); |
85 | 85 | systemDataLoaderService.deleteSystemWidgetBundle("alarm_widgets"); |
86 | 86 | |
87 | + case "1.3.0": | |
88 | + log.info("Upgrading ThingsBoard from version 1.3.0 to 1.3.1 ..."); | |
89 | + | |
90 | + log.info("Updating system data..."); | |
91 | + | |
92 | + systemDataLoaderService.deleteSystemWidgetBundle("charts"); | |
93 | + systemDataLoaderService.deleteSystemWidgetBundle("cards"); | |
94 | + systemDataLoaderService.deleteSystemWidgetBundle("maps"); | |
95 | + systemDataLoaderService.deleteSystemWidgetBundle("analogue_gauges"); | |
96 | + systemDataLoaderService.deleteSystemWidgetBundle("digital_gauges"); | |
97 | + systemDataLoaderService.deleteSystemWidgetBundle("gpio_widgets"); | |
98 | + systemDataLoaderService.deleteSystemWidgetBundle("alarm_widgets"); | |
99 | + systemDataLoaderService.deleteSystemWidgetBundle("control_widgets"); | |
100 | + systemDataLoaderService.deleteSystemWidgetBundle("maps_v2"); | |
101 | + | |
87 | 102 | systemDataLoaderService.loadSystemWidgets(); |
88 | 103 | |
89 | 104 | break; | ... | ... |
... | ... | @@ -116,6 +116,20 @@ function LedIndicatorController($element, $scope, $timeout, utils, types) { |
116 | 116 | if (vm.ctx.settings.requestTimeout) { |
117 | 117 | vm.requestTimeout = vm.ctx.settings.requestTimeout; |
118 | 118 | } |
119 | + vm.retrieveValueMethod = 'attribute'; | |
120 | + if (vm.ctx.settings.retrieveValueMethod && vm.ctx.settings.retrieveValueMethod.length) { | |
121 | + vm.retrieveValueMethod = vm.ctx.settings.retrieveValueMethod; | |
122 | + } | |
123 | + | |
124 | + vm.parseValueFunction = (data) => data ? true : false; | |
125 | + if (vm.ctx.settings.parseValueFunction && vm.ctx.settings.parseValueFunction.length) { | |
126 | + try { | |
127 | + vm.parseValueFunction = new Function('data', vm.ctx.settings.parseValueFunction); | |
128 | + } catch (e) { | |
129 | + vm.parseValueFunction = (data) => data ? true : false; | |
130 | + } | |
131 | + } | |
132 | + | |
119 | 133 | vm.checkStatusMethod = 'checkStatus'; |
120 | 134 | if (vm.ctx.settings.checkStatusMethod && vm.ctx.settings.checkStatusMethod.length) { |
121 | 135 | vm.checkStatusMethod = vm.ctx.settings.checkStatusMethod; |
... | ... | @@ -222,11 +236,19 @@ function LedIndicatorController($element, $scope, $timeout, utils, types) { |
222 | 236 | var subscriptionsInfo = [{ |
223 | 237 | type: types.datasourceType.entity, |
224 | 238 | entityType: types.entityType.device, |
225 | - entityId: vm.ctx.defaultSubscription.targetDeviceId, | |
226 | - attributes: [ | |
227 | - {name: vm.valueAttribute} | |
228 | - ] | |
239 | + entityId: vm.ctx.defaultSubscription.targetDeviceId | |
229 | 240 | }]; |
241 | + | |
242 | + if (vm.retrieveValueMethod == 'attribute') { | |
243 | + subscriptionsInfo[0].attributes = [ | |
244 | + {name: vm.valueAttribute} | |
245 | + ]; | |
246 | + } else { | |
247 | + subscriptionsInfo[0].timeseries = [ | |
248 | + {name: vm.valueAttribute} | |
249 | + ]; | |
250 | + } | |
251 | + | |
230 | 252 | vm.ctx.subscriptionApi.createSubscriptionFromInfo ( |
231 | 253 | types.widgetType.latest.value, subscriptionsInfo, vm.subscriptionOptions, false, true).then( |
232 | 254 | function(subscription) { |
... | ... | @@ -245,7 +267,7 @@ function LedIndicatorController($element, $scope, $timeout, utils, types) { |
245 | 267 | if (attrValue) { |
246 | 268 | var parsed = null; |
247 | 269 | try { |
248 | - parsed = angular.fromJson(attrValue); | |
270 | + parsed = vm.parseValueFunction(angular.fromJson(attrValue)); | |
249 | 271 | } catch (e){/**/} |
250 | 272 | value = parsed ? true : false; |
251 | 273 | } | ... | ... |
... | ... | @@ -41,7 +41,7 @@ function RoundSwitch() { |
41 | 41 | } |
42 | 42 | |
43 | 43 | /*@ngInject*/ |
44 | -function RoundSwitchController($element, $scope, utils) { | |
44 | +function RoundSwitchController($element, $scope, utils, types) { | |
45 | 45 | let vm = this; |
46 | 46 | |
47 | 47 | vm.showTitle = false; |
... | ... | @@ -64,12 +64,20 @@ function RoundSwitchController($element, $scope, utils) { |
64 | 64 | onValue(); |
65 | 65 | }); |
66 | 66 | |
67 | + vm.valueSubscription = null; | |
68 | + | |
67 | 69 | $scope.$watch('vm.ctx', () => { |
68 | 70 | if (vm.ctx) { |
69 | 71 | init(); |
70 | 72 | } |
71 | 73 | }); |
72 | 74 | |
75 | + $scope.$on('$destroy', () => { | |
76 | + if (vm.valueSubscription) { | |
77 | + vm.ctx.subscriptionApi.removeSubscription(vm.valueSubscription.id); | |
78 | + } | |
79 | + }); | |
80 | + | |
73 | 81 | resize(); |
74 | 82 | |
75 | 83 | function init() { |
... | ... | @@ -92,6 +100,35 @@ function RoundSwitchController($element, $scope, utils) { |
92 | 100 | if (vm.ctx.settings.requestTimeout) { |
93 | 101 | vm.requestTimeout = vm.ctx.settings.requestTimeout; |
94 | 102 | } |
103 | + | |
104 | + vm.retrieveValueMethod = 'rpc'; | |
105 | + if (vm.ctx.settings.retrieveValueMethod && vm.ctx.settings.retrieveValueMethod.length) { | |
106 | + vm.retrieveValueMethod = vm.ctx.settings.retrieveValueMethod; | |
107 | + } | |
108 | + | |
109 | + vm.valueKey = 'value'; | |
110 | + if (vm.ctx.settings.valueKey && vm.ctx.settings.valueKey.length) { | |
111 | + vm.valueKey = vm.ctx.settings.valueKey; | |
112 | + } | |
113 | + | |
114 | + vm.parseValueFunction = (data) => data ? true : false; | |
115 | + if (vm.ctx.settings.parseValueFunction && vm.ctx.settings.parseValueFunction.length) { | |
116 | + try { | |
117 | + vm.parseValueFunction = new Function('data', vm.ctx.settings.parseValueFunction); | |
118 | + } catch (e) { | |
119 | + vm.parseValueFunction = (data) => data ? true : false; | |
120 | + } | |
121 | + } | |
122 | + | |
123 | + vm.convertValueFunction = (value) => value; | |
124 | + if (vm.ctx.settings.convertValueFunction && vm.ctx.settings.convertValueFunction.length) { | |
125 | + try { | |
126 | + vm.convertValueFunction = new Function('value', vm.ctx.settings.convertValueFunction); | |
127 | + } catch (e) { | |
128 | + vm.convertValueFunction = (value) => value; | |
129 | + } | |
130 | + } | |
131 | + | |
95 | 132 | vm.getValueMethod = 'getValue'; |
96 | 133 | if (vm.ctx.settings.getValueMethod && vm.ctx.settings.getValueMethod.length) { |
97 | 134 | vm.getValueMethod = vm.ctx.settings.getValueMethod; |
... | ... | @@ -104,7 +141,11 @@ function RoundSwitchController($element, $scope, utils) { |
104 | 141 | onError('Target device is not set!'); |
105 | 142 | } else { |
106 | 143 | if (!vm.isSimulated) { |
107 | - rpcRequestValue(); | |
144 | + if (vm.retrieveValueMethod == 'rpc') { | |
145 | + rpcRequestValue(); | |
146 | + } else if (vm.retrieveValueMethod == 'attribute' || vm.retrieveValueMethod == 'timeseries') { | |
147 | + subscribeForValue(); | |
148 | + } | |
108 | 149 | } |
109 | 150 | } |
110 | 151 | } |
... | ... | @@ -127,6 +168,66 @@ function RoundSwitchController($element, $scope, utils) { |
127 | 168 | setFontSize(switchError, vm.error, switchErrorContainer.height(), switchErrorContainer.width()); |
128 | 169 | } |
129 | 170 | |
171 | + function subscribeForValue() { | |
172 | + var valueSubscriptionInfo = [{ | |
173 | + type: types.datasourceType.entity, | |
174 | + entityType: types.entityType.device, | |
175 | + entityId: vm.ctx.defaultSubscription.targetDeviceId | |
176 | + }]; | |
177 | + if (vm.retrieveValueMethod == 'attribute') { | |
178 | + valueSubscriptionInfo[0].attributes = [ | |
179 | + {name: vm.valueKey} | |
180 | + ]; | |
181 | + } else { | |
182 | + valueSubscriptionInfo[0].timeseries = [ | |
183 | + {name: vm.valueKey} | |
184 | + ]; | |
185 | + } | |
186 | + var subscriptionOptions = { | |
187 | + callbacks: { | |
188 | + onDataUpdated: onDataUpdated, | |
189 | + onDataUpdateError: onDataUpdateError | |
190 | + } | |
191 | + }; | |
192 | + vm.ctx.subscriptionApi.createSubscriptionFromInfo ( | |
193 | + types.widgetType.latest.value, valueSubscriptionInfo, subscriptionOptions, false, true).then( | |
194 | + (subscription) => { | |
195 | + vm.valueSubscription = subscription; | |
196 | + } | |
197 | + ); | |
198 | + } | |
199 | + | |
200 | + function onDataUpdated(subscription, apply) { | |
201 | + var value = false; | |
202 | + var data = subscription.data; | |
203 | + if (data.length) { | |
204 | + var keyData = data[0]; | |
205 | + if (keyData && keyData.data && keyData.data[0]) { | |
206 | + var attrValue = keyData.data[0][1]; | |
207 | + if (attrValue) { | |
208 | + var parsed = null; | |
209 | + try { | |
210 | + parsed = vm.parseValueFunction(angular.fromJson(attrValue)); | |
211 | + } catch (e){/**/} | |
212 | + value = parsed ? true : false; | |
213 | + } | |
214 | + } | |
215 | + } | |
216 | + setValue(value); | |
217 | + if (apply) { | |
218 | + $scope.$digest(); | |
219 | + } | |
220 | + } | |
221 | + | |
222 | + function onDataUpdateError(subscription, e) { | |
223 | + var exceptionData = utils.parseException(e); | |
224 | + var errorText = exceptionData.name; | |
225 | + if (exceptionData.message) { | |
226 | + errorText += ': ' + exceptionData.message; | |
227 | + } | |
228 | + onError(errorText); | |
229 | + } | |
230 | + | |
130 | 231 | function setValue(value) { |
131 | 232 | vm.value = value ? true : false; |
132 | 233 | onoff.prop('checked', !vm.value); |
... | ... | @@ -162,7 +263,7 @@ function RoundSwitchController($element, $scope, utils) { |
162 | 263 | vm.error = ''; |
163 | 264 | vm.ctx.controlApi.sendTwoWayCommand(vm.getValueMethod, null, vm.requestTimeout).then( |
164 | 265 | (responseBody) => { |
165 | - setValue(responseBody); | |
266 | + setValue(vm.parseValueFunction(responseBody)); | |
166 | 267 | }, |
167 | 268 | () => { |
168 | 269 | var errorText = vm.ctx.defaultSubscription.rpcErrorText; |
... | ... | @@ -181,7 +282,7 @@ function RoundSwitchController($element, $scope, utils) { |
181 | 282 | vm.executingUpdateValue = true; |
182 | 283 | } |
183 | 284 | vm.error = ''; |
184 | - vm.ctx.controlApi.sendOneWayCommand(vm.setValueMethod, value, vm.requestTimeout).then( | |
285 | + vm.ctx.controlApi.sendOneWayCommand(vm.setValueMethod, vm.convertValueFunction(value), vm.requestTimeout).then( | |
185 | 286 | () => { |
186 | 287 | vm.executingUpdateValue = false; |
187 | 288 | if (vm.scheduledValue != null && vm.scheduledValue != vm.rpcValue) { | ... | ... |
... | ... | @@ -41,7 +41,7 @@ function Switch() { |
41 | 41 | } |
42 | 42 | |
43 | 43 | /*@ngInject*/ |
44 | -function SwitchController($element, $scope) { | |
44 | +function SwitchController($element, $scope, types, utils) { | |
45 | 45 | let vm = this; |
46 | 46 | |
47 | 47 | vm.showTitle = false; |
... | ... | @@ -63,12 +63,20 @@ function SwitchController($element, $scope) { |
63 | 63 | |
64 | 64 | vm.onValue = onValue; |
65 | 65 | |
66 | + vm.valueSubscription = null; | |
67 | + | |
66 | 68 | $scope.$watch('vm.ctx', () => { |
67 | 69 | if (vm.ctx) { |
68 | 70 | init(); |
69 | 71 | } |
70 | 72 | }); |
71 | 73 | |
74 | + $scope.$on('$destroy', () => { | |
75 | + if (vm.valueSubscription) { | |
76 | + vm.ctx.subscriptionApi.removeSubscription(vm.valueSubscription.id); | |
77 | + } | |
78 | + }); | |
79 | + | |
72 | 80 | function init() { |
73 | 81 | |
74 | 82 | vm.title = angular.isDefined(vm.ctx.settings.title) ? vm.ctx.settings.title : ''; |
... | ... | @@ -90,6 +98,35 @@ function SwitchController($element, $scope) { |
90 | 98 | if (vm.ctx.settings.requestTimeout) { |
91 | 99 | vm.requestTimeout = vm.ctx.settings.requestTimeout; |
92 | 100 | } |
101 | + | |
102 | + vm.retrieveValueMethod = 'rpc'; | |
103 | + if (vm.ctx.settings.retrieveValueMethod && vm.ctx.settings.retrieveValueMethod.length) { | |
104 | + vm.retrieveValueMethod = vm.ctx.settings.retrieveValueMethod; | |
105 | + } | |
106 | + | |
107 | + vm.valueKey = 'value'; | |
108 | + if (vm.ctx.settings.valueKey && vm.ctx.settings.valueKey.length) { | |
109 | + vm.valueKey = vm.ctx.settings.valueKey; | |
110 | + } | |
111 | + | |
112 | + vm.parseValueFunction = (data) => data ? true : false; | |
113 | + if (vm.ctx.settings.parseValueFunction && vm.ctx.settings.parseValueFunction.length) { | |
114 | + try { | |
115 | + vm.parseValueFunction = new Function('data', vm.ctx.settings.parseValueFunction); | |
116 | + } catch (e) { | |
117 | + vm.parseValueFunction = (data) => data ? true : false; | |
118 | + } | |
119 | + } | |
120 | + | |
121 | + vm.convertValueFunction = (value) => value; | |
122 | + if (vm.ctx.settings.convertValueFunction && vm.ctx.settings.convertValueFunction.length) { | |
123 | + try { | |
124 | + vm.convertValueFunction = new Function('value', vm.ctx.settings.convertValueFunction); | |
125 | + } catch (e) { | |
126 | + vm.convertValueFunction = (value) => value; | |
127 | + } | |
128 | + } | |
129 | + | |
93 | 130 | vm.getValueMethod = 'getValue'; |
94 | 131 | if (vm.ctx.settings.getValueMethod && vm.ctx.settings.getValueMethod.length) { |
95 | 132 | vm.getValueMethod = vm.ctx.settings.getValueMethod; |
... | ... | @@ -102,7 +139,11 @@ function SwitchController($element, $scope) { |
102 | 139 | onError('Target device is not set!'); |
103 | 140 | } else { |
104 | 141 | if (!vm.isSimulated) { |
105 | - rpcRequestValue(); | |
142 | + if (vm.retrieveValueMethod == 'rpc') { | |
143 | + rpcRequestValue(); | |
144 | + } else if (vm.retrieveValueMethod == 'attribute' || vm.retrieveValueMethod == 'timeseries') { | |
145 | + subscribeForValue(); | |
146 | + } | |
106 | 147 | } |
107 | 148 | } |
108 | 149 | } |
... | ... | @@ -144,6 +185,66 @@ function SwitchController($element, $scope) { |
144 | 185 | setFontSize(switchError, vm.error, switchErrorContainer.height(), switchErrorContainer.width()); |
145 | 186 | } |
146 | 187 | |
188 | + function subscribeForValue() { | |
189 | + var valueSubscriptionInfo = [{ | |
190 | + type: types.datasourceType.entity, | |
191 | + entityType: types.entityType.device, | |
192 | + entityId: vm.ctx.defaultSubscription.targetDeviceId | |
193 | + }]; | |
194 | + if (vm.retrieveValueMethod == 'attribute') { | |
195 | + valueSubscriptionInfo[0].attributes = [ | |
196 | + {name: vm.valueKey} | |
197 | + ]; | |
198 | + } else { | |
199 | + valueSubscriptionInfo[0].timeseries = [ | |
200 | + {name: vm.valueKey} | |
201 | + ]; | |
202 | + } | |
203 | + var subscriptionOptions = { | |
204 | + callbacks: { | |
205 | + onDataUpdated: onDataUpdated, | |
206 | + onDataUpdateError: onDataUpdateError | |
207 | + } | |
208 | + }; | |
209 | + vm.ctx.subscriptionApi.createSubscriptionFromInfo ( | |
210 | + types.widgetType.latest.value, valueSubscriptionInfo, subscriptionOptions, false, true).then( | |
211 | + (subscription) => { | |
212 | + vm.valueSubscription = subscription; | |
213 | + } | |
214 | + ); | |
215 | + } | |
216 | + | |
217 | + function onDataUpdated(subscription, apply) { | |
218 | + var value = false; | |
219 | + var data = subscription.data; | |
220 | + if (data.length) { | |
221 | + var keyData = data[0]; | |
222 | + if (keyData && keyData.data && keyData.data[0]) { | |
223 | + var attrValue = keyData.data[0][1]; | |
224 | + if (attrValue) { | |
225 | + var parsed = null; | |
226 | + try { | |
227 | + parsed = vm.parseValueFunction(angular.fromJson(attrValue)); | |
228 | + } catch (e){/**/} | |
229 | + value = parsed ? true : false; | |
230 | + } | |
231 | + } | |
232 | + } | |
233 | + setValue(value); | |
234 | + if (apply) { | |
235 | + $scope.$digest(); | |
236 | + } | |
237 | + } | |
238 | + | |
239 | + function onDataUpdateError(subscription, e) { | |
240 | + var exceptionData = utils.parseException(e); | |
241 | + var errorText = exceptionData.name; | |
242 | + if (exceptionData.message) { | |
243 | + errorText += ': ' + exceptionData.message; | |
244 | + } | |
245 | + onError(errorText); | |
246 | + } | |
247 | + | |
147 | 248 | function setValue(value) { |
148 | 249 | vm.value = value ? true : false; |
149 | 250 | } |
... | ... | @@ -178,7 +279,7 @@ function SwitchController($element, $scope) { |
178 | 279 | vm.error = ''; |
179 | 280 | vm.ctx.controlApi.sendTwoWayCommand(vm.getValueMethod, null, vm.requestTimeout).then( |
180 | 281 | (responseBody) => { |
181 | - setValue(responseBody); | |
282 | + setValue(vm.parseValueFunction(responseBody)); | |
182 | 283 | }, |
183 | 284 | () => { |
184 | 285 | var errorText = vm.ctx.defaultSubscription.rpcErrorText; |
... | ... | @@ -197,7 +298,7 @@ function SwitchController($element, $scope) { |
197 | 298 | vm.executingUpdateValue = true; |
198 | 299 | } |
199 | 300 | vm.error = ''; |
200 | - vm.ctx.controlApi.sendOneWayCommand(vm.setValueMethod, value, vm.requestTimeout).then( | |
301 | + vm.ctx.controlApi.sendOneWayCommand(vm.setValueMethod, vm.convertValueFunction(value), vm.requestTimeout).then( | |
201 | 302 | () => { |
202 | 303 | vm.executingUpdateValue = false; |
203 | 304 | if (vm.scheduledValue != null && vm.scheduledValue != vm.rpcValue) { | ... | ... |