Commit e33a336ed93362a12658611a7b9660b4dba8e5e7
Merge remote-tracking branch 'origin/master' into feature/bulk-import/device-credentials
# Conflicts: # application/src/main/java/org/thingsboard/server/controller/DeviceController.java # application/src/main/java/org/thingsboard/server/controller/EdgeController.java # common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java # ui-ngx/src/app/core/http/device.service.ts
Showing
100 changed files
with
1270 additions
and
830 deletions
Too many changes to show.
To preserve performance only 100 of 261 files are displayed.
... | ... | @@ -66,6 +66,10 @@ |
66 | 66 | <artifactId>rule-engine-api</artifactId> |
67 | 67 | </dependency> |
68 | 68 | <dependency> |
69 | + <groupId>org.thingsboard.common</groupId> | |
70 | + <artifactId>cluster-api</artifactId> | |
71 | + </dependency> | |
72 | + <dependency> | |
69 | 73 | <groupId>org.thingsboard.rule-engine</groupId> |
70 | 74 | <artifactId>rule-engine-components</artifactId> |
71 | 75 | </dependency> |
... | ... | @@ -290,6 +294,11 @@ |
290 | 294 | <scope>test</scope> |
291 | 295 | </dependency> |
292 | 296 | <dependency> |
297 | + <groupId>org.awaitility</groupId> | |
298 | + <artifactId>awaitility</artifactId> | |
299 | + <scope>test</scope> | |
300 | + </dependency> | |
301 | + <dependency> | |
293 | 302 | <groupId>org.mockito</groupId> |
294 | 303 | <artifactId>mockito-core</artifactId> |
295 | 304 | <scope>test</scope> | ... | ... |
... | ... | @@ -18,8 +18,8 @@ |
18 | 18 | "resources": [], |
19 | 19 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", |
20 | 20 | "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n", |
21 | - "controllerScript": "var requestTimeout = 500;\nvar requestPersistent = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestPersistent, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n}", | |
22 | - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\",\n \"requestPersistent\"\n ]\n}", | |
21 | + "controllerScript": "var requestTimeout = 500;\nvar requestPersistent = false;\nvar persistentPollingInterval = 5000;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n if (self.ctx.settings.persistentPollingInterval) {\n persistentPollingInterval = self.ctx.settings.persistentPollingInterval;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestPersistent, persistentPollingInterval, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n self.ctx.controlApi.completedCommand();\n}", | |
22 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"persistentPollingInterval\": {\n \"title\": \"Polling interval in milliseconds to get persistent RPC command response\",\n \"type\": \"number\",\n \"default\": 5000,\n \"minimum\": 1000\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\",\n \"requestPersistent\",\n {\n \"key\": \"persistentPollingInterval\",\n \"condition\": \"model.requestPersistent === true\"\n }\n ]\n}", | |
23 | 23 | "dataKeySettingsSchema": "{}\n", |
24 | 24 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
25 | 25 | } |
... | ... | @@ -55,7 +55,7 @@ |
55 | 55 | "templateHtml": "<tb-knob [ctx]='ctx'></tb-knob>", |
56 | 56 | "templateCss": "", |
57 | 57 | "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
58 | - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\",\n \"default\": 0\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\",\n \"default\": 100\n },\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"number\",\n \"default\": 50\n },\n \"title\": {\n \"title\": \"Knob 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\": [\"minValue\", \"maxValue\", \"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"minValue\",\n \"maxValue\",\n \"initialValue\",\n \"title\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"requestTimeout\"\n ]\n}", | |
58 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\",\n \"default\": 0\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\",\n \"default\": 100\n },\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"number\",\n \"default\": 50\n },\n \"title\": {\n \"title\": \"Knob 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 \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"persistentPollingInterval\": {\n \"title\": \"Polling interval in milliseconds to get persistent RPC command response\",\n \"type\": \"number\",\n \"default\": 5000,\n \"minimum\": 1000\n }\n },\n \"required\": [\"minValue\", \"maxValue\", \"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"minValue\",\n \"maxValue\",\n \"initialValue\",\n \"title\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"requestTimeout\",\n \"requestPersistent\",\n {\n \"key\": \"persistentPollingInterval\",\n \"condition\": \"model.requestPersistent === true\"\n }\n ]\n}", | |
59 | 59 | "dataKeySettingsSchema": "{}\n", |
60 | 60 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"maxValue\":100,\"initialValue\":50,\"minValue\":0,\"title\":\"Knob control\",\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\"},\"title\":\"Knob Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
61 | 61 | } |
... | ... | @@ -73,7 +73,7 @@ |
73 | 73 | "templateHtml": "<tb-switch [ctx]='ctx'></tb-switch>", |
74 | 74 | "templateCss": "", |
75 | 75 | "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
76 | - "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}", | |
76 | + "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 \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"persistentPollingInterval\": {\n \"title\": \"Polling interval in milliseconds to get persistent RPC command response\",\n \"type\": \"number\",\n \"default\": 5000,\n \"minimum\": 1000\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 \"requestPersistent\",\n {\n \"key\": \"persistentPollingInterval\",\n \"condition\": \"model.requestPersistent === true\"\n }\n ]\n}", | |
77 | 77 | "dataKeySettingsSchema": "{}\n", |
78 | 78 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"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}" |
79 | 79 | } |
... | ... | @@ -91,7 +91,7 @@ |
91 | 91 | "templateHtml": "<tb-round-switch [ctx]='ctx'></tb-round-switch>", |
92 | 92 | "templateCss": "", |
93 | 93 | "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
94 | - "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}", | |
94 | + "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 \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"persistentPollingInterval\": {\n \"title\": \"Polling interval in milliseconds to get persistent RPC command response\",\n \"type\": \"number\",\n \"default\": 5000,\n \"minimum\": 1000\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 \"requestPersistent\",\n {\n \"key\": \"persistentPollingInterval\",\n \"condition\": \"model.requestPersistent === true\"\n }\n ]\n}", | |
95 | 95 | "dataKeySettingsSchema": "{}\n", |
96 | 96 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"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}" |
97 | 97 | } |
... | ... | @@ -109,7 +109,7 @@ |
109 | 109 | "templateHtml": "<tb-led-indicator [ctx]='ctx'></tb-led-indicator>", |
110 | 110 | "templateCss": "", |
111 | 111 | "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
112 | - "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 \"performCheckStatus\": {\n \"title\": \"Perform RPC device status check\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"checkStatusMethod\": {\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\": [\"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"performCheckStatus\",\n \"checkStatusMethod\",\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}", | |
112 | + "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 \"performCheckStatus\": {\n \"title\": \"Perform RPC device status check\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"checkStatusMethod\": {\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 \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"persistentPollingInterval\": {\n \"title\": \"Polling interval in milliseconds to get persistent RPC command response\",\n \"type\": \"number\",\n \"default\": 5000,\n \"minimum\": 1000\n }\n },\n \"required\": [\"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"performCheckStatus\",\n \"checkStatusMethod\",\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 \"requestPersistent\",\n {\n \"key\": \"persistentPollingInterval\",\n \"condition\": \"model.requestPersistent === true\"\n }\n ]\n}", | |
113 | 113 | "dataKeySettingsSchema": "{}\n", |
114 | 114 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"valueAttribute\":\"value\",\"retrieveValueMethod\":\"attribute\",\"parseValueFunction\":\"return data ? true : false;\",\"performCheckStatus\":true,\"checkStatusMethod\":\"checkStatus\"},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
115 | 115 | } |
... | ... | @@ -126,8 +126,8 @@ |
126 | 126 | "resources": [], |
127 | 127 | "templateHtml": "<div class=\"tb-rpc-button\" fxLayout=\"column\">\n <div fxFlex=\"20\" class=\"title-container\" fxLayout=\"row\"\n fxLayoutAlign=\"center center\" [fxShow]=\"showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div fxFlex=\"{{showTitle ? 80 : 100}}\" [ngStyle]=\"{paddingTop: showTitle ? '5px': '10px'}\"\n class=\"button-container\" fxLayout=\"column\" fxLayoutAlign=\"center center\">\n <div>\n <button mat-button (click)=\"sendCommand()\"\n [class.mat-raised-button]=\"styleButton?.isRaised\"\n [color]=\"styleButton?.isPrimary ? 'primary' : ''\"\n [ngStyle]=\"customStyle\">\n {{buttonLable}}\n </button>\n </div>\n </div>\n <div class=\"error-container\" [ngStyle]=\"{'background': error?.length ? 'rgba(255,255,255,0.25)' : 'none'}\"\n fxLayout=\"row\" fxLayoutAlign=\"center center\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>", |
128 | 128 | "templateCss": ".tb-rpc-button {\n width: 100%;\n height: 100%;\n}\n\n.tb-rpc-button .title-container {\n font-weight: 500;\n white-space: nowrap;\n margin: 10px 0;\n}\n\n.tb-rpc-button .button-container div{\n min-width: 80%\n}\n\n.tb-rpc-button .button-container .mat-button{\n width: 100%;\n margin: 0;\n}\n\n.tb-rpc-button .error-container {\n position: absolute;\n top: 2%;\n right: 0;\n left: 0;\n z-index: 4;\n height: 14px;\n}\n\n.tb-rpc-button .error-container .button-error {\n color: #ff3315;\n white-space: nowrap;\n}", |
129 | - "controllerScript": "self.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges();\n });\n};\n\nfunction init() {\n let rpcEnabled = self.ctx.defaultSubscription.rpcEnabled;\n\n self.ctx.$scope.buttonLable = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton.bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n if (!rpcEnabled) {\n self.ctx.$scope.error =\n 'Target device is not set!';\n }\n\n self.ctx.$scope.sendCommand = function() {\n var rpcMethod = self.ctx.settings.methodName;\n var rpcParams = self.ctx.settings.methodParams;\n var timeout = self.ctx.settings.requestTimeout;\n var oneWayElseTwoWay = self.ctx.settings.oneWayElseTwoWay ?\n true : false;\n\n var commandPromise;\n if (oneWayElseTwoWay) {\n commandPromise = self.ctx.controlApi.sendOneWayCommand(\n rpcMethod, rpcParams, timeout);\n } else {\n commandPromise = self.ctx.controlApi.sendTwoWayCommand(\n rpcMethod, rpcParams, timeout);\n }\n commandPromise.subscribe(\n function success() {\n self.ctx.$scope.error = \"\";\n self.ctx.detectChanges();\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n self.ctx.detectChanges();\n }\n }\n );\n };\n}\n", | |
130 | - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"title\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"buttonText\": {\n \"title\": \"Button label\",\n \"type\": \"string\",\n \"default\": \"Send RPC\"\n },\n \"oneWayElseTwoWay\": {\n \"title\": \"Is One Way Command\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showError\": {\n \"title\": \"Show RPC command execution error\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"methodName\": {\n \"title\": \"RPC method\",\n \"type\": \"string\",\n \"default\": \"rpcCommand\"\n },\n \"methodParams\": {\n \"title\": \"RPC method params\",\n \"type\": \"string\",\n \"default\": \"{}\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 5000\n },\n \"styleButton\": {\n \"type\": \"object\",\n \"title\": \"Button Style\",\n \"properties\": {\n \"isRaised\": {\n \"type\": \"boolean\",\n \"title\": \"Raised\",\n \"default\": true\n },\n \"isPrimary\": {\n \"type\": \"boolean\",\n \"title\": \"Primary color\",\n \"default\": false\n },\n \"bgColor\": {\n \"type\": \"string\",\n \"title\": \"Button background color\",\n \"default\": null\n },\n \"textColor\": {\n \"type\": \"string\",\n \"title\": \"Button text color\",\n \"default\": null\n }\n }\n },\n \"required\": []\n }\n },\n \"form\": [\n \"title\",\n \"buttonText\",\n \"oneWayElseTwoWay\",\n \"showError\",\n \"methodName\",\n {\n \"key\": \"methodParams\",\n \"type\": \"json\"\n },\n \"requestTimeout\",\n {\n \"key\": \"styleButton\",\n \"items\": [\n \"styleButton.isRaised\",\n \"styleButton.isPrimary\",\n {\n \"key\": \"styleButton.bgColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"styleButton.textColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n\n}", | |
129 | + "controllerScript": "var requestPersistent = false;\nvar persistentPollingInterval = 5000;\n\nself.onInit = function() {\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n if (self.ctx.settings.persistentPollingInterval) {\n persistentPollingInterval = self.ctx.settings.persistentPollingInterval;\n }\n \n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges();\n });\n};\n\nfunction init() {\n let rpcEnabled = self.ctx.defaultSubscription.rpcEnabled;\n\n self.ctx.$scope.buttonLable = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton.bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n if (!rpcEnabled) {\n self.ctx.$scope.error =\n 'Target device is not set!';\n }\n\n self.ctx.$scope.sendCommand = function() {\n var rpcMethod = self.ctx.settings.methodName;\n var rpcParams = self.ctx.settings.methodParams;\n var timeout = self.ctx.settings.requestTimeout;\n var oneWayElseTwoWay = self.ctx.settings.oneWayElseTwoWay ?\n true : false;\n\n var commandPromise;\n if (oneWayElseTwoWay) {\n commandPromise = self.ctx.controlApi.sendOneWayCommand(\n rpcMethod, rpcParams, timeout, requestPersistent, persistentPollingInterval);\n } else {\n commandPromise = self.ctx.controlApi.sendTwoWayCommand(\n rpcMethod, rpcParams, timeout, requestPersistent, persistentPollingInterval);\n }\n commandPromise.subscribe(\n function success() {\n self.ctx.$scope.error = \"\";\n self.ctx.detectChanges();\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n self.ctx.detectChanges();\n }\n }\n );\n };\n}\n\nself.onDestroy = function() {\n self.ctx.controlApi.completedCommand();\n}\n", | |
130 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"title\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"buttonText\": {\n \"title\": \"Button label\",\n \"type\": \"string\",\n \"default\": \"Send RPC\"\n },\n \"oneWayElseTwoWay\": {\n \"title\": \"Is One Way Command\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showError\": {\n \"title\": \"Show RPC command execution error\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"methodName\": {\n \"title\": \"RPC method\",\n \"type\": \"string\",\n \"default\": \"rpcCommand\"\n },\n \"methodParams\": {\n \"title\": \"RPC method params\",\n \"type\": \"string\",\n \"default\": \"{}\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 5000\n },\n \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"persistentPollingInterval\": {\n \"title\": \"Polling interval in milliseconds to get persistent RPC command response\",\n \"type\": \"number\",\n \"default\": 5000,\n \"minimum\": 1000\n },\n \"styleButton\": {\n \"type\": \"object\",\n \"title\": \"Button Style\",\n \"properties\": {\n \"isRaised\": {\n \"type\": \"boolean\",\n \"title\": \"Raised\",\n \"default\": true\n },\n \"isPrimary\": {\n \"type\": \"boolean\",\n \"title\": \"Primary color\",\n \"default\": false\n },\n \"bgColor\": {\n \"type\": \"string\",\n \"title\": \"Button background color\",\n \"default\": null\n },\n \"textColor\": {\n \"type\": \"string\",\n \"title\": \"Button text color\",\n \"default\": null\n }\n }\n },\n \"required\": []\n }\n },\n \"form\": [\n \"title\",\n \"buttonText\",\n \"oneWayElseTwoWay\",\n \"showError\",\n \"methodName\",\n {\n \"key\": \"methodParams\",\n \"type\": \"json\"\n },\n \"requestTimeout\",\n \"requestPersistent\",\n {\n \"key\": \"persistentPollingInterval\",\n \"condition\": \"model.requestPersistent === true\"\n },\n {\n \"key\": \"styleButton\",\n \"items\": [\n \"styleButton.isRaised\",\n \"styleButton.isPrimary\",\n {\n \"key\": \"styleButton.bgColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"styleButton.textColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n\n}", | |
131 | 131 | "dataKeySettingsSchema": "{}\n", |
132 | 132 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":5000,\"oneWayElseTwoWay\":true,\"buttonText\":\"Send RPC\",\"styleButton\":{\"isRaised\":true,\"isPrimary\":false},\"methodName\":\"rpcCommand\",\"methodParams\":\"{}\"},\"title\":\"RPC Button\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
133 | 133 | } | ... | ... |
... | ... | @@ -81,7 +81,7 @@ import org.thingsboard.server.service.executors.ExternalCallExecutorService; |
81 | 81 | import org.thingsboard.server.service.executors.SharedEventLoopGroupService; |
82 | 82 | import org.thingsboard.server.service.mail.MailExecutorService; |
83 | 83 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
84 | -import org.thingsboard.server.service.queue.TbClusterService; | |
84 | +import org.thingsboard.server.cluster.TbClusterService; | |
85 | 85 | import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; |
86 | 86 | import org.thingsboard.server.service.rpc.TbRpcService; |
87 | 87 | import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; | ... | ... |
... | ... | @@ -55,7 +55,7 @@ public class AppActor extends ContextAwareActor { |
55 | 55 | private final TbTenantProfileCache tenantProfileCache; |
56 | 56 | private final TenantService tenantService; |
57 | 57 | private final Set<TenantId> deletedTenants; |
58 | - private boolean ruleChainsInitialized; | |
58 | + private volatile boolean ruleChainsInitialized; | |
59 | 59 | |
60 | 60 | private AppActor(ActorSystemContext systemContext) { |
61 | 61 | super(systemContext); |
... | ... | @@ -69,7 +69,7 @@ public class AppActor extends ContextAwareActor { |
69 | 69 | if (!ruleChainsInitialized) { |
70 | 70 | initTenantActors(); |
71 | 71 | ruleChainsInitialized = true; |
72 | - if (msg.getMsgType() != MsgType.APP_INIT_MSG) { | |
72 | + if (msg.getMsgType() != MsgType.APP_INIT_MSG && msg.getMsgType() != MsgType.PARTITION_CHANGE_MSG) { | |
73 | 73 | log.warn("Rule Chains initialized by unexpected message: {}", msg); |
74 | 74 | } |
75 | 75 | } |
... | ... | @@ -95,6 +95,7 @@ public class AppActor extends ContextAwareActor { |
95 | 95 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: |
96 | 96 | case DEVICE_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
97 | 97 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
98 | + case REMOVE_RPC_TO_DEVICE_ACTOR_MSG: | |
98 | 99 | onToDeviceActorMsg((TenantAwareMsg) msg, true); |
99 | 100 | break; |
100 | 101 | case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG: | ... | ... |
... | ... | @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
28 | 28 | import org.thingsboard.server.common.msg.TbActorMsg; |
29 | 29 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; |
30 | 30 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg; |
31 | +import org.thingsboard.server.service.rpc.RemoveRpcActorMsg; | |
31 | 32 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
32 | 33 | import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; |
33 | 34 | |
... | ... | @@ -84,6 +85,9 @@ public class DeviceActor extends ContextAwareActor { |
84 | 85 | case DEVICE_EDGE_UPDATE_TO_DEVICE_ACTOR_MSG: |
85 | 86 | processor.processEdgeUpdate((DeviceEdgeUpdateMsg) msg); |
86 | 87 | break; |
88 | + case REMOVE_RPC_TO_DEVICE_ACTOR_MSG: | |
89 | + processor.processRemoveRpc(ctx, (RemoveRpcActorMsg) msg); | |
90 | + break; | |
87 | 91 | default: |
88 | 92 | return false; |
89 | 93 | } | ... | ... |
... | ... | @@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j; |
26 | 26 | import org.apache.commons.collections.CollectionUtils; |
27 | 27 | import org.thingsboard.common.util.JacksonUtil; |
28 | 28 | import org.thingsboard.common.util.LinkedHashMapRemoveEldest; |
29 | -import org.thingsboard.rule.engine.api.RpcError; | |
29 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
30 | 30 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
31 | 31 | import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; |
32 | 32 | import org.thingsboard.rule.engine.api.msg.DeviceEdgeUpdateMsg; |
... | ... | @@ -86,8 +86,9 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
86 | 86 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; |
87 | 87 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
88 | 88 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; |
89 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
89 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
90 | 90 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg; |
91 | +import org.thingsboard.server.service.rpc.RemoveRpcActorMsg; | |
91 | 92 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
92 | 93 | import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; |
93 | 94 | |
... | ... | @@ -97,11 +98,9 @@ import java.util.Arrays; |
97 | 98 | import java.util.Collections; |
98 | 99 | import java.util.HashMap; |
99 | 100 | import java.util.HashSet; |
100 | -import java.util.LinkedHashMap; | |
101 | 101 | import java.util.List; |
102 | 102 | import java.util.Map; |
103 | 103 | import java.util.Objects; |
104 | -import java.util.Optional; | |
105 | 104 | import java.util.Set; |
106 | 105 | import java.util.UUID; |
107 | 106 | import java.util.function.Consumer; |
... | ... | @@ -236,6 +235,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
236 | 235 | rpc.setExpirationTime(request.getExpirationTime()); |
237 | 236 | rpc.setRequest(JacksonUtil.valueToTree(request)); |
238 | 237 | rpc.setStatus(status); |
238 | + rpc.setAdditionalInfo(JacksonUtil.valueToTree(request.getAdditionalInfo())); | |
239 | 239 | return systemContext.getTbRpcService().save(tenantId, rpc); |
240 | 240 | } |
241 | 241 | |
... | ... | @@ -264,6 +264,21 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
264 | 264 | } |
265 | 265 | } |
266 | 266 | |
267 | + void processRemoveRpc(TbActorCtx context, RemoveRpcActorMsg msg) { | |
268 | + log.debug("[{}] Processing remove rpc command", msg.getRequestId()); | |
269 | + Integer requestId = null; | |
270 | + for (Map.Entry<Integer, ToDeviceRpcRequestMetadata> entry : toDeviceRpcPendingMap.entrySet()) { | |
271 | + if (entry.getValue().getMsg().getMsg().getId().equals(msg.getRequestId())) { | |
272 | + requestId = entry.getKey(); | |
273 | + break; | |
274 | + } | |
275 | + } | |
276 | + | |
277 | + if (requestId != null) { | |
278 | + toDeviceRpcPendingMap.remove(requestId); | |
279 | + } | |
280 | + } | |
281 | + | |
267 | 282 | private void registerPendingRpcRequest(TbActorCtx context, ToDeviceRpcRequestActorMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) { |
268 | 283 | toDeviceRpcPendingMap.put(rpcRequest.getRequestId(), new ToDeviceRpcRequestMetadata(msg, sent)); |
269 | 284 | DeviceActorServerSideRpcTimeoutMsg timeoutMsg = new DeviceActorServerSideRpcTimeoutMsg(rpcRequest.getRequestId(), timeout); |
... | ... | @@ -383,11 +398,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
383 | 398 | } |
384 | 399 | |
385 | 400 | private void reportSessionOpen() { |
386 | - systemContext.getDeviceStateService().onDeviceConnect(deviceId); | |
401 | + systemContext.getDeviceStateService().onDeviceConnect(tenantId, deviceId); | |
387 | 402 | } |
388 | 403 | |
389 | 404 | private void reportSessionClose() { |
390 | - systemContext.getDeviceStateService().onDeviceDisconnect(deviceId); | |
405 | + systemContext.getDeviceStateService().onDeviceDisconnect(tenantId, deviceId); | |
391 | 406 | } |
392 | 407 | |
393 | 408 | private void handleGetAttributesRequest(TbActorCtx context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { |
... | ... | @@ -586,13 +601,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
586 | 601 | log.debug("[{}] Received duplicate session open event [{}]", deviceId, sessionId); |
587 | 602 | return; |
588 | 603 | } |
589 | - log.info("[{}] Processing new session [{}]. Current sessions size {}", deviceId, sessionId, sessions.size()); | |
604 | + log.debug("[{}] Processing new session [{}]. Current sessions size {}", deviceId, sessionId, sessions.size()); | |
590 | 605 | |
591 | 606 | sessions.put(sessionId, new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfo.getNodeId()))); |
592 | 607 | if (sessions.size() == 1) { |
593 | 608 | reportSessionOpen(); |
594 | 609 | } |
595 | - systemContext.getDeviceStateService().onDeviceActivity(deviceId, System.currentTimeMillis()); | |
610 | + systemContext.getDeviceStateService().onDeviceActivity(tenantId, deviceId, System.currentTimeMillis()); | |
596 | 611 | dumpSessions(); |
597 | 612 | } else if (msg.getEvent() == SessionEvent.CLOSED) { |
598 | 613 | log.debug("[{}] Canceling subscriptions for closed session [{}]", deviceId, sessionId); |
... | ... | @@ -622,7 +637,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
622 | 637 | if (subscriptionInfo.getRpcSubscription()) { |
623 | 638 | rpcSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); |
624 | 639 | } |
625 | - systemContext.getDeviceStateService().onDeviceActivity(deviceId, subscriptionInfo.getLastActivityTime()); | |
640 | + systemContext.getDeviceStateService().onDeviceActivity(tenantId, deviceId, subscriptionInfo.getLastActivityTime()); | |
626 | 641 | dumpSessions(); |
627 | 642 | } |
628 | 643 | |
... | ... | @@ -729,18 +744,8 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
729 | 744 | edgeEvent.setBody(body); |
730 | 745 | |
731 | 746 | edgeEvent.setEdgeId(edgeId); |
732 | - ListenableFuture<EdgeEvent> future = systemContext.getEdgeEventService().saveAsync(edgeEvent); | |
733 | - Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | |
734 | - @Override | |
735 | - public void onSuccess(EdgeEvent result) { | |
736 | - systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId); | |
737 | - } | |
738 | - | |
739 | - @Override | |
740 | - public void onFailure(Throwable t) { | |
741 | - log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | |
742 | - } | |
743 | - }, systemContext.getDbCallbackExecutor()); | |
747 | + systemContext.getEdgeEventService().save(edgeEvent); | |
748 | + systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId); | |
744 | 749 | } |
745 | 750 | |
746 | 751 | private List<TsKvProto> toTsKvProtos(@Nullable List<AttributeKvEntry> result) { | ... | ... |
... | ... | @@ -33,6 +33,7 @@ import org.thingsboard.rule.engine.api.TbRelationTypes; |
33 | 33 | import org.thingsboard.rule.engine.api.sms.SmsSenderFactory; |
34 | 34 | import org.thingsboard.server.actors.ActorSystemContext; |
35 | 35 | import org.thingsboard.server.actors.TbActorRef; |
36 | +import org.thingsboard.server.cluster.TbClusterService; | |
36 | 37 | import org.thingsboard.server.common.data.Customer; |
37 | 38 | import org.thingsboard.server.common.data.DataConstants; |
38 | 39 | import org.thingsboard.server.common.data.Device; |
... | ... | @@ -454,6 +455,11 @@ class DefaultTbContext implements TbContext { |
454 | 455 | } |
455 | 456 | |
456 | 457 | @Override |
458 | + public TbClusterService getClusterService() { | |
459 | + return mainCtx.getClusterService(); | |
460 | + } | |
461 | + | |
462 | + @Override | |
457 | 463 | public DashboardService getDashboardService() { |
458 | 464 | return mainCtx.getDashboardService(); |
459 | 465 | } | ... | ... |
... | ... | @@ -49,7 +49,7 @@ import org.thingsboard.server.queue.TbQueueCallback; |
49 | 49 | import org.thingsboard.server.queue.common.MultipleTbQueueTbMsgCallbackWrapper; |
50 | 50 | import org.thingsboard.server.queue.common.TbQueueTbMsgCallbackWrapper; |
51 | 51 | import org.thingsboard.server.queue.usagestats.TbApiUsageClient; |
52 | -import org.thingsboard.server.service.queue.TbClusterService; | |
52 | +import org.thingsboard.server.cluster.TbClusterService; | |
53 | 53 | |
54 | 54 | import java.util.ArrayList; |
55 | 55 | import java.util.Collections; | ... | ... |
... | ... | @@ -165,6 +165,7 @@ public class TenantActor extends RuleChainManagerActor { |
165 | 165 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: |
166 | 166 | case DEVICE_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
167 | 167 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
168 | + case REMOVE_RPC_TO_DEVICE_ACTOR_MSG: | |
168 | 169 | onToDeviceActorMsg((DeviceAwareMsg) msg, true); |
169 | 170 | break; |
170 | 171 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.controller; | |
17 | + | |
18 | +import com.fasterxml.jackson.databind.JsonNode; | |
19 | +import com.google.common.util.concurrent.FutureCallback; | |
20 | +import lombok.extern.slf4j.Slf4j; | |
21 | +import org.springframework.beans.factory.annotation.Autowired; | |
22 | +import org.springframework.beans.factory.annotation.Value; | |
23 | +import org.springframework.http.HttpStatus; | |
24 | +import org.springframework.http.ResponseEntity; | |
25 | +import org.springframework.util.StringUtils; | |
26 | +import org.springframework.web.context.request.async.DeferredResult; | |
27 | +import org.thingsboard.common.util.JacksonUtil; | |
28 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
29 | +import org.thingsboard.server.common.data.DataConstants; | |
30 | +import org.thingsboard.server.common.data.audit.ActionType; | |
31 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | |
32 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
33 | +import org.thingsboard.server.common.data.id.DeviceId; | |
34 | +import org.thingsboard.server.common.data.id.EntityId; | |
35 | +import org.thingsboard.server.common.data.id.TenantId; | |
36 | +import org.thingsboard.server.common.data.id.UUIDBased; | |
37 | +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | |
38 | +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | |
39 | +import org.thingsboard.server.queue.util.TbCoreComponent; | |
40 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
41 | +import org.thingsboard.server.service.rpc.LocalRequestMetaData; | |
42 | +import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; | |
43 | +import org.thingsboard.server.service.security.AccessValidator; | |
44 | +import org.thingsboard.server.service.security.model.SecurityUser; | |
45 | +import org.thingsboard.server.service.security.permission.Operation; | |
46 | +import org.thingsboard.server.service.telemetry.exception.ToErrorResponseEntity; | |
47 | + | |
48 | +import javax.annotation.Nullable; | |
49 | +import java.util.Optional; | |
50 | +import java.util.UUID; | |
51 | + | |
52 | +/** | |
53 | + * Created by ashvayka on 22.03.18. | |
54 | + */ | |
55 | +@TbCoreComponent | |
56 | +@Slf4j | |
57 | +public abstract class AbstractRpcController extends BaseController { | |
58 | + | |
59 | + @Autowired | |
60 | + protected TbCoreDeviceRpcService deviceRpcService; | |
61 | + | |
62 | + @Autowired | |
63 | + private AccessValidator accessValidator; | |
64 | + | |
65 | + @Value("${server.rest.server_side_rpc.min_timeout:5000}") | |
66 | + protected long minTimeout; | |
67 | + | |
68 | + @Value("${server.rest.server_side_rpc.default_timeout:10000}") | |
69 | + protected long defaultTimeout; | |
70 | + | |
71 | + protected DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody, HttpStatus timeoutStatus, HttpStatus noActiveConnectionStatus) throws ThingsboardException { | |
72 | + try { | |
73 | + JsonNode rpcRequestBody = JacksonUtil.toJsonNode(requestBody); | |
74 | + ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(rpcRequestBody.get("method").asText(), JacksonUtil.toString(rpcRequestBody.get("params"))); | |
75 | + SecurityUser currentUser = getCurrentUser(); | |
76 | + TenantId tenantId = currentUser.getTenantId(); | |
77 | + final DeferredResult<ResponseEntity> response = new DeferredResult<>(); | |
78 | + long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout; | |
79 | + long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout); | |
80 | + UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID(); | |
81 | + boolean persisted = rpcRequestBody.has(DataConstants.PERSISTENT) && rpcRequestBody.get(DataConstants.PERSISTENT).asBoolean(); | |
82 | + String additionalInfo = JacksonUtil.toString(rpcRequestBody.get(DataConstants.ADDITIONAL_INFO)); | |
83 | + accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<>() { | |
84 | + @Override | |
85 | + public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) { | |
86 | + ToDeviceRpcRequest rpcRequest = new ToDeviceRpcRequest(rpcRequestUUID, | |
87 | + tenantId, | |
88 | + deviceId, | |
89 | + oneWay, | |
90 | + expTime, | |
91 | + body, | |
92 | + persisted, | |
93 | + additionalInfo | |
94 | + ); | |
95 | + deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse, timeoutStatus, noActiveConnectionStatus), currentUser); | |
96 | + } | |
97 | + | |
98 | + @Override | |
99 | + public void onFailure(Throwable e) { | |
100 | + ResponseEntity entity; | |
101 | + if (e instanceof ToErrorResponseEntity) { | |
102 | + entity = ((ToErrorResponseEntity) e).toErrorResponseEntity(); | |
103 | + } else { | |
104 | + entity = new ResponseEntity(HttpStatus.UNAUTHORIZED); | |
105 | + } | |
106 | + logRpcCall(currentUser, deviceId, body, oneWay, Optional.empty(), e); | |
107 | + response.setResult(entity); | |
108 | + } | |
109 | + })); | |
110 | + return response; | |
111 | + } catch (IllegalArgumentException ioe) { | |
112 | + throw new ThingsboardException("Invalid request body", ioe, ThingsboardErrorCode.BAD_REQUEST_PARAMS); | |
113 | + } | |
114 | + } | |
115 | + | |
116 | + public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response, HttpStatus timeoutStatus, HttpStatus noActiveConnectionStatus) { | |
117 | + Optional<RpcError> rpcError = response.getError(); | |
118 | + DeferredResult<ResponseEntity> responseWriter = rpcRequest.getResponseWriter(); | |
119 | + if (rpcError.isPresent()) { | |
120 | + logRpcCall(rpcRequest, rpcError, null); | |
121 | + RpcError error = rpcError.get(); | |
122 | + switch (error) { | |
123 | + case TIMEOUT: | |
124 | + responseWriter.setResult(new ResponseEntity<>(timeoutStatus)); | |
125 | + break; | |
126 | + case NO_ACTIVE_CONNECTION: | |
127 | + responseWriter.setResult(new ResponseEntity<>(noActiveConnectionStatus)); | |
128 | + break; | |
129 | + default: | |
130 | + responseWriter.setResult(new ResponseEntity<>(timeoutStatus)); | |
131 | + break; | |
132 | + } | |
133 | + } else { | |
134 | + Optional<String> responseData = response.getResponse(); | |
135 | + if (responseData.isPresent() && !StringUtils.isEmpty(responseData.get())) { | |
136 | + String data = responseData.get(); | |
137 | + try { | |
138 | + logRpcCall(rpcRequest, rpcError, null); | |
139 | + responseWriter.setResult(new ResponseEntity<>(JacksonUtil.toJsonNode(data), HttpStatus.OK)); | |
140 | + } catch (IllegalArgumentException e) { | |
141 | + log.debug("Failed to decode device response: {}", data, e); | |
142 | + logRpcCall(rpcRequest, rpcError, e); | |
143 | + responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE)); | |
144 | + } | |
145 | + } else { | |
146 | + logRpcCall(rpcRequest, rpcError, null); | |
147 | + responseWriter.setResult(new ResponseEntity<>(HttpStatus.OK)); | |
148 | + } | |
149 | + } | |
150 | + } | |
151 | + | |
152 | + private void logRpcCall(LocalRequestMetaData rpcRequest, Optional<RpcError> rpcError, Throwable e) { | |
153 | + logRpcCall(rpcRequest.getUser(), rpcRequest.getRequest().getDeviceId(), rpcRequest.getRequest().getBody(), rpcRequest.getRequest().isOneway(), rpcError, null); | |
154 | + } | |
155 | + | |
156 | + | |
157 | + private void logRpcCall(SecurityUser user, EntityId entityId, ToDeviceRpcRequestBody body, boolean oneWay, Optional<RpcError> rpcError, Throwable e) { | |
158 | + String rpcErrorStr = ""; | |
159 | + if (rpcError.isPresent()) { | |
160 | + rpcErrorStr = "RPC Error: " + rpcError.get().name(); | |
161 | + } | |
162 | + String method = body.getMethod(); | |
163 | + String params = body.getParams(); | |
164 | + | |
165 | + auditLogService.logEntityAction( | |
166 | + user.getTenantId(), | |
167 | + user.getCustomerId(), | |
168 | + user.getId(), | |
169 | + user.getName(), | |
170 | + (UUIDBased & EntityId) entityId, | |
171 | + null, | |
172 | + ActionType.RPC_CALL, | |
173 | + BaseController.toException(e), | |
174 | + rpcErrorStr, | |
175 | + oneWay, | |
176 | + method, | |
177 | + params); | |
178 | + } | |
179 | + | |
180 | + | |
181 | +} | ... | ... |
... | ... | @@ -26,12 +26,12 @@ import org.springframework.web.bind.annotation.ResponseBody; |
26 | 26 | import org.springframework.web.bind.annotation.RestController; |
27 | 27 | import org.thingsboard.rule.engine.api.MailService; |
28 | 28 | import org.thingsboard.rule.engine.api.SmsService; |
29 | -import org.thingsboard.server.common.data.sms.config.TestSmsRequest; | |
30 | 29 | import org.thingsboard.server.common.data.AdminSettings; |
31 | 30 | import org.thingsboard.server.common.data.UpdateMessage; |
32 | 31 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
33 | 32 | import org.thingsboard.server.common.data.id.TenantId; |
34 | 33 | import org.thingsboard.server.common.data.security.model.SecuritySettings; |
34 | +import org.thingsboard.server.common.data.sms.config.TestSmsRequest; | |
35 | 35 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
36 | 36 | import org.thingsboard.server.queue.util.TbCoreComponent; |
37 | 37 | import org.thingsboard.server.service.security.permission.Operation; |
... | ... | @@ -67,7 +67,7 @@ public class AdminController extends BaseController { |
67 | 67 | accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); |
68 | 68 | AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key)); |
69 | 69 | if (adminSettings.getKey().equals("mail")) { |
70 | - ((ObjectNode) adminSettings.getJsonValue()).put("password", ""); | |
70 | + ((ObjectNode) adminSettings.getJsonValue()).remove("password"); | |
71 | 71 | } |
72 | 72 | return adminSettings; |
73 | 73 | } catch (Exception e) { |
... | ... | @@ -84,7 +84,7 @@ public class AdminController extends BaseController { |
84 | 84 | adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings)); |
85 | 85 | if (adminSettings.getKey().equals("mail")) { |
86 | 86 | mailService.updateMailConfiguration(); |
87 | - ((ObjectNode) adminSettings.getJsonValue()).put("password", ""); | |
87 | + ((ObjectNode) adminSettings.getJsonValue()).remove("password"); | |
88 | 88 | } else if (adminSettings.getKey().equals("sms")) { |
89 | 89 | smsService.updateSmsConfiguration(); |
90 | 90 | } |
... | ... | @@ -126,6 +126,10 @@ public class AdminController extends BaseController { |
126 | 126 | accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); |
127 | 127 | adminSettings = checkNotNull(adminSettings); |
128 | 128 | if (adminSettings.getKey().equals("mail")) { |
129 | + if(!adminSettings.getJsonValue().has("password")) { | |
130 | + AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail")); | |
131 | + ((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText()); | |
132 | + } | |
129 | 133 | String email = getCurrentUser().getEmail(); |
130 | 134 | mailService.sendTestMail(adminSettings.getJsonValue(), email); |
131 | 135 | } | ... | ... |
... | ... | @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
38 | 38 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
39 | 39 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
40 | 40 | import org.thingsboard.server.common.data.id.AlarmId; |
41 | +import org.thingsboard.server.common.data.id.EdgeId; | |
41 | 42 | import org.thingsboard.server.common.data.id.EntityId; |
42 | 43 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
43 | 44 | import org.thingsboard.server.common.data.page.PageData; |
... | ... | @@ -46,6 +47,8 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
46 | 47 | import org.thingsboard.server.service.security.permission.Operation; |
47 | 48 | import org.thingsboard.server.service.security.permission.Resource; |
48 | 49 | |
50 | +import java.util.List; | |
51 | + | |
49 | 52 | @RestController |
50 | 53 | @TbCoreComponent |
51 | 54 | @RequestMapping("/api") |
... | ... | @@ -112,10 +115,13 @@ public class AlarmController extends BaseController { |
112 | 115 | AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); |
113 | 116 | Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); |
114 | 117 | |
118 | + List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(getTenantId(), alarm.getOriginator()); | |
119 | + | |
115 | 120 | logEntityAction(alarm.getOriginator(), alarm, |
116 | 121 | getCurrentUser().getCustomerId(), |
117 | 122 | ActionType.ALARM_DELETE, null); |
118 | - sendEntityNotificationMsg(getTenantId(), alarmId, EdgeEventActionType.DELETED); | |
123 | + | |
124 | + sendAlarmDeleteNotificationMsg(getTenantId(), alarmId, relatedEdgeIds, alarm); | |
119 | 125 | |
120 | 126 | return alarmService.deleteAlarm(getTenantId(), alarmId); |
121 | 127 | } catch (Exception e) { | ... | ... |
... | ... | @@ -33,7 +33,6 @@ import org.thingsboard.server.common.data.DashboardInfo; |
33 | 33 | import org.thingsboard.server.common.data.Device; |
34 | 34 | import org.thingsboard.server.common.data.DeviceInfo; |
35 | 35 | import org.thingsboard.server.common.data.DeviceProfile; |
36 | -import org.thingsboard.server.common.data.EdgeUtils; | |
37 | 36 | import org.thingsboard.server.common.data.EntityType; |
38 | 37 | import org.thingsboard.server.common.data.EntityView; |
39 | 38 | import org.thingsboard.server.common.data.EntityViewInfo; |
... | ... | @@ -118,7 +117,6 @@ import org.thingsboard.server.dao.user.UserService; |
118 | 117 | import org.thingsboard.server.dao.widget.WidgetTypeService; |
119 | 118 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
120 | 119 | import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; |
121 | -import org.thingsboard.server.gen.transport.TransportProtos; | |
122 | 120 | import org.thingsboard.server.queue.discovery.PartitionService; |
123 | 121 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
124 | 122 | import org.thingsboard.server.queue.util.TbCoreComponent; |
... | ... | @@ -129,7 +127,7 @@ import org.thingsboard.server.service.edge.rpc.EdgeRpcService; |
129 | 127 | import org.thingsboard.server.service.lwm2m.LwM2MServerSecurityInfoRepository; |
130 | 128 | import org.thingsboard.server.service.ota.OtaPackageStateService; |
131 | 129 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
132 | -import org.thingsboard.server.service.queue.TbClusterService; | |
130 | +import org.thingsboard.server.cluster.TbClusterService; | |
133 | 131 | import org.thingsboard.server.service.resource.TbResourceService; |
134 | 132 | import org.thingsboard.server.service.security.model.SecurityUser; |
135 | 133 | import org.thingsboard.server.service.security.permission.AccessControlService; |
... | ... | @@ -846,13 +844,25 @@ public abstract class BaseController { |
846 | 844 | } |
847 | 845 | |
848 | 846 | protected void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List<EdgeId> edgeIds) { |
847 | + sendDeleteNotificationMsg(tenantId, entityId, edgeIds, null); | |
848 | + } | |
849 | + | |
850 | + protected void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List<EdgeId> edgeIds, String body) { | |
849 | 851 | if (edgeIds != null && !edgeIds.isEmpty()) { |
850 | 852 | for (EdgeId edgeId : edgeIds) { |
851 | - sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, null, EdgeEventActionType.DELETED); | |
853 | + sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, null, EdgeEventActionType.DELETED); | |
852 | 854 | } |
853 | 855 | } |
854 | 856 | } |
855 | 857 | |
858 | + protected void sendAlarmDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List<EdgeId> edgeIds, Alarm alarm) { | |
859 | + try { | |
860 | + sendDeleteNotificationMsg(tenantId, entityId, edgeIds, json.writeValueAsString(alarm)); | |
861 | + } catch (Exception e) { | |
862 | + log.warn("Failed to push delete alarm msg to core: {}", alarm, e); | |
863 | + } | |
864 | + } | |
865 | + | |
856 | 866 | protected void sendEntityAssignToCustomerNotificationMsg(TenantId tenantId, EntityId entityId, CustomerId customerId, EdgeEventActionType action) { |
857 | 867 | try { |
858 | 868 | sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), null, action); |
... | ... | @@ -870,42 +880,7 @@ public abstract class BaseController { |
870 | 880 | } |
871 | 881 | |
872 | 882 | private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action) { |
873 | - if (!edgesEnabled) { | |
874 | - return; | |
875 | - } | |
876 | - if (type == null) { | |
877 | - if (entityId != null) { | |
878 | - type = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); | |
879 | - } else { | |
880 | - log.trace("[{}] entity id and type are null. Ignoring this notification", tenantId); | |
881 | - return; | |
882 | - } | |
883 | - if (type == null) { | |
884 | - log.trace("[{}] edge event type is null. Ignoring this notification [{}]", tenantId, entityId); | |
885 | - return; | |
886 | - } | |
887 | - } | |
888 | - TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder(); | |
889 | - builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); | |
890 | - builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); | |
891 | - builder.setType(type.name()); | |
892 | - builder.setAction(action.name()); | |
893 | - if (entityId != null) { | |
894 | - builder.setEntityIdMSB(entityId.getId().getMostSignificantBits()); | |
895 | - builder.setEntityIdLSB(entityId.getId().getLeastSignificantBits()); | |
896 | - builder.setEntityType(entityId.getEntityType().name()); | |
897 | - } | |
898 | - if (edgeId != null) { | |
899 | - builder.setEdgeIdMSB(edgeId.getId().getMostSignificantBits()); | |
900 | - builder.setEdgeIdLSB(edgeId.getId().getLeastSignificantBits()); | |
901 | - } | |
902 | - if (body != null) { | |
903 | - builder.setBody(body); | |
904 | - } | |
905 | - TransportProtos.EdgeNotificationMsgProto msg = builder.build(); | |
906 | - log.trace("[{}] sending notification to edge service {}", tenantId.getId(), msg); | |
907 | - tbClusterService.pushMsgToCore(tenantId, entityId != null ? entityId : tenantId, | |
908 | - TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null); | |
883 | + tbClusterService.sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, type, action); | |
909 | 884 | } |
910 | 885 | |
911 | 886 | protected List<EdgeId> findRelatedEdgeIds(TenantId tenantId, EntityId entityId) { | ... | ... |
... | ... | @@ -149,7 +149,7 @@ public class CustomerController extends BaseController { |
149 | 149 | ActionType.DELETED, null, strCustomerId); |
150 | 150 | |
151 | 151 | sendDeleteNotificationMsg(getTenantId(), customerId, relatedEdgeIds); |
152 | - tbClusterService.onEntityStateChange(getTenantId(), customerId, ComponentLifecycleEvent.DELETED); | |
152 | + tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), customerId, ComponentLifecycleEvent.DELETED); | |
153 | 153 | } catch (Exception e) { |
154 | 154 | |
155 | 155 | logEntityAction(emptyId(EntityType.CUSTOMER), | ... | ... |
... | ... | @@ -36,7 +36,6 @@ import org.springframework.web.bind.annotation.RestController; |
36 | 36 | import org.springframework.web.context.request.async.DeferredResult; |
37 | 37 | import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; |
38 | 38 | import org.thingsboard.rule.engine.api.msg.DeviceEdgeUpdateMsg; |
39 | -import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | |
40 | 39 | import org.thingsboard.server.common.data.ClaimRequest; |
41 | 40 | import org.thingsboard.server.common.data.Customer; |
42 | 41 | import org.thingsboard.server.common.data.DataConstants; |
... | ... | @@ -60,7 +59,6 @@ import org.thingsboard.server.common.data.ota.OtaPackageType; |
60 | 59 | import org.thingsboard.server.common.data.page.PageData; |
61 | 60 | import org.thingsboard.server.common.data.page.PageLink; |
62 | 61 | import org.thingsboard.server.common.data.page.TimePageLink; |
63 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | |
64 | 62 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
65 | 63 | import org.thingsboard.server.common.msg.TbMsg; |
66 | 64 | import org.thingsboard.server.common.msg.TbMsgDataType; |
... | ... | @@ -134,20 +132,16 @@ public class DeviceController extends BaseController { |
134 | 132 | try { |
135 | 133 | device.setTenantId(getCurrentUser().getTenantId()); |
136 | 134 | |
137 | - checkEntity(device.getId(), device, Resource.DEVICE); | |
138 | - | |
139 | - Device oldDevice; | |
135 | + Device oldDevice = null; | |
140 | 136 | if (!created) { |
141 | - oldDevice = deviceService.findDeviceById(getTenantId(), device.getId()); | |
137 | + oldDevice = checkDeviceId(device.getId(), Operation.WRITE); | |
142 | 138 | } else { |
143 | - oldDevice = null; | |
139 | + checkEntity(null, device, Resource.DEVICE); | |
144 | 140 | } |
145 | 141 | |
146 | 142 | Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); |
147 | 143 | |
148 | - onDeviceCreatedOrUpdated(savedDevice, !created); | |
149 | - | |
150 | - otaPackageStateService.update(savedDevice, oldDevice); | |
144 | + onDeviceCreatedOrUpdated(savedDevice, oldDevice, !created); | |
151 | 145 | |
152 | 146 | return savedDevice; |
153 | 147 | } catch (Exception e) { |
... | ... | @@ -158,29 +152,16 @@ public class DeviceController extends BaseController { |
158 | 152 | |
159 | 153 | } |
160 | 154 | |
161 | - private void onDeviceCreatedOrUpdated(Device device, boolean updated) { | |
162 | - tbClusterService.onDeviceChange(device, null); | |
163 | - tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(device.getTenantId(), | |
164 | - device.getId(), device.getName(), device.getType()), null); | |
165 | - tbClusterService.onEntityStateChange(device.getTenantId(), device.getId(), updated ? ComponentLifecycleEvent.UPDATED : ComponentLifecycleEvent.CREATED); | |
166 | - | |
167 | - if (updated) { | |
168 | - sendEntityNotificationMsg(device.getTenantId(), device.getId(), EdgeEventActionType.UPDATED); | |
169 | - } | |
155 | + private void onDeviceCreatedOrUpdated(Device savedDevice, Device oldDevice, boolean updated) { | |
156 | + tbClusterService.onDeviceUpdated(savedDevice, oldDevice); | |
170 | 157 | |
171 | 158 | try { |
172 | - logEntityAction(device.getId(), device, | |
173 | - device.getCustomerId(), | |
159 | + logEntityAction(savedDevice.getId(), savedDevice, | |
160 | + savedDevice.getCustomerId(), | |
174 | 161 | updated ? ActionType.UPDATED : ActionType.ADDED, null); |
175 | 162 | } catch (ThingsboardException e) { |
176 | 163 | log.error("Failed to log entity action", e); |
177 | 164 | } |
178 | - | |
179 | - if (updated) { | |
180 | - deviceStateService.onDeviceUpdated(device); | |
181 | - } else { | |
182 | - deviceStateService.onDeviceAdded(device); | |
183 | - } | |
184 | 165 | } |
185 | 166 | |
186 | 167 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
... | ... | @@ -197,15 +178,12 @@ public class DeviceController extends BaseController { |
197 | 178 | deviceService.deleteDevice(getCurrentUser().getTenantId(), deviceId); |
198 | 179 | |
199 | 180 | tbClusterService.onDeviceDeleted(device, null); |
200 | - tbClusterService.onEntityStateChange(device.getTenantId(), deviceId, ComponentLifecycleEvent.DELETED); | |
201 | 181 | |
202 | 182 | logEntityAction(deviceId, device, |
203 | 183 | device.getCustomerId(), |
204 | 184 | ActionType.DELETED, null, strDeviceId); |
205 | 185 | |
206 | 186 | sendDeleteNotificationMsg(getTenantId(), deviceId, relatedEdgeIds); |
207 | - | |
208 | - deviceStateService.onDeviceDeleted(device); | |
209 | 187 | } catch (Exception e) { |
210 | 188 | logEntityAction(emptyId(EntityType.DEVICE), |
211 | 189 | null, |
... | ... | @@ -819,8 +797,7 @@ public class DeviceController extends BaseController { |
819 | 797 | @PostMapping("/device/bulk_import") |
820 | 798 | public BulkImportResult<Device> processDevicesBulkImport(@RequestBody BulkImportRequest request) throws Exception { |
821 | 799 | return deviceBulkImportService.processBulkImport(request, getCurrentUser(), importedDeviceInfo -> { |
822 | - onDeviceCreatedOrUpdated(importedDeviceInfo.getEntity(), importedDeviceInfo.isUpdated()); | |
823 | - otaPackageStateService.update(importedDeviceInfo.getEntity(), importedDeviceInfo.getOldEntity()); | |
800 | + onDeviceCreatedOrUpdated(importedDeviceInfo.getEntity(), importedDeviceInfo.getOldEntity(), importedDeviceInfo.isUpdated()); | |
824 | 801 | }); |
825 | 802 | } |
826 | 803 | ... | ... |
... | ... | @@ -161,7 +161,7 @@ public class DeviceProfileController extends BaseController { |
161 | 161 | DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); |
162 | 162 | |
163 | 163 | tbClusterService.onDeviceProfileChange(savedDeviceProfile, null); |
164 | - tbClusterService.onEntityStateChange(deviceProfile.getTenantId(), savedDeviceProfile.getId(), | |
164 | + tbClusterService.broadcastEntityStateChangeEvent(deviceProfile.getTenantId(), savedDeviceProfile.getId(), | |
165 | 165 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
166 | 166 | |
167 | 167 | logEntityAction(savedDeviceProfile.getId(), savedDeviceProfile, |
... | ... | @@ -191,7 +191,7 @@ public class DeviceProfileController extends BaseController { |
191 | 191 | deviceProfileService.deleteDeviceProfile(getTenantId(), deviceProfileId); |
192 | 192 | |
193 | 193 | tbClusterService.onDeviceProfileDelete(deviceProfile, null); |
194 | - tbClusterService.onEntityStateChange(deviceProfile.getTenantId(), deviceProfile.getId(), ComponentLifecycleEvent.DELETED); | |
194 | + tbClusterService.broadcastEntityStateChangeEvent(deviceProfile.getTenantId(), deviceProfile.getId(), ComponentLifecycleEvent.DELETED); | |
195 | 195 | |
196 | 196 | logEntityAction(deviceProfileId, deviceProfile, |
197 | 197 | null, | ... | ... |
... | ... | @@ -153,7 +153,7 @@ public class EdgeController extends BaseController { |
153 | 153 | edgeService.assignDefaultRuleChainsToEdge(tenantId, edge.getId()); |
154 | 154 | } |
155 | 155 | |
156 | - tbClusterService.onEntityStateChange(edge.getTenantId(), edge.getId(), | |
156 | + tbClusterService.broadcastEntityStateChangeEvent(edge.getTenantId(), edge.getId(), | |
157 | 157 | updated ? ComponentLifecycleEvent.UPDATED : ComponentLifecycleEvent.CREATED); |
158 | 158 | |
159 | 159 | logEntityAction(edge.getId(), edge, null, updated ? ActionType.UPDATED : ActionType.ADDED, null); |
... | ... | @@ -169,7 +169,7 @@ public class EdgeController extends BaseController { |
169 | 169 | Edge edge = checkEdgeId(edgeId, Operation.DELETE); |
170 | 170 | edgeService.deleteEdge(getTenantId(), edgeId); |
171 | 171 | |
172 | - tbClusterService.onEntityStateChange(getTenantId(), edgeId, | |
172 | + tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, | |
173 | 173 | ComponentLifecycleEvent.DELETED); |
174 | 174 | |
175 | 175 | logEntityAction(edgeId, edge, |
... | ... | @@ -220,7 +220,7 @@ public class EdgeController extends BaseController { |
220 | 220 | |
221 | 221 | Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(getCurrentUser().getTenantId(), edgeId, customerId)); |
222 | 222 | |
223 | - tbClusterService.onEntityStateChange(getTenantId(), edgeId, | |
223 | + tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, | |
224 | 224 | ComponentLifecycleEvent.UPDATED); |
225 | 225 | |
226 | 226 | logEntityAction(edgeId, savedEdge, |
... | ... | @@ -254,7 +254,7 @@ public class EdgeController extends BaseController { |
254 | 254 | |
255 | 255 | Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(getCurrentUser().getTenantId(), edgeId)); |
256 | 256 | |
257 | - tbClusterService.onEntityStateChange(getTenantId(), edgeId, | |
257 | + tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, | |
258 | 258 | ComponentLifecycleEvent.UPDATED); |
259 | 259 | |
260 | 260 | logEntityAction(edgeId, edge, |
... | ... | @@ -284,7 +284,7 @@ public class EdgeController extends BaseController { |
284 | 284 | Customer publicCustomer = customerService.findOrCreatePublicCustomer(edge.getTenantId()); |
285 | 285 | Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(getCurrentUser().getTenantId(), edgeId, publicCustomer.getId())); |
286 | 286 | |
287 | - tbClusterService.onEntityStateChange(getTenantId(), edgeId, | |
287 | + tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, | |
288 | 288 | ComponentLifecycleEvent.UPDATED); |
289 | 289 | |
290 | 290 | logEntityAction(edgeId, savedEdge, |
... | ... | @@ -376,7 +376,7 @@ public class EdgeController extends BaseController { |
376 | 376 | |
377 | 377 | Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId); |
378 | 378 | |
379 | - tbClusterService.onEntityStateChange(updatedEdge.getTenantId(), updatedEdge.getId(), ComponentLifecycleEvent.UPDATED); | |
379 | + tbClusterService.broadcastEntityStateChangeEvent(updatedEdge.getTenantId(), updatedEdge.getId(), ComponentLifecycleEvent.UPDATED); | |
380 | 380 | |
381 | 381 | logEntityAction(updatedEdge.getId(), updatedEdge, null, ActionType.UPDATED, null); |
382 | 382 | ... | ... |
... | ... | @@ -24,13 +24,11 @@ import org.springframework.web.bind.annotation.RequestMapping; |
24 | 24 | import org.springframework.web.bind.annotation.RequestMethod; |
25 | 25 | import org.springframework.web.bind.annotation.ResponseBody; |
26 | 26 | import org.springframework.web.bind.annotation.RestController; |
27 | -import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | |
28 | 27 | import org.thingsboard.server.common.data.Device; |
29 | 28 | import org.thingsboard.server.common.data.EntityType; |
30 | 29 | import org.thingsboard.server.common.data.audit.ActionType; |
31 | 30 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
32 | 31 | import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; |
33 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | |
34 | 32 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
35 | 33 | import org.thingsboard.server.queue.util.TbCoreComponent; |
36 | 34 | import org.thingsboard.server.service.security.permission.Resource; |
... | ... | @@ -66,22 +64,11 @@ public class Lwm2mController extends BaseController { |
66 | 64 | checkEntity(device.getId(), device, Resource.DEVICE); |
67 | 65 | Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials); |
68 | 66 | checkNotNull(savedDevice); |
69 | - | |
70 | - tbClusterService.onDeviceChange(savedDevice, null); | |
71 | - tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(), | |
72 | - savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null); | |
73 | - tbClusterService.onEntityStateChange(savedDevice.getTenantId(), savedDevice.getId(), | |
74 | - device.getId() == null ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); | |
75 | - | |
67 | + tbClusterService.onDeviceUpdated(savedDevice, device); | |
76 | 68 | logEntityAction(savedDevice.getId(), savedDevice, |
77 | 69 | savedDevice.getCustomerId(), |
78 | 70 | device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); |
79 | 71 | |
80 | - if (device.getId() == null) { | |
81 | - deviceStateService.onDeviceAdded(savedDevice); | |
82 | - } else { | |
83 | - deviceStateService.onDeviceUpdated(savedDevice); | |
84 | - } | |
85 | 72 | return savedDevice; |
86 | 73 | } catch (Exception e) { |
87 | 74 | logEntityAction(emptyId(EntityType.DEVICE), device, | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.controller; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.springframework.http.HttpStatus; | |
20 | +import org.springframework.http.ResponseEntity; | |
21 | +import org.springframework.security.access.prepost.PreAuthorize; | |
22 | +import org.springframework.web.bind.annotation.PathVariable; | |
23 | +import org.springframework.web.bind.annotation.RequestBody; | |
24 | +import org.springframework.web.bind.annotation.RequestMapping; | |
25 | +import org.springframework.web.bind.annotation.RequestMethod; | |
26 | +import org.springframework.web.bind.annotation.ResponseBody; | |
27 | +import org.springframework.web.bind.annotation.RestController; | |
28 | +import org.springframework.web.context.request.async.DeferredResult; | |
29 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
30 | +import org.thingsboard.server.common.data.id.DeviceId; | |
31 | +import org.thingsboard.server.queue.util.TbCoreComponent; | |
32 | + | |
33 | +import java.util.UUID; | |
34 | + | |
35 | +@RestController | |
36 | +@TbCoreComponent | |
37 | +@RequestMapping(TbUrlConstants.RPC_V1_URL_PREFIX) | |
38 | +@Slf4j | |
39 | +public class RpcV1Controller extends AbstractRpcController { | |
40 | + | |
41 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | |
42 | + @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) | |
43 | + @ResponseBody | |
44 | + public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { | |
45 | + return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT); | |
46 | + } | |
47 | + | |
48 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | |
49 | + @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) | |
50 | + @ResponseBody | |
51 | + public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { | |
52 | + return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT); | |
53 | + } | |
54 | + | |
55 | +} | ... | ... |
application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java
renamed from
application/src/main/java/org/thingsboard/server/controller/RpcController.java
... | ... | @@ -15,16 +15,10 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.controller; |
17 | 17 | |
18 | -import com.fasterxml.jackson.databind.JsonNode; | |
19 | -import com.fasterxml.jackson.databind.ObjectMapper; | |
20 | -import com.google.common.util.concurrent.FutureCallback; | |
21 | 18 | import lombok.extern.slf4j.Slf4j; |
22 | -import org.springframework.beans.factory.annotation.Autowired; | |
23 | -import org.springframework.beans.factory.annotation.Value; | |
24 | 19 | import org.springframework.http.HttpStatus; |
25 | 20 | import org.springframework.http.ResponseEntity; |
26 | 21 | import org.springframework.security.access.prepost.PreAuthorize; |
27 | -import org.springframework.util.StringUtils; | |
28 | 22 | import org.springframework.web.bind.annotation.PathVariable; |
29 | 23 | import org.springframework.web.bind.annotation.RequestBody; |
30 | 24 | import org.springframework.web.bind.annotation.RequestMapping; |
... | ... | @@ -33,71 +27,43 @@ import org.springframework.web.bind.annotation.RequestParam; |
33 | 27 | import org.springframework.web.bind.annotation.ResponseBody; |
34 | 28 | import org.springframework.web.bind.annotation.RestController; |
35 | 29 | import org.springframework.web.context.request.async.DeferredResult; |
36 | -import org.thingsboard.rule.engine.api.RpcError; | |
37 | -import org.thingsboard.server.common.data.DataConstants; | |
38 | -import org.thingsboard.server.common.data.audit.ActionType; | |
39 | -import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | |
30 | +import org.thingsboard.common.util.JacksonUtil; | |
40 | 31 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
41 | 32 | import org.thingsboard.server.common.data.id.DeviceId; |
42 | -import org.thingsboard.server.common.data.id.EntityId; | |
43 | 33 | import org.thingsboard.server.common.data.id.RpcId; |
44 | 34 | import org.thingsboard.server.common.data.id.TenantId; |
45 | -import org.thingsboard.server.common.data.id.UUIDBased; | |
46 | 35 | import org.thingsboard.server.common.data.page.PageData; |
47 | 36 | import org.thingsboard.server.common.data.page.PageLink; |
48 | 37 | import org.thingsboard.server.common.data.rpc.Rpc; |
49 | 38 | import org.thingsboard.server.common.data.rpc.RpcStatus; |
50 | -import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | |
51 | -import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | |
39 | +import org.thingsboard.server.common.msg.TbMsg; | |
40 | +import org.thingsboard.server.common.msg.TbMsgMetaData; | |
52 | 41 | import org.thingsboard.server.queue.util.TbCoreComponent; |
53 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
54 | -import org.thingsboard.server.service.rpc.LocalRequestMetaData; | |
55 | -import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; | |
56 | -import org.thingsboard.server.service.security.AccessValidator; | |
57 | -import org.thingsboard.server.service.security.model.SecurityUser; | |
42 | +import org.thingsboard.server.service.rpc.RemoveRpcActorMsg; | |
58 | 43 | import org.thingsboard.server.service.security.permission.Operation; |
59 | -import org.thingsboard.server.service.telemetry.exception.ToErrorResponseEntity; | |
60 | 44 | |
61 | -import javax.annotation.Nullable; | |
62 | -import java.io.IOException; | |
63 | -import java.util.Optional; | |
64 | 45 | import java.util.UUID; |
65 | 46 | |
66 | -/** | |
67 | - * Created by ashvayka on 22.03.18. | |
68 | - */ | |
47 | +import static org.thingsboard.server.common.data.DataConstants.RPC_DELETED; | |
48 | + | |
69 | 49 | @RestController |
70 | 50 | @TbCoreComponent |
71 | -@RequestMapping(TbUrlConstants.RPC_URL_PREFIX) | |
51 | +@RequestMapping(TbUrlConstants.RPC_V2_URL_PREFIX) | |
72 | 52 | @Slf4j |
73 | -public class RpcController extends BaseController { | |
74 | - | |
75 | - protected final ObjectMapper jsonMapper = new ObjectMapper(); | |
76 | - | |
77 | - @Autowired | |
78 | - private TbCoreDeviceRpcService deviceRpcService; | |
79 | - | |
80 | - @Autowired | |
81 | - private AccessValidator accessValidator; | |
82 | - | |
83 | - @Value("${server.rest.server_side_rpc.min_timeout:5000}") | |
84 | - private long minTimeout; | |
85 | - | |
86 | - @Value("${server.rest.server_side_rpc.default_timeout:10000}") | |
87 | - private long defaultTimeout; | |
53 | +public class RpcV2Controller extends AbstractRpcController { | |
88 | 54 | |
89 | 55 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
90 | 56 | @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) |
91 | 57 | @ResponseBody |
92 | 58 | public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { |
93 | - return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody); | |
59 | + return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT); | |
94 | 60 | } |
95 | 61 | |
96 | 62 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
97 | 63 | @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) |
98 | 64 | @ResponseBody |
99 | 65 | public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { |
100 | - return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody); | |
66 | + return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT); | |
101 | 67 | } |
102 | 68 | |
103 | 69 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
... | ... | @@ -140,118 +106,23 @@ public class RpcController extends BaseController { |
140 | 106 | public void deleteResource(@PathVariable("rpcId") String strRpc) throws ThingsboardException { |
141 | 107 | checkParameter("RpcId", strRpc); |
142 | 108 | try { |
143 | - rpcService.deleteRpc(getTenantId(), new RpcId(UUID.fromString(strRpc))); | |
144 | - } catch (Exception e) { | |
145 | - throw handleException(e); | |
146 | - } | |
147 | - } | |
109 | + RpcId rpcId = new RpcId(UUID.fromString(strRpc)); | |
110 | + Rpc rpc = checkRpcId(rpcId, Operation.DELETE); | |
148 | 111 | |
149 | - private DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody) throws ThingsboardException { | |
150 | - try { | |
151 | - JsonNode rpcRequestBody = jsonMapper.readTree(requestBody); | |
152 | - ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(rpcRequestBody.get("method").asText(), jsonMapper.writeValueAsString(rpcRequestBody.get("params"))); | |
153 | - SecurityUser currentUser = getCurrentUser(); | |
154 | - TenantId tenantId = currentUser.getTenantId(); | |
155 | - final DeferredResult<ResponseEntity> response = new DeferredResult<>(); | |
156 | - long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout; | |
157 | - long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout); | |
158 | - UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID(); | |
159 | - boolean persisted = rpcRequestBody.has(DataConstants.PERSISTENT) && rpcRequestBody.get(DataConstants.PERSISTENT).asBoolean(); | |
160 | - accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() { | |
161 | - @Override | |
162 | - public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) { | |
163 | - ToDeviceRpcRequest rpcRequest = new ToDeviceRpcRequest(rpcRequestUUID, | |
164 | - tenantId, | |
165 | - deviceId, | |
166 | - oneWay, | |
167 | - expTime, | |
168 | - body, | |
169 | - persisted | |
170 | - ); | |
171 | - deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse), currentUser); | |
112 | + if (rpc != null) { | |
113 | + if (rpc.getStatus().equals(RpcStatus.QUEUED)) { | |
114 | + RemoveRpcActorMsg removeMsg = new RemoveRpcActorMsg(getTenantId(), rpc.getDeviceId(), rpc.getUuidId()); | |
115 | + log.trace("[{}] Forwarding msg {} to queue actor!", rpc.getDeviceId(), rpc); | |
116 | + tbClusterService.pushMsgToCore(removeMsg, null); | |
172 | 117 | } |
173 | 118 | |
174 | - @Override | |
175 | - public void onFailure(Throwable e) { | |
176 | - ResponseEntity entity; | |
177 | - if (e instanceof ToErrorResponseEntity) { | |
178 | - entity = ((ToErrorResponseEntity) e).toErrorResponseEntity(); | |
179 | - } else { | |
180 | - entity = new ResponseEntity(HttpStatus.UNAUTHORIZED); | |
181 | - } | |
182 | - logRpcCall(currentUser, deviceId, body, oneWay, Optional.empty(), e); | |
183 | - response.setResult(entity); | |
184 | - } | |
185 | - })); | |
186 | - return response; | |
187 | - } catch (IOException ioe) { | |
188 | - throw new ThingsboardException("Invalid request body", ioe, ThingsboardErrorCode.BAD_REQUEST_PARAMS); | |
189 | - } | |
190 | - } | |
119 | + rpcService.deleteRpc(getTenantId(), rpcId); | |
191 | 120 | |
192 | - public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response) { | |
193 | - Optional<RpcError> rpcError = response.getError(); | |
194 | - DeferredResult<ResponseEntity> responseWriter = rpcRequest.getResponseWriter(); | |
195 | - if (rpcError.isPresent()) { | |
196 | - logRpcCall(rpcRequest, rpcError, null); | |
197 | - RpcError error = rpcError.get(); | |
198 | - switch (error) { | |
199 | - case TIMEOUT: | |
200 | - responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT)); | |
201 | - break; | |
202 | - case NO_ACTIVE_CONNECTION: | |
203 | - responseWriter.setResult(new ResponseEntity<>(HttpStatus.CONFLICT)); | |
204 | - break; | |
205 | - default: | |
206 | - responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT)); | |
207 | - break; | |
208 | - } | |
209 | - } else { | |
210 | - Optional<String> responseData = response.getResponse(); | |
211 | - if (responseData.isPresent() && !StringUtils.isEmpty(responseData.get())) { | |
212 | - String data = responseData.get(); | |
213 | - try { | |
214 | - logRpcCall(rpcRequest, rpcError, null); | |
215 | - responseWriter.setResult(new ResponseEntity<>(jsonMapper.readTree(data), HttpStatus.OK)); | |
216 | - } catch (IOException e) { | |
217 | - log.debug("Failed to decode device response: {}", data, e); | |
218 | - logRpcCall(rpcRequest, rpcError, e); | |
219 | - responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE)); | |
220 | - } | |
221 | - } else { | |
222 | - logRpcCall(rpcRequest, rpcError, null); | |
223 | - responseWriter.setResult(new ResponseEntity<>(HttpStatus.OK)); | |
121 | + TbMsg msg = TbMsg.newMsg(RPC_DELETED, rpc.getDeviceId(), TbMsgMetaData.EMPTY, JacksonUtil.toString(rpc)); | |
122 | + tbClusterService.pushMsgToRuleEngine(getTenantId(), rpc.getDeviceId(), msg, null); | |
224 | 123 | } |
124 | + } catch (Exception e) { | |
125 | + throw handleException(e); | |
225 | 126 | } |
226 | 127 | } |
227 | - | |
228 | - private void logRpcCall(LocalRequestMetaData rpcRequest, Optional<RpcError> rpcError, Throwable e) { | |
229 | - logRpcCall(rpcRequest.getUser(), rpcRequest.getRequest().getDeviceId(), rpcRequest.getRequest().getBody(), rpcRequest.getRequest().isOneway(), rpcError, null); | |
230 | - } | |
231 | - | |
232 | - | |
233 | - private void logRpcCall(SecurityUser user, EntityId entityId, ToDeviceRpcRequestBody body, boolean oneWay, Optional<RpcError> rpcError, Throwable e) { | |
234 | - String rpcErrorStr = ""; | |
235 | - if (rpcError.isPresent()) { | |
236 | - rpcErrorStr = "RPC Error: " + rpcError.get().name(); | |
237 | - } | |
238 | - String method = body.getMethod(); | |
239 | - String params = body.getParams(); | |
240 | - | |
241 | - auditLogService.logEntityAction( | |
242 | - user.getTenantId(), | |
243 | - user.getCustomerId(), | |
244 | - user.getId(), | |
245 | - user.getName(), | |
246 | - (UUIDBased & EntityId) entityId, | |
247 | - null, | |
248 | - ActionType.RPC_CALL, | |
249 | - BaseController.toException(e), | |
250 | - rpcErrorStr, | |
251 | - oneWay, | |
252 | - method, | |
253 | - params); | |
254 | - } | |
255 | - | |
256 | - | |
257 | 128 | } | ... | ... |
... | ... | @@ -149,7 +149,7 @@ public class RuleChainController extends BaseController { |
149 | 149 | RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); |
150 | 150 | |
151 | 151 | if (RuleChainType.CORE.equals(savedRuleChain.getType())) { |
152 | - tbClusterService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(), | |
152 | + tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), savedRuleChain.getId(), | |
153 | 153 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
154 | 154 | } |
155 | 155 | |
... | ... | @@ -183,7 +183,7 @@ public class RuleChainController extends BaseController { |
183 | 183 | |
184 | 184 | RuleChain savedRuleChain = installScripts.createDefaultRuleChain(getCurrentUser().getTenantId(), request.getName()); |
185 | 185 | |
186 | - tbClusterService.onEntityStateChange(savedRuleChain.getTenantId(), savedRuleChain.getId(), ComponentLifecycleEvent.CREATED); | |
186 | + tbClusterService.broadcastEntityStateChangeEvent(savedRuleChain.getTenantId(), savedRuleChain.getId(), ComponentLifecycleEvent.CREATED); | |
187 | 187 | |
188 | 188 | logEntityAction(savedRuleChain.getId(), savedRuleChain, null, ActionType.ADDED, null); |
189 | 189 | |
... | ... | @@ -210,7 +210,7 @@ public class RuleChainController extends BaseController { |
210 | 210 | if (previousRootRuleChain != null) { |
211 | 211 | previousRootRuleChain = ruleChainService.findRuleChainById(getTenantId(), previousRootRuleChain.getId()); |
212 | 212 | |
213 | - tbClusterService.onEntityStateChange(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(), | |
213 | + tbClusterService.broadcastEntityStateChangeEvent(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(), | |
214 | 214 | ComponentLifecycleEvent.UPDATED); |
215 | 215 | |
216 | 216 | logEntityAction(previousRootRuleChain.getId(), previousRootRuleChain, |
... | ... | @@ -218,7 +218,7 @@ public class RuleChainController extends BaseController { |
218 | 218 | } |
219 | 219 | ruleChain = ruleChainService.findRuleChainById(getTenantId(), ruleChainId); |
220 | 220 | |
221 | - tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), | |
221 | + tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), ruleChain.getId(), | |
222 | 222 | ComponentLifecycleEvent.UPDATED); |
223 | 223 | |
224 | 224 | logEntityAction(ruleChain.getId(), ruleChain, |
... | ... | @@ -254,7 +254,7 @@ public class RuleChainController extends BaseController { |
254 | 254 | RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId())); |
255 | 255 | |
256 | 256 | if (RuleChainType.CORE.equals(ruleChain.getType())) { |
257 | - tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED); | |
257 | + tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED); | |
258 | 258 | } |
259 | 259 | |
260 | 260 | logEntityAction(ruleChain.getId(), ruleChain, |
... | ... | @@ -323,9 +323,9 @@ public class RuleChainController extends BaseController { |
323 | 323 | |
324 | 324 | if (RuleChainType.CORE.equals(ruleChain.getType())) { |
325 | 325 | referencingRuleChainIds.forEach(referencingRuleChainId -> |
326 | - tbClusterService.onEntityStateChange(ruleChain.getTenantId(), referencingRuleChainId, ComponentLifecycleEvent.UPDATED)); | |
326 | + tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), referencingRuleChainId, ComponentLifecycleEvent.UPDATED)); | |
327 | 327 | |
328 | - tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.DELETED); | |
328 | + tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.DELETED); | |
329 | 329 | } |
330 | 330 | |
331 | 331 | logEntityAction(ruleChainId, ruleChain, |
... | ... | @@ -456,7 +456,7 @@ public class RuleChainController extends BaseController { |
456 | 456 | List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, RuleChainType.CORE, overwrite); |
457 | 457 | if (!CollectionUtils.isEmpty(importResults)) { |
458 | 458 | for (RuleChainImportResult importResult : importResults) { |
459 | - tbClusterService.onEntityStateChange(importResult.getTenantId(), importResult.getRuleChainId(), importResult.getLifecycleEvent()); | |
459 | + tbClusterService.broadcastEntityStateChangeEvent(importResult.getTenantId(), importResult.getRuleChainId(), importResult.getLifecycleEvent()); | |
460 | 460 | } |
461 | 461 | } |
462 | 462 | } catch (Exception e) { | ... | ... |
... | ... | @@ -20,5 +20,6 @@ package org.thingsboard.server.controller; |
20 | 20 | */ |
21 | 21 | public class TbUrlConstants { |
22 | 22 | public static final String TELEMETRY_URL_PREFIX = "/api/plugins/telemetry"; |
23 | - public static final String RPC_URL_PREFIX = "/api/plugins/rpc"; | |
23 | + public static final String RPC_V1_URL_PREFIX = "/api/plugins/rpc"; | |
24 | + public static final String RPC_V2_URL_PREFIX = "/api/rpc"; | |
24 | 25 | } | ... | ... |
... | ... | @@ -99,7 +99,7 @@ public class TenantController extends BaseController { |
99 | 99 | } |
100 | 100 | tenantProfileCache.evict(tenant.getId()); |
101 | 101 | tbClusterService.onTenantChange(tenant, null); |
102 | - tbClusterService.onEntityStateChange(tenant.getId(), tenant.getId(), | |
102 | + tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), | |
103 | 103 | newTenant ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
104 | 104 | return tenant; |
105 | 105 | } catch (Exception e) { |
... | ... | @@ -118,7 +118,7 @@ public class TenantController extends BaseController { |
118 | 118 | tenantService.deleteTenant(tenantId); |
119 | 119 | tenantProfileCache.evict(tenantId); |
120 | 120 | tbClusterService.onTenantDelete(tenant, null); |
121 | - tbClusterService.onEntityStateChange(tenantId, tenantId, ComponentLifecycleEvent.DELETED); | |
121 | + tbClusterService.broadcastEntityStateChangeEvent(tenantId, tenantId, ComponentLifecycleEvent.DELETED); | |
122 | 122 | } catch (Exception e) { |
123 | 123 | throw handleException(e); |
124 | 124 | } | ... | ... |
... | ... | @@ -34,7 +34,6 @@ import org.thingsboard.server.common.data.id.TenantProfileId; |
34 | 34 | import org.thingsboard.server.common.data.page.PageData; |
35 | 35 | import org.thingsboard.server.common.data.page.PageLink; |
36 | 36 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
37 | -import org.thingsboard.server.dao.exception.DataValidationException; | |
38 | 37 | import org.thingsboard.server.queue.util.TbCoreComponent; |
39 | 38 | import org.thingsboard.server.service.security.permission.Operation; |
40 | 39 | import org.thingsboard.server.service.security.permission.Resource; |
... | ... | @@ -98,7 +97,7 @@ public class TenantProfileController extends BaseController { |
98 | 97 | tenantProfile = checkNotNull(tenantProfileService.saveTenantProfile(getTenantId(), tenantProfile)); |
99 | 98 | tenantProfileCache.put(tenantProfile); |
100 | 99 | tbClusterService.onTenantProfileChange(tenantProfile, null); |
101 | - tbClusterService.onEntityStateChange(TenantId.SYS_TENANT_ID, tenantProfile.getId(), | |
100 | + tbClusterService.broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, tenantProfile.getId(), | |
102 | 101 | newTenantProfile ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
103 | 102 | return tenantProfile; |
104 | 103 | } catch (Exception e) { | ... | ... |
... | ... | @@ -41,7 +41,7 @@ import org.thingsboard.server.common.msg.TbMsgDataType; |
41 | 41 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
42 | 42 | import org.thingsboard.server.dao.audit.AuditLogService; |
43 | 43 | import org.thingsboard.server.queue.util.TbCoreComponent; |
44 | -import org.thingsboard.server.service.queue.TbClusterService; | |
44 | +import org.thingsboard.server.cluster.TbClusterService; | |
45 | 45 | |
46 | 46 | import java.util.List; |
47 | 47 | import java.util.Map; | ... | ... |
application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java
... | ... | @@ -61,7 +61,7 @@ import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
61 | 61 | import org.thingsboard.server.queue.discovery.PartitionService; |
62 | 62 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
63 | 63 | import org.thingsboard.server.queue.scheduler.SchedulerComponent; |
64 | -import org.thingsboard.server.service.queue.TbClusterService; | |
64 | +import org.thingsboard.server.cluster.TbClusterService; | |
65 | 65 | import org.thingsboard.server.service.telemetry.InternalTelemetryService; |
66 | 66 | |
67 | 67 | import javax.annotation.PostConstruct; | ... | ... |
... | ... | @@ -29,6 +29,7 @@ import org.springframework.cache.CacheManager; |
29 | 29 | import org.springframework.stereotype.Service; |
30 | 30 | import org.springframework.util.StringUtils; |
31 | 31 | import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; |
32 | +import org.thingsboard.server.cluster.TbClusterService; | |
32 | 33 | import org.thingsboard.server.common.data.Customer; |
33 | 34 | import org.thingsboard.server.common.data.DataConstants; |
34 | 35 | import org.thingsboard.server.common.data.Device; |
... | ... | @@ -70,6 +71,8 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { |
70 | 71 | private static final ObjectMapper mapper = new ObjectMapper(); |
71 | 72 | |
72 | 73 | @Autowired |
74 | + private TbClusterService clusterService; | |
75 | + @Autowired | |
73 | 76 | private DeviceService deviceService; |
74 | 77 | @Autowired |
75 | 78 | private AttributesService attributesService; |
... | ... | @@ -155,6 +158,7 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { |
155 | 158 | if (device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { |
156 | 159 | device.setCustomerId(customerId); |
157 | 160 | Device savedDevice = deviceService.saveDevice(device); |
161 | + clusterService.onDeviceUpdated(savedDevice, device); | |
158 | 162 | return Futures.transform(removeClaimingSavedData(cache, claimData, device), result -> new ClaimResult(savedDevice, ClaimResponse.SUCCESS), MoreExecutors.directExecutor()); |
159 | 163 | } |
160 | 164 | return Futures.transform(removeClaimingSavedData(cache, claimData, device), result -> new ClaimResult(null, ClaimResponse.CLAIMED), MoreExecutors.directExecutor()); |
... | ... | @@ -179,13 +183,14 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { |
179 | 183 | cacheEviction(device.getId()); |
180 | 184 | Customer unassignedCustomer = customerService.findCustomerById(tenantId, device.getCustomerId()); |
181 | 185 | device.setCustomerId(null); |
182 | - deviceService.saveDevice(device); | |
186 | + Device savedDevice = deviceService.saveDevice(device); | |
187 | + clusterService.onDeviceUpdated(savedDevice, device); | |
183 | 188 | if (isAllowedClaimingByDefault) { |
184 | 189 | return Futures.immediateFuture(new ReclaimResult(unassignedCustomer)); |
185 | 190 | } |
186 | 191 | SettableFuture<ReclaimResult> result = SettableFuture.create(); |
187 | 192 | telemetryService.saveAndNotify( |
188 | - tenantId, device.getId(), DataConstants.SERVER_SCOPE, Collections.singletonList( | |
193 | + tenantId, savedDevice.getId(), DataConstants.SERVER_SCOPE, Collections.singletonList( | |
189 | 194 | new BaseAttributeKvEntry(new BooleanDataEntry(CLAIM_ATTRIBUTE_NAME, true), System.currentTimeMillis()) |
190 | 195 | ), |
191 | 196 | new FutureCallback<>() { |
... | ... | @@ -198,7 +203,7 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { |
198 | 203 | public void onFailure(Throwable t) { |
199 | 204 | result.setException(t); |
200 | 205 | } |
201 | - }); | |
206 | + }); | |
202 | 207 | return result; |
203 | 208 | } |
204 | 209 | cacheEviction(device.getId()); |
... | ... | @@ -238,7 +243,7 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { |
238 | 243 | public void onFailure(Throwable t) { |
239 | 244 | result.setException(t); |
240 | 245 | } |
241 | - }); | |
246 | + }); | |
242 | 247 | return result; |
243 | 248 | } |
244 | 249 | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.apache.commons.lang3.RandomStringUtils; |
24 | 24 | import org.springframework.beans.factory.annotation.Autowired; |
25 | 25 | import org.springframework.stereotype.Service; |
26 | 26 | import org.springframework.util.StringUtils; |
27 | +import org.thingsboard.server.cluster.TbClusterService; | |
27 | 28 | import org.thingsboard.server.common.data.DataConstants; |
28 | 29 | import org.thingsboard.server.common.data.Device; |
29 | 30 | import org.thingsboard.server.common.data.DeviceProfile; |
... | ... | @@ -78,6 +79,9 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService { |
78 | 79 | private static final String PROVISIONED_STATE = "provisioned"; |
79 | 80 | |
80 | 81 | @Autowired |
82 | + TbClusterService clusterService; | |
83 | + | |
84 | + @Autowired | |
81 | 85 | DeviceDao deviceDao; |
82 | 86 | |
83 | 87 | @Autowired |
... | ... | @@ -190,8 +194,7 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService { |
190 | 194 | provisionRequest.setDeviceName(newDeviceName); |
191 | 195 | } |
192 | 196 | Device savedDevice = deviceService.saveDevice(provisionRequest, profile); |
193 | - | |
194 | - deviceStateService.onDeviceAdded(savedDevice); | |
197 | + clusterService.onDeviceUpdated(savedDevice, null); | |
195 | 198 | saveProvisionStateAttribute(savedDevice).get(); |
196 | 199 | pushDeviceCreatedEventToRuleEngine(savedDevice); |
197 | 200 | notify(savedDevice, provisionRequest, DataConstants.PROVISION_SUCCESS, true); | ... | ... |
... | ... | @@ -16,11 +16,7 @@ |
16 | 16 | package org.thingsboard.server.service.edge; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | -import com.google.common.util.concurrent.FutureCallback; | |
20 | -import com.google.common.util.concurrent.Futures; | |
21 | -import com.google.common.util.concurrent.ListenableFuture; | |
22 | 19 | import lombok.extern.slf4j.Slf4j; |
23 | -import org.checkerframework.checker.nullness.qual.Nullable; | |
24 | 20 | import org.springframework.beans.factory.annotation.Autowired; |
25 | 21 | import org.springframework.stereotype.Service; |
26 | 22 | import org.thingsboard.server.common.data.edge.Edge; |
... | ... | @@ -41,8 +37,7 @@ import org.thingsboard.server.service.edge.rpc.processor.CustomerEdgeProcessor; |
41 | 37 | import org.thingsboard.server.service.edge.rpc.processor.EdgeProcessor; |
42 | 38 | import org.thingsboard.server.service.edge.rpc.processor.EntityEdgeProcessor; |
43 | 39 | import org.thingsboard.server.service.edge.rpc.processor.RelationEdgeProcessor; |
44 | -import org.thingsboard.server.service.executors.DbCallbackExecutorService; | |
45 | -import org.thingsboard.server.service.queue.TbClusterService; | |
40 | +import org.thingsboard.server.cluster.TbClusterService; | |
46 | 41 | |
47 | 42 | import javax.annotation.PostConstruct; |
48 | 43 | import javax.annotation.PreDestroy; |
... | ... | @@ -66,9 +61,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
66 | 61 | private TbClusterService clusterService; |
67 | 62 | |
68 | 63 | @Autowired |
69 | - private DbCallbackExecutorService dbCallbackExecutorService; | |
70 | - | |
71 | - @Autowired | |
72 | 64 | private EdgeProcessor edgeProcessor; |
73 | 65 | |
74 | 66 | @Autowired |
... | ... | @@ -123,23 +115,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { |
123 | 115 | edgeEvent.setEntityId(entityId.getId()); |
124 | 116 | } |
125 | 117 | edgeEvent.setBody(body); |
126 | - ListenableFuture<EdgeEvent> future = edgeEventService.saveAsync(edgeEvent); | |
127 | - Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | |
128 | - @Override | |
129 | - public void onSuccess(@Nullable EdgeEvent result) { | |
130 | - clusterService.onEdgeEventUpdate(tenantId, edgeId); | |
131 | - } | |
132 | - | |
133 | - @Override | |
134 | - public void onFailure(Throwable t) { | |
135 | - log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | |
136 | - } | |
137 | - }, dbCallbackExecutorService); | |
138 | - | |
118 | + edgeEventService.save(edgeEvent); | |
119 | + clusterService.onEdgeEventUpdate(tenantId, edgeId); | |
139 | 120 | } |
140 | 121 | |
141 | 122 | @Override |
142 | 123 | public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) { |
124 | + log.trace("Pushing notification to edge {}", edgeNotificationMsg); | |
143 | 125 | try { |
144 | 126 | TenantId tenantId = new TenantId(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB())); |
145 | 127 | EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); | ... | ... |
... | ... | @@ -259,7 +259,7 @@ public final class EdgeGrpcSession implements Closeable { |
259 | 259 | log.error("[{}] Msg processing failed! Error msg: {}", edge.getRoutingKey(), msg.getErrorMsg()); |
260 | 260 | } |
261 | 261 | if (sessionState.getPendingMsgsMap().isEmpty()) { |
262 | - log.debug("[{}] Pending msgs map is empty. Stopping current iteration {}", edge.getRoutingKey(), msg); | |
262 | + log.debug("[{}] Pending msgs map is empty. Stopping current iteration", edge.getRoutingKey()); | |
263 | 263 | if (sessionState.getScheduledSendDownlinkTask() != null) { |
264 | 264 | sessionState.getScheduledSendDownlinkTask().cancel(false); |
265 | 265 | } |
... | ... | @@ -527,7 +527,7 @@ public final class EdgeGrpcSession implements Closeable { |
527 | 527 | case RULE_CHAIN_METADATA: |
528 | 528 | return ctx.getRuleChainProcessor().processRuleChainMetadataToEdge(edgeEvent, msgType); |
529 | 529 | case ALARM: |
530 | - return ctx.getAlarmProcessor().processAlarmToEdge(edge, edgeEvent, msgType); | |
530 | + return ctx.getAlarmProcessor().processAlarmToEdge(edge, edgeEvent, msgType, action); | |
531 | 531 | case USER: |
532 | 532 | return ctx.getUserProcessor().processUserToEdge(edge, edgeEvent, msgType, action); |
533 | 533 | case RELATION: | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.service.edge.rpc; | |
17 | + | |
18 | +import com.google.protobuf.BoolValue; | |
19 | +import com.google.protobuf.ByteString; | |
20 | +import com.google.protobuf.BytesValue; | |
21 | +import com.google.protobuf.Int64Value; | |
22 | +import com.google.protobuf.StringValue; | |
23 | + | |
24 | +public class EdgeProtoUtils { | |
25 | + | |
26 | + private EdgeProtoUtils() { | |
27 | + } | |
28 | + | |
29 | + public static BoolValue getBoolValue(Boolean value) { | |
30 | + BoolValue.Builder builder = BoolValue.newBuilder(); | |
31 | + builder.setValue(value); | |
32 | + return builder.build(); | |
33 | + } | |
34 | + | |
35 | + public static StringValue getStringValue(String value) { | |
36 | + StringValue.Builder builder = StringValue.newBuilder(); | |
37 | + builder.setValue(value); | |
38 | + return builder.build(); | |
39 | + } | |
40 | + | |
41 | + public static Int64Value getInt64Value(Long value) { | |
42 | + Int64Value.Builder builder = Int64Value.newBuilder(); | |
43 | + builder.setValue(value); | |
44 | + return builder.build(); | |
45 | + } | |
46 | + | |
47 | + public static BytesValue getBytesValue(ByteString value) { | |
48 | + BytesValue.Builder builder = BytesValue.newBuilder(); | |
49 | + builder.setValue(value); | |
50 | + return builder.build(); | |
51 | + } | |
52 | +} | ... | ... |
... | ... | @@ -58,6 +58,8 @@ public class AlarmMsgConstructor { |
58 | 58 | } |
59 | 59 | AlarmUpdateMsg.Builder builder = AlarmUpdateMsg.newBuilder() |
60 | 60 | .setMsgType(msgType) |
61 | + .setIdMSB(alarm.getId().getId().getMostSignificantBits()) | |
62 | + .setIdLSB(alarm.getId().getId().getLeastSignificantBits()) | |
61 | 63 | .setName(alarm.getName()) |
62 | 64 | .setType(alarm.getType()) |
63 | 65 | .setOriginatorName(entityName) | ... | ... |
... | ... | @@ -24,6 +24,9 @@ import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; |
24 | 24 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
25 | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | |
27 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getInt64Value; | |
28 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
29 | + | |
27 | 30 | @Component |
28 | 31 | @TbCoreComponent |
29 | 32 | public class AssetMsgConstructor { |
... | ... | @@ -36,14 +39,14 @@ public class AssetMsgConstructor { |
36 | 39 | .setName(asset.getName()) |
37 | 40 | .setType(asset.getType()); |
38 | 41 | if (asset.getLabel() != null) { |
39 | - builder.setLabel(asset.getLabel()); | |
42 | + builder.setLabel(getStringValue(asset.getLabel())); | |
40 | 43 | } |
41 | 44 | if (customerId != null) { |
42 | - builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); | |
43 | - builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); | |
45 | + builder.setCustomerIdMSB(getInt64Value(customerId.getId().getMostSignificantBits())); | |
46 | + builder.setCustomerIdLSB(getInt64Value(customerId.getId().getLeastSignificantBits())); | |
44 | 47 | } |
45 | 48 | if (asset.getAdditionalInfo() != null) { |
46 | - builder.setAdditionalInfo(JacksonUtil.toString(asset.getAdditionalInfo())); | |
49 | + builder.setAdditionalInfo(getStringValue(JacksonUtil.toString(asset.getAdditionalInfo()))); | |
47 | 50 | } |
48 | 51 | return builder.build(); |
49 | 52 | } | ... | ... |
... | ... | @@ -23,6 +23,8 @@ import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; |
23 | 23 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
24 | 24 | import org.thingsboard.server.queue.util.TbCoreComponent; |
25 | 25 | |
26 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
27 | + | |
26 | 28 | @Component |
27 | 29 | @TbCoreComponent |
28 | 30 | public class CustomerMsgConstructor { |
... | ... | @@ -34,31 +36,31 @@ public class CustomerMsgConstructor { |
34 | 36 | .setIdLSB(customer.getId().getId().getLeastSignificantBits()) |
35 | 37 | .setTitle(customer.getTitle()); |
36 | 38 | if (customer.getCountry() != null) { |
37 | - builder.setCountry(customer.getCountry()); | |
39 | + builder.setCountry(getStringValue(customer.getCountry())); | |
38 | 40 | } |
39 | 41 | if (customer.getState() != null) { |
40 | - builder.setState(customer.getState()); | |
42 | + builder.setState(getStringValue(customer.getState())); | |
41 | 43 | } |
42 | 44 | if (customer.getCity() != null) { |
43 | - builder.setCity(customer.getCity()); | |
45 | + builder.setCity(getStringValue(customer.getCity())); | |
44 | 46 | } |
45 | 47 | if (customer.getAddress() != null) { |
46 | - builder.setAddress(customer.getAddress()); | |
48 | + builder.setAddress(getStringValue(customer.getAddress())); | |
47 | 49 | } |
48 | 50 | if (customer.getAddress2() != null) { |
49 | - builder.setAddress2(customer.getAddress2()); | |
51 | + builder.setAddress2(getStringValue(customer.getAddress2())); | |
50 | 52 | } |
51 | 53 | if (customer.getZip() != null) { |
52 | - builder.setZip(customer.getZip()); | |
54 | + builder.setZip(getStringValue(customer.getZip())); | |
53 | 55 | } |
54 | 56 | if (customer.getPhone() != null) { |
55 | - builder.setPhone(customer.getPhone()); | |
57 | + builder.setPhone(getStringValue(customer.getPhone())); | |
56 | 58 | } |
57 | 59 | if (customer.getEmail() != null) { |
58 | - builder.setEmail(customer.getEmail()); | |
60 | + builder.setEmail(getStringValue(customer.getEmail())); | |
59 | 61 | } |
60 | 62 | if (customer.getAdditionalInfo() != null) { |
61 | - builder.setAdditionalInfo(JacksonUtil.toString(customer.getAdditionalInfo())); | |
63 | + builder.setAdditionalInfo(getStringValue(JacksonUtil.toString(customer.getAdditionalInfo()))); | |
62 | 64 | } |
63 | 65 | return builder.build(); |
64 | 66 | } | ... | ... |
... | ... | @@ -24,6 +24,8 @@ import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg; |
24 | 24 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
25 | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | |
27 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getInt64Value; | |
28 | + | |
27 | 29 | @Component |
28 | 30 | @TbCoreComponent |
29 | 31 | public class DashboardMsgConstructor { |
... | ... | @@ -36,8 +38,8 @@ public class DashboardMsgConstructor { |
36 | 38 | .setTitle(dashboard.getTitle()) |
37 | 39 | .setConfiguration(JacksonUtil.toString(dashboard.getConfiguration())); |
38 | 40 | if (customerId != null) { |
39 | - builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); | |
40 | - builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); | |
41 | + builder.setCustomerIdMSB(getInt64Value(customerId.getId().getMostSignificantBits())); | |
42 | + builder.setCustomerIdLSB(getInt64Value(customerId.getId().getLeastSignificantBits())); | |
41 | 43 | } |
42 | 44 | return builder.build(); |
43 | 45 | } | ... | ... |
... | ... | @@ -32,6 +32,9 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
32 | 32 | |
33 | 33 | import java.util.UUID; |
34 | 34 | |
35 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getInt64Value; | |
36 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
37 | + | |
35 | 38 | @Component |
36 | 39 | @TbCoreComponent |
37 | 40 | public class DeviceMsgConstructor { |
... | ... | @@ -46,21 +49,21 @@ public class DeviceMsgConstructor { |
46 | 49 | .setName(device.getName()) |
47 | 50 | .setType(device.getType()); |
48 | 51 | if (device.getLabel() != null) { |
49 | - builder.setLabel(device.getLabel()); | |
52 | + builder.setLabel(getStringValue(device.getLabel())); | |
50 | 53 | } |
51 | 54 | if (customerId != null) { |
52 | - builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); | |
53 | - builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); | |
55 | + builder.setCustomerIdMSB(getInt64Value(customerId.getId().getMostSignificantBits())); | |
56 | + builder.setCustomerIdLSB(getInt64Value(customerId.getId().getLeastSignificantBits())); | |
54 | 57 | } |
55 | 58 | if (device.getDeviceProfileId() != null) { |
56 | - builder.setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits()); | |
57 | - builder.setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits()); | |
59 | + builder.setDeviceProfileIdMSB(getInt64Value(device.getDeviceProfileId().getId().getMostSignificantBits())); | |
60 | + builder.setDeviceProfileIdLSB(getInt64Value(device.getDeviceProfileId().getId().getLeastSignificantBits())); | |
58 | 61 | } |
59 | 62 | if (device.getAdditionalInfo() != null) { |
60 | - builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo())); | |
63 | + builder.setAdditionalInfo(getStringValue(JacksonUtil.toString(device.getAdditionalInfo()))); | |
61 | 64 | } |
62 | 65 | if (conflictName != null) { |
63 | - builder.setConflictName(conflictName); | |
66 | + builder.setConflictName(getStringValue(conflictName)); | |
64 | 67 | } |
65 | 68 | return builder.build(); |
66 | 69 | } |
... | ... | @@ -74,7 +77,7 @@ public class DeviceMsgConstructor { |
74 | 77 | .setCredentialsId(deviceCredentials.getCredentialsId()); |
75 | 78 | } |
76 | 79 | if (deviceCredentials.getCredentialsValue() != null) { |
77 | - builder.setCredentialsValue(deviceCredentials.getCredentialsValue()); | |
80 | + builder.setCredentialsValue(getStringValue(deviceCredentials.getCredentialsValue())); | |
78 | 81 | } |
79 | 82 | return builder.build(); |
80 | 83 | } | ... | ... |
... | ... | @@ -27,6 +27,9 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
27 | 27 | |
28 | 28 | import java.nio.charset.StandardCharsets; |
29 | 29 | |
30 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getBytesValue; | |
31 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
32 | + | |
30 | 33 | @Component |
31 | 34 | @TbCoreComponent |
32 | 35 | public class DeviceProfileMsgConstructor { |
... | ... | @@ -52,19 +55,19 @@ public class DeviceProfileMsgConstructor { |
52 | 55 | // builder.setDefaultQueueName(deviceProfile.getDefaultQueueName()); |
53 | 56 | // } |
54 | 57 | if (deviceProfile.getDescription() != null) { |
55 | - builder.setDescription(deviceProfile.getDescription()); | |
58 | + builder.setDescription(getStringValue(deviceProfile.getDescription())); | |
56 | 59 | } |
57 | 60 | if (deviceProfile.getTransportType() != null) { |
58 | - builder.setTransportType(deviceProfile.getTransportType().name()); | |
61 | + builder.setTransportType(getStringValue(deviceProfile.getTransportType().name())); | |
59 | 62 | } |
60 | 63 | if (deviceProfile.getProvisionType() != null) { |
61 | - builder.setProvisionType(deviceProfile.getProvisionType().name()); | |
64 | + builder.setProvisionType(getStringValue(deviceProfile.getProvisionType().name())); | |
62 | 65 | } |
63 | 66 | if (deviceProfile.getProvisionDeviceKey() != null) { |
64 | - builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey()); | |
67 | + builder.setProvisionDeviceKey(getStringValue(deviceProfile.getProvisionDeviceKey())); | |
65 | 68 | } |
66 | 69 | if (deviceProfile.getImage() != null) { |
67 | - builder.setImage(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8))); | |
70 | + builder.setImage(getBytesValue(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8)))); | |
68 | 71 | } |
69 | 72 | return builder.build(); |
70 | 73 | } | ... | ... |
... | ... | @@ -25,6 +25,9 @@ import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; |
25 | 25 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
26 | 26 | import org.thingsboard.server.queue.util.TbCoreComponent; |
27 | 27 | |
28 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getInt64Value; | |
29 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
30 | + | |
28 | 31 | @Component |
29 | 32 | @TbCoreComponent |
30 | 33 | public class EntityViewMsgConstructor { |
... | ... | @@ -51,11 +54,11 @@ public class EntityViewMsgConstructor { |
51 | 54 | .setEntityIdLSB(entityView.getEntityId().getId().getLeastSignificantBits()) |
52 | 55 | .setEntityType(entityType); |
53 | 56 | if (customerId != null) { |
54 | - builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); | |
55 | - builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); | |
57 | + builder.setCustomerIdMSB(getInt64Value(customerId.getId().getMostSignificantBits())); | |
58 | + builder.setCustomerIdLSB(getInt64Value(customerId.getId().getLeastSignificantBits())); | |
56 | 59 | } |
57 | 60 | if (entityView.getAdditionalInfo() != null) { |
58 | - builder.setAdditionalInfo(JacksonUtil.toString(entityView.getAdditionalInfo())); | |
61 | + builder.setAdditionalInfo(getStringValue(JacksonUtil.toString(entityView.getAdditionalInfo()))); | |
59 | 62 | } |
60 | 63 | return builder.build(); |
61 | 64 | } | ... | ... |
... | ... | @@ -22,6 +22,8 @@ import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; |
22 | 22 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
23 | 23 | import org.thingsboard.server.queue.util.TbCoreComponent; |
24 | 24 | |
25 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
26 | + | |
25 | 27 | @Component |
26 | 28 | @TbCoreComponent |
27 | 29 | public class RelationMsgConstructor { |
... | ... | @@ -35,10 +37,12 @@ public class RelationMsgConstructor { |
35 | 37 | .setToIdMSB(entityRelation.getTo().getId().getMostSignificantBits()) |
36 | 38 | .setToIdLSB(entityRelation.getTo().getId().getLeastSignificantBits()) |
37 | 39 | .setToEntityType(entityRelation.getTo().getEntityType().name()) |
38 | - .setType(entityRelation.getType()) | |
39 | - .setAdditionalInfo(JacksonUtil.toString(entityRelation.getAdditionalInfo())); | |
40 | + .setType(entityRelation.getType()); | |
41 | + if (entityRelation.getAdditionalInfo() != null) { | |
42 | + builder.setAdditionalInfo(JacksonUtil.toString(entityRelation.getAdditionalInfo())); | |
43 | + } | |
40 | 44 | if (entityRelation.getTypeGroup() != null) { |
41 | - builder.setTypeGroup(entityRelation.getTypeGroup().name()); | |
45 | + builder.setTypeGroup(getStringValue(entityRelation.getTypeGroup().name())); | |
42 | 46 | } |
43 | 47 | return builder.build(); |
44 | 48 | } | ... | ... |
... | ... | @@ -37,6 +37,8 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
37 | 37 | import java.util.ArrayList; |
38 | 38 | import java.util.List; |
39 | 39 | |
40 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getInt64Value; | |
41 | + | |
40 | 42 | @Component |
41 | 43 | @Slf4j |
42 | 44 | @TbCoreComponent |
... | ... | @@ -54,8 +56,8 @@ public class RuleChainMsgConstructor { |
54 | 56 | .setDebugMode(ruleChain.isDebugMode()) |
55 | 57 | .setConfiguration(JacksonUtil.toString(ruleChain.getConfiguration())); |
56 | 58 | if (ruleChain.getFirstRuleNodeId() != null) { |
57 | - builder.setFirstRuleNodeIdMSB(ruleChain.getFirstRuleNodeId().getId().getMostSignificantBits()) | |
58 | - .setFirstRuleNodeIdLSB(ruleChain.getFirstRuleNodeId().getId().getLeastSignificantBits()); | |
59 | + builder.setFirstRuleNodeIdMSB(getInt64Value(ruleChain.getFirstRuleNodeId().getId().getMostSignificantBits())) | |
60 | + .setFirstRuleNodeIdLSB(getInt64Value(ruleChain.getFirstRuleNodeId().getId().getLeastSignificantBits())); | |
59 | 61 | } |
60 | 62 | return builder.build(); |
61 | 63 | } | ... | ... |
... | ... | @@ -16,16 +16,19 @@ |
16 | 16 | package org.thingsboard.server.service.edge.rpc.constructor; |
17 | 17 | |
18 | 18 | import org.springframework.stereotype.Component; |
19 | +import org.thingsboard.common.util.JacksonUtil; | |
19 | 20 | import org.thingsboard.server.common.data.User; |
20 | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | 22 | import org.thingsboard.server.common.data.id.UserId; |
22 | 23 | import org.thingsboard.server.common.data.security.UserCredentials; |
23 | -import org.thingsboard.common.util.JacksonUtil; | |
24 | 24 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
25 | 25 | import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg; |
26 | 26 | import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; |
27 | 27 | import org.thingsboard.server.queue.util.TbCoreComponent; |
28 | 28 | |
29 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getInt64Value; | |
30 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
31 | + | |
29 | 32 | @Component |
30 | 33 | @TbCoreComponent |
31 | 34 | public class UserMsgConstructor { |
... | ... | @@ -38,20 +41,17 @@ public class UserMsgConstructor { |
38 | 41 | .setEmail(user.getEmail()) |
39 | 42 | .setAuthority(user.getAuthority().name()); |
40 | 43 | if (customerId != null) { |
41 | - builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); | |
42 | - builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); | |
44 | + builder.setCustomerIdMSB(getInt64Value(customerId.getId().getMostSignificantBits())); | |
45 | + builder.setCustomerIdLSB(getInt64Value(customerId.getId().getLeastSignificantBits())); | |
43 | 46 | } |
44 | 47 | if (user.getFirstName() != null) { |
45 | - builder.setFirstName(user.getFirstName()); | |
48 | + builder.setFirstName(getStringValue(user.getFirstName())); | |
46 | 49 | } |
47 | 50 | if (user.getLastName() != null) { |
48 | - builder.setLastName(user.getLastName()); | |
49 | - } | |
50 | - if (user.getAdditionalInfo() != null) { | |
51 | - builder.setAdditionalInfo(JacksonUtil.toString(user.getAdditionalInfo())); | |
51 | + builder.setLastName(getStringValue(user.getLastName())); | |
52 | 52 | } |
53 | 53 | if (user.getAdditionalInfo() != null) { |
54 | - builder.setAdditionalInfo(JacksonUtil.toString(user.getAdditionalInfo())); | |
54 | + builder.setAdditionalInfo(getStringValue(JacksonUtil.toString(user.getAdditionalInfo()))); | |
55 | 55 | } |
56 | 56 | return builder.build(); |
57 | 57 | } | ... | ... |
... | ... | @@ -16,14 +16,16 @@ |
16 | 16 | package org.thingsboard.server.service.edge.rpc.constructor; |
17 | 17 | |
18 | 18 | import org.springframework.stereotype.Component; |
19 | +import org.thingsboard.common.util.JacksonUtil; | |
19 | 20 | import org.thingsboard.server.common.data.id.TenantId; |
20 | 21 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
21 | 22 | import org.thingsboard.server.common.data.widget.WidgetType; |
22 | -import org.thingsboard.common.util.JacksonUtil; | |
23 | 23 | import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
24 | 24 | import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg; |
25 | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | |
27 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
28 | + | |
27 | 29 | @Component |
28 | 30 | @TbCoreComponent |
29 | 31 | public class WidgetTypeMsgConstructor { |
... | ... | @@ -33,21 +35,21 @@ public class WidgetTypeMsgConstructor { |
33 | 35 | .setMsgType(msgType) |
34 | 36 | .setIdMSB(widgetType.getId().getId().getMostSignificantBits()) |
35 | 37 | .setIdLSB(widgetType.getId().getId().getLeastSignificantBits()); |
36 | - if (widgetType.getBundleAlias() != null) { | |
37 | - builder.setBundleAlias(widgetType.getBundleAlias()); | |
38 | - } | |
39 | - if (widgetType.getAlias() != null) { | |
40 | - builder.setAlias(widgetType.getAlias()); | |
41 | - } | |
42 | - if (widgetType.getName() != null) { | |
43 | - builder.setName(widgetType.getName()); | |
44 | - } | |
45 | - if (widgetType.getDescriptor() != null) { | |
46 | - builder.setDescriptorJson(JacksonUtil.toString(widgetType.getDescriptor())); | |
47 | - } | |
48 | - if (widgetType.getTenantId().equals(TenantId.SYS_TENANT_ID)) { | |
49 | - builder.setIsSystem(true); | |
50 | - } | |
38 | + if (widgetType.getBundleAlias() != null) { | |
39 | + builder.setBundleAlias(getStringValue(widgetType.getBundleAlias())); | |
40 | + } | |
41 | + if (widgetType.getAlias() != null) { | |
42 | + builder.setAlias(getStringValue(widgetType.getAlias())); | |
43 | + } | |
44 | + if (widgetType.getName() != null) { | |
45 | + builder.setName(getStringValue(widgetType.getName())); | |
46 | + } | |
47 | + if (widgetType.getDescriptor() != null) { | |
48 | + builder.setDescriptorJson(getStringValue(JacksonUtil.toString(widgetType.getDescriptor()))); | |
49 | + } | |
50 | + if (widgetType.getTenantId().equals(TenantId.SYS_TENANT_ID)) { | |
51 | + builder.setIsSystem(true); | |
52 | + } | |
51 | 53 | return builder.build(); |
52 | 54 | } |
53 | 55 | ... | ... |
... | ... | @@ -26,6 +26,9 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | |
27 | 27 | import java.nio.charset.StandardCharsets; |
28 | 28 | |
29 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getBytesValue; | |
30 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
31 | + | |
29 | 32 | @Component |
30 | 33 | @TbCoreComponent |
31 | 34 | public class WidgetsBundleMsgConstructor { |
... | ... | @@ -38,10 +41,10 @@ public class WidgetsBundleMsgConstructor { |
38 | 41 | .setTitle(widgetsBundle.getTitle()) |
39 | 42 | .setAlias(widgetsBundle.getAlias()); |
40 | 43 | if (widgetsBundle.getImage() != null) { |
41 | - builder.setImage(ByteString.copyFrom(widgetsBundle.getImage().getBytes(StandardCharsets.UTF_8))); | |
44 | + builder.setImage(getBytesValue(ByteString.copyFrom(widgetsBundle.getImage().getBytes(StandardCharsets.UTF_8)))); | |
42 | 45 | } |
43 | 46 | if (widgetsBundle.getDescription() != null) { |
44 | - builder.setDescription(widgetsBundle.getDescription()); | |
47 | + builder.setDescription(getStringValue(widgetsBundle.getDescription())); | |
45 | 48 | } |
46 | 49 | if (widgetsBundle.getTenantId().equals(TenantId.SYS_TENANT_ID)) { |
47 | 50 | builder.setIsSystem(true); | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.service.edge.rpc.processor; |
17 | 17 | |
18 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
18 | 19 | import com.google.common.util.concurrent.FutureCallback; |
19 | 20 | import com.google.common.util.concurrent.Futures; |
20 | 21 | import com.google.common.util.concurrent.ListenableFuture; |
... | ... | @@ -54,6 +55,7 @@ public class AlarmEdgeProcessor extends BaseEdgeProcessor { |
54 | 55 | EntityId originatorId = getAlarmOriginator(tenantId, alarmUpdateMsg.getOriginatorName(), |
55 | 56 | EntityType.valueOf(alarmUpdateMsg.getOriginatorType())); |
56 | 57 | if (originatorId == null) { |
58 | + log.warn("Originator not found for the alarm msg {}", alarmUpdateMsg); | |
57 | 59 | return Futures.immediateFuture(null); |
58 | 60 | } |
59 | 61 | try { |
... | ... | @@ -113,59 +115,84 @@ public class AlarmEdgeProcessor extends BaseEdgeProcessor { |
113 | 115 | } |
114 | 116 | } |
115 | 117 | |
116 | - public DownlinkMsg processAlarmToEdge(Edge edge, EdgeEvent edgeEvent, UpdateMsgType msgType) { | |
118 | + public DownlinkMsg processAlarmToEdge(Edge edge, EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | |
119 | + AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); | |
117 | 120 | DownlinkMsg downlinkMsg = null; |
118 | - try { | |
119 | - AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); | |
120 | - Alarm alarm = alarmService.findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); | |
121 | - if (alarm != null) { | |
121 | + switch (action) { | |
122 | + case ADDED: | |
123 | + case UPDATED: | |
124 | + case ALARM_ACK: | |
125 | + case ALARM_CLEAR: | |
126 | + try { | |
127 | + Alarm alarm = alarmService.findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); | |
128 | + if (alarm != null) { | |
129 | + downlinkMsg = DownlinkMsg.newBuilder() | |
130 | + .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) | |
131 | + .addAlarmUpdateMsg(alarmMsgConstructor.constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm)) | |
132 | + .build(); | |
133 | + } | |
134 | + } catch (Exception e) { | |
135 | + log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e); | |
136 | + } | |
137 | + break; | |
138 | + case DELETED: | |
139 | + Alarm alarm = mapper.convertValue(edgeEvent.getBody(), Alarm.class); | |
140 | + AlarmUpdateMsg alarmUpdateMsg = | |
141 | + alarmMsgConstructor.constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm); | |
122 | 142 | downlinkMsg = DownlinkMsg.newBuilder() |
123 | 143 | .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) |
124 | - .addAlarmUpdateMsg(alarmMsgConstructor.constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm)) | |
144 | + .addAlarmUpdateMsg(alarmUpdateMsg) | |
125 | 145 | .build(); |
126 | - } | |
127 | - } catch (Exception e) { | |
128 | - log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e); | |
146 | + break; | |
129 | 147 | } |
130 | 148 | return downlinkMsg; |
131 | 149 | } |
132 | 150 | |
133 | - public void processAlarmNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | |
151 | + public void processAlarmNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException { | |
152 | + EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); | |
134 | 153 | AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); |
135 | - ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId); | |
136 | - Futures.addCallback(alarmFuture, new FutureCallback<Alarm>() { | |
137 | - @Override | |
138 | - public void onSuccess(@Nullable Alarm alarm) { | |
139 | - if (alarm != null) { | |
140 | - EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType()); | |
141 | - if (type != null) { | |
142 | - PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); | |
143 | - PageData<EdgeId> pageData; | |
144 | - do { | |
145 | - pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink); | |
146 | - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | |
147 | - for (EdgeId edgeId : pageData.getData()) { | |
148 | - saveEdgeEvent(tenantId, | |
149 | - edgeId, | |
150 | - EdgeEventType.ALARM, | |
151 | - EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()), | |
152 | - alarmId, | |
153 | - null); | |
154 | - } | |
155 | - if (pageData.hasNext()) { | |
156 | - pageLink = pageLink.nextPageLink(); | |
157 | - } | |
154 | + switch (actionType) { | |
155 | + case DELETED: | |
156 | + EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); | |
157 | + Alarm alarm = mapper.readValue(edgeNotificationMsg.getBody(), Alarm.class); | |
158 | + saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, actionType, alarmId, mapper.valueToTree(alarm)); | |
159 | + break; | |
160 | + default: | |
161 | + ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId); | |
162 | + Futures.addCallback(alarmFuture, new FutureCallback<Alarm>() { | |
163 | + @Override | |
164 | + public void onSuccess(@Nullable Alarm alarm) { | |
165 | + if (alarm != null) { | |
166 | + EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType()); | |
167 | + if (type != null) { | |
168 | + PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); | |
169 | + PageData<EdgeId> pageData; | |
170 | + do { | |
171 | + pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink); | |
172 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | |
173 | + for (EdgeId edgeId : pageData.getData()) { | |
174 | + saveEdgeEvent(tenantId, | |
175 | + edgeId, | |
176 | + EdgeEventType.ALARM, | |
177 | + EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()), | |
178 | + alarmId, | |
179 | + null); | |
180 | + } | |
181 | + if (pageData.hasNext()) { | |
182 | + pageLink = pageLink.nextPageLink(); | |
183 | + } | |
184 | + } | |
185 | + } while (pageData != null && pageData.hasNext()); | |
158 | 186 | } |
159 | - } while (pageData != null && pageData.hasNext()); | |
187 | + } | |
160 | 188 | } |
161 | - } | |
162 | - } | |
163 | 189 | |
164 | - @Override | |
165 | - public void onFailure(Throwable t) { | |
166 | - log.warn("[{}] can't find alarm by id [{}] {}", tenantId.getId(), alarmId.getId(), t); | |
167 | - } | |
168 | - }, dbCallbackExecutorService); | |
190 | + @Override | |
191 | + public void onFailure(Throwable t) { | |
192 | + log.warn("[{}] can't find alarm by id [{}] {}", tenantId.getId(), alarmId.getId(), t); | |
193 | + } | |
194 | + }, dbCallbackExecutorService); | |
195 | + } | |
169 | 196 | } |
170 | 197 | |
171 | 198 | } | ... | ... |
... | ... | @@ -17,11 +17,7 @@ package org.thingsboard.server.service.edge.rpc.processor; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | -import com.google.common.util.concurrent.FutureCallback; | |
21 | -import com.google.common.util.concurrent.Futures; | |
22 | -import com.google.common.util.concurrent.ListenableFuture; | |
23 | 20 | import lombok.extern.slf4j.Slf4j; |
24 | -import org.checkerframework.checker.nullness.qual.Nullable; | |
25 | 21 | import org.springframework.beans.factory.annotation.Autowired; |
26 | 22 | import org.thingsboard.server.common.data.HasCustomerId; |
27 | 23 | import org.thingsboard.server.common.data.edge.Edge; |
... | ... | @@ -66,7 +62,7 @@ import org.thingsboard.server.service.edge.rpc.constructor.WidgetTypeMsgConstruc |
66 | 62 | import org.thingsboard.server.service.edge.rpc.constructor.WidgetsBundleMsgConstructor; |
67 | 63 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
68 | 64 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
69 | -import org.thingsboard.server.service.queue.TbClusterService; | |
65 | +import org.thingsboard.server.cluster.TbClusterService; | |
70 | 66 | import org.thingsboard.server.service.state.DeviceStateService; |
71 | 67 | |
72 | 68 | @Slf4j |
... | ... | @@ -178,12 +174,12 @@ public abstract class BaseEdgeProcessor { |
178 | 174 | @Autowired |
179 | 175 | protected DbCallbackExecutorService dbCallbackExecutorService; |
180 | 176 | |
181 | - protected ListenableFuture<EdgeEvent> saveEdgeEvent(TenantId tenantId, | |
182 | - EdgeId edgeId, | |
183 | - EdgeEventType type, | |
184 | - EdgeEventActionType action, | |
185 | - EntityId entityId, | |
186 | - JsonNode body) { | |
177 | + protected void saveEdgeEvent(TenantId tenantId, | |
178 | + EdgeId edgeId, | |
179 | + EdgeEventType type, | |
180 | + EdgeEventActionType action, | |
181 | + EntityId entityId, | |
182 | + JsonNode body) { | |
187 | 183 | log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], type[{}], " + |
188 | 184 | "action [{}], entityId [{}], body [{}]", |
189 | 185 | tenantId, edgeId, type, action, entityId, body); |
... | ... | @@ -197,19 +193,8 @@ public abstract class BaseEdgeProcessor { |
197 | 193 | edgeEvent.setEntityId(entityId.getId()); |
198 | 194 | } |
199 | 195 | edgeEvent.setBody(body); |
200 | - ListenableFuture<EdgeEvent> future = edgeEventService.saveAsync(edgeEvent); | |
201 | - Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | |
202 | - @Override | |
203 | - public void onSuccess(@Nullable EdgeEvent result) { | |
204 | - tbClusterService.onEdgeEventUpdate(tenantId, edgeId); | |
205 | - } | |
206 | - | |
207 | - @Override | |
208 | - public void onFailure(Throwable t) { | |
209 | - log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | |
210 | - } | |
211 | - }, dbCallbackExecutorService); | |
212 | - return future; | |
196 | + edgeEventService.save(edgeEvent); | |
197 | + tbClusterService.onEdgeEventUpdate(tenantId, edgeId); | |
213 | 198 | } |
214 | 199 | |
215 | 200 | protected CustomerId getCustomerIdIfEdgeAssignedToCustomer(HasCustomerId hasCustomerIdEntity, Edge edge) { | ... | ... |
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java
... | ... | @@ -18,7 +18,6 @@ package org.thingsboard.server.service.edge.rpc.processor; |
18 | 18 | import com.datastax.oss.driver.api.core.uuid.Uuids; |
19 | 19 | import com.fasterxml.jackson.core.JsonProcessingException; |
20 | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
21 | -import com.google.common.util.concurrent.FutureCallback; | |
22 | 21 | import com.google.common.util.concurrent.Futures; |
23 | 22 | import com.google.common.util.concurrent.ListenableFuture; |
24 | 23 | import com.google.common.util.concurrent.SettableFuture; |
... | ... | @@ -27,7 +26,7 @@ import org.apache.commons.lang3.RandomStringUtils; |
27 | 26 | import org.apache.commons.lang3.StringUtils; |
28 | 27 | import org.springframework.stereotype.Component; |
29 | 28 | import org.thingsboard.common.util.JacksonUtil; |
30 | -import org.thingsboard.rule.engine.api.RpcError; | |
29 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
31 | 30 | import org.thingsboard.server.common.data.Customer; |
32 | 31 | import org.thingsboard.server.common.data.DataConstants; |
33 | 32 | import org.thingsboard.server.common.data.Device; |
... | ... | @@ -60,7 +59,7 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
60 | 59 | import org.thingsboard.server.queue.TbQueueCallback; |
61 | 60 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
62 | 61 | import org.thingsboard.server.queue.util.TbCoreComponent; |
63 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
62 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
64 | 63 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg; |
65 | 64 | |
66 | 65 | import java.util.UUID; |
... | ... | @@ -105,19 +104,8 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor { |
105 | 104 | Device newDevice = createDevice(tenantId, edge, deviceUpdateMsg, newDeviceName); |
106 | 105 | ObjectNode body = mapper.createObjectNode(); |
107 | 106 | body.put("conflictName", deviceName); |
108 | - ListenableFuture<EdgeEvent> future = | |
109 | - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, newDevice.getId(), body); | |
110 | - Futures.addCallback(future, new FutureCallback<>() { | |
111 | - @Override | |
112 | - public void onSuccess(EdgeEvent edgeEvent) { | |
113 | - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, newDevice.getId(), null); | |
114 | - } | |
115 | - | |
116 | - @Override | |
117 | - public void onFailure(Throwable t) { | |
118 | - log.error("[{}] Failed to save ENTITY_MERGE_REQUEST edge event [{}][{}]", tenantId, deviceUpdateMsg, edge.getId(), t); | |
119 | - } | |
120 | - }, dbCallbackExecutorService); | |
107 | + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, newDevice.getId(), body); | |
108 | + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, newDevice.getId(), null); | |
121 | 109 | } |
122 | 110 | } while (pageData != null && pageData.hasNext()); |
123 | 111 | } else { |
... | ... | @@ -155,7 +143,9 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor { |
155 | 143 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, device.getId()); |
156 | 144 | deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType())); |
157 | 145 | deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId()); |
158 | - deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue()); | |
146 | + if (deviceCredentialsUpdateMsg.hasCredentialsValue()) { | |
147 | + deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue().getValue()); | |
148 | + } | |
159 | 149 | deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials); |
160 | 150 | } catch (Exception e) { |
161 | 151 | log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); |
... | ... | @@ -173,14 +163,20 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor { |
173 | 163 | if (device != null) { |
174 | 164 | device.setName(deviceUpdateMsg.getName()); |
175 | 165 | device.setType(deviceUpdateMsg.getType()); |
176 | - device.setLabel(deviceUpdateMsg.getLabel()); | |
177 | - device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); | |
178 | - if (deviceUpdateMsg.getDeviceProfileIdMSB() != 0 && deviceUpdateMsg.getDeviceProfileIdLSB() != 0) { | |
166 | + if (deviceUpdateMsg.hasLabel()) { | |
167 | + device.setLabel(deviceUpdateMsg.getLabel().getValue()); | |
168 | + } | |
169 | + if (deviceUpdateMsg.hasAdditionalInfo()) { | |
170 | + device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo().getValue())); | |
171 | + } | |
172 | + if (deviceUpdateMsg.hasDeviceProfileIdMSB() && deviceUpdateMsg.hasDeviceProfileIdLSB()) { | |
179 | 173 | DeviceProfileId deviceProfileId = new DeviceProfileId( |
180 | - new UUID(deviceUpdateMsg.getDeviceProfileIdMSB(), deviceUpdateMsg.getDeviceProfileIdLSB())); | |
174 | + new UUID(deviceUpdateMsg.getDeviceProfileIdMSB().getValue(), | |
175 | + deviceUpdateMsg.getDeviceProfileIdLSB().getValue())); | |
181 | 176 | device.setDeviceProfileId(deviceProfileId); |
182 | 177 | } |
183 | - deviceService.saveDevice(device); | |
178 | + Device savedDevice = deviceService.saveDevice(device); | |
179 | + tbClusterService.onDeviceUpdated(savedDevice, device); | |
184 | 180 | saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null); |
185 | 181 | } else { |
186 | 182 | log.warn("[{}] can't find device [{}], edge [{}]", tenantId, deviceUpdateMsg, edge.getId()); |
... | ... | @@ -206,22 +202,26 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor { |
206 | 202 | device.setCustomerId(getCustomerId(edge)); |
207 | 203 | device.setName(deviceName); |
208 | 204 | device.setType(deviceUpdateMsg.getType()); |
209 | - device.setLabel(deviceUpdateMsg.getLabel()); | |
210 | - device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); | |
211 | - if (deviceUpdateMsg.getDeviceProfileIdMSB() != 0 && deviceUpdateMsg.getDeviceProfileIdLSB() != 0) { | |
205 | + if (deviceUpdateMsg.hasLabel()) { | |
206 | + device.setLabel(deviceUpdateMsg.getLabel().getValue()); | |
207 | + } | |
208 | + if (deviceUpdateMsg.hasAdditionalInfo()) { | |
209 | + device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo().getValue())); | |
210 | + } | |
211 | + if (deviceUpdateMsg.hasDeviceProfileIdMSB() && deviceUpdateMsg.hasDeviceProfileIdLSB()) { | |
212 | 212 | DeviceProfileId deviceProfileId = new DeviceProfileId( |
213 | - new UUID(deviceUpdateMsg.getDeviceProfileIdMSB(), deviceUpdateMsg.getDeviceProfileIdLSB())); | |
213 | + new UUID(deviceUpdateMsg.getDeviceProfileIdMSB().getValue(), | |
214 | + deviceUpdateMsg.getDeviceProfileIdLSB().getValue())); | |
214 | 215 | device.setDeviceProfileId(deviceProfileId); |
215 | 216 | } |
216 | 217 | Device savedDevice = deviceService.saveDevice(device, false); |
218 | + tbClusterService.onDeviceUpdated(savedDevice, device); | |
217 | 219 | if (created) { |
218 | 220 | DeviceCredentials deviceCredentials = new DeviceCredentials(); |
219 | 221 | deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId())); |
220 | 222 | deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); |
221 | 223 | deviceCredentials.setCredentialsId(org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric(20)); |
222 | 224 | deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials); |
223 | - | |
224 | - deviceStateService.onDeviceAdded(savedDevice); | |
225 | 225 | } |
226 | 226 | createRelationFromEdge(tenantId, edge.getId(), device.getId()); |
227 | 227 | pushDeviceCreatedEventToRuleEngine(tenantId, edge, device); | ... | ... |
... | ... | @@ -72,7 +72,9 @@ public class RelationEdgeProcessor extends BaseEdgeProcessor { |
72 | 72 | entityRelation.setTo(toId); |
73 | 73 | |
74 | 74 | entityRelation.setType(relationUpdateMsg.getType()); |
75 | - entityRelation.setTypeGroup(RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup())); | |
75 | + if (relationUpdateMsg.hasTypeGroup()) { | |
76 | + entityRelation.setTypeGroup(RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup().getValue())); | |
77 | + } | |
76 | 78 | entityRelation.setAdditionalInfo(mapper.readTree(relationUpdateMsg.getAdditionalInfo())); |
77 | 79 | switch (relationUpdateMsg.getMsgType()) { |
78 | 80 | case ENTITY_CREATED_RPC_MESSAGE: | ... | ... |
... | ... | @@ -73,7 +73,7 @@ import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg; |
73 | 73 | import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg; |
74 | 74 | import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; |
75 | 75 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
76 | -import org.thingsboard.server.service.queue.TbClusterService; | |
76 | +import org.thingsboard.server.cluster.TbClusterService; | |
77 | 77 | |
78 | 78 | import java.util.ArrayList; |
79 | 79 | import java.util.HashMap; |
... | ... | @@ -122,26 +122,13 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
122 | 122 | @Override |
123 | 123 | public ListenableFuture<Void> processRuleChainMetadataRequestMsg(TenantId tenantId, Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) { |
124 | 124 | log.trace("[{}] processRuleChainMetadataRequestMsg [{}][{}]", tenantId, edge.getName(), ruleChainMetadataRequestMsg); |
125 | - SettableFuture<Void> futureToSet = SettableFuture.create(); | |
126 | 125 | if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { |
127 | 126 | RuleChainId ruleChainId = |
128 | 127 | new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); |
129 | - ListenableFuture<EdgeEvent> future = saveEdgeEvent(tenantId, edge.getId(), | |
128 | + saveEdgeEvent(tenantId, edge.getId(), | |
130 | 129 | EdgeEventType.RULE_CHAIN_METADATA, EdgeEventActionType.ADDED, ruleChainId, null); |
131 | - Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | |
132 | - @Override | |
133 | - public void onSuccess(@Nullable EdgeEvent result) { | |
134 | - futureToSet.set(null); | |
135 | - } | |
136 | - | |
137 | - @Override | |
138 | - public void onFailure(Throwable t) { | |
139 | - log.error("Can't save edge event [{}]", ruleChainMetadataRequestMsg, t); | |
140 | - futureToSet.setException(t); | |
141 | - } | |
142 | - }, dbCallbackExecutorService); | |
143 | 130 | } |
144 | - return futureToSet; | |
131 | + return Futures.immediateFuture(null); | |
145 | 132 | } |
146 | 133 | |
147 | 134 | @Override |
... | ... | @@ -154,8 +141,8 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
154 | 141 | if (type != null) { |
155 | 142 | SettableFuture<Void> futureToSet = SettableFuture.create(); |
156 | 143 | String scope = attributesRequestMsg.getScope(); |
157 | - ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = attributesService.findAll(tenantId, entityId, scope); | |
158 | - Futures.addCallback(ssAttrFuture, new FutureCallback<List<AttributeKvEntry>>() { | |
144 | + ListenableFuture<List<AttributeKvEntry>> findAttrFuture = attributesService.findAll(tenantId, entityId, scope); | |
145 | + Futures.addCallback(findAttrFuture, new FutureCallback<List<AttributeKvEntry>>() { | |
159 | 146 | @Override |
160 | 147 | public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) { |
161 | 148 | if (ssAttributes != null && !ssAttributes.isEmpty()) { |
... | ... | @@ -184,8 +171,9 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
184 | 171 | entityId, |
185 | 172 | body); |
186 | 173 | } catch (Exception e) { |
187 | - log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); | |
188 | - throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); | |
174 | + log.error("[{}] Failed to save attribute updates to the edge", edge.getName(), e); | |
175 | + futureToSet.setException(new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e)); | |
176 | + return; | |
189 | 177 | } |
190 | 178 | } else { |
191 | 179 | log.trace("[{}][{}] No attributes found for entity {} [{}]", tenantId, |
... | ... | @@ -198,7 +186,7 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
198 | 186 | |
199 | 187 | @Override |
200 | 188 | public void onFailure(Throwable t) { |
201 | - log.error("Can't save attributes [{}]", attributesRequestMsg, t); | |
189 | + log.error("Can't find attributes [{}]", attributesRequestMsg, t); | |
202 | 190 | futureToSet.setException(t); |
203 | 191 | } |
204 | 192 | }, dbCallbackExecutorService); |
... | ... | @@ -273,82 +261,39 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
273 | 261 | @Override |
274 | 262 | public ListenableFuture<Void> processDeviceCredentialsRequestMsg(TenantId tenantId, Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { |
275 | 263 | log.trace("[{}] processDeviceCredentialsRequestMsg [{}][{}]", tenantId, edge.getName(), deviceCredentialsRequestMsg); |
276 | - SettableFuture<Void> futureToSet = SettableFuture.create(); | |
277 | 264 | if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) { |
278 | 265 | DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); |
279 | - ListenableFuture<EdgeEvent> future = saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, | |
266 | + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, | |
280 | 267 | EdgeEventActionType.CREDENTIALS_UPDATED, deviceId, null); |
281 | - Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | |
282 | - @Override | |
283 | - public void onSuccess(@Nullable EdgeEvent result) { | |
284 | - futureToSet.set(null); | |
285 | - } | |
286 | - | |
287 | - @Override | |
288 | - public void onFailure(Throwable t) { | |
289 | - log.error("Can't save edge event [{}]", deviceCredentialsRequestMsg, t); | |
290 | - futureToSet.setException(t); | |
291 | - } | |
292 | - }, dbCallbackExecutorService); | |
293 | 268 | } |
294 | - return futureToSet; | |
269 | + return Futures.immediateFuture(null); | |
295 | 270 | } |
296 | 271 | |
297 | 272 | @Override |
298 | 273 | public ListenableFuture<Void> processUserCredentialsRequestMsg(TenantId tenantId, Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { |
299 | 274 | log.trace("[{}] processUserCredentialsRequestMsg [{}][{}]", tenantId, edge.getName(), userCredentialsRequestMsg); |
300 | - SettableFuture<Void> futureToSet = SettableFuture.create(); | |
301 | 275 | if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) { |
302 | 276 | UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); |
303 | - ListenableFuture<EdgeEvent> future = saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.USER, | |
277 | + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.USER, | |
304 | 278 | EdgeEventActionType.CREDENTIALS_UPDATED, userId, null); |
305 | - Futures.addCallback(future, new FutureCallback<>() { | |
306 | - @Override | |
307 | - public void onSuccess(@Nullable EdgeEvent result) { | |
308 | - futureToSet.set(null); | |
309 | - } | |
310 | - | |
311 | - @Override | |
312 | - public void onFailure(Throwable t) { | |
313 | - log.error("Can't save edge event [{}]", userCredentialsRequestMsg, t); | |
314 | - futureToSet.setException(t); | |
315 | - } | |
316 | - }, dbCallbackExecutorService); | |
317 | 279 | } |
318 | - return futureToSet; | |
280 | + return Futures.immediateFuture(null); | |
319 | 281 | } |
320 | 282 | |
321 | 283 | @Override |
322 | 284 | public ListenableFuture<Void> processDeviceProfileDevicesRequestMsg(TenantId tenantId, Edge edge, DeviceProfileDevicesRequestMsg deviceProfileDevicesRequestMsg) { |
323 | 285 | log.trace("[{}] processDeviceProfileDevicesRequestMsg [{}][{}]", tenantId, edge.getName(), deviceProfileDevicesRequestMsg); |
324 | - SettableFuture<Void> futureToSet = SettableFuture.create(); | |
325 | 286 | if (deviceProfileDevicesRequestMsg.getDeviceProfileIdMSB() != 0 && deviceProfileDevicesRequestMsg.getDeviceProfileIdLSB() != 0) { |
326 | 287 | DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(deviceProfileDevicesRequestMsg.getDeviceProfileIdMSB(), deviceProfileDevicesRequestMsg.getDeviceProfileIdLSB())); |
327 | 288 | DeviceProfile deviceProfileById = deviceProfileService.findDeviceProfileById(tenantId, deviceProfileId); |
328 | - List<ListenableFuture<EdgeEvent>> futures; | |
329 | 289 | if (deviceProfileById != null) { |
330 | - futures = syncDevices(tenantId, edge, deviceProfileById.getName()); | |
331 | - } else { | |
332 | - futures = new ArrayList<>(); | |
290 | + syncDevices(tenantId, edge, deviceProfileById.getName()); | |
333 | 291 | } |
334 | - Futures.addCallback(Futures.allAsList(futures), new FutureCallback<>() { | |
335 | - @Override | |
336 | - public void onSuccess(@Nullable List<EdgeEvent> result) { | |
337 | - futureToSet.set(null); | |
338 | - } | |
339 | - | |
340 | - @Override | |
341 | - public void onFailure(Throwable t) { | |
342 | - log.error("Can't sync devices by device profile [{}]", deviceProfileDevicesRequestMsg, t); | |
343 | - futureToSet.setException(t); | |
344 | - } | |
345 | - }, dbCallbackExecutorService); | |
346 | 292 | } |
347 | - return futureToSet; | |
293 | + return Futures.immediateFuture(null); | |
348 | 294 | } |
349 | 295 | |
350 | - private List<ListenableFuture<EdgeEvent>> syncDevices(TenantId tenantId, Edge edge, String deviceType) { | |
351 | - List<ListenableFuture<EdgeEvent>> futures = new ArrayList<>(); | |
296 | + private void syncDevices(TenantId tenantId, Edge edge, String deviceType) { | |
352 | 297 | log.trace("[{}] syncDevices [{}][{}]", tenantId, edge.getName(), deviceType); |
353 | 298 | try { |
354 | 299 | PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); |
... | ... | @@ -358,7 +303,7 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
358 | 303 | if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { |
359 | 304 | log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); |
360 | 305 | for (Device device : pageData.getData()) { |
361 | - futures.add(saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ADDED, device.getId(), null)); | |
306 | + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ADDED, device.getId(), null); | |
362 | 307 | } |
363 | 308 | if (pageData.hasNext()) { |
364 | 309 | pageLink = pageLink.nextPageLink(); |
... | ... | @@ -368,40 +313,25 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
368 | 313 | } catch (Exception e) { |
369 | 314 | log.error("Exception during loading edge device(s) on sync!", e); |
370 | 315 | } |
371 | - return futures; | |
372 | 316 | } |
373 | 317 | |
374 | 318 | @Override |
375 | 319 | public ListenableFuture<Void> processWidgetBundleTypesRequestMsg(TenantId tenantId, Edge edge, |
376 | 320 | WidgetBundleTypesRequestMsg widgetBundleTypesRequestMsg) { |
377 | 321 | log.trace("[{}] processWidgetBundleTypesRequestMsg [{}][{}]", tenantId, edge.getName(), widgetBundleTypesRequestMsg); |
378 | - SettableFuture<Void> futureToSet = SettableFuture.create(); | |
379 | 322 | if (widgetBundleTypesRequestMsg.getWidgetBundleIdMSB() != 0 && widgetBundleTypesRequestMsg.getWidgetBundleIdLSB() != 0) { |
380 | 323 | WidgetsBundleId widgetsBundleId = new WidgetsBundleId(new UUID(widgetBundleTypesRequestMsg.getWidgetBundleIdMSB(), widgetBundleTypesRequestMsg.getWidgetBundleIdLSB())); |
381 | 324 | WidgetsBundle widgetsBundleById = widgetsBundleService.findWidgetsBundleById(tenantId, widgetsBundleId); |
382 | - List<ListenableFuture<EdgeEvent>> futures = new ArrayList<>(); | |
383 | 325 | if (widgetsBundleById != null) { |
384 | 326 | List<WidgetType> widgetTypesToPush = |
385 | 327 | widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(widgetsBundleById.getTenantId(), widgetsBundleById.getAlias()); |
386 | 328 | |
387 | 329 | for (WidgetType widgetType : widgetTypesToPush) { |
388 | - futures.add(saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.WIDGET_TYPE, EdgeEventActionType.ADDED, widgetType.getId(), null)); | |
330 | + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.WIDGET_TYPE, EdgeEventActionType.ADDED, widgetType.getId(), null); | |
389 | 331 | } |
390 | 332 | } |
391 | - Futures.addCallback(Futures.allAsList(futures), new FutureCallback<>() { | |
392 | - @Override | |
393 | - public void onSuccess(@Nullable List<EdgeEvent> result) { | |
394 | - futureToSet.set(null); | |
395 | - } | |
396 | - | |
397 | - @Override | |
398 | - public void onFailure(Throwable t) { | |
399 | - log.error("Can't sync widget types by widget bundle [{}]", widgetBundleTypesRequestMsg, t); | |
400 | - futureToSet.setException(t); | |
401 | - } | |
402 | - }, dbCallbackExecutorService); | |
403 | 333 | } |
404 | - return futureToSet; | |
334 | + return Futures.immediateFuture(null); | |
405 | 335 | } |
406 | 336 | |
407 | 337 | @Override |
... | ... | @@ -416,9 +346,12 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
416 | 346 | public void onSuccess(@Nullable List<EntityView> entityViews) { |
417 | 347 | try { |
418 | 348 | if (entityViews != null && !entityViews.isEmpty()) { |
349 | + List<ListenableFuture<Boolean>> futures = new ArrayList<>(); | |
419 | 350 | for (EntityView entityView : entityViews) { |
420 | - Futures.addCallback(relationService.checkRelation(tenantId, edge.getId(), entityView.getId(), | |
421 | - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE), new FutureCallback<>() { | |
351 | + ListenableFuture<Boolean> future = relationService.checkRelation(tenantId, edge.getId(), entityView.getId(), | |
352 | + EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); | |
353 | + futures.add(future); | |
354 | + Futures.addCallback(future, new FutureCallback<>() { | |
422 | 355 | @Override |
423 | 356 | public void onSuccess(@Nullable Boolean result) { |
424 | 357 | if (Boolean.TRUE.equals(result)) { |
... | ... | @@ -426,16 +359,27 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
426 | 359 | EdgeEventActionType.ADDED, entityView.getId(), null); |
427 | 360 | } |
428 | 361 | } |
429 | - | |
430 | 362 | @Override |
431 | 363 | public void onFailure(Throwable t) { |
432 | - log.error("Exception during loading relation [{}] to edge on sync!", t, t); | |
433 | - futureToSet.setException(t); | |
364 | + // Do nothing - error handles in allAsList | |
434 | 365 | } |
435 | 366 | }, dbCallbackExecutorService); |
436 | 367 | } |
368 | + Futures.addCallback(Futures.allAsList(futures), new FutureCallback<>() { | |
369 | + @Override | |
370 | + public void onSuccess(@Nullable List<Boolean> result) { | |
371 | + futureToSet.set(null); | |
372 | + } | |
373 | + | |
374 | + @Override | |
375 | + public void onFailure(Throwable t) { | |
376 | + log.error("Exception during loading relation [{}] to edge on sync!", t, t); | |
377 | + futureToSet.setException(t); | |
378 | + } | |
379 | + }, dbCallbackExecutorService); | |
380 | + } else { | |
381 | + futureToSet.set(null); | |
437 | 382 | } |
438 | - futureToSet.set(null); | |
439 | 383 | } catch (Exception e) { |
440 | 384 | log.error("Exception during loading relation(s) to edge on sync!", e); |
441 | 385 | futureToSet.setException(e); |
... | ... | @@ -451,30 +395,19 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { |
451 | 395 | return futureToSet; |
452 | 396 | } |
453 | 397 | |
454 | - private ListenableFuture<EdgeEvent> saveEdgeEvent(TenantId tenantId, | |
455 | - EdgeId edgeId, | |
456 | - EdgeEventType type, | |
457 | - EdgeEventActionType action, | |
458 | - EntityId entityId, | |
459 | - JsonNode body) { | |
398 | + private void saveEdgeEvent(TenantId tenantId, | |
399 | + EdgeId edgeId, | |
400 | + EdgeEventType type, | |
401 | + EdgeEventActionType action, | |
402 | + EntityId entityId, | |
403 | + JsonNode body) { | |
460 | 404 | log.trace("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], type [{}], action[{}], entityId [{}], body [{}]", |
461 | 405 | tenantId, edgeId, type, action, entityId, body); |
462 | 406 | |
463 | 407 | EdgeEvent edgeEvent = EdgeEventUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body); |
464 | 408 | |
465 | - ListenableFuture<EdgeEvent> future = edgeEventService.saveAsync(edgeEvent); | |
466 | - Futures.addCallback(future, new FutureCallback<>() { | |
467 | - @Override | |
468 | - public void onSuccess(@Nullable EdgeEvent result) { | |
469 | - tbClusterService.onEdgeEventUpdate(tenantId, edgeId); | |
470 | - } | |
471 | - | |
472 | - @Override | |
473 | - public void onFailure(Throwable t) { | |
474 | - log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | |
475 | - } | |
476 | - }, dbCallbackExecutorService); | |
477 | - return future; | |
409 | + edgeEventService.save(edgeEvent); | |
410 | + tbClusterService.onEdgeEventUpdate(tenantId, edgeId); | |
478 | 411 | } |
479 | 412 | |
480 | 413 | } | ... | ... |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
... | ... | @@ -215,6 +215,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { |
215 | 215 | node.put("password", ""); |
216 | 216 | node.put("tlsVersion", "TLSv1.2");//NOSONAR, key used to identify password field (not password value itself) |
217 | 217 | node.put("enableProxy", false); |
218 | + node.put("showChangePassword", false); | |
218 | 219 | mailSettings.setJsonValue(node); |
219 | 220 | adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, mailSettings); |
220 | 221 | } |
... | ... | @@ -480,6 +481,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { |
480 | 481 | device.setAdditionalInfo(additionalInfo); |
481 | 482 | } |
482 | 483 | device = deviceService.saveDevice(device); |
484 | + //TODO: No access to cluster service, so we should manually update the status of device. | |
483 | 485 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, device.getId()); |
484 | 486 | deviceCredentials.setCredentialsId(accessToken); |
485 | 487 | deviceCredentialsService.updateDeviceCredentials(TenantId.SYS_TENANT_ID, deviceCredentials); | ... | ... |
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.service.ota; |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.FutureCallback; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.springframework.context.annotation.Lazy; | |
20 | 21 | import org.springframework.stereotype.Service; |
21 | 22 | import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; |
22 | 23 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
... | ... | @@ -49,7 +50,7 @@ import org.thingsboard.server.queue.TbQueueProducer; |
49 | 50 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
50 | 51 | import org.thingsboard.server.queue.provider.TbCoreQueueFactory; |
51 | 52 | import org.thingsboard.server.queue.util.TbCoreComponent; |
52 | -import org.thingsboard.server.service.queue.TbClusterService; | |
53 | +import org.thingsboard.server.cluster.TbClusterService; | |
53 | 54 | |
54 | 55 | import javax.annotation.Nullable; |
55 | 56 | import java.util.ArrayList; |
... | ... | @@ -87,10 +88,11 @@ public class DefaultOtaPackageStateService implements OtaPackageStateService { |
87 | 88 | private final RuleEngineTelemetryService telemetryService; |
88 | 89 | private final TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> otaPackageStateMsgProducer; |
89 | 90 | |
90 | - public DefaultOtaPackageStateService(TbClusterService tbClusterService, OtaPackageService otaPackageService, | |
91 | + public DefaultOtaPackageStateService(@Lazy TbClusterService tbClusterService, | |
92 | + OtaPackageService otaPackageService, | |
91 | 93 | DeviceService deviceService, |
92 | 94 | DeviceProfileService deviceProfileService, |
93 | - RuleEngineTelemetryService telemetryService, | |
95 | + @Lazy RuleEngineTelemetryService telemetryService, | |
94 | 96 | TbCoreQueueFactory coreQueueFactory) { |
95 | 97 | this.tbClusterService = tbClusterService; |
96 | 98 | this.otaPackageService = otaPackageService; | ... | ... |
... | ... | @@ -16,11 +16,17 @@ |
16 | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | |
18 | 18 | import com.google.protobuf.ByteString; |
19 | +import lombok.RequiredArgsConstructor; | |
19 | 20 | import lombok.extern.slf4j.Slf4j; |
20 | 21 | import org.springframework.beans.factory.annotation.Value; |
21 | 22 | import org.springframework.scheduling.annotation.Scheduled; |
22 | 23 | import org.springframework.stereotype.Service; |
23 | -import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; | |
24 | +import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | |
25 | +import org.thingsboard.server.cluster.TbClusterService; | |
26 | +import org.thingsboard.server.common.data.EdgeUtils; | |
27 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | |
28 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | |
29 | +import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; | |
24 | 30 | import org.thingsboard.server.common.data.ApiUsageState; |
25 | 31 | import org.thingsboard.server.common.data.Device; |
26 | 32 | import org.thingsboard.server.common.data.DeviceProfile; |
... | ... | @@ -29,7 +35,6 @@ import org.thingsboard.server.common.data.HasName; |
29 | 35 | import org.thingsboard.server.common.data.TbResource; |
30 | 36 | import org.thingsboard.server.common.data.Tenant; |
31 | 37 | import org.thingsboard.server.common.data.TenantProfile; |
32 | -import org.thingsboard.server.common.data.id.CustomerId; | |
33 | 38 | import org.thingsboard.server.common.data.id.DeviceId; |
34 | 39 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
35 | 40 | import org.thingsboard.server.common.data.id.EdgeId; |
... | ... | @@ -56,8 +61,9 @@ import org.thingsboard.server.queue.common.MultipleTbQueueCallbackWrapper; |
56 | 61 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
57 | 62 | import org.thingsboard.server.queue.discovery.PartitionService; |
58 | 63 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
64 | +import org.thingsboard.server.service.ota.OtaPackageStateService; | |
59 | 65 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
60 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
66 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
61 | 67 | |
62 | 68 | import java.util.HashSet; |
63 | 69 | import java.util.Set; |
... | ... | @@ -66,10 +72,13 @@ import java.util.concurrent.atomic.AtomicInteger; |
66 | 72 | |
67 | 73 | @Service |
68 | 74 | @Slf4j |
75 | +@RequiredArgsConstructor | |
69 | 76 | public class DefaultTbClusterService implements TbClusterService { |
70 | 77 | |
71 | 78 | @Value("${cluster.stats.enabled:false}") |
72 | 79 | private boolean statsEnabled; |
80 | + @Value("${edges.enabled}") | |
81 | + protected boolean edgesEnabled; | |
73 | 82 | |
74 | 83 | private final AtomicInteger toCoreMsgs = new AtomicInteger(0); |
75 | 84 | private final AtomicInteger toCoreNfs = new AtomicInteger(0); |
... | ... | @@ -81,13 +90,7 @@ public class DefaultTbClusterService implements TbClusterService { |
81 | 90 | private final PartitionService partitionService; |
82 | 91 | private final DataDecodingEncodingService encodingService; |
83 | 92 | private final TbDeviceProfileCache deviceProfileCache; |
84 | - | |
85 | - public DefaultTbClusterService(TbQueueProducerProvider producerProvider, PartitionService partitionService, DataDecodingEncodingService encodingService, TbDeviceProfileCache deviceProfileCache) { | |
86 | - this.producerProvider = producerProvider; | |
87 | - this.partitionService = partitionService; | |
88 | - this.encodingService = encodingService; | |
89 | - this.deviceProfileCache = deviceProfileCache; | |
90 | - } | |
93 | + private final OtaPackageStateService otaPackageStateService; | |
91 | 94 | |
92 | 95 | @Override |
93 | 96 | public void pushMsgToCore(TenantId tenantId, EntityId entityId, ToCoreMsg msg, TbQueueCallback callback) { |
... | ... | @@ -200,55 +203,52 @@ public class DefaultTbClusterService implements TbClusterService { |
200 | 203 | } |
201 | 204 | |
202 | 205 | @Override |
203 | - public void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state) { | |
206 | + public void broadcastEntityStateChangeEvent(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state) { | |
204 | 207 | log.trace("[{}] Processing {} state change event: {}", tenantId, entityId.getEntityType(), state); |
205 | 208 | broadcast(new ComponentLifecycleMsg(tenantId, entityId, state)); |
206 | 209 | } |
207 | 210 | |
208 | 211 | @Override |
209 | 212 | public void onDeviceProfileChange(DeviceProfile deviceProfile, TbQueueCallback callback) { |
210 | - onEntityChange(deviceProfile.getTenantId(), deviceProfile.getId(), deviceProfile, callback); | |
213 | + broadcastEntityChangeToTransport(deviceProfile.getTenantId(), deviceProfile.getId(), deviceProfile, callback); | |
211 | 214 | } |
212 | 215 | |
213 | 216 | @Override |
214 | 217 | public void onTenantProfileChange(TenantProfile tenantProfile, TbQueueCallback callback) { |
215 | - onEntityChange(TenantId.SYS_TENANT_ID, tenantProfile.getId(), tenantProfile, callback); | |
218 | + broadcastEntityChangeToTransport(TenantId.SYS_TENANT_ID, tenantProfile.getId(), tenantProfile, callback); | |
216 | 219 | } |
217 | 220 | |
218 | 221 | @Override |
219 | 222 | public void onTenantChange(Tenant tenant, TbQueueCallback callback) { |
220 | - onEntityChange(TenantId.SYS_TENANT_ID, tenant.getId(), tenant, callback); | |
223 | + broadcastEntityChangeToTransport(TenantId.SYS_TENANT_ID, tenant.getId(), tenant, callback); | |
221 | 224 | } |
222 | 225 | |
223 | 226 | @Override |
224 | 227 | public void onApiStateChange(ApiUsageState apiUsageState, TbQueueCallback callback) { |
225 | - onEntityChange(apiUsageState.getTenantId(), apiUsageState.getId(), apiUsageState, callback); | |
228 | + broadcastEntityChangeToTransport(apiUsageState.getTenantId(), apiUsageState.getId(), apiUsageState, callback); | |
226 | 229 | broadcast(new ComponentLifecycleMsg(apiUsageState.getTenantId(), apiUsageState.getId(), ComponentLifecycleEvent.UPDATED)); |
227 | 230 | } |
228 | 231 | |
229 | 232 | @Override |
230 | 233 | public void onDeviceProfileDelete(DeviceProfile entity, TbQueueCallback callback) { |
231 | - onEntityDelete(entity.getTenantId(), entity.getId(), entity.getName(), callback); | |
234 | + broadcastEntityDeleteToTransport(entity.getTenantId(), entity.getId(), entity.getName(), callback); | |
232 | 235 | } |
233 | 236 | |
234 | 237 | @Override |
235 | 238 | public void onTenantProfileDelete(TenantProfile entity, TbQueueCallback callback) { |
236 | - onEntityDelete(TenantId.SYS_TENANT_ID, entity.getId(), entity.getName(), callback); | |
239 | + broadcastEntityDeleteToTransport(TenantId.SYS_TENANT_ID, entity.getId(), entity.getName(), callback); | |
237 | 240 | } |
238 | 241 | |
239 | 242 | @Override |
240 | 243 | public void onTenantDelete(Tenant entity, TbQueueCallback callback) { |
241 | - onEntityDelete(TenantId.SYS_TENANT_ID, entity.getId(), entity.getName(), callback); | |
244 | + broadcastEntityDeleteToTransport(TenantId.SYS_TENANT_ID, entity.getId(), entity.getName(), callback); | |
242 | 245 | } |
243 | 246 | |
244 | 247 | @Override |
245 | - public void onDeviceChange(Device entity, TbQueueCallback callback) { | |
246 | - onEntityChange(entity.getTenantId(), entity.getId(), entity, callback); | |
247 | - } | |
248 | - | |
249 | - @Override | |
250 | - public void onDeviceDeleted(Device entity, TbQueueCallback callback) { | |
251 | - onEntityDelete(entity.getTenantId(), entity.getId(), entity.getName(), callback); | |
248 | + public void onDeviceDeleted(Device device, TbQueueCallback callback) { | |
249 | + broadcastEntityDeleteToTransport(device.getTenantId(), device.getId(), device.getName(), callback); | |
250 | + sendDeviceStateServiceEvent(device.getTenantId(), device.getId(), false, false, true); | |
251 | + broadcastEntityStateChangeEvent(device.getTenantId(), device.getId(), ComponentLifecycleEvent.DELETED); | |
252 | 252 | } |
253 | 253 | |
254 | 254 | @Override |
... | ... | @@ -278,7 +278,7 @@ public class DefaultTbClusterService implements TbClusterService { |
278 | 278 | broadcast(transportMsg, callback); |
279 | 279 | } |
280 | 280 | |
281 | - public <T> void onEntityChange(TenantId tenantId, EntityId entityid, T entity, TbQueueCallback callback) { | |
281 | + public <T> void broadcastEntityChangeToTransport(TenantId tenantId, EntityId entityid, T entity, TbQueueCallback callback) { | |
282 | 282 | String entityName = (entity instanceof HasName) ? ((HasName) entity).getName() : entity.getClass().getName(); |
283 | 283 | log.trace("[{}][{}][{}] Processing [{}] change event", tenantId, entityid.getEntityType(), entityid.getId(), entityName); |
284 | 284 | TransportProtos.EntityUpdateMsg entityUpdateMsg = TransportProtos.EntityUpdateMsg.newBuilder() |
... | ... | @@ -288,7 +288,7 @@ public class DefaultTbClusterService implements TbClusterService { |
288 | 288 | broadcast(transportMsg, callback); |
289 | 289 | } |
290 | 290 | |
291 | - private void onEntityDelete(TenantId tenantId, EntityId entityId, String name, TbQueueCallback callback) { | |
291 | + private void broadcastEntityDeleteToTransport(TenantId tenantId, EntityId entityId, String name, TbQueueCallback callback) { | |
292 | 292 | log.trace("[{}][{}][{}] Processing [{}] delete event", tenantId, entityId.getEntityType(), entityId.getId(), name); |
293 | 293 | TransportProtos.EntityDeleteMsg entityDeleteMsg = TransportProtos.EntityDeleteMsg.newBuilder() |
294 | 294 | .setEntityType(entityId.getEntityType().name()) |
... | ... | @@ -369,4 +369,72 @@ public class DefaultTbClusterService implements TbClusterService { |
369 | 369 | } |
370 | 370 | } |
371 | 371 | } |
372 | + | |
373 | + private void sendDeviceStateServiceEvent(TenantId tenantId, DeviceId deviceId, boolean added, boolean updated, boolean deleted) { | |
374 | + TransportProtos.DeviceStateServiceMsgProto.Builder builder = TransportProtos.DeviceStateServiceMsgProto.newBuilder(); | |
375 | + builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); | |
376 | + builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); | |
377 | + builder.setDeviceIdMSB(deviceId.getId().getMostSignificantBits()); | |
378 | + builder.setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()); | |
379 | + builder.setAdded(added); | |
380 | + builder.setUpdated(updated); | |
381 | + builder.setDeleted(deleted); | |
382 | + TransportProtos.DeviceStateServiceMsgProto msg = builder.build(); | |
383 | + pushMsgToCore(tenantId, deviceId, TransportProtos.ToCoreMsg.newBuilder().setDeviceStateServiceMsg(msg).build(), null); | |
384 | + } | |
385 | + | |
386 | + @Override | |
387 | + public void onDeviceUpdated(Device device, Device old) { | |
388 | + var created = old == null; | |
389 | + broadcastEntityChangeToTransport(device.getTenantId(), device.getId(), device, null); | |
390 | + if (old != null && (!device.getName().equals(old.getName()) || !device.getType().equals(old.getType()))) { | |
391 | + pushMsgToCore(new DeviceNameOrTypeUpdateMsg(device.getTenantId(), device.getId(), device.getName(), device.getType()), null); | |
392 | + } | |
393 | + broadcastEntityStateChangeEvent(device.getTenantId(), device.getId(), created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); | |
394 | + sendDeviceStateServiceEvent(device.getTenantId(), device.getId(), created, !created, false); | |
395 | + otaPackageStateService.update(device, old); | |
396 | + if (!created) { | |
397 | + sendNotificationMsgToEdgeService(device.getTenantId(), null, device.getId(), null, null, EdgeEventActionType.UPDATED); | |
398 | + } | |
399 | + } | |
400 | + | |
401 | + @Override | |
402 | + public void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action) { | |
403 | + if (!edgesEnabled) { | |
404 | + return; | |
405 | + } | |
406 | + if (type == null) { | |
407 | + if (entityId != null) { | |
408 | + type = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); | |
409 | + } else { | |
410 | + log.trace("[{}] entity id and type are null. Ignoring this notification", tenantId); | |
411 | + return; | |
412 | + } | |
413 | + if (type == null) { | |
414 | + log.trace("[{}] edge event type is null. Ignoring this notification [{}]", tenantId, entityId); | |
415 | + return; | |
416 | + } | |
417 | + } | |
418 | + TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder(); | |
419 | + builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); | |
420 | + builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); | |
421 | + builder.setType(type.name()); | |
422 | + builder.setAction(action.name()); | |
423 | + if (entityId != null) { | |
424 | + builder.setEntityIdMSB(entityId.getId().getMostSignificantBits()); | |
425 | + builder.setEntityIdLSB(entityId.getId().getLeastSignificantBits()); | |
426 | + builder.setEntityType(entityId.getEntityType().name()); | |
427 | + } | |
428 | + if (edgeId != null) { | |
429 | + builder.setEdgeIdMSB(edgeId.getId().getMostSignificantBits()); | |
430 | + builder.setEdgeIdLSB(edgeId.getId().getLeastSignificantBits()); | |
431 | + } | |
432 | + if (body != null) { | |
433 | + builder.setBody(body); | |
434 | + } | |
435 | + TransportProtos.EdgeNotificationMsgProto msg = builder.build(); | |
436 | + log.trace("[{}] sending notification to edge service {}", tenantId.getId(), msg); | |
437 | + pushMsgToCore(tenantId, entityId != null ? entityId : tenantId, TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null); | |
438 | + } | |
439 | + | |
372 | 440 | } | ... | ... |
... | ... | @@ -26,7 +26,7 @@ import org.springframework.scheduling.annotation.Scheduled; |
26 | 26 | import org.springframework.stereotype.Service; |
27 | 27 | import org.thingsboard.common.util.JacksonUtil; |
28 | 28 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
29 | -import org.thingsboard.rule.engine.api.RpcError; | |
29 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
30 | 30 | import org.thingsboard.server.actors.ActorSystemContext; |
31 | 31 | import org.thingsboard.server.common.data.alarm.Alarm; |
32 | 32 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -64,7 +64,7 @@ import org.thingsboard.server.service.ota.OtaPackageStateService; |
64 | 64 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
65 | 65 | import org.thingsboard.server.service.queue.processing.AbstractConsumerService; |
66 | 66 | import org.thingsboard.server.service.queue.processing.IdMsgPair; |
67 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
67 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
68 | 68 | import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; |
69 | 69 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
70 | 70 | import org.thingsboard.server.service.state.DeviceStateService; | ... | ... |
... | ... | @@ -21,7 +21,7 @@ import org.springframework.beans.factory.annotation.Value; |
21 | 21 | import org.springframework.scheduling.annotation.Scheduled; |
22 | 22 | import org.springframework.stereotype.Service; |
23 | 23 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
24 | -import org.thingsboard.rule.engine.api.RpcError; | |
24 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
25 | 25 | import org.thingsboard.server.actors.ActorSystemContext; |
26 | 26 | import org.thingsboard.server.common.data.id.TenantId; |
27 | 27 | import org.thingsboard.server.common.msg.TbMsg; |
... | ... | @@ -55,7 +55,7 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStr |
55 | 55 | import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory; |
56 | 56 | import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; |
57 | 57 | import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory; |
58 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
58 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
59 | 59 | import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; |
60 | 60 | import org.thingsboard.server.service.stats.RuleEngineStatisticsService; |
61 | 61 | ... | ... |
... | ... | @@ -22,18 +22,19 @@ import lombok.extern.slf4j.Slf4j; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | 23 | import org.springframework.stereotype.Service; |
24 | 24 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
25 | -import org.thingsboard.rule.engine.api.RpcError; | |
25 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
26 | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
27 | 27 | import org.thingsboard.server.common.data.DataConstants; |
28 | 28 | import org.thingsboard.server.common.data.Device; |
29 | 29 | import org.thingsboard.server.common.msg.TbMsg; |
30 | 30 | import org.thingsboard.server.common.msg.TbMsgDataType; |
31 | 31 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
32 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
32 | 33 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
33 | 34 | import org.thingsboard.server.dao.device.DeviceService; |
34 | 35 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
35 | 36 | import org.thingsboard.server.queue.util.TbCoreComponent; |
36 | -import org.thingsboard.server.service.queue.TbClusterService; | |
37 | +import org.thingsboard.server.cluster.TbClusterService; | |
37 | 38 | import org.thingsboard.server.service.security.model.SecurityUser; |
38 | 39 | |
39 | 40 | import javax.annotation.PostConstruct; |
... | ... | @@ -138,6 +139,12 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { |
138 | 139 | } |
139 | 140 | } |
140 | 141 | |
142 | + @Override | |
143 | + public void processRemoveRpc(RemoveRpcActorMsg removeRpcMsg) { | |
144 | + log.trace("[{}][{}] Processing remove RPC [{}]", removeRpcMsg.getTenantId(), removeRpcMsg.getRequestId(), removeRpcMsg.getDeviceId()); | |
145 | + actorContext.tellWithHighPriority(removeRpcMsg); | |
146 | + } | |
147 | + | |
141 | 148 | private void sendRpcResponseToTbRuleEngine(String originServiceId, FromDeviceRpcResponse response) { |
142 | 149 | if (serviceId.equals(originServiceId)) { |
143 | 150 | if (tbRuleEngineRpcService.isPresent()) { |
... | ... | @@ -168,6 +175,8 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { |
168 | 175 | entityNode.put("method", msg.getBody().getMethod()); |
169 | 176 | entityNode.put("params", msg.getBody().getParams()); |
170 | 177 | |
178 | + entityNode.put(DataConstants.ADDITIONAL_INFO, msg.getAdditionalInfo()); | |
179 | + | |
171 | 180 | try { |
172 | 181 | TbMsg tbMsg = TbMsg.newMsg(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE, msg.getDeviceId(), currentUser.getCustomerId(), metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); |
173 | 182 | clusterService.pushMsgToRuleEngine(msg.getTenantId(), msg.getDeviceId(), tbMsg, null); | ... | ... |
... | ... | @@ -19,18 +19,19 @@ import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.springframework.beans.factory.annotation.Autowired; |
20 | 20 | import org.springframework.stereotype.Service; |
21 | 21 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
22 | -import org.thingsboard.rule.engine.api.RpcError; | |
22 | +import org.thingsboard.server.common.data.rpc.RpcError; | |
23 | 23 | import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; |
24 | 24 | import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcResponse; |
25 | 25 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; |
26 | 26 | import org.thingsboard.server.common.msg.queue.ServiceType; |
27 | 27 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
28 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
28 | 29 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
29 | 30 | import org.thingsboard.server.gen.transport.TransportProtos; |
30 | 31 | import org.thingsboard.server.queue.discovery.PartitionService; |
31 | 32 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
32 | 33 | import org.thingsboard.server.queue.util.TbRuleEngineComponent; |
33 | -import org.thingsboard.server.service.queue.TbClusterService; | |
34 | +import org.thingsboard.server.cluster.TbClusterService; | |
34 | 35 | |
35 | 36 | import javax.annotation.PostConstruct; |
36 | 37 | import javax.annotation.PreDestroy; |
... | ... | @@ -100,7 +101,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi |
100 | 101 | @Override |
101 | 102 | public void sendRpcRequestToDevice(RuleEngineDeviceRpcRequest src, Consumer<RuleEngineDeviceRpcResponse> consumer) { |
102 | 103 | ToDeviceRpcRequest request = new ToDeviceRpcRequest(src.getRequestUUID(), src.getTenantId(), src.getDeviceId(), |
103 | - src.isOneway(), src.getExpirationTime(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody()), src.isPersisted()); | |
104 | + src.isOneway(), src.getExpirationTime(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody()), src.isPersisted(), src.getAdditionalInfo()); | |
104 | 105 | forwardRpcRequestToDeviceActor(request, response -> { |
105 | 106 | if (src.isRestApiCall()) { |
106 | 107 | sendRpcResponseToTbCore(src.getOriginServiceId(), response); | ... | ... |
... | ... | @@ -18,10 +18,11 @@ package org.thingsboard.server.service.rpc; |
18 | 18 | import lombok.Getter; |
19 | 19 | import lombok.RequiredArgsConstructor; |
20 | 20 | import lombok.ToString; |
21 | -import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; | |
21 | +import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; | |
22 | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
23 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 24 | import org.thingsboard.server.common.msg.MsgType; |
25 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
25 | 26 | |
26 | 27 | @ToString |
27 | 28 | @RequiredArgsConstructor | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.service.rpc; | |
17 | + | |
18 | +import lombok.Getter; | |
19 | +import lombok.RequiredArgsConstructor; | |
20 | +import lombok.ToString; | |
21 | +import org.thingsboard.server.common.data.id.DeviceId; | |
22 | +import org.thingsboard.server.common.data.id.TenantId; | |
23 | +import org.thingsboard.server.common.msg.MsgType; | |
24 | +import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; | |
25 | + | |
26 | +import java.util.UUID; | |
27 | + | |
28 | +@ToString | |
29 | +@RequiredArgsConstructor | |
30 | +public class RemoveRpcActorMsg implements ToDeviceActorNotificationMsg { | |
31 | + | |
32 | + @Getter | |
33 | + private final TenantId tenantId; | |
34 | + @Getter | |
35 | + private final DeviceId deviceId; | |
36 | + | |
37 | + @Getter | |
38 | + private final UUID requestId; | |
39 | + | |
40 | + @Override | |
41 | + public MsgType getMsgType() { | |
42 | + return MsgType.REMOVE_RPC_TO_DEVICE_ACTOR_MSG; | |
43 | + } | |
44 | +} | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.service.rpc; |
17 | 17 | |
18 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
18 | 19 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
19 | 20 | import org.thingsboard.server.service.security.model.SecurityUser; |
20 | 21 | |
... | ... | @@ -55,4 +56,6 @@ public interface TbCoreDeviceRpcService { |
55 | 56 | */ |
56 | 57 | void processRpcResponseFromDeviceActor(FromDeviceRpcResponse response); |
57 | 58 | |
59 | + void processRemoveRpc(RemoveRpcActorMsg removeRpcMsg); | |
60 | + | |
58 | 61 | } | ... | ... |
... | ... | @@ -31,7 +31,7 @@ import org.thingsboard.server.common.msg.TbMsg; |
31 | 31 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
32 | 32 | import org.thingsboard.server.dao.rpc.RpcService; |
33 | 33 | import org.thingsboard.server.queue.util.TbCoreComponent; |
34 | -import org.thingsboard.server.service.queue.TbClusterService; | |
34 | +import org.thingsboard.server.cluster.TbClusterService; | |
35 | 35 | |
36 | 36 | @TbCoreComponent |
37 | 37 | @Service | ... | ... |
... | ... | @@ -18,7 +18,7 @@ package org.thingsboard.server.service.rpc; |
18 | 18 | import lombok.Getter; |
19 | 19 | import lombok.RequiredArgsConstructor; |
20 | 20 | import lombok.ToString; |
21 | -import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; | |
21 | +import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; | |
22 | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
23 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 24 | import org.thingsboard.server.common.msg.MsgType; | ... | ... |
... | ... | @@ -47,7 +47,7 @@ import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
47 | 47 | import org.thingsboard.server.dao.tenant.TenantService; |
48 | 48 | import org.thingsboard.server.dao.user.UserService; |
49 | 49 | import org.thingsboard.server.service.install.InstallScripts; |
50 | -import org.thingsboard.server.service.queue.TbClusterService; | |
50 | +import org.thingsboard.server.cluster.TbClusterService; | |
51 | 51 | import org.thingsboard.server.service.security.model.SecurityUser; |
52 | 52 | import org.thingsboard.server.service.security.model.UserPrincipal; |
53 | 53 | |
... | ... | @@ -180,7 +180,7 @@ public abstract class AbstractOAuth2ClientMapper { |
180 | 180 | installScripts.createDefaultEdgeRuleChains(tenant.getId()); |
181 | 181 | tenantProfileCache.evict(tenant.getId()); |
182 | 182 | tbClusterService.onTenantChange(tenant, null); |
183 | - tbClusterService.onEntityStateChange(tenant.getId(), tenant.getId(), | |
183 | + tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), | |
184 | 184 | ComponentLifecycleEvent.CREATED); |
185 | 185 | } else { |
186 | 186 | tenant = tenants.get(0); | ... | ... |
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
19 | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; | |
20 | 21 | import lombok.extern.slf4j.Slf4j; |
21 | 22 | import org.springframework.boot.web.client.RestTemplateBuilder; |
22 | 23 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
... | ... | @@ -29,6 +30,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
29 | 30 | import org.thingsboard.server.dao.oauth2.OAuth2User; |
30 | 31 | import org.thingsboard.server.service.security.model.SecurityUser; |
31 | 32 | |
33 | +import javax.annotation.PostConstruct; | |
32 | 34 | import javax.servlet.http.HttpServletRequest; |
33 | 35 | |
34 | 36 | @Service(value = "customOAuth2ClientMapper") |
... | ... | @@ -40,6 +42,15 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme |
40 | 42 | |
41 | 43 | private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); |
42 | 44 | |
45 | + @PostConstruct | |
46 | + public void init() { | |
47 | + // Register time module to parse Instant objects. | |
48 | + // com.fasterxml.jackson.databind.exc.InvalidDefinitionException: | |
49 | + // Java 8 date/time type `java.time.Instant` not supported by default: | |
50 | + // add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling | |
51 | + json.registerModule(new JavaTimeModule()); | |
52 | + } | |
53 | + | |
43 | 54 | @Override |
44 | 55 | public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) { |
45 | 56 | OAuth2MapperConfig config = registration.getMapperConfig(); | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | |
18 | +import lombok.extern.slf4j.Slf4j; | |
18 | 19 | import org.springframework.beans.factory.annotation.Autowired; |
19 | 20 | import org.springframework.security.core.Authentication; |
20 | 21 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |
... | ... | @@ -42,6 +43,7 @@ import java.net.URLEncoder; |
42 | 43 | import java.nio.charset.StandardCharsets; |
43 | 44 | import java.util.UUID; |
44 | 45 | |
46 | +@Slf4j | |
45 | 47 | @Component(value = "oauth2AuthenticationSuccessHandler") |
46 | 48 | public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { |
47 | 49 | |
... | ... | @@ -99,6 +101,8 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS |
99 | 101 | clearAuthenticationAttributes(request, response); |
100 | 102 | getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); |
101 | 103 | } catch (Exception e) { |
104 | + log.debug("Error occurred during processing authentication success result. " + | |
105 | + "request [{}], response [{}], authentication [{}]", request, response, authentication, e); | |
102 | 106 | clearAuthenticationAttributes(request, response); |
103 | 107 | String errorPrefix; |
104 | 108 | if (!StringUtils.isEmpty(callbackUrlScheme)) { | ... | ... |
... | ... | @@ -22,7 +22,6 @@ import com.google.common.util.concurrent.Futures; |
22 | 22 | import com.google.common.util.concurrent.ListenableFuture; |
23 | 23 | import com.google.common.util.concurrent.ListeningScheduledExecutorService; |
24 | 24 | import com.google.common.util.concurrent.MoreExecutors; |
25 | -import com.google.common.util.concurrent.SettableFuture; | |
26 | 25 | import lombok.Getter; |
27 | 26 | import lombok.extern.slf4j.Slf4j; |
28 | 27 | import org.springframework.beans.factory.annotation.Autowired; |
... | ... | @@ -59,7 +58,7 @@ import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
59 | 58 | import org.thingsboard.server.queue.discovery.PartitionService; |
60 | 59 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
61 | 60 | import org.thingsboard.server.queue.util.TbCoreComponent; |
62 | -import org.thingsboard.server.service.queue.TbClusterService; | |
61 | +import org.thingsboard.server.cluster.TbClusterService; | |
63 | 62 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; |
64 | 63 | |
65 | 64 | import javax.annotation.Nonnull; |
... | ... | @@ -71,7 +70,6 @@ import java.util.Arrays; |
71 | 70 | import java.util.Collections; |
72 | 71 | import java.util.HashSet; |
73 | 72 | import java.util.List; |
74 | -import java.util.Optional; | |
75 | 73 | import java.util.Queue; |
76 | 74 | import java.util.Random; |
77 | 75 | import java.util.Set; |
... | ... | @@ -137,7 +135,6 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
137 | 135 | private ExecutorService deviceStateExecutor; |
138 | 136 | private final ConcurrentMap<TopicPartitionInfo, Set<DeviceId>> partitionedDevices = new ConcurrentHashMap<>(); |
139 | 137 | final ConcurrentMap<DeviceId, DeviceStateData> deviceStates = new ConcurrentHashMap<>(); |
140 | - private final ConcurrentMap<DeviceId, Long> deviceLastSavedActivity = new ConcurrentHashMap<>(); | |
141 | 138 | |
142 | 139 | final Queue<Set<TopicPartitionInfo>> subscribeQueue = new ConcurrentLinkedQueue<>(); |
143 | 140 | |
... | ... | @@ -177,22 +174,7 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
177 | 174 | } |
178 | 175 | |
179 | 176 | @Override |
180 | - public void onDeviceAdded(Device device) { | |
181 | - sendDeviceEvent(device.getTenantId(), device.getId(), true, false, false); | |
182 | - } | |
183 | - | |
184 | - @Override | |
185 | - public void onDeviceUpdated(Device device) { | |
186 | - sendDeviceEvent(device.getTenantId(), device.getId(), false, true, false); | |
187 | - } | |
188 | - | |
189 | - @Override | |
190 | - public void onDeviceDeleted(Device device) { | |
191 | - sendDeviceEvent(device.getTenantId(), device.getId(), false, false, true); | |
192 | - } | |
193 | - | |
194 | - @Override | |
195 | - public void onDeviceConnect(DeviceId deviceId) { | |
177 | + public void onDeviceConnect(TenantId tenantId, DeviceId deviceId) { | |
196 | 178 | log.trace("on Device Connect [{}]", deviceId.getId()); |
197 | 179 | DeviceStateData stateData = getOrFetchDeviceStateData(deviceId); |
198 | 180 | long ts = System.currentTimeMillis(); |
... | ... | @@ -200,23 +182,23 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
200 | 182 | save(deviceId, LAST_CONNECT_TIME, ts); |
201 | 183 | pushRuleEngineMessage(stateData, CONNECT_EVENT); |
202 | 184 | checkAndUpdateState(deviceId, stateData); |
185 | + cleanDeviceStateIfBelongsExternalPartition(tenantId, deviceId); | |
203 | 186 | } |
204 | 187 | |
205 | 188 | @Override |
206 | - public void onDeviceActivity(DeviceId deviceId, long lastReportedActivity) { | |
189 | + public void onDeviceActivity(TenantId tenantId, DeviceId deviceId, long lastReportedActivity) { | |
207 | 190 | log.trace("on Device Activity [{}], lastReportedActivity [{}]", deviceId.getId(), lastReportedActivity); |
208 | - long lastSavedActivity = deviceLastSavedActivity.getOrDefault(deviceId, 0L); | |
209 | - if (lastReportedActivity > 0 && lastReportedActivity > lastSavedActivity) { | |
210 | - final DeviceStateData stateData = getOrFetchDeviceStateData(deviceId); | |
191 | + final DeviceStateData stateData = getOrFetchDeviceStateData(deviceId); | |
192 | + if (lastReportedActivity > 0 && lastReportedActivity > stateData.getState().getLastActivityTime()) { | |
211 | 193 | updateActivityState(deviceId, stateData, lastReportedActivity); |
212 | 194 | } |
195 | + cleanDeviceStateIfBelongsExternalPartition(tenantId, deviceId); | |
213 | 196 | } |
214 | 197 | |
215 | 198 | void updateActivityState(DeviceId deviceId, DeviceStateData stateData, long lastReportedActivity) { |
216 | 199 | log.trace("updateActivityState - fetched state {} for device {}, lastReportedActivity {}", stateData, deviceId, lastReportedActivity); |
217 | 200 | if (stateData != null) { |
218 | 201 | save(deviceId, LAST_ACTIVITY_TIME, lastReportedActivity); |
219 | - deviceLastSavedActivity.put(deviceId, lastReportedActivity); | |
220 | 202 | DeviceState state = stateData.getState(); |
221 | 203 | state.setLastActivityTime(lastReportedActivity); |
222 | 204 | if (!state.isActive()) { |
... | ... | @@ -225,21 +207,23 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
225 | 207 | pushRuleEngineMessage(stateData, ACTIVITY_EVENT); |
226 | 208 | } |
227 | 209 | } else { |
228 | - log.warn("updateActivityState - fetched state IN NULL for device {}, lastReportedActivity {}", deviceId, lastReportedActivity); | |
210 | + log.debug("updateActivityState - fetched state IN NULL for device {}, lastReportedActivity {}", deviceId, lastReportedActivity); | |
211 | + cleanUpDeviceStateMap(deviceId); | |
229 | 212 | } |
230 | 213 | } |
231 | 214 | |
232 | 215 | @Override |
233 | - public void onDeviceDisconnect(DeviceId deviceId) { | |
216 | + public void onDeviceDisconnect(TenantId tenantId, DeviceId deviceId) { | |
234 | 217 | DeviceStateData stateData = getOrFetchDeviceStateData(deviceId); |
235 | 218 | long ts = System.currentTimeMillis(); |
236 | 219 | stateData.getState().setLastDisconnectTime(ts); |
237 | 220 | save(deviceId, LAST_DISCONNECT_TIME, ts); |
238 | 221 | pushRuleEngineMessage(stateData, DISCONNECT_EVENT); |
222 | + cleanDeviceStateIfBelongsExternalPartition(tenantId, deviceId); | |
239 | 223 | } |
240 | 224 | |
241 | 225 | @Override |
242 | - public void onDeviceInactivityTimeoutUpdate(DeviceId deviceId, long inactivityTimeout) { | |
226 | + public void onDeviceInactivityTimeoutUpdate(TenantId tenantId, DeviceId deviceId, long inactivityTimeout) { | |
243 | 227 | if (inactivityTimeout <= 0L) { |
244 | 228 | return; |
245 | 229 | } |
... | ... | @@ -247,6 +231,7 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
247 | 231 | DeviceStateData stateData = getOrFetchDeviceStateData(deviceId); |
248 | 232 | stateData.getState().setInactivityTimeout(inactivityTimeout); |
249 | 233 | checkAndUpdateState(deviceId, stateData); |
234 | + cleanDeviceStateIfBelongsExternalPartition(tenantId, deviceId); | |
250 | 235 | } |
251 | 236 | |
252 | 237 | @Override |
... | ... | @@ -267,6 +252,7 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
267 | 252 | TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, device.getId()); |
268 | 253 | if (partitionedDevices.containsKey(tpi)) { |
269 | 254 | addDeviceUsingState(tpi, state); |
255 | + save(deviceId, ACTIVITY_STATE, false); | |
270 | 256 | callback.onSuccess(); |
271 | 257 | } else { |
272 | 258 | log.warn("[{}][{}] Device belongs to external partition. Probably rebalancing is in progress. Topic: {}" |
... | ... | @@ -283,12 +269,11 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
283 | 269 | }, deviceStateExecutor); |
284 | 270 | } else if (proto.getUpdated()) { |
285 | 271 | DeviceStateData stateData = getOrFetchDeviceStateData(device.getId()); |
286 | - if (stateData != null) { | |
287 | - TbMsgMetaData md = new TbMsgMetaData(); | |
288 | - md.putValue("deviceName", device.getName()); | |
289 | - md.putValue("deviceType", device.getType()); | |
290 | - stateData.setMetaData(md); | |
291 | - } | |
272 | + TbMsgMetaData md = new TbMsgMetaData(); | |
273 | + md.putValue("deviceName", device.getName()); | |
274 | + md.putValue("deviceType", device.getType()); | |
275 | + stateData.setMetaData(md); | |
276 | + callback.onSuccess(); | |
292 | 277 | } |
293 | 278 | } else { |
294 | 279 | //Device was probably deleted while message was in queue; |
... | ... | @@ -356,10 +341,7 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
356 | 341 | // We no longer manage current partition of devices; |
357 | 342 | removedPartitions.forEach(partition -> { |
358 | 343 | Set<DeviceId> devices = partitionedDevices.remove(partition); |
359 | - devices.forEach(deviceId -> { | |
360 | - deviceStates.remove(deviceId); | |
361 | - deviceLastSavedActivity.remove(deviceId); | |
362 | - }); | |
344 | + devices.forEach(this::cleanUpDeviceStateMap); | |
363 | 345 | }); |
364 | 346 | |
365 | 347 | addedPartitions.forEach(tpi -> partitionedDevices.computeIfAbsent(tpi, key -> ConcurrentHashMap.newKeySet())); |
... | ... | @@ -457,17 +439,18 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
457 | 439 | deviceStates.put(state.getDeviceId(), state); |
458 | 440 | } else { |
459 | 441 | log.warn("Device belongs to external partition {}" + tpi.getFullTopicName()); |
460 | - new RuntimeException("Device belongs to external partition " + tpi.getFullTopicName() + "!"); | |
442 | + throw new RuntimeException("Device belongs to external partition " + tpi.getFullTopicName() + "!"); | |
461 | 443 | } |
462 | 444 | } |
463 | 445 | |
464 | 446 | void updateInactivityStateIfExpired() { |
465 | 447 | final long ts = System.currentTimeMillis(); |
466 | - log.debug("Calculating state updates for {} devices", deviceStates.size()); | |
467 | - Set<DeviceId> deviceIds = new HashSet<>(deviceStates.keySet()); | |
468 | - for (DeviceId deviceId : deviceIds) { | |
469 | - updateInactivityStateIfExpired(ts, deviceId); | |
470 | - } | |
448 | + partitionedDevices.forEach((tpi, deviceIds) -> { | |
449 | + log.debug("Calculating state updates. tpi {} for {} devices", tpi.getFullTopicName(), deviceIds.size()); | |
450 | + for (DeviceId deviceId : deviceIds) { | |
451 | + updateInactivityStateIfExpired(ts, deviceId); | |
452 | + } | |
453 | + }); | |
471 | 454 | } |
472 | 455 | |
473 | 456 | void updateInactivityStateIfExpired(long ts, DeviceId deviceId) { |
... | ... | @@ -488,8 +471,7 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
488 | 471 | } |
489 | 472 | } else { |
490 | 473 | log.debug("[{}] Device that belongs to other server is detected and removed.", deviceId); |
491 | - deviceStates.remove(deviceId); | |
492 | - deviceLastSavedActivity.remove(deviceId); | |
474 | + cleanUpDeviceStateMap(deviceId); | |
493 | 475 | } |
494 | 476 | } |
495 | 477 | |
... | ... | @@ -522,27 +504,26 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
522 | 504 | } |
523 | 505 | } |
524 | 506 | |
525 | - private void sendDeviceEvent(TenantId tenantId, DeviceId deviceId, boolean added, boolean updated, boolean deleted) { | |
526 | - TransportProtos.DeviceStateServiceMsgProto.Builder builder = TransportProtos.DeviceStateServiceMsgProto.newBuilder(); | |
527 | - builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); | |
528 | - builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); | |
529 | - builder.setDeviceIdMSB(deviceId.getId().getMostSignificantBits()); | |
530 | - builder.setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()); | |
531 | - builder.setAdded(added); | |
532 | - builder.setUpdated(updated); | |
533 | - builder.setDeleted(deleted); | |
534 | - TransportProtos.DeviceStateServiceMsgProto msg = builder.build(); | |
535 | - clusterService.pushMsgToCore(tenantId, deviceId, TransportProtos.ToCoreMsg.newBuilder().setDeviceStateServiceMsg(msg).build(), null); | |
507 | + private void cleanDeviceStateIfBelongsExternalPartition(TenantId tenantId, final DeviceId deviceId) { | |
508 | + TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId); | |
509 | + if (!partitionedDevices.containsKey(tpi)) { | |
510 | + cleanUpDeviceStateMap(deviceId); | |
511 | + log.debug("[{}][{}] device belongs to external partition. Probably rebalancing is in progress. Topic: {}" | |
512 | + , tenantId, deviceId, tpi.getFullTopicName()); | |
513 | + } | |
536 | 514 | } |
537 | 515 | |
538 | 516 | private void onDeviceDeleted(TenantId tenantId, DeviceId deviceId) { |
539 | - deviceStates.remove(deviceId); | |
540 | - deviceLastSavedActivity.remove(deviceId); | |
517 | + cleanUpDeviceStateMap(deviceId); | |
541 | 518 | TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId); |
542 | 519 | Set<DeviceId> deviceIdSet = partitionedDevices.get(tpi); |
543 | 520 | deviceIdSet.remove(deviceId); |
544 | 521 | } |
545 | 522 | |
523 | + private void cleanUpDeviceStateMap(DeviceId deviceId) { | |
524 | + deviceStates.remove(deviceId); | |
525 | + } | |
526 | + | |
546 | 527 | private ListenableFuture<DeviceStateData> fetchDeviceState(Device device) { |
547 | 528 | ListenableFuture<DeviceStateData> future; |
548 | 529 | if (persistToTelemetry) { |
... | ... | @@ -573,7 +554,7 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
573 | 554 | } |
574 | 555 | |
575 | 556 | private <T extends KvEntry> Function<List<T>, DeviceStateData> extractDeviceStateData(Device device) { |
576 | - return new Function<List<T>, DeviceStateData>() { | |
557 | + return new Function<>() { | |
577 | 558 | @Nonnull |
578 | 559 | @Override |
579 | 560 | public DeviceStateData apply(@Nullable List<T> data) { |
... | ... | @@ -660,9 +641,9 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
660 | 641 | tsSubService.saveAndNotifyInternal( |
661 | 642 | TenantId.SYS_TENANT_ID, deviceId, |
662 | 643 | Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new LongDataEntry(key, value))), |
663 | - new AttributeSaveCallback<>(deviceId, key, value)); | |
644 | + new TelemetrySaveCallback<>(deviceId, key, value)); | |
664 | 645 | } else { |
665 | - tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback<>(deviceId, key, value)); | |
646 | + tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new TelemetrySaveCallback<>(deviceId, key, value)); | |
666 | 647 | } |
667 | 648 | } |
668 | 649 | |
... | ... | @@ -671,18 +652,18 @@ public class DefaultDeviceStateService extends TbApplicationEventListener<Partit |
671 | 652 | tsSubService.saveAndNotifyInternal( |
672 | 653 | TenantId.SYS_TENANT_ID, deviceId, |
673 | 654 | Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new BooleanDataEntry(key, value))), |
674 | - new AttributeSaveCallback<>(deviceId, key, value)); | |
655 | + new TelemetrySaveCallback<>(deviceId, key, value)); | |
675 | 656 | } else { |
676 | - tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback<>(deviceId, key, value)); | |
657 | + tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new TelemetrySaveCallback<>(deviceId, key, value)); | |
677 | 658 | } |
678 | 659 | } |
679 | 660 | |
680 | - private static class AttributeSaveCallback<T> implements FutureCallback<T> { | |
661 | + private static class TelemetrySaveCallback<T> implements FutureCallback<T> { | |
681 | 662 | private final DeviceId deviceId; |
682 | 663 | private final String key; |
683 | 664 | private final Object value; |
684 | 665 | |
685 | - AttributeSaveCallback(DeviceId deviceId, String key, Object value) { | |
666 | + TelemetrySaveCallback(DeviceId deviceId, String key, Object value) { | |
686 | 667 | this.deviceId = deviceId; |
687 | 668 | this.key = key; |
688 | 669 | this.value = value; | ... | ... |
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.service.state; |
18 | 18 | import org.springframework.context.ApplicationListener; |
19 | 19 | import org.thingsboard.server.common.data.Device; |
20 | 20 | import org.thingsboard.server.common.data.id.DeviceId; |
21 | +import org.thingsboard.server.common.data.id.TenantId; | |
21 | 22 | import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
22 | 23 | import org.thingsboard.server.gen.transport.TransportProtos; |
23 | 24 | import org.thingsboard.server.common.msg.queue.TbCallback; |
... | ... | @@ -27,19 +28,13 @@ import org.thingsboard.server.common.msg.queue.TbCallback; |
27 | 28 | */ |
28 | 29 | public interface DeviceStateService extends ApplicationListener<PartitionChangeEvent> { |
29 | 30 | |
30 | - void onDeviceAdded(Device device); | |
31 | + void onDeviceConnect(TenantId tenantId, DeviceId deviceId); | |
31 | 32 | |
32 | - void onDeviceUpdated(Device device); | |
33 | + void onDeviceActivity(TenantId tenantId, DeviceId deviceId, long lastReportedActivityTime); | |
33 | 34 | |
34 | - void onDeviceDeleted(Device device); | |
35 | + void onDeviceDisconnect(TenantId tenantId, DeviceId deviceId); | |
35 | 36 | |
36 | - void onDeviceConnect(DeviceId deviceId); | |
37 | - | |
38 | - void onDeviceActivity(DeviceId deviceId, long lastReportedActivityTime); | |
39 | - | |
40 | - void onDeviceDisconnect(DeviceId deviceId); | |
41 | - | |
42 | - void onDeviceInactivityTimeoutUpdate(DeviceId deviceId, long inactivityTimeout); | |
37 | + void onDeviceInactivityTimeoutUpdate(TenantId tenantId, DeviceId deviceId, long inactivityTimeout); | |
43 | 38 | |
44 | 39 | void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto proto, TbCallback bytes); |
45 | 40 | ... | ... |
... | ... | @@ -53,7 +53,7 @@ import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
53 | 53 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
54 | 54 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
55 | 55 | import org.thingsboard.server.queue.util.TbCoreComponent; |
56 | -import org.thingsboard.server.service.queue.TbClusterService; | |
56 | +import org.thingsboard.server.cluster.TbClusterService; | |
57 | 57 | import org.thingsboard.server.service.state.DefaultDeviceStateService; |
58 | 58 | import org.thingsboard.server.service.state.DeviceStateService; |
59 | 59 | import org.thingsboard.server.service.telemetry.sub.AlarmSubscriptionUpdate; |
... | ... | @@ -224,7 +224,7 @@ public class DefaultSubscriptionManagerService extends TbApplicationEventListene |
224 | 224 | return subscriptionUpdate; |
225 | 225 | }); |
226 | 226 | if (entityId.getEntityType() == EntityType.DEVICE) { |
227 | - updateDeviceInactivityTimeout(entityId, ts); | |
227 | + updateDeviceInactivityTimeout(tenantId, entityId, ts); | |
228 | 228 | } |
229 | 229 | callback.onSuccess(); |
230 | 230 | } |
... | ... | @@ -259,7 +259,7 @@ public class DefaultSubscriptionManagerService extends TbApplicationEventListene |
259 | 259 | }); |
260 | 260 | if (entityId.getEntityType() == EntityType.DEVICE) { |
261 | 261 | if (TbAttributeSubscriptionScope.SERVER_SCOPE.name().equalsIgnoreCase(scope)) { |
262 | - updateDeviceInactivityTimeout(entityId, attributes); | |
262 | + updateDeviceInactivityTimeout(tenantId, entityId, attributes); | |
263 | 263 | } else if (TbAttributeSubscriptionScope.SHARED_SCOPE.name().equalsIgnoreCase(scope) && notifyDevice) { |
264 | 264 | clusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onUpdate(tenantId, |
265 | 265 | new DeviceId(entityId.getId()), DataConstants.SHARED_SCOPE, new ArrayList<>(attributes)) |
... | ... | @@ -269,10 +269,10 @@ public class DefaultSubscriptionManagerService extends TbApplicationEventListene |
269 | 269 | callback.onSuccess(); |
270 | 270 | } |
271 | 271 | |
272 | - private void updateDeviceInactivityTimeout(EntityId entityId, List<? extends KvEntry> kvEntries) { | |
272 | + private void updateDeviceInactivityTimeout(TenantId tenantId, EntityId entityId, List<? extends KvEntry> kvEntries) { | |
273 | 273 | for (KvEntry kvEntry : kvEntries) { |
274 | 274 | if (kvEntry.getKey().equals(DefaultDeviceStateService.INACTIVITY_TIMEOUT)) { |
275 | - deviceStateService.onDeviceInactivityTimeoutUpdate(new DeviceId(entityId.getId()), kvEntry.getLongValue().orElse(0L)); | |
275 | + deviceStateService.onDeviceInactivityTimeoutUpdate(tenantId, new DeviceId(entityId.getId()), kvEntry.getLongValue().orElse(0L)); | |
276 | 276 | } |
277 | 277 | } |
278 | 278 | } | ... | ... |
... | ... | @@ -30,7 +30,7 @@ import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
30 | 30 | import org.thingsboard.server.common.msg.queue.TbCallback; |
31 | 31 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
32 | 32 | import org.thingsboard.server.queue.util.TbCoreComponent; |
33 | -import org.thingsboard.server.service.queue.TbClusterService; | |
33 | +import org.thingsboard.server.cluster.TbClusterService; | |
34 | 34 | import org.thingsboard.server.service.telemetry.sub.AlarmSubscriptionUpdate; |
35 | 35 | import org.thingsboard.server.service.telemetry.sub.TelemetrySubscriptionUpdate; |
36 | 36 | |
... | ... | @@ -42,7 +42,6 @@ import java.util.Map; |
42 | 42 | import java.util.Set; |
43 | 43 | import java.util.concurrent.ConcurrentHashMap; |
44 | 44 | import java.util.concurrent.ExecutorService; |
45 | -import java.util.concurrent.Executors; | |
46 | 45 | |
47 | 46 | @Slf4j |
48 | 47 | @TbCoreComponent | ... | ... |
... | ... | @@ -20,15 +20,13 @@ import com.google.common.util.concurrent.Futures; |
20 | 20 | import com.google.common.util.concurrent.ListenableFuture; |
21 | 21 | import lombok.extern.slf4j.Slf4j; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | -import org.springframework.context.ApplicationListener; | |
24 | -import org.springframework.context.event.EventListener; | |
25 | 23 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
26 | 24 | import org.thingsboard.server.common.msg.queue.ServiceType; |
27 | 25 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
28 | 26 | import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
29 | 27 | import org.thingsboard.server.queue.discovery.PartitionService; |
30 | 28 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
31 | -import org.thingsboard.server.service.queue.TbClusterService; | |
29 | +import org.thingsboard.server.cluster.TbClusterService; | |
32 | 30 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; |
33 | 31 | |
34 | 32 | import javax.annotation.Nullable; | ... | ... |
... | ... | @@ -46,7 +46,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; |
46 | 46 | import org.thingsboard.server.queue.discovery.PartitionService; |
47 | 47 | import org.thingsboard.server.queue.usagestats.TbApiUsageClient; |
48 | 48 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
49 | -import org.thingsboard.server.service.queue.TbClusterService; | |
49 | +import org.thingsboard.server.cluster.TbClusterService; | |
50 | 50 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; |
51 | 51 | import org.thingsboard.server.service.subscription.TbSubscriptionUtils; |
52 | 52 | ... | ... |
... | ... | @@ -45,7 +45,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; |
45 | 45 | import org.thingsboard.server.queue.discovery.PartitionService; |
46 | 46 | import org.thingsboard.server.queue.usagestats.TbApiUsageClient; |
47 | 47 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
48 | -import org.thingsboard.server.service.queue.TbClusterService; | |
48 | +import org.thingsboard.server.cluster.TbClusterService; | |
49 | 49 | import org.thingsboard.server.service.subscription.TbSubscriptionUtils; |
50 | 50 | |
51 | 51 | import javax.annotation.Nullable; | ... | ... |
... | ... | @@ -95,7 +95,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
95 | 95 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
96 | 96 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
97 | 97 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
98 | -import org.thingsboard.server.service.queue.TbClusterService; | |
98 | +import org.thingsboard.server.cluster.TbClusterService; | |
99 | 99 | import org.thingsboard.server.service.resource.TbResourceService; |
100 | 100 | import org.thingsboard.server.service.state.DeviceStateService; |
101 | 101 | |
... | ... | @@ -265,9 +265,11 @@ public class DefaultTransportApiService implements TransportApiService { |
265 | 265 | device.setCustomerId(gateway.getCustomerId()); |
266 | 266 | DeviceProfile deviceProfile = deviceProfileCache.findOrCreateDeviceProfile(gateway.getTenantId(), requestMsg.getDeviceType()); |
267 | 267 | device.setDeviceProfileId(deviceProfile.getId()); |
268 | - device = deviceService.saveDevice(device); | |
268 | + Device savedDevice = deviceService.saveDevice(device); | |
269 | + tbClusterService.onDeviceUpdated(savedDevice, device); | |
270 | + device = savedDevice; | |
271 | + | |
269 | 272 | relationService.saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(gateway.getId(), device.getId(), "Created")); |
270 | - deviceStateService.onDeviceAdded(device); | |
271 | 273 | |
272 | 274 | TbMsgMetaData metaData = new TbMsgMetaData(); |
273 | 275 | CustomerId customerId = gateway.getCustomerId(); |
... | ... | @@ -581,7 +583,7 @@ public class DefaultTransportApiService implements TransportApiService { |
581 | 583 | device.setName(deviceName); |
582 | 584 | device.setType("LwM2M"); |
583 | 585 | device = deviceService.saveDevice(device); |
584 | - deviceStateService.onDeviceAdded(device); | |
586 | + tbClusterService.onDeviceUpdated(device, null); | |
585 | 587 | } |
586 | 588 | TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg = |
587 | 589 | TransportProtos.LwM2MRegistrationResponseMsg.newBuilder() | ... | ... |
... | ... | @@ -588,6 +588,7 @@ transport: |
588 | 588 | bind_address: "${MQTT_BIND_ADDRESS:0.0.0.0}" |
589 | 589 | bind_port: "${MQTT_BIND_PORT:1883}" |
590 | 590 | timeout: "${MQTT_TIMEOUT:10000}" |
591 | + msg_queue_size_per_device_limit: "${MQTT_MSG_QUEUE_SIZE_PER_DEVICE_LIMIT:100}" # messages await in the queue before device connected state. This limit works on low level before TenantProfileLimits mechanism | |
591 | 592 | netty: |
592 | 593 | leak_detector_level: "${NETTY_LEAK_DETECTOR_LVL:DISABLED}" |
593 | 594 | boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}" |
... | ... | @@ -747,6 +748,8 @@ queue: |
747 | 748 | compression.type: "${TB_KAFKA_COMPRESSION_TYPE:none}" # none or gzip |
748 | 749 | batch.size: "${TB_KAFKA_BATCH_SIZE:16384}" |
749 | 750 | linger.ms: "${TB_KAFKA_LINGER_MS:1}" |
751 | + max.request.size: "${TB_KAFKA_MAX_REQUEST_SIZE:1048576}" | |
752 | + max.in.flight.requests.per.connection: "${TB_KAFKA_MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION:5}" | |
750 | 753 | buffer.memory: "${TB_BUFFER_MEMORY:33554432}" |
751 | 754 | replication_factor: "${TB_QUEUE_KAFKA_REPLICATION_FACTOR:1}" |
752 | 755 | max_poll_interval_ms: "${TB_QUEUE_KAFKA_MAX_POLL_INTERVAL_MS:300000}" |
... | ... | @@ -763,7 +766,11 @@ queue: |
763 | 766 | tb_ota_package: |
764 | 767 | - key: max.poll.records |
765 | 768 | value: 10 |
766 | - other: | |
769 | + other: # In this section you can specify custom parameters for Kafka consumer/producer and expose the env variables to configure outside | |
770 | + - key: "request.timeout.ms" # refer to https://docs.confluent.io/platform/current/installation/configuration/producer-configs.html#producerconfigs_request.timeout.ms | |
771 | + value: "${TB_QUEUE_KAFKA_REQUEST_TIMEOUT_MS:30000}" # (30 seconds) | |
772 | + - key: "session.timeout.ms" # refer to https://docs.confluent.io/platform/current/installation/configuration/consumer-configs.html#consumerconfigs_session.timeout.ms | |
773 | + value: "${TB_QUEUE_KAFKA_SESSION_TIMEOUT_MS:10000}" # (10 seconds) | |
767 | 774 | topic-properties: |
768 | 775 | rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}" |
769 | 776 | core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}" | ... | ... |
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.type.TypeReference; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.awaitility.Awaitility; | |
20 | 21 | import org.junit.After; |
21 | 22 | import org.junit.Assert; |
22 | 23 | import org.junit.Before; |
... | ... | @@ -28,13 +29,14 @@ import org.thingsboard.server.common.data.asset.Asset; |
28 | 29 | import org.thingsboard.server.common.data.edge.Edge; |
29 | 30 | import org.thingsboard.server.common.data.edge.EdgeEvent; |
30 | 31 | import org.thingsboard.server.common.data.edge.EdgeEventType; |
31 | -import org.thingsboard.server.common.data.id.TenantId; | |
32 | +import org.thingsboard.server.common.data.id.EdgeId; | |
32 | 33 | import org.thingsboard.server.common.data.page.PageData; |
33 | 34 | import org.thingsboard.server.common.data.page.TimePageLink; |
34 | 35 | import org.thingsboard.server.common.data.relation.EntityRelation; |
35 | 36 | import org.thingsboard.server.common.data.security.Authority; |
36 | 37 | |
37 | 38 | import java.util.List; |
39 | +import java.util.concurrent.TimeUnit; | |
38 | 40 | |
39 | 41 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
40 | 42 | |
... | ... | @@ -83,34 +85,37 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { |
83 | 85 | Device device = constructDevice("TestDevice", "default"); |
84 | 86 | Device savedDevice = doPost("/api/device", device, Device.class); |
85 | 87 | |
86 | - doPost("/api/edge/" + edge.getId().toString() + "/device/" + savedDevice.getId().toString(), Device.class); | |
88 | + final EdgeId edgeId = edge.getId(); | |
89 | + doPost("/api/edge/" + edgeId.toString() + "/device/" + savedDevice.getId().toString(), Device.class); | |
87 | 90 | |
88 | 91 | Asset asset = constructAsset("TestAsset", "default"); |
89 | 92 | Asset savedAsset = doPost("/api/asset", asset, Asset.class); |
90 | 93 | |
91 | - doPost("/api/edge/" + edge.getId().toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); | |
94 | + doPost("/api/edge/" + edgeId.toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); | |
92 | 95 | |
93 | 96 | EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE); |
94 | 97 | |
95 | 98 | doPost("/api/relation", relation); |
96 | 99 | |
97 | - // wait while edge event for the relation entity persisted to DB | |
98 | - Thread.sleep(100); | |
99 | - List<EdgeEvent> edgeEvents; | |
100 | - int attempt = 1; | |
101 | - do { | |
102 | - edgeEvents = doGetTypedWithTimePageLink("/api/edge/" + edge.getId().toString() + "/events?", | |
103 | - new TypeReference<PageData<EdgeEvent>>() {}, new TimePageLink(4)).getData(); | |
104 | - attempt++; | |
105 | - Thread.sleep(100); | |
106 | - } while (edgeEvents.size() != 4 && attempt < 5); | |
107 | - Assert.assertEquals(4, edgeEvents.size()); | |
100 | + Awaitility.await() | |
101 | + .atMost(30, TimeUnit.SECONDS) | |
102 | + .until(() -> { | |
103 | + List<EdgeEvent> edgeEvents = findEdgeEvents(edgeId); | |
104 | + return edgeEvents.size() == 4; | |
105 | + }); | |
106 | + List<EdgeEvent> edgeEvents = findEdgeEvents(edgeId); | |
108 | 107 | Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.RULE_CHAIN.equals(ee.getType()))); |
109 | 108 | Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.DEVICE.equals(ee.getType()))); |
110 | 109 | Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.ASSET.equals(ee.getType()))); |
111 | 110 | Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.RELATION.equals(ee.getType()))); |
112 | 111 | } |
113 | 112 | |
113 | + private List<EdgeEvent> findEdgeEvents(EdgeId edgeId) throws Exception { | |
114 | + return doGetTypedWithTimePageLink("/api/edge/" + edgeId.toString() + "/events?", | |
115 | + new TypeReference<PageData<EdgeEvent>>() { | |
116 | + }, new TimePageLink(10)).getData(); | |
117 | + } | |
118 | + | |
114 | 119 | private Device constructDevice(String name, String type) { |
115 | 120 | Device device = new Device(); |
116 | 121 | device.setName(name); | ... | ... |
... | ... | @@ -27,6 +27,7 @@ import com.google.protobuf.InvalidProtocolBufferException; |
27 | 27 | import com.google.protobuf.MessageLite; |
28 | 28 | import lombok.extern.slf4j.Slf4j; |
29 | 29 | import org.apache.commons.lang3.RandomStringUtils; |
30 | +import org.awaitility.Awaitility; | |
30 | 31 | import org.junit.After; |
31 | 32 | import org.junit.Assert; |
32 | 33 | import org.junit.Before; |
... | ... | @@ -114,7 +115,7 @@ import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; |
114 | 115 | import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg; |
115 | 116 | import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg; |
116 | 117 | import org.thingsboard.server.gen.transport.TransportProtos; |
117 | -import org.thingsboard.server.service.queue.TbClusterService; | |
118 | +import org.thingsboard.server.cluster.TbClusterService; | |
118 | 119 | |
119 | 120 | import java.util.ArrayList; |
120 | 121 | import java.util.List; |
... | ... | @@ -126,6 +127,7 @@ import java.util.UUID; |
126 | 127 | import java.util.concurrent.TimeUnit; |
127 | 128 | |
128 | 129 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
130 | +import static org.thingsboard.server.service.edge.rpc.EdgeProtoUtils.getStringValue; | |
129 | 131 | |
130 | 132 | @Slf4j |
131 | 133 | abstract public class BaseEdgeTest extends AbstractControllerTest { |
... | ... | @@ -648,7 +650,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
648 | 650 | Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); |
649 | 651 | Assert.assertEquals(relationUpdateMsg.getToIdLSB(), relation.getTo().getId().getLeastSignificantBits()); |
650 | 652 | Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); |
651 | - Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name()); | |
653 | + Assert.assertEquals(relationUpdateMsg.getTypeGroup().getValue(), relation.getTypeGroup().name()); | |
652 | 654 | |
653 | 655 | // 2 |
654 | 656 | edgeImitator.expectMessageAmount(1); |
... | ... | @@ -672,7 +674,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
672 | 674 | Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); |
673 | 675 | Assert.assertEquals(relationUpdateMsg.getToIdLSB(), relation.getTo().getId().getLeastSignificantBits()); |
674 | 676 | Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); |
675 | - Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name()); | |
677 | + Assert.assertEquals(relationUpdateMsg.getTypeGroup().getValue(), relation.getTypeGroup().name()); | |
676 | 678 | |
677 | 679 | log.info("Relations tested successfully"); |
678 | 680 | } |
... | ... | @@ -730,7 +732,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
730 | 732 | edgeImitator.expectMessageAmount(1); |
731 | 733 | doDelete("/api/alarm/" + savedAlarm.getId().getId().toString()) |
732 | 734 | .andExpect(status().isOk()); |
733 | - Assert.assertFalse(edgeImitator.waitForMessages(1)); | |
735 | + Assert.assertTrue(edgeImitator.waitForMessages(1)); | |
736 | + latestMessage = edgeImitator.getLatestMessage(); | |
737 | + Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); | |
738 | + alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; | |
739 | + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, alarmUpdateMsg.getMsgType()); | |
740 | + Assert.assertEquals(alarmUpdateMsg.getType(), savedAlarm.getType()); | |
741 | + Assert.assertEquals(alarmUpdateMsg.getName(), savedAlarm.getName()); | |
742 | + Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName()); | |
743 | + Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.CLEARED_ACK.name()); | |
734 | 744 | |
735 | 745 | log.info("Alarms tested successfully"); |
736 | 746 | } |
... | ... | @@ -900,9 +910,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
900 | 910 | Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, widgetTypeUpdateMsg.getMsgType()); |
901 | 911 | Assert.assertEquals(widgetTypeUpdateMsg.getIdMSB(), savedWidgetType.getUuidId().getMostSignificantBits()); |
902 | 912 | Assert.assertEquals(widgetTypeUpdateMsg.getIdLSB(), savedWidgetType.getUuidId().getLeastSignificantBits()); |
903 | - Assert.assertEquals(widgetTypeUpdateMsg.getAlias(), savedWidgetType.getAlias()); | |
904 | - Assert.assertEquals(widgetTypeUpdateMsg.getName(), savedWidgetType.getName()); | |
905 | - Assert.assertEquals(JacksonUtil.toJsonNode(widgetTypeUpdateMsg.getDescriptorJson()), savedWidgetType.getDescriptor()); | |
913 | + Assert.assertEquals(widgetTypeUpdateMsg.getAlias().getValue(), savedWidgetType.getAlias()); | |
914 | + Assert.assertEquals(widgetTypeUpdateMsg.getName().getValue(), savedWidgetType.getName()); | |
915 | + Assert.assertEquals(JacksonUtil.toJsonNode(widgetTypeUpdateMsg.getDescriptorJson().getValue()), savedWidgetType.getDescriptor()); | |
906 | 916 | |
907 | 917 | // 3 |
908 | 918 | edgeImitator.expectMessageAmount(1); |
... | ... | @@ -939,7 +949,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
939 | 949 | String timeseriesData = "{\"data\":{\"temperature\":25},\"ts\":" + System.currentTimeMillis() + "}"; |
940 | 950 | JsonNode timeseriesEntityData = mapper.readTree(timeseriesData); |
941 | 951 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); |
942 | - edgeEventService.saveAsync(edgeEvent); | |
952 | + edgeEventService.save(edgeEvent); | |
943 | 953 | clusterService.onEdgeEventUpdate(tenantId, edge.getId()); |
944 | 954 | Assert.assertTrue(edgeImitator.waitForMessages()); |
945 | 955 | |
... | ... | @@ -978,7 +988,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
978 | 988 | JsonNode attributesEntityData = mapper.readTree(attributesData); |
979 | 989 | EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); |
980 | 990 | edgeImitator.expectMessageAmount(1); |
981 | - edgeEventService.saveAsync(edgeEvent1); | |
991 | + edgeEventService.save(edgeEvent1); | |
982 | 992 | clusterService.onEdgeEventUpdate(tenantId, edge.getId()); |
983 | 993 | Assert.assertTrue(edgeImitator.waitForMessages()); |
984 | 994 | |
... | ... | @@ -1003,7 +1013,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1003 | 1013 | JsonNode postAttributesEntityData = mapper.readTree(postAttributesData); |
1004 | 1014 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.POST_ATTRIBUTES, device.getId().getId(), EdgeEventType.DEVICE, postAttributesEntityData); |
1005 | 1015 | edgeImitator.expectMessageAmount(1); |
1006 | - edgeEventService.saveAsync(edgeEvent); | |
1016 | + edgeEventService.save(edgeEvent); | |
1007 | 1017 | clusterService.onEdgeEventUpdate(tenantId, edge.getId()); |
1008 | 1018 | Assert.assertTrue(edgeImitator.waitForMessages()); |
1009 | 1019 | |
... | ... | @@ -1028,7 +1038,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1028 | 1038 | JsonNode deleteAttributesEntityData = mapper.readTree(deleteAttributesData); |
1029 | 1039 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_DELETED, device.getId().getId(), EdgeEventType.DEVICE, deleteAttributesEntityData); |
1030 | 1040 | edgeImitator.expectMessageAmount(1); |
1031 | - edgeEventService.saveAsync(edgeEvent); | |
1041 | + edgeEventService.save(edgeEvent); | |
1032 | 1042 | clusterService.onEdgeEventUpdate(tenantId, edge.getId()); |
1033 | 1043 | Assert.assertTrue(edgeImitator.waitForMessages()); |
1034 | 1044 | |
... | ... | @@ -1062,7 +1072,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1062 | 1072 | |
1063 | 1073 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.RPC_CALL, device.getId().getId(), EdgeEventType.DEVICE, body); |
1064 | 1074 | edgeImitator.expectMessageAmount(1); |
1065 | - edgeEventService.saveAsync(edgeEvent); | |
1075 | + edgeEventService.save(edgeEvent); | |
1066 | 1076 | clusterService.onEdgeEventUpdate(tenantId, edge.getId()); |
1067 | 1077 | Assert.assertTrue(edgeImitator.waitForMessages()); |
1068 | 1078 | |
... | ... | @@ -1088,7 +1098,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1088 | 1098 | JsonNode timeseriesEntityData = mapper.readTree(timeseriesData); |
1089 | 1099 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, |
1090 | 1100 | device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); |
1091 | - edgeEventService.saveAsync(edgeEvent); | |
1101 | + edgeEventService.save(edgeEvent); | |
1092 | 1102 | clusterService.onEdgeEventUpdate(tenantId, edge.getId()); |
1093 | 1103 | } |
1094 | 1104 | |
... | ... | @@ -1202,7 +1212,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1202 | 1212 | Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); |
1203 | 1213 | DeviceUpdateMsg latestDeviceUpdateMsg = (DeviceUpdateMsg) latestMessage; |
1204 | 1214 | Assert.assertNotEquals(deviceOnCloudName, latestDeviceUpdateMsg.getName()); |
1205 | - Assert.assertEquals(deviceOnCloudName, latestDeviceUpdateMsg.getConflictName()); | |
1215 | + Assert.assertEquals(deviceOnCloudName, latestDeviceUpdateMsg.getConflictName().getValue()); | |
1206 | 1216 | |
1207 | 1217 | UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB()); |
1208 | 1218 | |
... | ... | @@ -1269,7 +1279,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1269 | 1279 | EntityId toEntityId = EntityIdFactory.getByTypeAndUuid(relationUpdateMsg.getToEntityType(), toUUID); |
1270 | 1280 | Assert.assertEquals(relation.getTo(), toEntityId); |
1271 | 1281 | |
1272 | - Assert.assertEquals(relation.getTypeGroup().name(), relationUpdateMsg.getTypeGroup()); | |
1282 | + Assert.assertEquals(relation.getTypeGroup().name(), relationUpdateMsg.getTypeGroup().getValue()); | |
1273 | 1283 | } |
1274 | 1284 | |
1275 | 1285 | private void sendAlarm() throws Exception { |
... | ... | @@ -1348,15 +1358,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1348 | 1358 | edgeImitator.sendUplinkMsg(uplinkMsgBuilder2.build()); |
1349 | 1359 | Assert.assertTrue(edgeImitator.waitForResponses()); |
1350 | 1360 | |
1351 | - int attempt = 0; | |
1352 | - Map<String, List<Map<String, String>>> timeseries; | |
1353 | - do { | |
1354 | - timeseries = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + device.getUuidId() + "/values/timeseries?keys=" + timeseriesKey, | |
1355 | - new TypeReference<>() {}); | |
1356 | - // Wait before device attributes saved to database before requesting them from controller | |
1357 | - Thread.sleep(100); | |
1358 | - attempt++; | |
1359 | - } while (!timeseries.containsKey(timeseriesKey) || attempt < 10); | |
1361 | + Awaitility.await() | |
1362 | + .atMost(2, TimeUnit.SECONDS) | |
1363 | + .until(() -> loadDeviceTimeseries(device, timeseriesKey).containsKey(timeseriesKey)); | |
1364 | + | |
1365 | + Map<String, List<Map<String, String>>> timeseries = loadDeviceTimeseries(device, timeseriesKey); | |
1360 | 1366 | Assert.assertTrue(timeseries.containsKey(timeseriesKey)); |
1361 | 1367 | Assert.assertEquals(1, timeseries.get(timeseriesKey).size()); |
1362 | 1368 | Assert.assertEquals(timeseriesValue, timeseries.get(timeseriesKey).get(0).get("value")); |
... | ... | @@ -1365,7 +1371,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1365 | 1371 | Assert.assertEquals(1, attributes.size()); |
1366 | 1372 | Assert.assertEquals(attributes.get(0).get("key"), attributesKey); |
1367 | 1373 | Assert.assertEquals(attributes.get(0).get("value"), attributesValue); |
1374 | + } | |
1368 | 1375 | |
1376 | + private Map<String, List<Map<String, String>>> loadDeviceTimeseries(Device device, String timeseriesKey) throws Exception { | |
1377 | + return doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + device.getUuidId() + "/values/timeseries?keys=" + timeseriesKey, | |
1378 | + new TypeReference<>() {}); | |
1369 | 1379 | } |
1370 | 1380 | |
1371 | 1381 | private void sendRelation() throws Exception { |
... | ... | @@ -1381,7 +1391,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1381 | 1391 | UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder(); |
1382 | 1392 | RelationUpdateMsg.Builder relationUpdateMsgBuilder = RelationUpdateMsg.newBuilder(); |
1383 | 1393 | relationUpdateMsgBuilder.setType("test"); |
1384 | - relationUpdateMsgBuilder.setTypeGroup(RelationTypeGroup.COMMON.name()); | |
1394 | + relationUpdateMsgBuilder.setTypeGroup(getStringValue(RelationTypeGroup.COMMON.name())); | |
1385 | 1395 | relationUpdateMsgBuilder.setToIdMSB(device1.getId().getId().getMostSignificantBits()); |
1386 | 1396 | relationUpdateMsgBuilder.setToIdLSB(device1.getId().getId().getLeastSignificantBits()); |
1387 | 1397 | relationUpdateMsgBuilder.setToEntityType(device1.getId().getEntityType().name()); |
... | ... | @@ -1447,7 +1457,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
1447 | 1457 | edgeImitator.expectMessageAmount(1); |
1448 | 1458 | edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); |
1449 | 1459 | Assert.assertTrue(edgeImitator.waitForResponses()); |
1450 | - Assert.assertTrue(edgeImitator.waitForMessages());; | |
1460 | + Assert.assertTrue(edgeImitator.waitForMessages()); | |
1451 | 1461 | |
1452 | 1462 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); |
1453 | 1463 | Assert.assertTrue(latestMessage instanceof RuleChainMetadataUpdateMsg); | ... | ... |
... | ... | @@ -27,7 +27,7 @@ import org.thingsboard.server.dao.device.DeviceService; |
27 | 27 | import org.thingsboard.server.dao.tenant.TenantService; |
28 | 28 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
29 | 29 | import org.thingsboard.server.queue.discovery.PartitionService; |
30 | -import org.thingsboard.server.service.queue.TbClusterService; | |
30 | +import org.thingsboard.server.cluster.TbClusterService; | |
31 | 31 | |
32 | 32 | import static org.hamcrest.CoreMatchers.is; |
33 | 33 | import static org.hamcrest.MatcherAssert.assertThat; | ... | ... |
... | ... | @@ -43,7 +43,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab |
43 | 43 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}"; |
44 | 44 | String deviceId = savedDevice.getId().getId().toString(); |
45 | 45 | |
46 | - doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409), | |
46 | + doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(504), | |
47 | 47 | asyncContextTimeoutToUseRpcPlugin); |
48 | 48 | } |
49 | 49 | |
... | ... | @@ -52,7 +52,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab |
52 | 52 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"25\",\"value\": 1}}"; |
53 | 53 | String nonExistentDeviceId = Uuids.timeBased().toString(); |
54 | 54 | |
55 | - String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
55 | + String result = doPostAsync("/api/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
56 | 56 | status().isNotFound()); |
57 | 57 | Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); |
58 | 58 | } |
... | ... | @@ -62,7 +62,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab |
62 | 62 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}"; |
63 | 63 | String deviceId = savedDevice.getId().getId().toString(); |
64 | 64 | |
65 | - doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409), | |
65 | + doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(504), | |
66 | 66 | asyncContextTimeoutToUseRpcPlugin); |
67 | 67 | } |
68 | 68 | |
... | ... | @@ -71,7 +71,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab |
71 | 71 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"28\",\"value\": 1}}"; |
72 | 72 | String nonExistentDeviceId = Uuids.timeBased().toString(); |
73 | 73 | |
74 | - String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
74 | + String result = doPostAsync("/api/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
75 | 75 | status().isNotFound()); |
76 | 76 | Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); |
77 | 77 | } | ... | ... |
... | ... | @@ -71,7 +71,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC |
71 | 71 | |
72 | 72 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
73 | 73 | String deviceId = savedDevice.getId().getId().toString(); |
74 | - String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
74 | + String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
75 | 75 | |
76 | 76 | latch.await(3, TimeUnit.SECONDS); |
77 | 77 | |
... | ... | @@ -99,14 +99,14 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC |
99 | 99 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; |
100 | 100 | String deviceId = savedDevice.getId().getId().toString(); |
101 | 101 | |
102 | - String actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
102 | + String actualResult = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
103 | 103 | latch.await(3, TimeUnit.SECONDS); |
104 | 104 | |
105 | 105 | validateTwoWayStateChangedNotification(callback, 1, expectedResponseResult, actualResult); |
106 | 106 | |
107 | 107 | latch = new CountDownLatch(1); |
108 | 108 | |
109 | - actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
109 | + actualResult = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
110 | 110 | latch.await(3, TimeUnit.SECONDS); |
111 | 111 | |
112 | 112 | validateTwoWayStateChangedNotification(callback, 2, expectedResponseResult, actualResult); | ... | ... |
... | ... | @@ -27,6 +27,7 @@ import org.springframework.mock.web.MockMultipartFile; |
27 | 27 | import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; |
28 | 28 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; |
29 | 29 | import org.thingsboard.common.util.JacksonUtil; |
30 | +import org.thingsboard.common.util.ThingsBoardThreadFactory; | |
30 | 31 | import org.thingsboard.server.common.data.Device; |
31 | 32 | import org.thingsboard.server.common.data.DeviceProfile; |
32 | 33 | import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
... | ... | @@ -261,7 +262,7 @@ public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { |
261 | 262 | |
262 | 263 | @Before |
263 | 264 | public void beforeTest() throws Exception { |
264 | - executor = Executors.newScheduledThreadPool(10); | |
265 | + executor = Executors.newScheduledThreadPool(10, ThingsBoardThreadFactory.forName("test-lwm2m-scheduled")); | |
265 | 266 | loginTenantAdmin(); |
266 | 267 | |
267 | 268 | String[] resources = new String[]{"1.xml", "2.xml", "3.xml", "5.xml", "9.xml"}; | ... | ... |
... | ... | @@ -16,6 +16,8 @@ |
16 | 16 | package org.thingsboard.server.transport.lwm2m; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.type.TypeReference; |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.junit.After; | |
19 | 21 | import org.junit.Assert; |
20 | 22 | import org.junit.Test; |
21 | 23 | import org.thingsboard.server.common.data.Device; |
... | ... | @@ -23,16 +25,18 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCr |
23 | 25 | import org.thingsboard.server.common.data.kv.KvEntry; |
24 | 26 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
25 | 27 | import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus; |
26 | -import org.thingsboard.server.common.data.query.EntityKey; | |
27 | -import org.thingsboard.server.common.data.query.EntityKeyType; | |
28 | 28 | import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; |
29 | 29 | |
30 | 30 | import java.util.Arrays; |
31 | 31 | import java.util.Collections; |
32 | 32 | import java.util.Comparator; |
33 | 33 | import java.util.List; |
34 | +import java.util.UUID; | |
35 | +import java.util.concurrent.TimeUnit; | |
34 | 36 | import java.util.stream.Collectors; |
35 | 37 | |
38 | +import static org.awaitility.Awaitility.await; | |
39 | +import static org.hamcrest.Matchers.is; | |
36 | 40 | import static org.thingsboard.rest.client.utils.RestJsonConverter.toTimeseries; |
37 | 41 | import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED; |
38 | 42 | import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADING; |
... | ... | @@ -43,8 +47,10 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDA |
43 | 47 | import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; |
44 | 48 | import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED; |
45 | 49 | |
50 | +@Slf4j | |
46 | 51 | public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
47 | 52 | |
53 | + public static final int TIMEOUT = 30; | |
48 | 54 | private final String OTA_TRANSPORT_CONFIGURATION = "{\n" + |
49 | 55 | " \"observeAttr\": {\n" + |
50 | 56 | " \"keyName\": {\n" + |
... | ... | @@ -122,6 +128,15 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
122 | 128 | " \"type\": \"LWM2M\"\n" + |
123 | 129 | "}"; |
124 | 130 | |
131 | + LwM2MTestClient client = null; | |
132 | + | |
133 | + @After | |
134 | + public void tearDown() { | |
135 | + if (client != null) { | |
136 | + client.destroy(); | |
137 | + } | |
138 | + } | |
139 | + | |
125 | 140 | @Test |
126 | 141 | public void testConnectAndObserveTelemetry() throws Exception { |
127 | 142 | NoSecClientCredentials clientCredentials = new NoSecClientCredentials(); |
... | ... | @@ -196,37 +211,68 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
196 | 211 | } |
197 | 212 | } |
198 | 213 | |
214 | + /** | |
215 | + * This is the example how to use the AWAITILITY instead Thread.sleep() | |
216 | + * Test will finish as fast as possible, but will await until TIMEOUT if a build machine is busy or slow | |
217 | + * Check the detailed log output to learn how Awaitility polling the API and when exactly expected result appears | |
218 | + * */ | |
199 | 219 | @Test |
200 | 220 | public void testSoftwareUpdateByObject9() throws Exception { |
201 | - LwM2MTestClient client = null; | |
202 | - try { | |
203 | - createDeviceProfile(OTA_TRANSPORT_CONFIGURATION); | |
204 | - NoSecClientCredentials clientCredentials = new NoSecClientCredentials(); | |
205 | - clientCredentials.setEndpoint("OTA_" + ENDPOINT); | |
206 | - Device device = createDevice(clientCredentials); | |
207 | - | |
208 | - device.setSoftwareId(createSoftware().getId()); | |
209 | - device = doPost("/api/device", device, Device.class); | |
221 | + //given | |
222 | + final List<OtaPackageUpdateStatus> expectedStatuses = Collections.unmodifiableList(Arrays.asList( | |
223 | + QUEUED, INITIATED, DOWNLOADING, DOWNLOADING, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATED)); | |
210 | 224 | |
211 | - Thread.sleep(1000); | |
212 | - | |
213 | - client = new LwM2MTestClient(executor, "OTA_" + ENDPOINT); | |
214 | - client.init(SECURITY, COAP_CONFIG); | |
215 | - | |
216 | - Thread.sleep(3000); | |
217 | - | |
218 | - List<TsKvEntry> ts = toTimeseries(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + device.getId().getId() + "/values/timeseries?orderBy=ASC&keys=sw_state&startTs=0&endTs=" + System.currentTimeMillis(), new TypeReference<>() { | |
219 | - })); | |
220 | - | |
221 | - List<OtaPackageUpdateStatus> statuses = ts.stream().sorted(Comparator.comparingLong(TsKvEntry::getTs)).map(KvEntry::getValueAsString).map(OtaPackageUpdateStatus::valueOf).collect(Collectors.toList()); | |
225 | + createDeviceProfile(OTA_TRANSPORT_CONFIGURATION); | |
226 | + NoSecClientCredentials clientCredentials = new NoSecClientCredentials(); | |
227 | + clientCredentials.setEndpoint("OTA_" + ENDPOINT); | |
228 | + final Device device = createDevice(clientCredentials); | |
229 | + device.setSoftwareId(createSoftware().getId()); | |
230 | + | |
231 | + log.warn("Saving by API " + device); | |
232 | + final Device savedDevice = doPost("/api/device", device, Device.class); | |
233 | + Assert.assertNotNull(savedDevice); | |
234 | + log.warn("Device saved by API {}", savedDevice); | |
235 | + | |
236 | + log.warn("AWAIT atMost {} SECONDS on get device by API...", TIMEOUT); | |
237 | + await() | |
238 | + .atMost(TIMEOUT, TimeUnit.SECONDS) | |
239 | + .until(() -> getDeviceFromAPI(device.getId().getId()), is(savedDevice)); | |
240 | + log.warn("Got device by API."); | |
241 | + | |
242 | + //when | |
243 | + log.warn("Init the client..."); | |
244 | + client = new LwM2MTestClient(executor, "OTA_" + ENDPOINT); | |
245 | + client.init(SECURITY, COAP_CONFIG); | |
246 | + log.warn("Init done"); | |
247 | + | |
248 | + log.warn("AWAIT atMost {} SECONDS on timeseries List<TsKvEntry> by API with list size {}...", TIMEOUT, expectedStatuses.size()); | |
249 | + await() | |
250 | + .atMost(30, TimeUnit.SECONDS) | |
251 | + .until(() -> getSwStateTelemetryFromAPI(device.getId().getId()) | |
252 | + .size(), is(expectedStatuses.size())); | |
253 | + log.warn("Got an expected await condition!"); | |
254 | + | |
255 | + //then | |
256 | + log.warn("Fetching ts for the final asserts"); | |
257 | + List<TsKvEntry> ts = getSwStateTelemetryFromAPI(device.getId().getId()); | |
258 | + log.warn("Got an ts {}", ts); | |
259 | + | |
260 | + List<OtaPackageUpdateStatus> statuses = ts.stream().sorted(Comparator.comparingLong(TsKvEntry::getTs)).map(KvEntry::getValueAsString).map(OtaPackageUpdateStatus::valueOf).collect(Collectors.toList()); | |
261 | + log.warn("Converted ts to statuses {}", statuses); | |
262 | + | |
263 | + Assert.assertEquals(expectedStatuses, statuses); | |
264 | + } | |
222 | 265 | |
223 | - List<OtaPackageUpdateStatus> expectedStatuses = Arrays.asList(QUEUED, INITIATED, DOWNLOADING, DOWNLOADING, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATED); | |
266 | + private Device getDeviceFromAPI(UUID deviceId) throws Exception { | |
267 | + final Device device = doGet("/api/device/" + deviceId, Device.class); | |
268 | + log.warn("Fetched device by API for deviceId {}, device is {}", deviceId, device); | |
269 | + return device; | |
270 | + } | |
224 | 271 | |
225 | - Assert.assertEquals(expectedStatuses, statuses); | |
226 | - } finally { | |
227 | - if (client != null) { | |
228 | - client.destroy(); | |
229 | - } | |
230 | - } | |
272 | + private List<TsKvEntry> getSwStateTelemetryFromAPI(UUID deviceId) throws Exception { | |
273 | + final List<TsKvEntry> tsKvEntries = toTimeseries(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?orderBy=ASC&keys=sw_state&startTs=0&endTs=" + System.currentTimeMillis(), new TypeReference<>() { | |
274 | + })); | |
275 | + log.warn("Fetched telemetry by API for deviceId {}, list size {}, tsKvEntries {}", deviceId, tsKvEntries.size(), tsKvEntries); | |
276 | + return tsKvEntries; | |
231 | 277 | } |
232 | 278 | } | ... | ... |
... | ... | @@ -46,7 +46,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab |
46 | 46 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}"; |
47 | 47 | String deviceId = savedDevice.getId().getId().toString(); |
48 | 48 | |
49 | - doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409), | |
49 | + doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(504), | |
50 | 50 | asyncContextTimeoutToUseRpcPlugin); |
51 | 51 | } |
52 | 52 | |
... | ... | @@ -55,7 +55,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab |
55 | 55 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"25\",\"value\": 1}}"; |
56 | 56 | String nonExistentDeviceId = Uuids.timeBased().toString(); |
57 | 57 | |
58 | - String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
58 | + String result = doPostAsync("/api/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
59 | 59 | status().isNotFound()); |
60 | 60 | Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); |
61 | 61 | } |
... | ... | @@ -65,7 +65,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab |
65 | 65 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}"; |
66 | 66 | String deviceId = savedDevice.getId().getId().toString(); |
67 | 67 | |
68 | - doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409), | |
68 | + doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(504), | |
69 | 69 | asyncContextTimeoutToUseRpcPlugin); |
70 | 70 | } |
71 | 71 | |
... | ... | @@ -74,7 +74,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab |
74 | 74 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"28\",\"value\": 1}}"; |
75 | 75 | String nonExistentDeviceId = Uuids.timeBased().toString(); |
76 | 76 | |
77 | - String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
77 | + String result = doPostAsync("/api/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
78 | 78 | status().isNotFound()); |
79 | 79 | Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); |
80 | 80 | } | ... | ... |
... | ... | @@ -69,7 +69,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
69 | 69 | |
70 | 70 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
71 | 71 | String deviceId = savedDevice.getId().getId().toString(); |
72 | - String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
72 | + String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
73 | 73 | Assert.assertTrue(StringUtils.isEmpty(result)); |
74 | 74 | latch.await(3, TimeUnit.SECONDS); |
75 | 75 | assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS()); |
... | ... | @@ -95,7 +95,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
95 | 95 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; |
96 | 96 | String deviceId = savedDevice.getId().getId().toString(); |
97 | 97 | |
98 | - String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
98 | + String result = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
99 | 99 | String expected = "{\"value1\":\"A\",\"value2\":\"B\"}"; |
100 | 100 | latch.await(3, TimeUnit.SECONDS); |
101 | 101 | Assert.assertEquals(expected, result); |
... | ... | @@ -130,7 +130,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
130 | 130 | |
131 | 131 | String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}"; |
132 | 132 | String deviceId = savedDevice.getId().getId().toString(); |
133 | - String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
133 | + String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
134 | 134 | Assert.assertTrue(StringUtils.isEmpty(result)); |
135 | 135 | latch.await(3, TimeUnit.SECONDS); |
136 | 136 | assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS()); |
... | ... | @@ -156,7 +156,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
156 | 156 | |
157 | 157 | String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}"; |
158 | 158 | String deviceId = savedDevice.getId().getId().toString(); |
159 | - String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
159 | + String result = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
160 | 160 | latch.await(3, TimeUnit.SECONDS); |
161 | 161 | String expected = "{\"success\":true}"; |
162 | 162 | assertEquals(expected, result); | ... | ... |
... | ... | @@ -131,7 +131,7 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst |
131 | 131 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; |
132 | 132 | String deviceId = savedDevice.getId().getId().toString(); |
133 | 133 | |
134 | - String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
134 | + String result = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | |
135 | 135 | String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}"; |
136 | 136 | latch.await(3, TimeUnit.SECONDS); |
137 | 137 | Assert.assertEquals(expected, result); | ... | ... |
common/cluster-api/pom.xml
0 → 100644
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2021 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
20 | + <modelVersion>4.0.0</modelVersion> | |
21 | + <parent> | |
22 | + <groupId>org.thingsboard</groupId> | |
23 | + <version>3.3.0-SNAPSHOT</version> | |
24 | + <artifactId>common</artifactId> | |
25 | + </parent> | |
26 | + <groupId>org.thingsboard.common</groupId> | |
27 | + <artifactId>cluster-api</artifactId> | |
28 | + <packaging>jar</packaging> | |
29 | + | |
30 | + <name>Thingsboard Server Common Cluster API</name> | |
31 | + <url>https://thingsboard.io</url> | |
32 | + | |
33 | + <properties> | |
34 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
35 | + <main.dir>${basedir}/../..</main.dir> | |
36 | + </properties> | |
37 | + | |
38 | + <dependencies> | |
39 | + <dependency> | |
40 | + <groupId>org.thingsboard.common</groupId> | |
41 | + <artifactId>data</artifactId> | |
42 | + </dependency> | |
43 | + <dependency> | |
44 | + <groupId>org.thingsboard.common</groupId> | |
45 | + <artifactId>message</artifactId> | |
46 | + </dependency> | |
47 | + <dependency> | |
48 | + <groupId>org.thingsboard.common</groupId> | |
49 | + <artifactId>stats</artifactId> | |
50 | + </dependency> | |
51 | + <dependency> | |
52 | + <groupId>com.google.guava</groupId> | |
53 | + <artifactId>guava</artifactId> | |
54 | + </dependency> | |
55 | + <dependency> | |
56 | + <groupId>javax.annotation</groupId> | |
57 | + <artifactId>javax.annotation-api</artifactId> | |
58 | + </dependency> | |
59 | + <dependency> | |
60 | + <groupId>com.github.fge</groupId> | |
61 | + <artifactId>json-schema-validator</artifactId> | |
62 | + </dependency> | |
63 | + <dependency> | |
64 | + <groupId>org.slf4j</groupId> | |
65 | + <artifactId>slf4j-api</artifactId> | |
66 | + </dependency> | |
67 | + <dependency> | |
68 | + <groupId>org.slf4j</groupId> | |
69 | + <artifactId>log4j-over-slf4j</artifactId> | |
70 | + </dependency> | |
71 | + <dependency> | |
72 | + <groupId>ch.qos.logback</groupId> | |
73 | + <artifactId>logback-core</artifactId> | |
74 | + </dependency> | |
75 | + <dependency> | |
76 | + <groupId>ch.qos.logback</groupId> | |
77 | + <artifactId>logback-classic</artifactId> | |
78 | + </dependency> | |
79 | + <dependency> | |
80 | + <groupId>com.fasterxml.jackson.core</groupId> | |
81 | + <artifactId>jackson-databind</artifactId> | |
82 | + </dependency> | |
83 | + <dependency> | |
84 | + <groupId>org.springframework.boot</groupId> | |
85 | + <artifactId>spring-boot-autoconfigure</artifactId> | |
86 | + <scope>provided</scope> | |
87 | + </dependency> | |
88 | + <dependency> | |
89 | + <groupId>com.datastax.oss</groupId> | |
90 | + <artifactId>java-driver-core</artifactId> | |
91 | + <scope>provided</scope> | |
92 | + </dependency> | |
93 | + <dependency> | |
94 | + <groupId>io.dropwizard.metrics</groupId> | |
95 | + <artifactId>metrics-jmx</artifactId> | |
96 | + <scope>provided</scope> | |
97 | + </dependency> | |
98 | + <dependency> | |
99 | + <groupId>org.apache.commons</groupId> | |
100 | + <artifactId>commons-lang3</artifactId> | |
101 | + <scope>provided</scope> | |
102 | + </dependency> | |
103 | + <dependency> | |
104 | + <groupId>junit</groupId> | |
105 | + <artifactId>junit</artifactId> | |
106 | + <scope>test</scope> | |
107 | + </dependency> | |
108 | + <dependency> | |
109 | + <groupId>org.mockito</groupId> | |
110 | + <artifactId>mockito-core</artifactId> | |
111 | + <scope>test</scope> | |
112 | + </dependency> | |
113 | + </dependencies> | |
114 | + | |
115 | + <build> | |
116 | + <plugins> | |
117 | + <plugin> | |
118 | + <groupId>org.xolstice.maven.plugins</groupId> | |
119 | + <artifactId>protobuf-maven-plugin</artifactId> | |
120 | + </plugin> | |
121 | + <plugin> | |
122 | + <groupId>org.apache.maven.plugins</groupId> | |
123 | + <artifactId>maven-source-plugin</artifactId> | |
124 | + <executions> | |
125 | + <execution> | |
126 | + <id>attach-sources</id> | |
127 | + <goals> | |
128 | + <goal>jar</goal> | |
129 | + </goals> | |
130 | + </execution> | |
131 | + </executions> | |
132 | + </plugin> | |
133 | + <plugin> | |
134 | + <groupId>org.apache.maven.plugins</groupId> | |
135 | + <artifactId>maven-deploy-plugin</artifactId> | |
136 | + <configuration> | |
137 | + <skip>false</skip> | |
138 | + </configuration> | |
139 | + </plugin> | |
140 | + </plugins> | |
141 | + </build> | |
142 | + | |
143 | + | |
144 | +</project> | ... | ... |
common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java
renamed from
application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java
... | ... | @@ -13,26 +13,29 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.service.queue; | |
16 | +package org.thingsboard.server.cluster; | |
17 | 17 | |
18 | -import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; | |
18 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | |
19 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | |
20 | +import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; | |
19 | 21 | import org.thingsboard.server.common.data.ApiUsageState; |
20 | 22 | import org.thingsboard.server.common.data.Device; |
21 | 23 | import org.thingsboard.server.common.data.DeviceProfile; |
22 | 24 | import org.thingsboard.server.common.data.TbResource; |
23 | 25 | import org.thingsboard.server.common.data.Tenant; |
24 | 26 | import org.thingsboard.server.common.data.TenantProfile; |
27 | +import org.thingsboard.server.common.data.id.DeviceId; | |
25 | 28 | import org.thingsboard.server.common.data.id.EdgeId; |
26 | 29 | import org.thingsboard.server.common.data.id.EntityId; |
27 | 30 | import org.thingsboard.server.common.data.id.TenantId; |
28 | 31 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
29 | 32 | import org.thingsboard.server.common.msg.TbMsg; |
30 | 33 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
34 | +import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; | |
31 | 35 | import org.thingsboard.server.gen.transport.TransportProtos; |
32 | 36 | import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
33 | 37 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
34 | 38 | import org.thingsboard.server.queue.TbQueueCallback; |
35 | -import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | |
36 | 39 | |
37 | 40 | import java.util.UUID; |
38 | 41 | |
... | ... | @@ -54,7 +57,7 @@ public interface TbClusterService { |
54 | 57 | |
55 | 58 | void pushNotificationToTransport(String targetServiceId, ToTransportMsg response, TbQueueCallback callback); |
56 | 59 | |
57 | - void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state); | |
60 | + void broadcastEntityStateChangeEvent(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state); | |
58 | 61 | |
59 | 62 | void onDeviceProfileChange(DeviceProfile deviceProfile, TbQueueCallback callback); |
60 | 63 | |
... | ... | @@ -70,7 +73,7 @@ public interface TbClusterService { |
70 | 73 | |
71 | 74 | void onApiStateChange(ApiUsageState apiUsageState, TbQueueCallback callback); |
72 | 75 | |
73 | - void onDeviceChange(Device device, TbQueueCallback callback); | |
76 | + void onDeviceUpdated(Device device, Device old); | |
74 | 77 | |
75 | 78 | void onDeviceDeleted(Device device, TbQueueCallback callback); |
76 | 79 | |
... | ... | @@ -79,4 +82,6 @@ public interface TbClusterService { |
79 | 82 | void onResourceDeleted(TbResource resource, TbQueueCallback callback); |
80 | 83 | |
81 | 84 | void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId); |
85 | + | |
86 | + void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action); | |
82 | 87 | } | ... | ... |
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueAdmin.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueAdmin.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueCallback.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueCallback.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueConsumer.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueConsumer.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueHandler.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueHandler.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueMsg.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueMsg.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueMsgDecoder.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueMsgDecoder.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueMsgHeaders.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueMsgHeaders.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueMsgMetadata.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueMsgMetadata.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueProducer.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueProducer.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueRequestTemplate.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueRequestTemplate.java
common/cluster-api/src/main/java/org/thingsboard/server/queue/TbQueueResponseTemplate.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/TbQueueResponseTemplate.java
common/cluster-api/src/main/proto/jsinvoke.proto
renamed from
common/queue/src/main/proto/jsinvoke.proto
common/cluster-api/src/main/proto/queue.proto
renamed from
common/queue/src/main/proto/queue.proto
... | ... | @@ -54,6 +54,8 @@ public interface DeviceService { |
54 | 54 | |
55 | 55 | Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials); |
56 | 56 | |
57 | + Device saveDevice(ProvisionRequest provisionRequest, DeviceProfile profile); | |
58 | + | |
57 | 59 | void createAccessTokenCredentials(Device device, String accessToken); |
58 | 60 | |
59 | 61 | Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId); |
... | ... | @@ -100,8 +102,6 @@ public interface DeviceService { |
100 | 102 | |
101 | 103 | Device assignDeviceToTenant(TenantId tenantId, Device device); |
102 | 104 | |
103 | - Device saveDevice(ProvisionRequest provisionRequest, DeviceProfile profile); | |
104 | - | |
105 | 105 | PageData<UUID> findDevicesIdsByDeviceProfileTransportType(DeviceTransportType transportType, PageLink pageLink); |
106 | 106 | |
107 | 107 | Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId); | ... | ... |