Commit 9317281f573a965c4a1b90af696514716425f4f0
Merge remote-tracking branch 'thingsboard/master' into edge/cleanups-fixes
Showing
53 changed files
with
1789 additions
and
1561 deletions
Too many changes to show.
To preserve performance only 53 of 613 files are displayed.
@@ -33,15 +33,15 @@ | @@ -33,15 +33,15 @@ | ||
33 | "enableSearch": true, | 33 | "enableSearch": true, |
34 | "displayPagination": true, | 34 | "displayPagination": true, |
35 | "defaultPageSize": 10, | 35 | "defaultPageSize": 10, |
36 | - "defaultSortOrder": "entityLabel", | ||
37 | - "displayEntityName": false, | 36 | + "defaultSortOrder": "entityName", |
37 | + "displayEntityName": true, | ||
38 | "displayEntityType": false, | 38 | "displayEntityType": false, |
39 | "enableSelectColumnDisplay": false, | 39 | "enableSelectColumnDisplay": false, |
40 | "enableStickyHeader": true, | 40 | "enableStickyHeader": true, |
41 | "enableStickyAction": false, | 41 | "enableStickyAction": false, |
42 | "entitiesTitle": "Devices", | 42 | "entitiesTitle": "Devices", |
43 | - "displayEntityLabel": true, | ||
44 | - "entityLabelColumnTitle": "Device" | 43 | + "displayEntityLabel": false, |
44 | + "entityNameColumnTitle": "Device" | ||
45 | }, | 45 | }, |
46 | "title": "New Entities table", | 46 | "title": "New Entities table", |
47 | "dropShadow": true, | 47 | "dropShadow": true, |
@@ -828,15 +828,15 @@ | @@ -828,15 +828,15 @@ | ||
828 | "enableSearch": true, | 828 | "enableSearch": true, |
829 | "displayPagination": true, | 829 | "displayPagination": true, |
830 | "defaultPageSize": 10, | 830 | "defaultPageSize": 10, |
831 | - "defaultSortOrder": "entityLabel", | ||
832 | - "displayEntityName": false, | 831 | + "defaultSortOrder": "entityName", |
832 | + "displayEntityName": true, | ||
833 | "displayEntityType": false, | 833 | "displayEntityType": false, |
834 | "enableSelectColumnDisplay": false, | 834 | "enableSelectColumnDisplay": false, |
835 | "enableStickyHeader": true, | 835 | "enableStickyHeader": true, |
836 | "enableStickyAction": true, | 836 | "enableStickyAction": true, |
837 | "entitiesTitle": "Devices", | 837 | "entitiesTitle": "Devices", |
838 | - "displayEntityLabel": true, | ||
839 | - "entityLabelColumnTitle": "Device" | 838 | + "displayEntityLabel": false, |
839 | + "entityNameColumnTitle": "Device" | ||
840 | }, | 840 | }, |
841 | "title": "New Entities table", | 841 | "title": "New Entities table", |
842 | "dropShadow": true, | 842 | "dropShadow": true, |
@@ -1125,15 +1125,15 @@ | @@ -1125,15 +1125,15 @@ | ||
1125 | "enableSearch": true, | 1125 | "enableSearch": true, |
1126 | "displayPagination": true, | 1126 | "displayPagination": true, |
1127 | "defaultPageSize": 10, | 1127 | "defaultPageSize": 10, |
1128 | - "defaultSortOrder": "entityLabel", | ||
1129 | - "displayEntityName": false, | 1128 | + "defaultSortOrder": "entityName", |
1129 | + "displayEntityName": true, | ||
1130 | "displayEntityType": false, | 1130 | "displayEntityType": false, |
1131 | "enableSelectColumnDisplay": false, | 1131 | "enableSelectColumnDisplay": false, |
1132 | "enableStickyHeader": true, | 1132 | "enableStickyHeader": true, |
1133 | "enableStickyAction": true, | 1133 | "enableStickyAction": true, |
1134 | "entitiesTitle": "Devices", | 1134 | "entitiesTitle": "Devices", |
1135 | - "displayEntityLabel": true, | ||
1136 | - "entityLabelColumnTitle": "Device" | 1135 | + "displayEntityLabel": false, |
1136 | + "entityNameColumnTitle": "Device" | ||
1137 | }, | 1137 | }, |
1138 | "title": "New Entities table", | 1138 | "title": "New Entities table", |
1139 | "dropShadow": true, | 1139 | "dropShadow": true, |
@@ -1422,15 +1422,15 @@ | @@ -1422,15 +1422,15 @@ | ||
1422 | "enableSearch": true, | 1422 | "enableSearch": true, |
1423 | "displayPagination": true, | 1423 | "displayPagination": true, |
1424 | "defaultPageSize": 10, | 1424 | "defaultPageSize": 10, |
1425 | - "defaultSortOrder": "entityLabel", | ||
1426 | - "displayEntityName": false, | 1425 | + "defaultSortOrder": "entityName", |
1426 | + "displayEntityName": true, | ||
1427 | "displayEntityType": false, | 1427 | "displayEntityType": false, |
1428 | "enableSelectColumnDisplay": false, | 1428 | "enableSelectColumnDisplay": false, |
1429 | "enableStickyHeader": true, | 1429 | "enableStickyHeader": true, |
1430 | "enableStickyAction": true, | 1430 | "enableStickyAction": true, |
1431 | "entitiesTitle": "Devices", | 1431 | "entitiesTitle": "Devices", |
1432 | - "displayEntityLabel": true, | ||
1433 | - "entityLabelColumnTitle": "Device" | 1432 | + "displayEntityLabel": false, |
1433 | + "entityNameColumnTitle": "Device" | ||
1434 | }, | 1434 | }, |
1435 | "title": "New Entities table", | 1435 | "title": "New Entities table", |
1436 | "dropShadow": true, | 1436 | "dropShadow": true, |
@@ -1719,15 +1719,15 @@ | @@ -1719,15 +1719,15 @@ | ||
1719 | "enableSearch": true, | 1719 | "enableSearch": true, |
1720 | "displayPagination": true, | 1720 | "displayPagination": true, |
1721 | "defaultPageSize": 10, | 1721 | "defaultPageSize": 10, |
1722 | - "defaultSortOrder": "entityLabel", | ||
1723 | - "displayEntityName": false, | 1722 | + "defaultSortOrder": "entityName", |
1723 | + "displayEntityName": true, | ||
1724 | "displayEntityType": false, | 1724 | "displayEntityType": false, |
1725 | "enableSelectColumnDisplay": false, | 1725 | "enableSelectColumnDisplay": false, |
1726 | "enableStickyHeader": true, | 1726 | "enableStickyHeader": true, |
1727 | "enableStickyAction": true, | 1727 | "enableStickyAction": true, |
1728 | "entitiesTitle": "Devices", | 1728 | "entitiesTitle": "Devices", |
1729 | - "displayEntityLabel": true, | ||
1730 | - "entityLabelColumnTitle": "Device" | 1729 | + "displayEntityLabel": false, |
1730 | + "entityNameColumnTitle": "Device" | ||
1731 | }, | 1731 | }, |
1732 | "title": "New Entities table", | 1732 | "title": "New Entities table", |
1733 | "dropShadow": true, | 1733 | "dropShadow": true, |
@@ -33,15 +33,15 @@ | @@ -33,15 +33,15 @@ | ||
33 | "enableSearch": true, | 33 | "enableSearch": true, |
34 | "displayPagination": true, | 34 | "displayPagination": true, |
35 | "defaultPageSize": 10, | 35 | "defaultPageSize": 10, |
36 | - "defaultSortOrder": "entityLabel", | ||
37 | - "displayEntityName": false, | 36 | + "defaultSortOrder": "entityName", |
37 | + "displayEntityName": true, | ||
38 | "displayEntityType": false, | 38 | "displayEntityType": false, |
39 | "enableSelectColumnDisplay": false, | 39 | "enableSelectColumnDisplay": false, |
40 | "enableStickyHeader": true, | 40 | "enableStickyHeader": true, |
41 | "enableStickyAction": false, | 41 | "enableStickyAction": false, |
42 | "entitiesTitle": "Devices", | 42 | "entitiesTitle": "Devices", |
43 | - "displayEntityLabel": true, | ||
44 | - "entityLabelColumnTitle": "Device" | 43 | + "displayEntityLabel": false, |
44 | + "entityNameColumnTitle": "Device" | ||
45 | }, | 45 | }, |
46 | "title": "New Entities table", | 46 | "title": "New Entities table", |
47 | "dropShadow": true, | 47 | "dropShadow": true, |
@@ -828,15 +828,15 @@ | @@ -828,15 +828,15 @@ | ||
828 | "enableSearch": true, | 828 | "enableSearch": true, |
829 | "displayPagination": true, | 829 | "displayPagination": true, |
830 | "defaultPageSize": 10, | 830 | "defaultPageSize": 10, |
831 | - "defaultSortOrder": "entityLabel", | ||
832 | - "displayEntityName": false, | 831 | + "defaultSortOrder": "entityName", |
832 | + "displayEntityName": true, | ||
833 | "displayEntityType": false, | 833 | "displayEntityType": false, |
834 | "enableSelectColumnDisplay": false, | 834 | "enableSelectColumnDisplay": false, |
835 | "enableStickyHeader": true, | 835 | "enableStickyHeader": true, |
836 | "enableStickyAction": true, | 836 | "enableStickyAction": true, |
837 | "entitiesTitle": "Devices", | 837 | "entitiesTitle": "Devices", |
838 | - "displayEntityLabel": true, | ||
839 | - "entityLabelColumnTitle": "Device" | 838 | + "displayEntityLabel": false, |
839 | + "entityNameColumnTitle": "Device" | ||
840 | }, | 840 | }, |
841 | "title": "New Entities table", | 841 | "title": "New Entities table", |
842 | "dropShadow": true, | 842 | "dropShadow": true, |
@@ -1125,15 +1125,15 @@ | @@ -1125,15 +1125,15 @@ | ||
1125 | "enableSearch": true, | 1125 | "enableSearch": true, |
1126 | "displayPagination": true, | 1126 | "displayPagination": true, |
1127 | "defaultPageSize": 10, | 1127 | "defaultPageSize": 10, |
1128 | - "defaultSortOrder": "entityLabel", | ||
1129 | - "displayEntityName": false, | 1128 | + "defaultSortOrder": "entityName", |
1129 | + "displayEntityName": true, | ||
1130 | "displayEntityType": false, | 1130 | "displayEntityType": false, |
1131 | "enableSelectColumnDisplay": false, | 1131 | "enableSelectColumnDisplay": false, |
1132 | "enableStickyHeader": true, | 1132 | "enableStickyHeader": true, |
1133 | "enableStickyAction": true, | 1133 | "enableStickyAction": true, |
1134 | "entitiesTitle": "Devices", | 1134 | "entitiesTitle": "Devices", |
1135 | - "displayEntityLabel": true, | ||
1136 | - "entityLabelColumnTitle": "Device" | 1135 | + "displayEntityLabel": false, |
1136 | + "entityNameColumnTitle": "Device" | ||
1137 | }, | 1137 | }, |
1138 | "title": "New Entities table", | 1138 | "title": "New Entities table", |
1139 | "dropShadow": true, | 1139 | "dropShadow": true, |
@@ -1422,15 +1422,15 @@ | @@ -1422,15 +1422,15 @@ | ||
1422 | "enableSearch": true, | 1422 | "enableSearch": true, |
1423 | "displayPagination": true, | 1423 | "displayPagination": true, |
1424 | "defaultPageSize": 10, | 1424 | "defaultPageSize": 10, |
1425 | - "defaultSortOrder": "entityLabel", | ||
1426 | - "displayEntityName": false, | 1425 | + "defaultSortOrder": "entityName", |
1426 | + "displayEntityName": true, | ||
1427 | "displayEntityType": false, | 1427 | "displayEntityType": false, |
1428 | "enableSelectColumnDisplay": false, | 1428 | "enableSelectColumnDisplay": false, |
1429 | "enableStickyHeader": true, | 1429 | "enableStickyHeader": true, |
1430 | "enableStickyAction": true, | 1430 | "enableStickyAction": true, |
1431 | "entitiesTitle": "Devices", | 1431 | "entitiesTitle": "Devices", |
1432 | - "displayEntityLabel": true, | ||
1433 | - "entityLabelColumnTitle": "Device" | 1432 | + "displayEntityLabel": false, |
1433 | + "entityNameColumnTitle": "Device" | ||
1434 | }, | 1434 | }, |
1435 | "title": "New Entities table", | 1435 | "title": "New Entities table", |
1436 | "dropShadow": true, | 1436 | "dropShadow": true, |
@@ -1719,15 +1719,15 @@ | @@ -1719,15 +1719,15 @@ | ||
1719 | "enableSearch": true, | 1719 | "enableSearch": true, |
1720 | "displayPagination": true, | 1720 | "displayPagination": true, |
1721 | "defaultPageSize": 10, | 1721 | "defaultPageSize": 10, |
1722 | - "defaultSortOrder": "entityLabel", | ||
1723 | - "displayEntityName": false, | 1722 | + "defaultSortOrder": "entityName", |
1723 | + "displayEntityName": true, | ||
1724 | "displayEntityType": false, | 1724 | "displayEntityType": false, |
1725 | "enableSelectColumnDisplay": false, | 1725 | "enableSelectColumnDisplay": false, |
1726 | "enableStickyHeader": true, | 1726 | "enableStickyHeader": true, |
1727 | "enableStickyAction": true, | 1727 | "enableStickyAction": true, |
1728 | "entitiesTitle": "Devices", | 1728 | "entitiesTitle": "Devices", |
1729 | - "displayEntityLabel": true, | ||
1730 | - "entityLabelColumnTitle": "Device" | 1729 | + "displayEntityLabel": false, |
1730 | + "entityNameColumnTitle": "Device" | ||
1731 | }, | 1731 | }, |
1732 | "title": "New Entities table", | 1732 | "title": "New Entities table", |
1733 | "dropShadow": true, | 1733 | "dropShadow": true, |
application/src/main/data/json/demo/edge_management/rule_chains/edge_root_rule_chain.json
deleted
100644 → 0
1 | -{ | ||
2 | - "ruleChain": { | ||
3 | - "additionalInfo": null, | ||
4 | - "name": "Edge Root Rule Chain", | ||
5 | - "type": "EDGE", | ||
6 | - "firstRuleNodeId": null, | ||
7 | - "root": true, | ||
8 | - "debugMode": false, | ||
9 | - "configuration": null | ||
10 | - }, | ||
11 | - "metadata": { | ||
12 | - "firstNodeIndex": 0, | ||
13 | - "nodes": [ | ||
14 | - { | ||
15 | - "additionalInfo": { | ||
16 | - "description": "Process incoming messages from devices with the alarm rules defined in the device profile. Dispatch all incoming messages with \"Success\" relation type.", | ||
17 | - "layoutX": 203, | ||
18 | - "layoutY": 259 | ||
19 | - }, | ||
20 | - "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", | ||
21 | - "name": "Device Profile Node", | ||
22 | - "debugMode": false, | ||
23 | - "configuration": { | ||
24 | - "persistAlarmRulesState": false, | ||
25 | - "fetchAlarmRulesStateOnStart": false | ||
26 | - } | ||
27 | - }, | ||
28 | - { | ||
29 | - "additionalInfo": { | ||
30 | - "layoutX": 823, | ||
31 | - "layoutY": 157 | ||
32 | - }, | ||
33 | - "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", | ||
34 | - "name": "Save Timeseries", | ||
35 | - "debugMode": false, | ||
36 | - "configuration": { | ||
37 | - "defaultTTL": 0 | ||
38 | - } | ||
39 | - }, | ||
40 | - { | ||
41 | - "additionalInfo": { | ||
42 | - "layoutX": 824, | ||
43 | - "layoutY": 52 | ||
44 | - }, | ||
45 | - "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", | ||
46 | - "name": "Save Client Attributes", | ||
47 | - "debugMode": false, | ||
48 | - "configuration": { | ||
49 | - "scope": "CLIENT_SCOPE" | ||
50 | - } | ||
51 | - }, | ||
52 | - { | ||
53 | - "additionalInfo": { | ||
54 | - "layoutX": 347, | ||
55 | - "layoutY": 149 | ||
56 | - }, | ||
57 | - "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", | ||
58 | - "name": "Message Type Switch", | ||
59 | - "debugMode": false, | ||
60 | - "configuration": { | ||
61 | - "version": 0 | ||
62 | - } | ||
63 | - }, | ||
64 | - { | ||
65 | - "additionalInfo": { | ||
66 | - "layoutX": 825, | ||
67 | - "layoutY": 266 | ||
68 | - }, | ||
69 | - "type": "org.thingsboard.rule.engine.action.TbLogNode", | ||
70 | - "name": "Log RPC from Device", | ||
71 | - "debugMode": false, | ||
72 | - "configuration": { | ||
73 | - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" | ||
74 | - } | ||
75 | - }, | ||
76 | - { | ||
77 | - "additionalInfo": { | ||
78 | - "layoutX": 824, | ||
79 | - "layoutY": 378 | ||
80 | - }, | ||
81 | - "type": "org.thingsboard.rule.engine.action.TbLogNode", | ||
82 | - "name": "Log Other", | ||
83 | - "debugMode": false, | ||
84 | - "configuration": { | ||
85 | - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" | ||
86 | - } | ||
87 | - }, | ||
88 | - { | ||
89 | - "additionalInfo": { | ||
90 | - "layoutX": 824, | ||
91 | - "layoutY": 466 | ||
92 | - }, | ||
93 | - "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", | ||
94 | - "name": "RPC Call Request", | ||
95 | - "debugMode": false, | ||
96 | - "configuration": { | ||
97 | - "timeoutInSeconds": 60 | ||
98 | - } | ||
99 | - }, | ||
100 | - { | ||
101 | - "additionalInfo": { | ||
102 | - "layoutX": 1134, | ||
103 | - "layoutY": 132 | ||
104 | - }, | ||
105 | - "type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode", | ||
106 | - "name": "Push to cloud", | ||
107 | - "debugMode": false, | ||
108 | - "configuration": { | ||
109 | - "version": 0 | ||
110 | - } | ||
111 | - } | ||
112 | - ], | ||
113 | - "connections": [ | ||
114 | - { | ||
115 | - "fromIndex": 0, | ||
116 | - "toIndex": 3, | ||
117 | - "type": "Success" | ||
118 | - }, | ||
119 | - { | ||
120 | - "fromIndex": 1, | ||
121 | - "toIndex": 7, | ||
122 | - "type": "Success" | ||
123 | - }, | ||
124 | - { | ||
125 | - "fromIndex": 2, | ||
126 | - "toIndex": 7, | ||
127 | - "type": "Success" | ||
128 | - }, | ||
129 | - { | ||
130 | - "fromIndex": 3, | ||
131 | - "toIndex": 6, | ||
132 | - "type": "RPC Request to Device" | ||
133 | - }, | ||
134 | - { | ||
135 | - "fromIndex": 3, | ||
136 | - "toIndex": 5, | ||
137 | - "type": "Other" | ||
138 | - }, | ||
139 | - { | ||
140 | - "fromIndex": 3, | ||
141 | - "toIndex": 2, | ||
142 | - "type": "Post attributes" | ||
143 | - }, | ||
144 | - { | ||
145 | - "fromIndex": 3, | ||
146 | - "toIndex": 1, | ||
147 | - "type": "Post telemetry" | ||
148 | - }, | ||
149 | - { | ||
150 | - "fromIndex": 3, | ||
151 | - "toIndex": 4, | ||
152 | - "type": "RPC Request from Device" | ||
153 | - }, | ||
154 | - { | ||
155 | - "fromIndex": 4, | ||
156 | - "toIndex": 7, | ||
157 | - "type": "Success" | ||
158 | - } | ||
159 | - ], | ||
160 | - "ruleChainConnections": null | ||
161 | - } | ||
162 | -} |
@@ -18,8 +18,8 @@ | @@ -18,8 +18,8 @@ | ||
18 | "resources": [], | 18 | "resources": [], |
19 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", | 19 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", |
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", | 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;\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 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, 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 },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\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}", | ||
23 | "dataKeySettingsSchema": "{}\n", | 23 | "dataKeySettingsSchema": "{}\n", |
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\":{}}" | 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 | } |
@@ -14,8 +14,8 @@ | @@ -14,8 +14,8 @@ | ||
14 | { | 14 | { |
15 | "additionalInfo": { | 15 | "additionalInfo": { |
16 | "description": "Process incoming messages from devices with the alarm rules defined in the device profile. Dispatch all incoming messages with \"Success\" relation type.", | 16 | "description": "Process incoming messages from devices with the alarm rules defined in the device profile. Dispatch all incoming messages with \"Success\" relation type.", |
17 | - "layoutX": 203, | ||
18 | - "layoutY": 259 | 17 | + "layoutX": 187, |
18 | + "layoutY": 468 | ||
19 | }, | 19 | }, |
20 | "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", | 20 | "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", |
21 | "name": "Device Profile Node", | 21 | "name": "Device Profile Node", |
@@ -99,14 +99,14 @@ | @@ -99,14 +99,14 @@ | ||
99 | }, | 99 | }, |
100 | { | 100 | { |
101 | "additionalInfo": { | 101 | "additionalInfo": { |
102 | - "layoutX": 1134, | ||
103 | - "layoutY": 132 | 102 | + "layoutX": 1129, |
103 | + "layoutY": 52 | ||
104 | }, | 104 | }, |
105 | "type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode", | 105 | "type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode", |
106 | "name": "Push to cloud", | 106 | "name": "Push to cloud", |
107 | "debugMode": false, | 107 | "debugMode": false, |
108 | "configuration": { | 108 | "configuration": { |
109 | - "version": 0 | 109 | + "scope": "SERVER_SCOPE" |
110 | } | 110 | } |
111 | } | 111 | } |
112 | ], | 112 | ], |
@@ -152,6 +152,11 @@ | @@ -152,6 +152,11 @@ | ||
152 | "type": "RPC Request from Device" | 152 | "type": "RPC Request from Device" |
153 | }, | 153 | }, |
154 | { | 154 | { |
155 | + "fromIndex": 3, | ||
156 | + "toIndex": 7, | ||
157 | + "type": "Attributes Updated" | ||
158 | + }, | ||
159 | + { | ||
155 | "fromIndex": 4, | 160 | "fromIndex": 4, |
156 | "toIndex": 7, | 161 | "toIndex": 7, |
157 | "type": "Success" | 162 | "type": "Success" |
@@ -18,17 +18,18 @@ CREATE OR REPLACE PROCEDURE drop_partitions_by_max_ttl(IN partition_type varchar | @@ -18,17 +18,18 @@ CREATE OR REPLACE PROCEDURE drop_partitions_by_max_ttl(IN partition_type varchar | ||
18 | LANGUAGE plpgsql AS | 18 | LANGUAGE plpgsql AS |
19 | $$ | 19 | $$ |
20 | DECLARE | 20 | DECLARE |
21 | - max_tenant_ttl bigint; | ||
22 | - max_customer_ttl bigint; | ||
23 | - max_ttl bigint; | ||
24 | - date timestamp; | ||
25 | - partition_by_max_ttl_date varchar; | ||
26 | - partition_month varchar; | ||
27 | - partition_day varchar; | ||
28 | - partition_year varchar; | ||
29 | - partition varchar; | ||
30 | - partition_to_delete varchar; | ||
31 | - | 21 | + max_tenant_ttl bigint; |
22 | + max_customer_ttl bigint; | ||
23 | + max_ttl bigint; | ||
24 | + date timestamp; | ||
25 | + partition_by_max_ttl_date varchar; | ||
26 | + partition_by_max_ttl_month varchar; | ||
27 | + partition_by_max_ttl_day varchar; | ||
28 | + partition_by_max_ttl_year varchar; | ||
29 | + partition varchar; | ||
30 | + partition_year integer; | ||
31 | + partition_month integer; | ||
32 | + partition_day integer; | ||
32 | 33 | ||
33 | BEGIN | 34 | BEGIN |
34 | SELECT max(attribute_kv.long_v) | 35 | SELECT max(attribute_kv.long_v) |
@@ -45,53 +46,138 @@ BEGIN | @@ -45,53 +46,138 @@ BEGIN | ||
45 | if max_ttl IS NOT NULL AND max_ttl > 0 THEN | 46 | if max_ttl IS NOT NULL AND max_ttl > 0 THEN |
46 | date := to_timestamp(EXTRACT(EPOCH FROM current_timestamp) - max_ttl); | 47 | date := to_timestamp(EXTRACT(EPOCH FROM current_timestamp) - max_ttl); |
47 | partition_by_max_ttl_date := get_partition_by_max_ttl_date(partition_type, date); | 48 | partition_by_max_ttl_date := get_partition_by_max_ttl_date(partition_type, date); |
49 | + RAISE NOTICE 'Date by max ttl: %', date; | ||
48 | RAISE NOTICE 'Partition by max ttl: %', partition_by_max_ttl_date; | 50 | RAISE NOTICE 'Partition by max ttl: %', partition_by_max_ttl_date; |
49 | IF partition_by_max_ttl_date IS NOT NULL THEN | 51 | IF partition_by_max_ttl_date IS NOT NULL THEN |
50 | CASE | 52 | CASE |
51 | WHEN partition_type = 'DAYS' THEN | 53 | WHEN partition_type = 'DAYS' THEN |
52 | - partition_year := SPLIT_PART(partition_by_max_ttl_date, '_', 3); | ||
53 | - partition_month := SPLIT_PART(partition_by_max_ttl_date, '_', 4); | ||
54 | - partition_day := SPLIT_PART(partition_by_max_ttl_date, '_', 5); | 54 | + partition_by_max_ttl_year := SPLIT_PART(partition_by_max_ttl_date, '_', 3); |
55 | + partition_by_max_ttl_month := SPLIT_PART(partition_by_max_ttl_date, '_', 4); | ||
56 | + partition_by_max_ttl_day := SPLIT_PART(partition_by_max_ttl_date, '_', 5); | ||
55 | WHEN partition_type = 'MONTHS' THEN | 57 | WHEN partition_type = 'MONTHS' THEN |
56 | - partition_year := SPLIT_PART(partition_by_max_ttl_date, '_', 3); | ||
57 | - partition_month := SPLIT_PART(partition_by_max_ttl_date, '_', 4); | 58 | + partition_by_max_ttl_year := SPLIT_PART(partition_by_max_ttl_date, '_', 3); |
59 | + partition_by_max_ttl_month := SPLIT_PART(partition_by_max_ttl_date, '_', 4); | ||
58 | ELSE | 60 | ELSE |
59 | - partition_year := SPLIT_PART(partition_by_max_ttl_date, '_', 3); | 61 | + partition_by_max_ttl_year := SPLIT_PART(partition_by_max_ttl_date, '_', 3); |
60 | END CASE; | 62 | END CASE; |
61 | - FOR partition IN SELECT tablename | ||
62 | - FROM pg_tables | ||
63 | - WHERE schemaname = 'public' | ||
64 | - AND tablename like 'ts_kv_' || '%' | ||
65 | - AND tablename != 'ts_kv_latest' | ||
66 | - AND tablename != 'ts_kv_dictionary' | ||
67 | - AND tablename != 'ts_kv_indefinite' | ||
68 | - LOOP | ||
69 | - IF partition != partition_by_max_ttl_date THEN | ||
70 | - IF partition_year IS NOT NULL THEN | ||
71 | - IF SPLIT_PART(partition, '_', 3)::integer < partition_year::integer THEN | ||
72 | - partition_to_delete := partition; | ||
73 | - ELSE | ||
74 | - IF partition_month IS NOT NULL THEN | ||
75 | - IF SPLIT_PART(partition, '_', 4)::integer < partition_month::integer THEN | ||
76 | - partition_to_delete := partition; | 63 | + IF partition_by_max_ttl_year IS NULL THEN |
64 | + RAISE NOTICE 'Failed to remove partitions by max ttl date due to partition_by_max_ttl_year is null!'; | ||
65 | + ELSE | ||
66 | + IF partition_type = 'YEARS' THEN | ||
67 | + FOR partition IN SELECT tablename | ||
68 | + FROM pg_tables | ||
69 | + WHERE schemaname = 'public' | ||
70 | + AND tablename like 'ts_kv_' || '%' | ||
71 | + AND tablename != 'ts_kv_latest' | ||
72 | + AND tablename != 'ts_kv_dictionary' | ||
73 | + AND tablename != 'ts_kv_indefinite' | ||
74 | + AND tablename != partition_by_max_ttl_date | ||
75 | + LOOP | ||
76 | + partition_year := SPLIT_PART(partition, '_', 3)::integer; | ||
77 | + IF partition_year < partition_by_max_ttl_year::integer THEN | ||
78 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition; | ||
79 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition); | ||
80 | + deleted := deleted + 1; | ||
81 | + END IF; | ||
82 | + END LOOP; | ||
83 | + ELSE | ||
84 | + IF partition_type = 'MONTHS' THEN | ||
85 | + IF partition_by_max_ttl_month IS NULL THEN | ||
86 | + RAISE NOTICE 'Failed to remove months partitions by max ttl date due to partition_by_max_ttl_month is null!'; | ||
87 | + ELSE | ||
88 | + FOR partition IN SELECT tablename | ||
89 | + FROM pg_tables | ||
90 | + WHERE schemaname = 'public' | ||
91 | + AND tablename like 'ts_kv_' || '%' | ||
92 | + AND tablename != 'ts_kv_latest' | ||
93 | + AND tablename != 'ts_kv_dictionary' | ||
94 | + AND tablename != 'ts_kv_indefinite' | ||
95 | + AND tablename != partition_by_max_ttl_date | ||
96 | + LOOP | ||
97 | + partition_year := SPLIT_PART(partition, '_', 3)::integer; | ||
98 | + IF partition_year > partition_by_max_ttl_year::integer THEN | ||
99 | + RAISE NOTICE 'Skip iteration! Partition: % is valid!', partition; | ||
100 | + CONTINUE; | ||
77 | ELSE | 101 | ELSE |
78 | - IF partition_day IS NOT NULL THEN | ||
79 | - IF SPLIT_PART(partition, '_', 5)::integer < partition_day::integer THEN | ||
80 | - partition_to_delete := partition; | 102 | + IF partition_year < partition_by_max_ttl_year::integer THEN |
103 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition; | ||
104 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition); | ||
105 | + deleted := deleted + 1; | ||
106 | + ELSE | ||
107 | + partition_month := SPLIT_PART(partition, '_', 4)::integer; | ||
108 | + IF partition_year = partition_by_max_ttl_year::integer THEN | ||
109 | + IF partition_month >= partition_by_max_ttl_month::integer THEN | ||
110 | + RAISE NOTICE 'Skip iteration! Partition: % is valid!', partition; | ||
111 | + CONTINUE; | ||
112 | + ELSE | ||
113 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition; | ||
114 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition); | ||
115 | + deleted := deleted + 1; | ||
116 | + END IF; | ||
81 | END IF; | 117 | END IF; |
82 | END IF; | 118 | END IF; |
83 | END IF; | 119 | END IF; |
120 | + END LOOP; | ||
121 | + END IF; | ||
122 | + ELSE | ||
123 | + IF partition_type = 'DAYS' THEN | ||
124 | + IF partition_by_max_ttl_month IS NULL THEN | ||
125 | + RAISE NOTICE 'Failed to remove days partitions by max ttl date due to partition_by_max_ttl_month is null!'; | ||
126 | + ELSE | ||
127 | + IF partition_by_max_ttl_day IS NULL THEN | ||
128 | + RAISE NOTICE 'Failed to remove days partitions by max ttl date due to partition_by_max_ttl_day is null!'; | ||
129 | + ELSE | ||
130 | + FOR partition IN SELECT tablename | ||
131 | + FROM pg_tables | ||
132 | + WHERE schemaname = 'public' | ||
133 | + AND tablename like 'ts_kv_' || '%' | ||
134 | + AND tablename != 'ts_kv_latest' | ||
135 | + AND tablename != 'ts_kv_dictionary' | ||
136 | + AND tablename != 'ts_kv_indefinite' | ||
137 | + AND tablename != partition_by_max_ttl_date | ||
138 | + LOOP | ||
139 | + partition_year := SPLIT_PART(partition, '_', 3)::integer; | ||
140 | + IF partition_year > partition_by_max_ttl_year::integer THEN | ||
141 | + RAISE NOTICE 'Skip iteration! Partition: % is valid!', partition; | ||
142 | + CONTINUE; | ||
143 | + ELSE | ||
144 | + IF partition_year < partition_by_max_ttl_year::integer THEN | ||
145 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition; | ||
146 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition); | ||
147 | + deleted := deleted + 1; | ||
148 | + ELSE | ||
149 | + partition_month := SPLIT_PART(partition, '_', 4)::integer; | ||
150 | + IF partition_month > partition_by_max_ttl_month::integer THEN | ||
151 | + RAISE NOTICE 'Skip iteration! Partition: % is valid!', partition; | ||
152 | + CONTINUE; | ||
153 | + ELSE | ||
154 | + IF partition_month < partition_by_max_ttl_month::integer THEN | ||
155 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition; | ||
156 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition); | ||
157 | + deleted := deleted + 1; | ||
158 | + ELSE | ||
159 | + partition_day := SPLIT_PART(partition, '_', 5)::integer; | ||
160 | + IF partition_day >= partition_by_max_ttl_day::integer THEN | ||
161 | + RAISE NOTICE 'Skip iteration! Partition: % is valid!', partition; | ||
162 | + CONTINUE; | ||
163 | + ELSE | ||
164 | + IF partition_day < partition_by_max_ttl_day::integer THEN | ||
165 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition; | ||
166 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition); | ||
167 | + deleted := deleted + 1; | ||
168 | + END IF; | ||
169 | + END IF; | ||
170 | + END IF; | ||
171 | + END IF; | ||
172 | + END IF; | ||
173 | + END IF; | ||
174 | + END LOOP; | ||
84 | END IF; | 175 | END IF; |
85 | END IF; | 176 | END IF; |
86 | END IF; | 177 | END IF; |
87 | - IF partition_to_delete IS NOT NULL THEN | ||
88 | - RAISE NOTICE 'Partition to delete by max ttl: %', partition_to_delete; | ||
89 | - EXECUTE format('DROP TABLE IF EXISTS %I', partition_to_delete); | ||
90 | - partition_to_delete := NULL; | ||
91 | - deleted := deleted + 1; | ||
92 | - END IF; | ||
93 | END IF; | 178 | END IF; |
94 | - END LOOP; | 179 | + END IF; |
180 | + END IF; | ||
95 | END IF; | 181 | END IF; |
96 | END IF; | 182 | END IF; |
97 | END | 183 | END |
@@ -107,8 +193,6 @@ BEGIN | @@ -107,8 +193,6 @@ BEGIN | ||
107 | partition := 'ts_kv_' || to_char(date, 'yyyy') || '_' || to_char(date, 'MM'); | 193 | partition := 'ts_kv_' || to_char(date, 'yyyy') || '_' || to_char(date, 'MM'); |
108 | WHEN partition_type = 'YEARS' THEN | 194 | WHEN partition_type = 'YEARS' THEN |
109 | partition := 'ts_kv_' || to_char(date, 'yyyy'); | 195 | partition := 'ts_kv_' || to_char(date, 'yyyy'); |
110 | - WHEN partition_type = 'INDEFINITE' THEN | ||
111 | - partition := NULL; | ||
112 | ELSE | 196 | ELSE |
113 | partition := NULL; | 197 | partition := NULL; |
114 | END CASE; | 198 | END CASE; |
@@ -197,3 +197,17 @@ $$; | @@ -197,3 +197,17 @@ $$; | ||
197 | ALTER TABLE api_usage_state | 197 | ALTER TABLE api_usage_state |
198 | ADD COLUMN IF NOT EXISTS alarm_exec VARCHAR(32); | 198 | ADD COLUMN IF NOT EXISTS alarm_exec VARCHAR(32); |
199 | UPDATE api_usage_state SET alarm_exec = 'ENABLED' WHERE alarm_exec IS NULL; | 199 | UPDATE api_usage_state SET alarm_exec = 'ENABLED' WHERE alarm_exec IS NULL; |
200 | + | ||
201 | +CREATE TABLE IF NOT EXISTS rpc ( | ||
202 | + id uuid NOT NULL CONSTRAINT rpc_pkey PRIMARY KEY, | ||
203 | + created_time bigint NOT NULL, | ||
204 | + tenant_id uuid NOT NULL, | ||
205 | + device_id uuid NOT NULL, | ||
206 | + expiration_time bigint NOT NULL, | ||
207 | + request varchar(10000000) NOT NULL, | ||
208 | + response varchar(10000000), | ||
209 | + status varchar(255) NOT NULL | ||
210 | +); | ||
211 | + | ||
212 | +CREATE INDEX IF NOT EXISTS idx_rpc_tenant_id_device_id ON rpc(tenant_id, device_id); | ||
213 | + |
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 | + | ||
17 | +-- PROCEDURE: public.cleanup_events_by_ttl(bigint, bigint, bigint) | ||
18 | + | ||
19 | +DROP PROCEDURE IF EXISTS public.cleanup_events_by_ttl(bigint, bigint, bigint); | ||
20 | + | ||
21 | +CREATE OR REPLACE PROCEDURE public.cleanup_events_by_ttl( | ||
22 | + ttl bigint, | ||
23 | + debug_ttl bigint, | ||
24 | + INOUT deleted bigint) | ||
25 | +LANGUAGE 'plpgsql' | ||
26 | +AS $BODY$ | ||
27 | +DECLARE | ||
28 | + ttl_ts bigint; | ||
29 | + debug_ttl_ts bigint; | ||
30 | + ttl_deleted_count bigint DEFAULT 0; | ||
31 | + debug_ttl_deleted_count bigint DEFAULT 0; | ||
32 | +BEGIN | ||
33 | + IF ttl > 0 THEN | ||
34 | + ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint; | ||
35 | + | ||
36 | + DELETE FROM event | ||
37 | + WHERE ts < ttl_ts | ||
38 | + AND NOT event_type IN ('DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN', 'DEBUG_CONVERTER', 'DEBUG_INTEGRATION'); | ||
39 | + | ||
40 | + GET DIAGNOSTICS ttl_deleted_count = ROW_COUNT; | ||
41 | + END IF; | ||
42 | + | ||
43 | + IF debug_ttl > 0 THEN | ||
44 | + debug_ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - debug_ttl::bigint * 1000)::bigint; | ||
45 | + | ||
46 | + DELETE FROM event | ||
47 | + WHERE ts < debug_ttl_ts | ||
48 | + AND event_type IN ('DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN', 'DEBUG_CONVERTER', 'DEBUG_INTEGRATION'); | ||
49 | + | ||
50 | + GET DIAGNOSTICS debug_ttl_deleted_count = ROW_COUNT; | ||
51 | + END IF; | ||
52 | + | ||
53 | + RAISE NOTICE 'Events removed by ttl: %', ttl_deleted_count; | ||
54 | + RAISE NOTICE 'Debug Events removed by ttl: %', debug_ttl_deleted_count; | ||
55 | + deleted := ttl_deleted_count + debug_ttl_deleted_count; | ||
56 | +END | ||
57 | +$BODY$; | ||
58 | + | ||
59 | + | ||
60 | +-- Index: idx_event_ts | ||
61 | + | ||
62 | +DROP INDEX IF EXISTS public.idx_event_ts; | ||
63 | + | ||
64 | +-- Hint: add CONCURRENTLY to CREATE INDEX query in case of more then 1 million records or during live update | ||
65 | +-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_ts | ||
66 | +CREATE INDEX IF NOT EXISTS idx_event_ts | ||
67 | + ON public.event | ||
68 | + (ts DESC NULLS LAST) | ||
69 | + WITH (FILLFACTOR=95); | ||
70 | + | ||
71 | +COMMENT ON INDEX public.idx_event_ts | ||
72 | + IS 'This index helps to delete events by TTL using timestamp'; | ||
73 | + | ||
74 | + | ||
75 | +-- Index: idx_event_tenant_entity_type_entity_event_type_created_time_des | ||
76 | + | ||
77 | +DROP INDEX IF EXISTS public.idx_event_tenant_entity_type_entity_event_type_created_time_des; | ||
78 | + | ||
79 | +-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des | ||
80 | +CREATE INDEX IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des | ||
81 | + ON public.event | ||
82 | + (tenant_id ASC, entity_type ASC, entity_id ASC, event_type ASC, created_time DESC NULLS LAST) | ||
83 | + WITH (FILLFACTOR=95); | ||
84 | + | ||
85 | +COMMENT ON INDEX public.idx_event_tenant_entity_type_entity_event_type_created_time_des | ||
86 | + IS 'This index helps to open latest events on UI fast'; | ||
87 | + | ||
88 | +-- Index: idx_event_type_entity_id | ||
89 | +-- Description: replaced with more suitable idx_event_tenant_entity_type_entity_event_type_created_time_des | ||
90 | +DROP INDEX IF EXISTS public.idx_event_type_entity_id; |
@@ -65,6 +65,7 @@ import org.thingsboard.server.dao.relation.RelationService; | @@ -65,6 +65,7 @@ import org.thingsboard.server.dao.relation.RelationService; | ||
65 | import org.thingsboard.server.dao.resource.ResourceService; | 65 | import org.thingsboard.server.dao.resource.ResourceService; |
66 | import org.thingsboard.server.dao.rule.RuleChainService; | 66 | import org.thingsboard.server.dao.rule.RuleChainService; |
67 | import org.thingsboard.server.dao.rule.RuleNodeStateService; | 67 | import org.thingsboard.server.dao.rule.RuleNodeStateService; |
68 | +import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | ||
68 | import org.thingsboard.server.dao.tenant.TenantProfileService; | 69 | import org.thingsboard.server.dao.tenant.TenantProfileService; |
69 | import org.thingsboard.server.dao.tenant.TenantService; | 70 | import org.thingsboard.server.dao.tenant.TenantService; |
70 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 71 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
@@ -80,9 +81,9 @@ import org.thingsboard.server.service.executors.ExternalCallExecutorService; | @@ -80,9 +81,9 @@ import org.thingsboard.server.service.executors.ExternalCallExecutorService; | ||
80 | import org.thingsboard.server.service.executors.SharedEventLoopGroupService; | 81 | import org.thingsboard.server.service.executors.SharedEventLoopGroupService; |
81 | import org.thingsboard.server.service.mail.MailExecutorService; | 82 | import org.thingsboard.server.service.mail.MailExecutorService; |
82 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; | 83 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
83 | -import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | ||
84 | import org.thingsboard.server.service.queue.TbClusterService; | 84 | import org.thingsboard.server.service.queue.TbClusterService; |
85 | import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; | 85 | import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; |
86 | +import org.thingsboard.server.service.rpc.TbRpcService; | ||
86 | import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; | 87 | import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; |
87 | import org.thingsboard.server.service.script.JsExecutorService; | 88 | import org.thingsboard.server.service.script.JsExecutorService; |
88 | import org.thingsboard.server.service.script.JsInvokeService; | 89 | import org.thingsboard.server.service.script.JsInvokeService; |
@@ -303,23 +304,33 @@ public class ActorSystemContext { | @@ -303,23 +304,33 @@ public class ActorSystemContext { | ||
303 | 304 | ||
304 | @Lazy | 305 | @Lazy |
305 | @Autowired(required = false) | 306 | @Autowired(required = false) |
306 | - @Getter private EdgeService edgeService; | 307 | + @Getter |
308 | + private EdgeService edgeService; | ||
307 | 309 | ||
308 | @Lazy | 310 | @Lazy |
309 | @Autowired(required = false) | 311 | @Autowired(required = false) |
310 | - @Getter private EdgeEventService edgeEventService; | 312 | + @Getter |
313 | + private EdgeEventService edgeEventService; | ||
311 | 314 | ||
312 | @Lazy | 315 | @Lazy |
313 | @Autowired(required = false) | 316 | @Autowired(required = false) |
314 | - @Getter private EdgeRpcService edgeRpcService; | 317 | + @Getter |
318 | + private EdgeRpcService edgeRpcService; | ||
315 | 319 | ||
316 | @Lazy | 320 | @Lazy |
317 | @Autowired(required = false) | 321 | @Autowired(required = false) |
318 | - @Getter private ResourceService resourceService; | 322 | + @Getter |
323 | + private ResourceService resourceService; | ||
319 | 324 | ||
320 | @Lazy | 325 | @Lazy |
321 | @Autowired(required = false) | 326 | @Autowired(required = false) |
322 | - @Getter private OtaPackageService otaPackageService; | 327 | + @Getter |
328 | + private OtaPackageService otaPackageService; | ||
329 | + | ||
330 | + @Lazy | ||
331 | + @Autowired(required = false) | ||
332 | + @Getter | ||
333 | + private TbRpcService tbRpcService; | ||
323 | 334 | ||
324 | @Value("${actors.session.max_concurrent_sessions_per_device:1}") | 335 | @Value("${actors.session.max_concurrent_sessions_per_device:1}") |
325 | @Getter | 336 | @Getter |
@@ -46,7 +46,7 @@ public class DeviceActor extends ContextAwareActor { | @@ -46,7 +46,7 @@ public class DeviceActor extends ContextAwareActor { | ||
46 | super.init(ctx); | 46 | super.init(ctx); |
47 | log.debug("[{}][{}] Starting device actor.", processor.tenantId, processor.deviceId); | 47 | log.debug("[{}][{}] Starting device actor.", processor.tenantId, processor.deviceId); |
48 | try { | 48 | try { |
49 | - processor.initSessionTimeout(ctx); | 49 | + processor.init(ctx); |
50 | log.debug("[{}][{}] Device actor started.", processor.tenantId, processor.deviceId); | 50 | log.debug("[{}][{}] Device actor started.", processor.tenantId, processor.deviceId); |
51 | } catch (Exception e) { | 51 | } catch (Exception e) { |
52 | log.warn("[{}][{}] Unknown failure", processor.tenantId, processor.deviceId, e); | 52 | log.warn("[{}][{}] Unknown failure", processor.tenantId, processor.deviceId, e); |
@@ -23,6 +23,8 @@ import com.google.common.util.concurrent.MoreExecutors; | @@ -23,6 +23,8 @@ import com.google.common.util.concurrent.MoreExecutors; | ||
23 | import com.google.protobuf.InvalidProtocolBufferException; | 23 | import com.google.protobuf.InvalidProtocolBufferException; |
24 | import lombok.extern.slf4j.Slf4j; | 24 | import lombok.extern.slf4j.Slf4j; |
25 | import org.apache.commons.collections.CollectionUtils; | 25 | import org.apache.commons.collections.CollectionUtils; |
26 | +import org.thingsboard.common.util.JacksonUtil; | ||
27 | +import org.thingsboard.common.util.LinkedHashMapRemoveEldest; | ||
26 | import org.thingsboard.rule.engine.api.RpcError; | 28 | import org.thingsboard.rule.engine.api.RpcError; |
27 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 29 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
28 | import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; | 30 | import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; |
@@ -38,12 +40,17 @@ import org.thingsboard.server.common.data.edge.EdgeEventActionType; | @@ -38,12 +40,17 @@ import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
38 | import org.thingsboard.server.common.data.edge.EdgeEventType; | 40 | import org.thingsboard.server.common.data.edge.EdgeEventType; |
39 | import org.thingsboard.server.common.data.id.DeviceId; | 41 | import org.thingsboard.server.common.data.id.DeviceId; |
40 | import org.thingsboard.server.common.data.id.EdgeId; | 42 | import org.thingsboard.server.common.data.id.EdgeId; |
43 | +import org.thingsboard.server.common.data.id.RpcId; | ||
41 | import org.thingsboard.server.common.data.id.TenantId; | 44 | import org.thingsboard.server.common.data.id.TenantId; |
42 | import org.thingsboard.server.common.data.kv.AttributeKey; | 45 | import org.thingsboard.server.common.data.kv.AttributeKey; |
43 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 46 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
44 | import org.thingsboard.server.common.data.kv.KvEntry; | 47 | import org.thingsboard.server.common.data.kv.KvEntry; |
48 | +import org.thingsboard.server.common.data.page.PageData; | ||
49 | +import org.thingsboard.server.common.data.page.PageLink; | ||
45 | import org.thingsboard.server.common.data.relation.EntityRelation; | 50 | import org.thingsboard.server.common.data.relation.EntityRelation; |
46 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 51 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
52 | +import org.thingsboard.server.common.data.rpc.Rpc; | ||
53 | +import org.thingsboard.server.common.data.rpc.RpcStatus; | ||
47 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | 54 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; |
48 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 55 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
49 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 56 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
@@ -52,8 +59,8 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | @@ -52,8 +59,8 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
52 | import org.thingsboard.server.common.msg.queue.TbCallback; | 59 | import org.thingsboard.server.common.msg.queue.TbCallback; |
53 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 60 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
54 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; | 61 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; |
55 | -import org.thingsboard.server.gen.transport.TransportProtos; | ||
56 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | 62 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
63 | +import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; | ||
57 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; | 64 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; |
58 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; | 65 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; |
59 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; | 66 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; |
@@ -68,10 +75,12 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; | @@ -68,10 +75,12 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; | ||
68 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; | 75 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; |
69 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; | 76 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; |
70 | import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionInfoProto; | 77 | import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionInfoProto; |
78 | +import org.thingsboard.server.gen.transport.TransportProtos.ToDevicePersistedRpcResponseMsg; | ||
71 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; | 79 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; |
72 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; | 80 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; |
73 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; | 81 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; |
74 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; | 82 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
83 | +import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; | ||
75 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; | 84 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
76 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; | 85 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; |
77 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | 86 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
@@ -88,6 +97,8 @@ import java.util.HashSet; | @@ -88,6 +97,8 @@ import java.util.HashSet; | ||
88 | import java.util.LinkedHashMap; | 97 | import java.util.LinkedHashMap; |
89 | import java.util.List; | 98 | import java.util.List; |
90 | import java.util.Map; | 99 | import java.util.Map; |
100 | +import java.util.Objects; | ||
101 | +import java.util.Optional; | ||
91 | import java.util.Set; | 102 | import java.util.Set; |
92 | import java.util.UUID; | 103 | import java.util.UUID; |
93 | import java.util.function.Consumer; | 104 | import java.util.function.Consumer; |
@@ -102,7 +113,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -102,7 +113,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
102 | 113 | ||
103 | final TenantId tenantId; | 114 | final TenantId tenantId; |
104 | final DeviceId deviceId; | 115 | final DeviceId deviceId; |
105 | - private final Map<UUID, SessionInfoMetaData> sessions; | 116 | + final LinkedHashMapRemoveEldest<UUID, SessionInfoMetaData> sessions; |
106 | private final Map<UUID, SessionInfo> attributeSubscriptions; | 117 | private final Map<UUID, SessionInfo> attributeSubscriptions; |
107 | private final Map<UUID, SessionInfo> rpcSubscriptions; | 118 | private final Map<UUID, SessionInfo> rpcSubscriptions; |
108 | private final Map<Integer, ToDeviceRpcRequestMetadata> toDeviceRpcPendingMap; | 119 | private final Map<Integer, ToDeviceRpcRequestMetadata> toDeviceRpcPendingMap; |
@@ -117,16 +128,16 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -117,16 +128,16 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
117 | super(systemContext); | 128 | super(systemContext); |
118 | this.tenantId = tenantId; | 129 | this.tenantId = tenantId; |
119 | this.deviceId = deviceId; | 130 | this.deviceId = deviceId; |
120 | - this.sessions = new LinkedHashMap<>(); | ||
121 | this.attributeSubscriptions = new HashMap<>(); | 131 | this.attributeSubscriptions = new HashMap<>(); |
122 | this.rpcSubscriptions = new HashMap<>(); | 132 | this.rpcSubscriptions = new HashMap<>(); |
123 | this.toDeviceRpcPendingMap = new HashMap<>(); | 133 | this.toDeviceRpcPendingMap = new HashMap<>(); |
134 | + this.sessions = new LinkedHashMapRemoveEldest<>(systemContext.getMaxConcurrentSessionsPerDevice(), this::notifyTransportAboutClosedSessionMaxSessionsLimit); | ||
124 | if (initAttributes()) { | 135 | if (initAttributes()) { |
125 | restoreSessions(); | 136 | restoreSessions(); |
126 | } | 137 | } |
127 | } | 138 | } |
128 | 139 | ||
129 | - private boolean initAttributes() { | 140 | + boolean initAttributes() { |
130 | Device device = systemContext.getDeviceService().findDeviceById(tenantId, deviceId); | 141 | Device device = systemContext.getDeviceService().findDeviceById(tenantId, deviceId); |
131 | if (device != null) { | 142 | if (device != null) { |
132 | this.deviceName = device.getName(); | 143 | this.deviceName = device.getName(); |
@@ -162,20 +173,19 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -162,20 +173,19 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
162 | 173 | ||
163 | void processRpcRequest(TbActorCtx context, ToDeviceRpcRequestActorMsg msg) { | 174 | void processRpcRequest(TbActorCtx context, ToDeviceRpcRequestActorMsg msg) { |
164 | ToDeviceRpcRequest request = msg.getMsg(); | 175 | ToDeviceRpcRequest request = msg.getMsg(); |
165 | - ToDeviceRpcRequestBody body = request.getBody(); | ||
166 | - ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder() | ||
167 | - .setRequestId(rpcSeq++) | ||
168 | - .setMethodName(body.getMethod()) | ||
169 | - .setParams(body.getParams()) | ||
170 | - .setExpirationTime(request.getExpirationTime()) | ||
171 | - .setRequestIdMSB(request.getId().getMostSignificantBits()) | ||
172 | - .setRequestIdLSB(request.getId().getLeastSignificantBits()) | ||
173 | - .build(); | 176 | + ToDeviceRpcRequestMsg rpcRequest = creteToDeviceRpcRequestMsg(request); |
174 | 177 | ||
175 | long timeout = request.getExpirationTime() - System.currentTimeMillis(); | 178 | long timeout = request.getExpirationTime() - System.currentTimeMillis(); |
179 | + boolean persisted = request.isPersisted(); | ||
180 | + | ||
176 | if (timeout <= 0) { | 181 | if (timeout <= 0) { |
177 | log.debug("[{}][{}] Ignoring message due to exp time reached, {}", deviceId, request.getId(), request.getExpirationTime()); | 182 | log.debug("[{}][{}] Ignoring message due to exp time reached, {}", deviceId, request.getId(), request.getExpirationTime()); |
183 | + if (persisted) { | ||
184 | + createRpc(request, RpcStatus.TIMEOUT); | ||
185 | + } | ||
178 | return; | 186 | return; |
187 | + } else if (persisted) { | ||
188 | + createRpc(request, RpcStatus.QUEUED); | ||
179 | } | 189 | } |
180 | 190 | ||
181 | boolean sent; | 191 | boolean sent; |
@@ -192,11 +202,17 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -192,11 +202,17 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
192 | syncSessionSet.add(key); | 202 | syncSessionSet.add(key); |
193 | } | 203 | } |
194 | }); | 204 | }); |
195 | - log.trace("46) Rpc syncSessionSet [{}] subscription after sent [{}]",syncSessionSet, rpcSubscriptions); | 205 | + log.trace("46) Rpc syncSessionSet [{}] subscription after sent [{}]", syncSessionSet, rpcSubscriptions); |
196 | syncSessionSet.forEach(rpcSubscriptions::remove); | 206 | syncSessionSet.forEach(rpcSubscriptions::remove); |
197 | } | 207 | } |
198 | 208 | ||
199 | - if (request.isOneway() && sent) { | 209 | + if (persisted) { |
210 | + ObjectNode response = JacksonUtil.newObjectNode(); | ||
211 | + response.put("rpcId", request.getId().toString()); | ||
212 | + systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), JacksonUtil.toString(response), null)); | ||
213 | + } | ||
214 | + | ||
215 | + if (!persisted && request.isOneway() && sent) { | ||
200 | log.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId()); | 216 | log.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId()); |
201 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null)); | 217 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null)); |
202 | } else { | 218 | } else { |
@@ -209,6 +225,31 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -209,6 +225,31 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
209 | } | 225 | } |
210 | } | 226 | } |
211 | 227 | ||
228 | + private Rpc createRpc(ToDeviceRpcRequest request, RpcStatus status) { | ||
229 | + Rpc rpc = new Rpc(new RpcId(request.getId())); | ||
230 | + rpc.setCreatedTime(System.currentTimeMillis()); | ||
231 | + rpc.setTenantId(tenantId); | ||
232 | + rpc.setDeviceId(deviceId); | ||
233 | + rpc.setExpirationTime(request.getExpirationTime()); | ||
234 | + rpc.setRequest(JacksonUtil.valueToTree(request)); | ||
235 | + rpc.setStatus(status); | ||
236 | + return systemContext.getTbRpcService().save(tenantId, rpc); | ||
237 | + } | ||
238 | + | ||
239 | + private ToDeviceRpcRequestMsg creteToDeviceRpcRequestMsg(ToDeviceRpcRequest request) { | ||
240 | + ToDeviceRpcRequestBody body = request.getBody(); | ||
241 | + return ToDeviceRpcRequestMsg.newBuilder() | ||
242 | + .setRequestId(rpcSeq++) | ||
243 | + .setMethodName(body.getMethod()) | ||
244 | + .setParams(body.getParams()) | ||
245 | + .setExpirationTime(request.getExpirationTime()) | ||
246 | + .setRequestIdMSB(request.getId().getMostSignificantBits()) | ||
247 | + .setRequestIdLSB(request.getId().getLeastSignificantBits()) | ||
248 | + .setOneway(request.isOneway()) | ||
249 | + .setPersisted(request.isPersisted()) | ||
250 | + .build(); | ||
251 | + } | ||
252 | + | ||
212 | void processRpcResponsesFromEdge(TbActorCtx context, FromDeviceRpcResponseActorMsg responseMsg) { | 253 | void processRpcResponsesFromEdge(TbActorCtx context, FromDeviceRpcResponseActorMsg responseMsg) { |
213 | log.debug("[{}] Processing rpc command response from edge session", deviceId); | 254 | log.debug("[{}] Processing rpc command response from edge session", deviceId); |
214 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); | 255 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); |
@@ -230,6 +271,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -230,6 +271,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
230 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); | 271 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); |
231 | if (requestMd != null) { | 272 | if (requestMd != null) { |
232 | log.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); | 273 | log.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); |
274 | + if (requestMd.getMsg().getMsg().isPersisted()) { | ||
275 | + systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), RpcStatus.TIMEOUT, null); | ||
276 | + } | ||
233 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | 277 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), |
234 | null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION)); | 278 | null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION)); |
235 | } | 279 | } |
@@ -253,7 +297,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -253,7 +297,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
253 | toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds)); | 297 | toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds)); |
254 | } | 298 | } |
255 | 299 | ||
256 | - sentOneWayIds.forEach(toDeviceRpcPendingMap::remove); | 300 | + sentOneWayIds.stream().filter(id -> !toDeviceRpcPendingMap.get(id).getMsg().getMsg().isPersisted()).forEach(toDeviceRpcPendingMap::remove); |
257 | } | 301 | } |
258 | 302 | ||
259 | private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(TbActorCtx context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) { | 303 | private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(TbActorCtx context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) { |
@@ -271,7 +315,10 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -271,7 +315,10 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
271 | .setExpirationTime(request.getExpirationTime()) | 315 | .setExpirationTime(request.getExpirationTime()) |
272 | .setRequestIdMSB(request.getId().getMostSignificantBits()) | 316 | .setRequestIdMSB(request.getId().getMostSignificantBits()) |
273 | .setRequestIdLSB(request.getId().getLeastSignificantBits()) | 317 | .setRequestIdLSB(request.getId().getLeastSignificantBits()) |
318 | + .setOneway(request.isOneway()) | ||
319 | + .setPersisted(request.isPersisted()) | ||
274 | .build(); | 320 | .build(); |
321 | + | ||
275 | sendToTransport(rpcRequest, sessionId, nodeId); | 322 | sendToTransport(rpcRequest, sessionId, nodeId); |
276 | }; | 323 | }; |
277 | } | 324 | } |
@@ -279,31 +326,39 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -279,31 +326,39 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
279 | void process(TbActorCtx context, TransportToDeviceActorMsgWrapper wrapper) { | 326 | void process(TbActorCtx context, TransportToDeviceActorMsgWrapper wrapper) { |
280 | TransportToDeviceActorMsg msg = wrapper.getMsg(); | 327 | TransportToDeviceActorMsg msg = wrapper.getMsg(); |
281 | TbCallback callback = wrapper.getCallback(); | 328 | TbCallback callback = wrapper.getCallback(); |
329 | + var sessionInfo = msg.getSessionInfo(); | ||
330 | + | ||
282 | if (msg.hasSessionEvent()) { | 331 | if (msg.hasSessionEvent()) { |
283 | - processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); | 332 | + processSessionStateMsgs(sessionInfo, msg.getSessionEvent()); |
284 | } | 333 | } |
285 | if (msg.hasSubscribeToAttributes()) { | 334 | if (msg.hasSubscribeToAttributes()) { |
286 | - processSubscriptionCommands(context, msg.getSessionInfo(), msg.getSubscribeToAttributes()); | 335 | + processSubscriptionCommands(context, sessionInfo, msg.getSubscribeToAttributes()); |
287 | } | 336 | } |
288 | if (msg.hasSubscribeToRPC()) { | 337 | if (msg.hasSubscribeToRPC()) { |
289 | - processSubscriptionCommands(context, msg.getSessionInfo(), msg.getSubscribeToRPC()); | 338 | + processSubscriptionCommands(context, sessionInfo, msg.getSubscribeToRPC()); |
339 | + } | ||
340 | + if (msg.hasSendPendingRPC()) { | ||
341 | + sendPendingRequests(context, getSessionId(sessionInfo), sessionInfo); | ||
290 | } | 342 | } |
291 | if (msg.hasGetAttributes()) { | 343 | if (msg.hasGetAttributes()) { |
292 | - handleGetAttributesRequest(context, msg.getSessionInfo(), msg.getGetAttributes()); | 344 | + handleGetAttributesRequest(context, sessionInfo, msg.getGetAttributes()); |
293 | } | 345 | } |
294 | if (msg.hasToDeviceRPCCallResponse()) { | 346 | if (msg.hasToDeviceRPCCallResponse()) { |
295 | - processRpcResponses(context, msg.getSessionInfo(), msg.getToDeviceRPCCallResponse()); | 347 | + processRpcResponses(context, sessionInfo, msg.getToDeviceRPCCallResponse()); |
296 | } | 348 | } |
297 | if (msg.hasSubscriptionInfo()) { | 349 | if (msg.hasSubscriptionInfo()) { |
298 | - handleSessionActivity(context, msg.getSessionInfo(), msg.getSubscriptionInfo()); | 350 | + handleSessionActivity(context, sessionInfo, msg.getSubscriptionInfo()); |
299 | } | 351 | } |
300 | if (msg.hasClaimDevice()) { | 352 | if (msg.hasClaimDevice()) { |
301 | - handleClaimDeviceMsg(context, msg.getSessionInfo(), msg.getClaimDevice()); | 353 | + handleClaimDeviceMsg(context, sessionInfo, msg.getClaimDevice()); |
354 | + } | ||
355 | + if (msg.hasPersistedRpcResponseMsg()) { | ||
356 | + processPersistedRpcResponses(context, sessionInfo, msg.getPersistedRpcResponseMsg()); | ||
302 | } | 357 | } |
303 | callback.onSuccess(); | 358 | callback.onSuccess(); |
304 | } | 359 | } |
305 | 360 | ||
306 | - private void handleClaimDeviceMsg(TbActorCtx context, SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg) { | 361 | + private void handleClaimDeviceMsg(TbActorCtx context, SessionInfoProto sessionInfo, ClaimDeviceMsg msg) { |
307 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); | 362 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); |
308 | systemContext.getClaimDevicesService().registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()); | 363 | systemContext.getClaimDevicesService().registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()); |
309 | } | 364 | } |
@@ -442,11 +497,19 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -442,11 +497,19 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
442 | if (success) { | 497 | if (success) { |
443 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | 498 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), |
444 | responseMsg.getPayload(), null)); | 499 | responseMsg.getPayload(), null)); |
500 | + if (requestMd.getMsg().getMsg().isPersisted()) { | ||
501 | + systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), RpcStatus.SUCCESSFUL, JacksonUtil.toJsonNode(responseMsg.getPayload())); | ||
502 | + } | ||
445 | } else { | 503 | } else { |
446 | log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId()); | 504 | log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId()); |
447 | } | 505 | } |
448 | } | 506 | } |
449 | 507 | ||
508 | + private void processPersistedRpcResponses(TbActorCtx context, SessionInfoProto sessionInfo, ToDevicePersistedRpcResponseMsg responseMsg) { | ||
509 | + UUID rpcId = new UUID(responseMsg.getRequestIdMSB(), responseMsg.getRequestIdLSB()); | ||
510 | + systemContext.getTbRpcService().save(tenantId, new RpcId(rpcId), RpcStatus.valueOf(responseMsg.getStatus()), null); | ||
511 | + } | ||
512 | + | ||
450 | private void processSubscriptionCommands(TbActorCtx context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { | 513 | private void processSubscriptionCommands(TbActorCtx context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { |
451 | UUID sessionId = getSessionId(sessionInfo); | 514 | UUID sessionId = getSessionId(sessionInfo); |
452 | if (subscribeCmd.getUnsubscribe()) { | 515 | if (subscribeCmd.getUnsubscribe()) { |
@@ -488,18 +551,14 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -488,18 +551,14 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
488 | 551 | ||
489 | private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) { | 552 | private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) { |
490 | UUID sessionId = getSessionId(sessionInfo); | 553 | UUID sessionId = getSessionId(sessionInfo); |
554 | + Objects.requireNonNull(sessionId); | ||
491 | if (msg.getEvent() == SessionEvent.OPEN) { | 555 | if (msg.getEvent() == SessionEvent.OPEN) { |
492 | if (sessions.containsKey(sessionId)) { | 556 | if (sessions.containsKey(sessionId)) { |
493 | log.debug("[{}] Received duplicate session open event [{}]", deviceId, sessionId); | 557 | log.debug("[{}] Received duplicate session open event [{}]", deviceId, sessionId); |
494 | return; | 558 | return; |
495 | } | 559 | } |
496 | - log.debug("[{}] Processing new session [{}]", deviceId, sessionId); | ||
497 | - if (sessions.size() >= systemContext.getMaxConcurrentSessionsPerDevice()) { | ||
498 | - UUID sessionIdToRemove = sessions.keySet().stream().findFirst().orElse(null); | ||
499 | - if (sessionIdToRemove != null) { | ||
500 | - notifyTransportAboutClosedSession(sessionIdToRemove, sessions.remove(sessionIdToRemove), "max concurrent sessions limit reached per device!"); | ||
501 | - } | ||
502 | - } | 560 | + log.info("[{}] Processing new session [{}]. Current sessions size {}", deviceId, sessionId, sessions.size()); |
561 | + | ||
503 | sessions.put(sessionId, new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfo.getNodeId()))); | 562 | sessions.put(sessionId, new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfo.getNodeId()))); |
504 | if (sessions.size() == 1) { | 563 | if (sessions.size() == 1) { |
505 | reportSessionOpen(); | 564 | reportSessionOpen(); |
@@ -520,8 +579,10 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -520,8 +579,10 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
520 | 579 | ||
521 | private void handleSessionActivity(TbActorCtx context, SessionInfoProto sessionInfoProto, SubscriptionInfoProto subscriptionInfo) { | 580 | private void handleSessionActivity(TbActorCtx context, SessionInfoProto sessionInfoProto, SubscriptionInfoProto subscriptionInfo) { |
522 | UUID sessionId = getSessionId(sessionInfoProto); | 581 | UUID sessionId = getSessionId(sessionInfoProto); |
582 | + Objects.requireNonNull(sessionId); | ||
583 | + | ||
523 | SessionInfoMetaData sessionMD = sessions.computeIfAbsent(sessionId, | 584 | SessionInfoMetaData sessionMD = sessions.computeIfAbsent(sessionId, |
524 | - id -> new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfoProto.getNodeId()), 0L)); | 585 | + id -> new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfoProto.getNodeId()), subscriptionInfo.getLastActivityTime())); |
525 | 586 | ||
526 | sessionMD.setLastActivityTime(subscriptionInfo.getLastActivityTime()); | 587 | sessionMD.setLastActivityTime(subscriptionInfo.getLastActivityTime()); |
527 | sessionMD.setSubscribedToAttributes(subscriptionInfo.getAttributeSubscription()); | 588 | sessionMD.setSubscribedToAttributes(subscriptionInfo.getAttributeSubscription()); |
@@ -551,6 +612,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -551,6 +612,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
551 | } | 612 | } |
552 | } | 613 | } |
553 | 614 | ||
615 | + private void notifyTransportAboutClosedSessionMaxSessionsLimit(UUID sessionId, SessionInfoMetaData sessionMd) { | ||
616 | + notifyTransportAboutClosedSession(sessionId, sessionMd, "max concurrent sessions limit reached per device!"); | ||
617 | + } | ||
618 | + | ||
619 | + | ||
554 | private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd, String message) { | 620 | private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd, String message) { |
555 | SessionCloseNotificationProto sessionCloseNotificationProto = SessionCloseNotificationProto | 621 | SessionCloseNotificationProto sessionCloseNotificationProto = SessionCloseNotificationProto |
556 | .newBuilder() | 622 | .newBuilder() |
@@ -565,7 +631,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -565,7 +631,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
565 | 631 | ||
566 | void notifyTransportAboutProfileUpdate(UUID sessionId, SessionInfoMetaData sessionMd, DeviceCredentials deviceCredentials) { | 632 | void notifyTransportAboutProfileUpdate(UUID sessionId, SessionInfoMetaData sessionMd, DeviceCredentials deviceCredentials) { |
567 | log.info("2) LwM2Mtype: "); | 633 | log.info("2) LwM2Mtype: "); |
568 | - TransportProtos.ToTransportUpdateCredentialsProto.Builder notification = TransportProtos.ToTransportUpdateCredentialsProto.newBuilder(); | 634 | + ToTransportUpdateCredentialsProto.Builder notification = ToTransportUpdateCredentialsProto.newBuilder(); |
569 | notification.addCredentialsId(deviceCredentials.getCredentialsId()); | 635 | notification.addCredentialsId(deviceCredentials.getCredentialsId()); |
570 | notification.addCredentialsValue(deviceCredentials.getCredentialsValue()); | 636 | notification.addCredentialsValue(deviceCredentials.getCredentialsValue()); |
571 | ToTransportMsg msg = ToTransportMsg.newBuilder() | 637 | ToTransportMsg msg = ToTransportMsg.newBuilder() |
@@ -640,7 +706,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -640,7 +706,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
640 | ListenableFuture<EdgeEvent> future = systemContext.getEdgeEventService().saveAsync(edgeEvent); | 706 | ListenableFuture<EdgeEvent> future = systemContext.getEdgeEventService().saveAsync(edgeEvent); |
641 | Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | 707 | Futures.addCallback(future, new FutureCallback<EdgeEvent>() { |
642 | @Override | 708 | @Override |
643 | - public void onSuccess( EdgeEvent result) { | 709 | + public void onSuccess(EdgeEvent result) { |
644 | systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId); | 710 | systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId); |
645 | } | 711 | } |
646 | 712 | ||
@@ -697,7 +763,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -697,7 +763,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
697 | return builder.build(); | 763 | return builder.build(); |
698 | } | 764 | } |
699 | 765 | ||
700 | - private void restoreSessions() { | 766 | + void restoreSessions() { |
701 | log.debug("[{}] Restoring sessions from cache", deviceId); | 767 | log.debug("[{}] Restoring sessions from cache", deviceId); |
702 | DeviceSessionsCacheEntry sessionsDump = null; | 768 | DeviceSessionsCacheEntry sessionsDump = null; |
703 | try { | 769 | try { |
@@ -710,6 +776,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -710,6 +776,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
710 | log.debug("[{}] No session information found", deviceId); | 776 | log.debug("[{}] No session information found", deviceId); |
711 | return; | 777 | return; |
712 | } | 778 | } |
779 | + // TODO: Take latest max allowed sessions size from cache | ||
713 | for (SessionSubscriptionInfoProto sessionSubscriptionInfoProto : sessionsDump.getSessionsList()) { | 780 | for (SessionSubscriptionInfoProto sessionSubscriptionInfoProto : sessionsDump.getSessionsList()) { |
714 | SessionInfoProto sessionInfoProto = sessionSubscriptionInfoProto.getSessionInfo(); | 781 | SessionInfoProto sessionInfoProto = sessionSubscriptionInfoProto.getSessionInfo(); |
715 | UUID sessionId = getSessionId(sessionInfoProto); | 782 | UUID sessionId = getSessionId(sessionInfoProto); |
@@ -756,11 +823,30 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -756,11 +823,30 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
756 | .addAllSessions(sessionsList).build().toByteArray()); | 823 | .addAllSessions(sessionsList).build().toByteArray()); |
757 | } | 824 | } |
758 | 825 | ||
759 | - void initSessionTimeout(TbActorCtx ctx) { | 826 | + void init(TbActorCtx ctx) { |
760 | schedulePeriodicMsgWithDelay(ctx, SessionTimeoutCheckMsg.instance(), systemContext.getSessionReportTimeout(), systemContext.getSessionReportTimeout()); | 827 | schedulePeriodicMsgWithDelay(ctx, SessionTimeoutCheckMsg.instance(), systemContext.getSessionReportTimeout(), systemContext.getSessionReportTimeout()); |
828 | + PageLink pageLink = new PageLink(1024); | ||
829 | + PageData<Rpc> pageData; | ||
830 | + do { | ||
831 | + pageData = systemContext.getTbRpcService().findAllByDeviceIdAndStatus(tenantId, deviceId, RpcStatus.QUEUED, pageLink); | ||
832 | + pageData.getData().forEach(rpc -> { | ||
833 | + ToDeviceRpcRequest msg = JacksonUtil.convertValue(rpc.getRequest(), ToDeviceRpcRequest.class); | ||
834 | + long timeout = rpc.getExpirationTime() - System.currentTimeMillis(); | ||
835 | + if (timeout <= 0) { | ||
836 | + rpc.setStatus(RpcStatus.TIMEOUT); | ||
837 | + systemContext.getTbRpcService().save(tenantId, rpc); | ||
838 | + } else { | ||
839 | + registerPendingRpcRequest(ctx, new ToDeviceRpcRequestActorMsg(systemContext.getServiceId(), msg), false, creteToDeviceRpcRequestMsg(msg), timeout); | ||
840 | + } | ||
841 | + }); | ||
842 | + if (pageData.hasNext()) { | ||
843 | + pageLink = pageLink.nextPageLink(); | ||
844 | + } | ||
845 | + } while (pageData.hasNext()); | ||
761 | } | 846 | } |
762 | 847 | ||
763 | void checkSessionsTimeout() { | 848 | void checkSessionsTimeout() { |
849 | + log.debug("[{}] checkSessionsTimeout started. Size before check {}", deviceId, sessions.size()); | ||
764 | long expTime = System.currentTimeMillis() - systemContext.getSessionInactivityTimeout(); | 850 | long expTime = System.currentTimeMillis() - systemContext.getSessionInactivityTimeout(); |
765 | Map<UUID, SessionInfoMetaData> sessionsToRemove = sessions.entrySet().stream().filter(kv -> kv.getValue().getLastActivityTime() < expTime).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | 851 | Map<UUID, SessionInfoMetaData> sessionsToRemove = sessions.entrySet().stream().filter(kv -> kv.getValue().getLastActivityTime() < expTime).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
766 | sessionsToRemove.forEach((sessionId, sessionMD) -> { | 852 | sessionsToRemove.forEach((sessionId, sessionMD) -> { |
@@ -772,6 +858,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -772,6 +858,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
772 | if (!sessionsToRemove.isEmpty()) { | 858 | if (!sessionsToRemove.isEmpty()) { |
773 | dumpSessions(); | 859 | dumpSessions(); |
774 | } | 860 | } |
861 | + log.debug("[{}] checkSessionsTimeout finished. Size after check {}", deviceId, sessions.size()); | ||
775 | } | 862 | } |
776 | 863 | ||
777 | } | 864 | } |
@@ -25,5 +25,4 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; | @@ -25,5 +25,4 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; | ||
25 | public class SessionInfo { | 25 | public class SessionInfo { |
26 | private final SessionType type; | 26 | private final SessionType type; |
27 | private final String nodeId; | 27 | private final String nodeId; |
28 | - private long lastActivityTime; | ||
29 | } | 28 | } |
@@ -245,11 +245,11 @@ public class TenantActor extends RuleChainManagerActor { | @@ -245,11 +245,11 @@ public class TenantActor extends RuleChainManagerActor { | ||
245 | EdgeId edgeId = new EdgeId(msg.getEntityId().getId()); | 245 | EdgeId edgeId = new EdgeId(msg.getEntityId().getId()); |
246 | EdgeRpcService edgeRpcService = systemContext.getEdgeRpcService(); | 246 | EdgeRpcService edgeRpcService = systemContext.getEdgeRpcService(); |
247 | if (msg.getEvent() == ComponentLifecycleEvent.DELETED) { | 247 | if (msg.getEvent() == ComponentLifecycleEvent.DELETED) { |
248 | - edgeRpcService.deleteEdge(edgeId); | 248 | + edgeRpcService.deleteEdge(tenantId, edgeId); |
249 | } else { | 249 | } else { |
250 | Edge edge = systemContext.getEdgeService().findEdgeById(tenantId, edgeId); | 250 | Edge edge = systemContext.getEdgeService().findEdgeById(tenantId, edgeId); |
251 | if (msg.getEvent() == ComponentLifecycleEvent.UPDATED) { | 251 | if (msg.getEvent() == ComponentLifecycleEvent.UPDATED) { |
252 | - edgeRpcService.updateEdge(edge); | 252 | + edgeRpcService.updateEdge(tenantId, edge); |
253 | } | 253 | } |
254 | } | 254 | } |
255 | } else if (isRuleEngineForCurrentTenant) { | 255 | } else if (isRuleEngineForCurrentTenant) { |
@@ -277,7 +277,7 @@ public class TenantActor extends RuleChainManagerActor { | @@ -277,7 +277,7 @@ public class TenantActor extends RuleChainManagerActor { | ||
277 | 277 | ||
278 | private void onToEdgeSessionMsg(EdgeEventUpdateMsg msg) { | 278 | private void onToEdgeSessionMsg(EdgeEventUpdateMsg msg) { |
279 | log.trace("[{}] onToEdgeSessionMsg [{}]", msg.getTenantId(), msg); | 279 | log.trace("[{}] onToEdgeSessionMsg [{}]", msg.getTenantId(), msg); |
280 | - systemContext.getEdgeRpcService().onEdgeEvent(msg.getEdgeId()); | 280 | + systemContext.getEdgeRpcService().onEdgeEvent(tenantId, msg.getEdgeId()); |
281 | } | 281 | } |
282 | 282 | ||
283 | public static class ActorCreator extends ContextBasedCreator { | 283 | public static class ActorCreator extends ContextBasedCreator { |
@@ -135,7 +135,7 @@ public class AuthController extends BaseController { | @@ -135,7 +135,7 @@ public class AuthController extends BaseController { | ||
135 | } | 135 | } |
136 | } | 136 | } |
137 | 137 | ||
138 | - @RequestMapping(value = "/noauth/activate", params = { "activateToken" }, method = RequestMethod.GET) | 138 | + @RequestMapping(value = "/noauth/activate", params = {"activateToken"}, method = RequestMethod.GET) |
139 | public ResponseEntity<String> checkActivateToken( | 139 | public ResponseEntity<String> checkActivateToken( |
140 | @RequestParam(value = "activateToken") String activateToken) { | 140 | @RequestParam(value = "activateToken") String activateToken) { |
141 | HttpHeaders headers = new HttpHeaders(); | 141 | HttpHeaders headers = new HttpHeaders(); |
@@ -159,7 +159,7 @@ public class AuthController extends BaseController { | @@ -159,7 +159,7 @@ public class AuthController extends BaseController { | ||
159 | 159 | ||
160 | @RequestMapping(value = "/noauth/resetPasswordByEmail", method = RequestMethod.POST) | 160 | @RequestMapping(value = "/noauth/resetPasswordByEmail", method = RequestMethod.POST) |
161 | @ResponseStatus(value = HttpStatus.OK) | 161 | @ResponseStatus(value = HttpStatus.OK) |
162 | - public void requestResetPasswordByEmail ( | 162 | + public void requestResetPasswordByEmail( |
163 | @RequestBody JsonNode resetPasswordByEmailRequest, | 163 | @RequestBody JsonNode resetPasswordByEmailRequest, |
164 | HttpServletRequest request) throws ThingsboardException { | 164 | HttpServletRequest request) throws ThingsboardException { |
165 | try { | 165 | try { |
@@ -170,13 +170,13 @@ public class AuthController extends BaseController { | @@ -170,13 +170,13 @@ public class AuthController extends BaseController { | ||
170 | String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, | 170 | String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, |
171 | userCredentials.getResetToken()); | 171 | userCredentials.getResetToken()); |
172 | 172 | ||
173 | - mailService.sendResetPasswordEmail(resetUrl, email); | 173 | + mailService.sendResetPasswordEmailAsync(resetUrl, email); |
174 | } catch (Exception e) { | 174 | } catch (Exception e) { |
175 | - throw handleException(e); | 175 | + log.warn("Error occurred: {}", e.getMessage()); |
176 | } | 176 | } |
177 | } | 177 | } |
178 | 178 | ||
179 | - @RequestMapping(value = "/noauth/resetPassword", params = { "resetToken" }, method = RequestMethod.GET) | 179 | + @RequestMapping(value = "/noauth/resetPassword", params = {"resetToken"}, method = RequestMethod.GET) |
180 | public ResponseEntity<String> checkResetToken( | 180 | public ResponseEntity<String> checkResetToken( |
181 | @RequestParam(value = "resetToken") String resetToken) { | 181 | @RequestParam(value = "resetToken") String resetToken) { |
182 | HttpHeaders headers = new HttpHeaders(); | 182 | HttpHeaders headers = new HttpHeaders(); |
@@ -37,12 +37,12 @@ import org.thingsboard.server.common.data.EdgeUtils; | @@ -37,12 +37,12 @@ import org.thingsboard.server.common.data.EdgeUtils; | ||
37 | import org.thingsboard.server.common.data.EntityType; | 37 | import org.thingsboard.server.common.data.EntityType; |
38 | import org.thingsboard.server.common.data.EntityView; | 38 | import org.thingsboard.server.common.data.EntityView; |
39 | import org.thingsboard.server.common.data.EntityViewInfo; | 39 | import org.thingsboard.server.common.data.EntityViewInfo; |
40 | -import org.thingsboard.server.common.data.OtaPackage; | ||
41 | -import org.thingsboard.server.common.data.OtaPackageInfo; | ||
42 | import org.thingsboard.server.common.data.HasName; | 40 | import org.thingsboard.server.common.data.HasName; |
43 | import org.thingsboard.server.common.data.HasTenantId; | 41 | import org.thingsboard.server.common.data.HasTenantId; |
44 | -import org.thingsboard.server.common.data.TbResourceInfo; | 42 | +import org.thingsboard.server.common.data.OtaPackage; |
43 | +import org.thingsboard.server.common.data.OtaPackageInfo; | ||
45 | import org.thingsboard.server.common.data.TbResource; | 44 | import org.thingsboard.server.common.data.TbResource; |
45 | +import org.thingsboard.server.common.data.TbResourceInfo; | ||
46 | import org.thingsboard.server.common.data.Tenant; | 46 | import org.thingsboard.server.common.data.Tenant; |
47 | import org.thingsboard.server.common.data.TenantInfo; | 47 | import org.thingsboard.server.common.data.TenantInfo; |
48 | import org.thingsboard.server.common.data.TenantProfile; | 48 | import org.thingsboard.server.common.data.TenantProfile; |
@@ -69,20 +69,23 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -69,20 +69,23 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
69 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 69 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
70 | import org.thingsboard.server.common.data.id.EntityViewId; | 70 | import org.thingsboard.server.common.data.id.EntityViewId; |
71 | import org.thingsboard.server.common.data.id.OtaPackageId; | 71 | import org.thingsboard.server.common.data.id.OtaPackageId; |
72 | -import org.thingsboard.server.common.data.id.TbResourceId; | 72 | +import org.thingsboard.server.common.data.id.RpcId; |
73 | import org.thingsboard.server.common.data.id.RuleChainId; | 73 | import org.thingsboard.server.common.data.id.RuleChainId; |
74 | import org.thingsboard.server.common.data.id.RuleNodeId; | 74 | import org.thingsboard.server.common.data.id.RuleNodeId; |
75 | +import org.thingsboard.server.common.data.id.TbResourceId; | ||
75 | import org.thingsboard.server.common.data.id.TenantId; | 76 | import org.thingsboard.server.common.data.id.TenantId; |
76 | import org.thingsboard.server.common.data.id.TenantProfileId; | 77 | import org.thingsboard.server.common.data.id.TenantProfileId; |
77 | import org.thingsboard.server.common.data.id.UserId; | 78 | import org.thingsboard.server.common.data.id.UserId; |
78 | import org.thingsboard.server.common.data.id.WidgetTypeId; | 79 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
79 | import org.thingsboard.server.common.data.id.WidgetsBundleId; | 80 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
81 | +import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId; | ||
80 | import org.thingsboard.server.common.data.page.PageLink; | 82 | import org.thingsboard.server.common.data.page.PageLink; |
81 | import org.thingsboard.server.common.data.page.SortOrder; | 83 | import org.thingsboard.server.common.data.page.SortOrder; |
82 | import org.thingsboard.server.common.data.page.TimePageLink; | 84 | import org.thingsboard.server.common.data.page.TimePageLink; |
83 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | 85 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; |
84 | import org.thingsboard.server.common.data.plugin.ComponentType; | 86 | import org.thingsboard.server.common.data.plugin.ComponentType; |
85 | import org.thingsboard.server.common.data.relation.EntityRelation; | 87 | import org.thingsboard.server.common.data.relation.EntityRelation; |
88 | +import org.thingsboard.server.common.data.rpc.Rpc; | ||
86 | import org.thingsboard.server.common.data.rule.RuleChain; | 89 | import org.thingsboard.server.common.data.rule.RuleChain; |
87 | import org.thingsboard.server.common.data.rule.RuleChainType; | 90 | import org.thingsboard.server.common.data.rule.RuleChainType; |
88 | import org.thingsboard.server.common.data.rule.RuleNode; | 91 | import org.thingsboard.server.common.data.rule.RuleNode; |
@@ -101,11 +104,12 @@ import org.thingsboard.server.dao.edge.EdgeService; | @@ -101,11 +104,12 @@ import org.thingsboard.server.dao.edge.EdgeService; | ||
101 | import org.thingsboard.server.dao.entityview.EntityViewService; | 104 | import org.thingsboard.server.dao.entityview.EntityViewService; |
102 | import org.thingsboard.server.dao.exception.DataValidationException; | 105 | import org.thingsboard.server.dao.exception.DataValidationException; |
103 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 106 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
104 | -import org.thingsboard.server.dao.ota.OtaPackageService; | ||
105 | import org.thingsboard.server.dao.model.ModelConstants; | 107 | import org.thingsboard.server.dao.model.ModelConstants; |
106 | import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; | 108 | import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; |
107 | import org.thingsboard.server.dao.oauth2.OAuth2Service; | 109 | import org.thingsboard.server.dao.oauth2.OAuth2Service; |
110 | +import org.thingsboard.server.dao.ota.OtaPackageService; | ||
108 | import org.thingsboard.server.dao.relation.RelationService; | 111 | import org.thingsboard.server.dao.relation.RelationService; |
112 | +import org.thingsboard.server.dao.rpc.RpcService; | ||
109 | import org.thingsboard.server.dao.rule.RuleChainService; | 113 | import org.thingsboard.server.dao.rule.RuleChainService; |
110 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | 114 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
111 | import org.thingsboard.server.dao.tenant.TenantProfileService; | 115 | import org.thingsboard.server.dao.tenant.TenantProfileService; |
@@ -120,11 +124,10 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider; | @@ -120,11 +124,10 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider; | ||
120 | import org.thingsboard.server.queue.util.TbCoreComponent; | 124 | import org.thingsboard.server.queue.util.TbCoreComponent; |
121 | import org.thingsboard.server.service.action.RuleEngineEntityActionService; | 125 | import org.thingsboard.server.service.action.RuleEngineEntityActionService; |
122 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 126 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
123 | -import org.thingsboard.server.service.ota.OtaPackageStateService; | ||
124 | import org.thingsboard.server.service.edge.EdgeNotificationService; | 127 | import org.thingsboard.server.service.edge.EdgeNotificationService; |
125 | -import org.thingsboard.server.service.edge.rpc.EdgeGrpcService; | ||
126 | -import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; | 128 | +import org.thingsboard.server.service.edge.rpc.EdgeRpcService; |
127 | import org.thingsboard.server.service.lwm2m.LwM2MServerSecurityInfoRepository; | 129 | import org.thingsboard.server.service.lwm2m.LwM2MServerSecurityInfoRepository; |
130 | +import org.thingsboard.server.service.ota.OtaPackageStateService; | ||
128 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; | 131 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
129 | import org.thingsboard.server.service.queue.TbClusterService; | 132 | import org.thingsboard.server.service.queue.TbClusterService; |
130 | import org.thingsboard.server.service.resource.TbResourceService; | 133 | import org.thingsboard.server.service.resource.TbResourceService; |
@@ -138,6 +141,8 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | @@ -138,6 +141,8 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | ||
138 | 141 | ||
139 | import javax.mail.MessagingException; | 142 | import javax.mail.MessagingException; |
140 | import javax.servlet.http.HttpServletResponse; | 143 | import javax.servlet.http.HttpServletResponse; |
144 | +import java.util.ArrayList; | ||
145 | +import java.util.Collections; | ||
141 | import java.util.List; | 146 | import java.util.List; |
142 | import java.util.Optional; | 147 | import java.util.Optional; |
143 | import java.util.Set; | 148 | import java.util.Set; |
@@ -153,6 +158,8 @@ public abstract class BaseController { | @@ -153,6 +158,8 @@ public abstract class BaseController { | ||
153 | protected static final String DEFAULT_DASHBOARD = "defaultDashboardId"; | 158 | protected static final String DEFAULT_DASHBOARD = "defaultDashboardId"; |
154 | protected static final String HOME_DASHBOARD = "homeDashboardId"; | 159 | protected static final String HOME_DASHBOARD = "homeDashboardId"; |
155 | 160 | ||
161 | + private static final int DEFAULT_PAGE_SIZE = 1000; | ||
162 | + | ||
156 | private static final ObjectMapper json = new ObjectMapper(); | 163 | private static final ObjectMapper json = new ObjectMapper(); |
157 | 164 | ||
158 | @Autowired | 165 | @Autowired |
@@ -246,6 +253,9 @@ public abstract class BaseController { | @@ -246,6 +253,9 @@ public abstract class BaseController { | ||
246 | protected OtaPackageStateService otaPackageStateService; | 253 | protected OtaPackageStateService otaPackageStateService; |
247 | 254 | ||
248 | @Autowired | 255 | @Autowired |
256 | + protected RpcService rpcService; | ||
257 | + | ||
258 | + @Autowired | ||
249 | protected TbQueueProducerProvider producerProvider; | 259 | protected TbQueueProducerProvider producerProvider; |
250 | 260 | ||
251 | @Autowired | 261 | @Autowired |
@@ -264,10 +274,7 @@ public abstract class BaseController { | @@ -264,10 +274,7 @@ public abstract class BaseController { | ||
264 | protected EdgeNotificationService edgeNotificationService; | 274 | protected EdgeNotificationService edgeNotificationService; |
265 | 275 | ||
266 | @Autowired(required = false) | 276 | @Autowired(required = false) |
267 | - protected SyncEdgeService syncEdgeService; | ||
268 | - | ||
269 | - @Autowired(required = false) | ||
270 | - protected EdgeGrpcService edgeGrpcService; | 277 | + protected EdgeRpcService edgeGrpcService; |
271 | 278 | ||
272 | @Autowired | 279 | @Autowired |
273 | protected RuleEngineEntityActionService ruleEngineEntityActionService; | 280 | protected RuleEngineEntityActionService ruleEngineEntityActionService; |
@@ -786,6 +793,18 @@ public abstract class BaseController { | @@ -786,6 +793,18 @@ public abstract class BaseController { | ||
786 | } | 793 | } |
787 | } | 794 | } |
788 | 795 | ||
796 | + Rpc checkRpcId(RpcId rpcId, Operation operation) throws ThingsboardException { | ||
797 | + try { | ||
798 | + validateId(rpcId, "Incorrect rpcId " + rpcId); | ||
799 | + Rpc rpc = rpcService.findById(getCurrentUser().getTenantId(), rpcId); | ||
800 | + checkNotNull(rpc); | ||
801 | + accessControlService.checkPermission(getCurrentUser(), Resource.RPC, operation, rpcId, rpc); | ||
802 | + return rpc; | ||
803 | + } catch (Exception e) { | ||
804 | + throw handleException(e, false); | ||
805 | + } | ||
806 | + } | ||
807 | + | ||
789 | @SuppressWarnings("unchecked") | 808 | @SuppressWarnings("unchecked") |
790 | protected <I extends EntityId> I emptyId(EntityType entityType) { | 809 | protected <I extends EntityId> I emptyId(EntityType entityType) { |
791 | return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); | 810 | return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); |
@@ -899,11 +918,14 @@ public abstract class BaseController { | @@ -899,11 +918,14 @@ public abstract class BaseController { | ||
899 | if (!edgesEnabled) { | 918 | if (!edgesEnabled) { |
900 | return null; | 919 | return null; |
901 | } | 920 | } |
902 | - List<EdgeId> result = null; | ||
903 | - try { | ||
904 | - result = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId).get(); | ||
905 | - } catch (Exception e) { | ||
906 | - log.error("[{}] can't find related edge ids for entity [{}]", tenantId, entityId, e); | 921 | + if (EntityType.EDGE.equals(entityId.getEntityType())) { |
922 | + return Collections.singletonList(new EdgeId(entityId.getId())); | ||
923 | + } | ||
924 | + PageDataIterableByTenantIdEntityId<EdgeId> relatedEdgeIdsIterator = | ||
925 | + new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE); | ||
926 | + List<EdgeId> result = new ArrayList<>(); | ||
927 | + for(EdgeId edgeId : relatedEdgeIdsIterator) { | ||
928 | + result.add(edgeId); | ||
907 | } | 929 | } |
908 | return result; | 930 | return result; |
909 | } | 931 | } |
@@ -782,15 +782,17 @@ public class DeviceController extends BaseController { | @@ -782,15 +782,17 @@ public class DeviceController extends BaseController { | ||
782 | } | 782 | } |
783 | 783 | ||
784 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 784 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
785 | - @RequestMapping(value = "/devices/count/{otaPackageType}", method = RequestMethod.GET) | 785 | + @RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET) |
786 | @ResponseBody | 786 | @ResponseBody |
787 | - public Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(@PathVariable("otaPackageType") String otaPackageType, | ||
788 | - @RequestParam String deviceProfileId) throws ThingsboardException { | 787 | + public Long countByDeviceProfileAndEmptyOtaPackage(@PathVariable("otaPackageType") String otaPackageType, |
788 | + @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { | ||
789 | checkParameter("OtaPackageType", otaPackageType); | 789 | checkParameter("OtaPackageType", otaPackageType); |
790 | checkParameter("DeviceProfileId", deviceProfileId); | 790 | checkParameter("DeviceProfileId", deviceProfileId); |
791 | try { | 791 | try { |
792 | return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage( | 792 | return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage( |
793 | - getCurrentUser().getTenantId(), new DeviceProfileId(UUID.fromString(deviceProfileId)), OtaPackageType.valueOf(otaPackageType)); | 793 | + getTenantId(), |
794 | + new DeviceProfileId(UUID.fromString(deviceProfileId)), | ||
795 | + OtaPackageType.valueOf(otaPackageType)); | ||
794 | } catch (Exception e) { | 796 | } catch (Exception e) { |
795 | throw handleException(e); | 797 | throw handleException(e); |
796 | } | 798 | } |
@@ -49,7 +49,6 @@ import org.thingsboard.server.dao.exception.DataValidationException; | @@ -49,7 +49,6 @@ import org.thingsboard.server.dao.exception.DataValidationException; | ||
49 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 49 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
50 | import org.thingsboard.server.dao.model.ModelConstants; | 50 | import org.thingsboard.server.dao.model.ModelConstants; |
51 | import org.thingsboard.server.queue.util.TbCoreComponent; | 51 | import org.thingsboard.server.queue.util.TbCoreComponent; |
52 | -import org.thingsboard.server.service.edge.rpc.EdgeGrpcSession; | ||
53 | import org.thingsboard.server.service.security.model.SecurityUser; | 52 | import org.thingsboard.server.service.security.model.SecurityUser; |
54 | import org.thingsboard.server.service.security.permission.Operation; | 53 | import org.thingsboard.server.service.security.permission.Operation; |
55 | import org.thingsboard.server.service.security.permission.Resource; | 54 | import org.thingsboard.server.service.security.permission.Resource; |
@@ -128,7 +127,7 @@ public class EdgeController extends BaseController { | @@ -128,7 +127,7 @@ public class EdgeController extends BaseController { | ||
128 | accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, | 127 | accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, |
129 | edge.getId(), edge); | 128 | edge.getId(), edge); |
130 | 129 | ||
131 | - Edge savedEdge = checkNotNull(edgeService.saveEdge(edge)); | 130 | + Edge savedEdge = checkNotNull(edgeService.saveEdge(edge, true)); |
132 | 131 | ||
133 | if (created) { | 132 | if (created) { |
134 | ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), savedEdge.getId()); | 133 | ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), savedEdge.getId()); |
@@ -536,9 +535,7 @@ public class EdgeController extends BaseController { | @@ -536,9 +535,7 @@ public class EdgeController extends BaseController { | ||
536 | edgeId = checkNotNull(edgeId); | 535 | edgeId = checkNotNull(edgeId); |
537 | SecurityUser user = getCurrentUser(); | 536 | SecurityUser user = getCurrentUser(); |
538 | TenantId tenantId = user.getTenantId(); | 537 | TenantId tenantId = user.getTenantId(); |
539 | - EdgeGrpcSession session = edgeGrpcService.getEdgeGrpcSessionById(tenantId, edgeId); | ||
540 | - Edge edge = session.getEdge(); | ||
541 | - syncEdgeService.sync(tenantId, edge); | 538 | + edgeGrpcService.startSyncProcess(tenantId, edgeId); |
542 | } else { | 539 | } else { |
543 | throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL); | 540 | throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL); |
544 | } | 541 | } |
@@ -32,12 +32,13 @@ import org.springframework.web.multipart.MultipartFile; | @@ -32,12 +32,13 @@ import org.springframework.web.multipart.MultipartFile; | ||
32 | import org.thingsboard.server.common.data.EntityType; | 32 | import org.thingsboard.server.common.data.EntityType; |
33 | import org.thingsboard.server.common.data.OtaPackage; | 33 | import org.thingsboard.server.common.data.OtaPackage; |
34 | import org.thingsboard.server.common.data.OtaPackageInfo; | 34 | import org.thingsboard.server.common.data.OtaPackageInfo; |
35 | +import org.thingsboard.server.common.data.SaveOtaPackageInfoRequest; | ||
35 | import org.thingsboard.server.common.data.audit.ActionType; | 36 | import org.thingsboard.server.common.data.audit.ActionType; |
36 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 37 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
37 | -import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; | ||
38 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | ||
39 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 38 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
40 | import org.thingsboard.server.common.data.id.OtaPackageId; | 39 | import org.thingsboard.server.common.data.id.OtaPackageId; |
40 | +import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; | ||
41 | +import org.thingsboard.server.common.data.ota.OtaPackageType; | ||
41 | import org.thingsboard.server.common.data.page.PageData; | 42 | import org.thingsboard.server.common.data.page.PageData; |
42 | import org.thingsboard.server.common.data.page.PageLink; | 43 | import org.thingsboard.server.common.data.page.PageLink; |
43 | import org.thingsboard.server.queue.util.TbCoreComponent; | 44 | import org.thingsboard.server.queue.util.TbCoreComponent; |
@@ -109,12 +110,12 @@ public class OtaPackageController extends BaseController { | @@ -109,12 +110,12 @@ public class OtaPackageController extends BaseController { | ||
109 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | 110 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
110 | @RequestMapping(value = "/otaPackage", method = RequestMethod.POST) | 111 | @RequestMapping(value = "/otaPackage", method = RequestMethod.POST) |
111 | @ResponseBody | 112 | @ResponseBody |
112 | - public OtaPackageInfo saveOtaPackageInfo(@RequestBody OtaPackageInfo otaPackageInfo) throws ThingsboardException { | 113 | + public OtaPackageInfo saveOtaPackageInfo(@RequestBody SaveOtaPackageInfoRequest otaPackageInfo) throws ThingsboardException { |
113 | boolean created = otaPackageInfo.getId() == null; | 114 | boolean created = otaPackageInfo.getId() == null; |
114 | try { | 115 | try { |
115 | otaPackageInfo.setTenantId(getTenantId()); | 116 | otaPackageInfo.setTenantId(getTenantId()); |
116 | checkEntity(otaPackageInfo.getId(), otaPackageInfo, Resource.OTA_PACKAGE); | 117 | checkEntity(otaPackageInfo.getId(), otaPackageInfo, Resource.OTA_PACKAGE); |
117 | - OtaPackageInfo savedOtaPackageInfo = otaPackageService.saveOtaPackageInfo(otaPackageInfo); | 118 | + OtaPackageInfo savedOtaPackageInfo = otaPackageService.saveOtaPackageInfo(new OtaPackageInfo(otaPackageInfo), otaPackageInfo.isUsesUrl()); |
118 | logEntityAction(savedOtaPackageInfo.getId(), savedOtaPackageInfo, | 119 | logEntityAction(savedOtaPackageInfo.getId(), savedOtaPackageInfo, |
119 | null, created ? ActionType.ADDED : ActionType.UPDATED, null); | 120 | null, created ? ActionType.ADDED : ActionType.UPDATED, null); |
120 | return savedOtaPackageInfo; | 121 | return savedOtaPackageInfo; |
@@ -29,17 +29,24 @@ import org.springframework.web.bind.annotation.PathVariable; | @@ -29,17 +29,24 @@ import org.springframework.web.bind.annotation.PathVariable; | ||
29 | import org.springframework.web.bind.annotation.RequestBody; | 29 | import org.springframework.web.bind.annotation.RequestBody; |
30 | import org.springframework.web.bind.annotation.RequestMapping; | 30 | import org.springframework.web.bind.annotation.RequestMapping; |
31 | import org.springframework.web.bind.annotation.RequestMethod; | 31 | import org.springframework.web.bind.annotation.RequestMethod; |
32 | +import org.springframework.web.bind.annotation.RequestParam; | ||
32 | import org.springframework.web.bind.annotation.ResponseBody; | 33 | import org.springframework.web.bind.annotation.ResponseBody; |
33 | import org.springframework.web.bind.annotation.RestController; | 34 | import org.springframework.web.bind.annotation.RestController; |
34 | import org.springframework.web.context.request.async.DeferredResult; | 35 | import org.springframework.web.context.request.async.DeferredResult; |
35 | import org.thingsboard.rule.engine.api.RpcError; | 36 | import org.thingsboard.rule.engine.api.RpcError; |
37 | +import org.thingsboard.server.common.data.DataConstants; | ||
36 | import org.thingsboard.server.common.data.audit.ActionType; | 38 | import org.thingsboard.server.common.data.audit.ActionType; |
37 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 39 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
38 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 40 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
39 | import org.thingsboard.server.common.data.id.DeviceId; | 41 | import org.thingsboard.server.common.data.id.DeviceId; |
40 | import org.thingsboard.server.common.data.id.EntityId; | 42 | import org.thingsboard.server.common.data.id.EntityId; |
43 | +import org.thingsboard.server.common.data.id.RpcId; | ||
41 | import org.thingsboard.server.common.data.id.TenantId; | 44 | import org.thingsboard.server.common.data.id.TenantId; |
42 | import org.thingsboard.server.common.data.id.UUIDBased; | 45 | import org.thingsboard.server.common.data.id.UUIDBased; |
46 | +import org.thingsboard.server.common.data.page.PageData; | ||
47 | +import org.thingsboard.server.common.data.page.PageLink; | ||
48 | +import org.thingsboard.server.common.data.rpc.Rpc; | ||
49 | +import org.thingsboard.server.common.data.rpc.RpcStatus; | ||
43 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | 50 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; |
44 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 51 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
45 | import org.thingsboard.server.queue.util.TbCoreComponent; | 52 | import org.thingsboard.server.queue.util.TbCoreComponent; |
@@ -93,6 +100,52 @@ public class RpcController extends BaseController { | @@ -93,6 +100,52 @@ public class RpcController extends BaseController { | ||
93 | return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody); | 100 | return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody); |
94 | } | 101 | } |
95 | 102 | ||
103 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
104 | + @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET) | ||
105 | + @ResponseBody | ||
106 | + public Rpc getPersistedRpc(@PathVariable("rpcId") String strRpc) throws ThingsboardException { | ||
107 | + checkParameter("RpcId", strRpc); | ||
108 | + try { | ||
109 | + RpcId rpcId = new RpcId(UUID.fromString(strRpc)); | ||
110 | + return checkRpcId(rpcId, Operation.READ); | ||
111 | + } catch (Exception e) { | ||
112 | + throw handleException(e); | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
117 | + @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET) | ||
118 | + @ResponseBody | ||
119 | + public PageData<Rpc> getPersistedRpcByDevice(@PathVariable("deviceId") String strDeviceId, | ||
120 | + @RequestParam int pageSize, | ||
121 | + @RequestParam int page, | ||
122 | + @RequestParam RpcStatus rpcStatus, | ||
123 | + @RequestParam(required = false) String textSearch, | ||
124 | + @RequestParam(required = false) String sortProperty, | ||
125 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
126 | + checkParameter("DeviceId", strDeviceId); | ||
127 | + try { | ||
128 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
129 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
130 | + DeviceId deviceId = new DeviceId(UUID.fromString(strDeviceId)); | ||
131 | + return checkNotNull(rpcService.findAllByDeviceIdAndStatus(tenantId, deviceId, rpcStatus, pageLink)); | ||
132 | + } catch (Exception e) { | ||
133 | + throw handleException(e); | ||
134 | + } | ||
135 | + } | ||
136 | + | ||
137 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | ||
138 | + @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.DELETE) | ||
139 | + @ResponseBody | ||
140 | + public void deleteResource(@PathVariable("rpcId") String strRpc) throws ThingsboardException { | ||
141 | + checkParameter("RpcId", strRpc); | ||
142 | + try { | ||
143 | + rpcService.deleteRpc(getTenantId(), new RpcId(UUID.fromString(strRpc))); | ||
144 | + } catch (Exception e) { | ||
145 | + throw handleException(e); | ||
146 | + } | ||
147 | + } | ||
148 | + | ||
96 | private DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody) throws ThingsboardException { | 149 | private DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody) throws ThingsboardException { |
97 | try { | 150 | try { |
98 | JsonNode rpcRequestBody = jsonMapper.readTree(requestBody); | 151 | JsonNode rpcRequestBody = jsonMapper.readTree(requestBody); |
@@ -103,6 +156,7 @@ public class RpcController extends BaseController { | @@ -103,6 +156,7 @@ public class RpcController extends BaseController { | ||
103 | long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout; | 156 | long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout; |
104 | long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout); | 157 | long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout); |
105 | UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID(); | 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(); | ||
106 | accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() { | 160 | accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() { |
107 | @Override | 161 | @Override |
108 | public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) { | 162 | public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) { |
@@ -111,7 +165,8 @@ public class RpcController extends BaseController { | @@ -111,7 +165,8 @@ public class RpcController extends BaseController { | ||
111 | deviceId, | 165 | deviceId, |
112 | oneWay, | 166 | oneWay, |
113 | expTime, | 167 | expTime, |
114 | - body | 168 | + body, |
169 | + persisted | ||
115 | ); | 170 | ); |
116 | deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse), currentUser); | 171 | deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse), currentUser); |
117 | } | 172 | } |
@@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; | @@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; | ||
50 | import org.thingsboard.server.common.data.id.RuleNodeId; | 50 | import org.thingsboard.server.common.data.id.RuleNodeId; |
51 | import org.thingsboard.server.common.data.id.TenantId; | 51 | import org.thingsboard.server.common.data.id.TenantId; |
52 | import org.thingsboard.server.common.data.page.PageData; | 52 | import org.thingsboard.server.common.data.page.PageData; |
53 | +import org.thingsboard.server.common.data.page.PageDataIterableByTenant; | ||
53 | import org.thingsboard.server.common.data.page.PageLink; | 54 | import org.thingsboard.server.common.data.page.PageLink; |
54 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 55 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
55 | import org.thingsboard.server.common.data.rule.DefaultRuleChainCreateRequest; | 56 | import org.thingsboard.server.common.data.rule.DefaultRuleChainCreateRequest; |
@@ -70,10 +71,12 @@ import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; | @@ -70,10 +71,12 @@ import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; | ||
70 | import org.thingsboard.server.service.security.permission.Operation; | 71 | import org.thingsboard.server.service.security.permission.Operation; |
71 | import org.thingsboard.server.service.security.permission.Resource; | 72 | import org.thingsboard.server.service.security.permission.Resource; |
72 | 73 | ||
74 | +import java.util.ArrayList; | ||
73 | import java.util.List; | 75 | import java.util.List; |
74 | import java.util.Map; | 76 | import java.util.Map; |
75 | import java.util.Set; | 77 | import java.util.Set; |
76 | import java.util.concurrent.ConcurrentMap; | 78 | import java.util.concurrent.ConcurrentMap; |
79 | +import java.util.concurrent.TimeUnit; | ||
77 | import java.util.stream.Collectors; | 80 | import java.util.stream.Collectors; |
78 | 81 | ||
79 | @Slf4j | 82 | @Slf4j |
@@ -85,7 +88,10 @@ public class RuleChainController extends BaseController { | @@ -85,7 +88,10 @@ public class RuleChainController extends BaseController { | ||
85 | public static final String RULE_CHAIN_ID = "ruleChainId"; | 88 | public static final String RULE_CHAIN_ID = "ruleChainId"; |
86 | public static final String RULE_NODE_ID = "ruleNodeId"; | 89 | public static final String RULE_NODE_ID = "ruleNodeId"; |
87 | 90 | ||
91 | + private static final int DEFAULT_PAGE_SIZE = 1000; | ||
92 | + | ||
88 | private static final ObjectMapper objectMapper = new ObjectMapper(); | 93 | private static final ObjectMapper objectMapper = new ObjectMapper(); |
94 | + public static final int TIMEOUT = 20; | ||
89 | 95 | ||
90 | @Autowired | 96 | @Autowired |
91 | private InstallScripts installScripts; | 97 | private InstallScripts installScripts; |
@@ -388,25 +394,25 @@ public class RuleChainController extends BaseController { | @@ -388,25 +394,25 @@ public class RuleChainController extends BaseController { | ||
388 | TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data); | 394 | TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data); |
389 | switch (scriptType) { | 395 | switch (scriptType) { |
390 | case "update": | 396 | case "update": |
391 | - output = msgToOutput(engine.executeUpdate(inMsg)); | 397 | + output = msgToOutput(engine.executeUpdateAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS)); |
392 | break; | 398 | break; |
393 | case "generate": | 399 | case "generate": |
394 | - output = msgToOutput(engine.executeGenerate(inMsg)); | 400 | + output = msgToOutput(engine.executeGenerateAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS)); |
395 | break; | 401 | break; |
396 | case "filter": | 402 | case "filter": |
397 | - boolean result = engine.executeFilter(inMsg); | 403 | + boolean result = engine.executeFilterAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); |
398 | output = Boolean.toString(result); | 404 | output = Boolean.toString(result); |
399 | break; | 405 | break; |
400 | case "switch": | 406 | case "switch": |
401 | - Set<String> states = engine.executeSwitch(inMsg); | 407 | + Set<String> states = engine.executeSwitchAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); |
402 | output = objectMapper.writeValueAsString(states); | 408 | output = objectMapper.writeValueAsString(states); |
403 | break; | 409 | break; |
404 | case "json": | 410 | case "json": |
405 | - JsonNode json = engine.executeJson(inMsg); | 411 | + JsonNode json = engine.executeJsonAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); |
406 | output = objectMapper.writeValueAsString(json); | 412 | output = objectMapper.writeValueAsString(json); |
407 | break; | 413 | break; |
408 | case "string": | 414 | case "string": |
409 | - output = engine.executeToString(inMsg); | 415 | + output = engine.executeToStringAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); |
410 | break; | 416 | break; |
411 | default: | 417 | default: |
412 | throw new IllegalArgumentException("Unsupported script type: " + scriptType); | 418 | throw new IllegalArgumentException("Unsupported script type: " + scriptType); |
@@ -477,7 +483,7 @@ public class RuleChainController extends BaseController { | @@ -477,7 +483,7 @@ public class RuleChainController extends BaseController { | ||
477 | return objectMapper.writeValueAsString(resultNode); | 483 | return objectMapper.writeValueAsString(resultNode); |
478 | } | 484 | } |
479 | 485 | ||
480 | - private JsonNode convertMsgToOut(TbMsg msg) throws Exception{ | 486 | + private JsonNode convertMsgToOut(TbMsg msg) throws Exception { |
481 | ObjectNode msgData = objectMapper.createObjectNode(); | 487 | ObjectNode msgData = objectMapper.createObjectNode(); |
482 | if (!StringUtils.isEmpty(msg.getData())) { | 488 | if (!StringUtils.isEmpty(msg.getData())) { |
483 | msgData.set("msg", objectMapper.readTree(msg.getData())); | 489 | msgData.set("msg", objectMapper.readTree(msg.getData())); |
@@ -632,13 +638,20 @@ public class RuleChainController extends BaseController { | @@ -632,13 +638,20 @@ public class RuleChainController extends BaseController { | ||
632 | } | 638 | } |
633 | } | 639 | } |
634 | 640 | ||
641 | + // TODO: @voba refactor this - add new config to edge rule chain to set it as auto-assign | ||
635 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | 642 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
636 | @RequestMapping(value = "/ruleChain/autoAssignToEdgeRuleChains", method = RequestMethod.GET) | 643 | @RequestMapping(value = "/ruleChain/autoAssignToEdgeRuleChains", method = RequestMethod.GET) |
637 | @ResponseBody | 644 | @ResponseBody |
638 | public List<RuleChain> getAutoAssignToEdgeRuleChains() throws ThingsboardException { | 645 | public List<RuleChain> getAutoAssignToEdgeRuleChains() throws ThingsboardException { |
639 | try { | 646 | try { |
640 | TenantId tenantId = getCurrentUser().getTenantId(); | 647 | TenantId tenantId = getCurrentUser().getTenantId(); |
641 | - return checkNotNull(ruleChainService.findAutoAssignToEdgeRuleChainsByTenantId(tenantId)).get(); | 648 | + List<RuleChain> result = new ArrayList<>(); |
649 | + PageDataIterableByTenant<RuleChain> autoAssignRuleChainsIterator = | ||
650 | + new PageDataIterableByTenant<>(ruleChainService::findAutoAssignToEdgeRuleChainsByTenantId, tenantId, DEFAULT_PAGE_SIZE); | ||
651 | + for (RuleChain ruleChain : autoAssignRuleChainsIterator) { | ||
652 | + result.add(ruleChain); | ||
653 | + } | ||
654 | + return checkNotNull(result); | ||
642 | } catch (Exception e) { | 655 | } catch (Exception e) { |
643 | throw handleException(e); | 656 | throw handleException(e); |
644 | } | 657 | } |
@@ -95,9 +95,7 @@ public class TenantController extends BaseController { | @@ -95,9 +95,7 @@ public class TenantController extends BaseController { | ||
95 | tenant = checkNotNull(tenantService.saveTenant(tenant)); | 95 | tenant = checkNotNull(tenantService.saveTenant(tenant)); |
96 | if (newTenant) { | 96 | if (newTenant) { |
97 | installScripts.createDefaultRuleChains(tenant.getId()); | 97 | installScripts.createDefaultRuleChains(tenant.getId()); |
98 | - if (edgesEnabled) { | ||
99 | - installScripts.createDefaultEdgeRuleChains(tenant.getId()); | ||
100 | - } | 98 | + installScripts.createDefaultEdgeRuleChains(tenant.getId()); |
101 | } | 99 | } |
102 | tenantProfileCache.evict(tenant.getId()); | 100 | tenantProfileCache.evict(tenant.getId()); |
103 | tbClusterService.onTenantChange(tenant, null); | 101 | tbClusterService.onTenantChange(tenant, null); |
@@ -25,9 +25,12 @@ import org.springframework.security.authentication.BadCredentialsException; | @@ -25,9 +25,12 @@ import org.springframework.security.authentication.BadCredentialsException; | ||
25 | import org.springframework.security.authentication.DisabledException; | 25 | import org.springframework.security.authentication.DisabledException; |
26 | import org.springframework.security.authentication.LockedException; | 26 | import org.springframework.security.authentication.LockedException; |
27 | import org.springframework.security.core.AuthenticationException; | 27 | import org.springframework.security.core.AuthenticationException; |
28 | +import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
28 | import org.springframework.security.web.access.AccessDeniedHandler; | 29 | import org.springframework.security.web.access.AccessDeniedHandler; |
29 | -import org.springframework.stereotype.Component; | 30 | +import org.springframework.web.bind.annotation.ExceptionHandler; |
31 | +import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
30 | import org.springframework.web.client.HttpClientErrorException; | 32 | import org.springframework.web.client.HttpClientErrorException; |
33 | +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; | ||
31 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 34 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
32 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 35 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
33 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; | 36 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; |
@@ -40,14 +43,15 @@ import javax.servlet.http.HttpServletRequest; | @@ -40,14 +43,15 @@ import javax.servlet.http.HttpServletRequest; | ||
40 | import javax.servlet.http.HttpServletResponse; | 43 | import javax.servlet.http.HttpServletResponse; |
41 | import java.io.IOException; | 44 | import java.io.IOException; |
42 | 45 | ||
43 | -@Component | ||
44 | @Slf4j | 46 | @Slf4j |
45 | -public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | 47 | +@RestControllerAdvice |
48 | +public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHandler implements AccessDeniedHandler { | ||
46 | 49 | ||
47 | @Autowired | 50 | @Autowired |
48 | private ObjectMapper mapper; | 51 | private ObjectMapper mapper; |
49 | 52 | ||
50 | @Override | 53 | @Override |
54 | + @ExceptionHandler(AccessDeniedException.class) | ||
51 | public void handle(HttpServletRequest request, HttpServletResponse response, | 55 | public void handle(HttpServletRequest request, HttpServletResponse response, |
52 | AccessDeniedException accessDeniedException) throws IOException, | 56 | AccessDeniedException accessDeniedException) throws IOException, |
53 | ServletException { | 57 | ServletException { |
@@ -60,6 +64,7 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | @@ -60,6 +64,7 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | ||
60 | } | 64 | } |
61 | } | 65 | } |
62 | 66 | ||
67 | + @ExceptionHandler(Exception.class) | ||
63 | public void handle(Exception exception, HttpServletResponse response) { | 68 | public void handle(Exception exception, HttpServletResponse response) { |
64 | log.debug("Processing exception {}", exception.getMessage(), exception); | 69 | log.debug("Processing exception {}", exception.getMessage(), exception); |
65 | if (!response.isCommitted()) { | 70 | if (!response.isCommitted()) { |
@@ -148,7 +153,7 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | @@ -148,7 +153,7 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | ||
148 | 153 | ||
149 | private void handleAuthenticationException(AuthenticationException authenticationException, HttpServletResponse response) throws IOException { | 154 | private void handleAuthenticationException(AuthenticationException authenticationException, HttpServletResponse response) throws IOException { |
150 | response.setStatus(HttpStatus.UNAUTHORIZED.value()); | 155 | response.setStatus(HttpStatus.UNAUTHORIZED.value()); |
151 | - if (authenticationException instanceof BadCredentialsException) { | 156 | + if (authenticationException instanceof BadCredentialsException || authenticationException instanceof UsernameNotFoundException) { |
152 | mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); | 157 | mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); |
153 | } else if (authenticationException instanceof DisabledException) { | 158 | } else if (authenticationException instanceof DisabledException) { |
154 | mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); | 159 | mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); |
@@ -159,7 +164,7 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | @@ -159,7 +164,7 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { | ||
159 | } else if (authenticationException instanceof AuthMethodNotSupportedException) { | 164 | } else if (authenticationException instanceof AuthMethodNotSupportedException) { |
160 | mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of(authenticationException.getMessage(), ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); | 165 | mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of(authenticationException.getMessage(), ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); |
161 | } else if (authenticationException instanceof UserPasswordExpiredException) { | 166 | } else if (authenticationException instanceof UserPasswordExpiredException) { |
162 | - UserPasswordExpiredException expiredException = (UserPasswordExpiredException)authenticationException; | 167 | + UserPasswordExpiredException expiredException = (UserPasswordExpiredException) authenticationException; |
163 | String resetToken = expiredException.getResetToken(); | 168 | String resetToken = expiredException.getResetToken(); |
164 | mapper.writeValue(response.getWriter(), ThingsboardCredentialsExpiredResponse.of(expiredException.getMessage(), resetToken)); | 169 | mapper.writeValue(response.getWriter(), ThingsboardCredentialsExpiredResponse.of(expiredException.getMessage(), resetToken)); |
165 | } else { | 170 | } else { |
@@ -15,9 +15,7 @@ | @@ -15,9 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.edge; | 16 | package org.thingsboard.server.service.edge; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.core.JsonProcessingException; | ||
19 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
20 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
21 | import com.google.common.util.concurrent.FutureCallback; | 19 | import com.google.common.util.concurrent.FutureCallback; |
22 | import com.google.common.util.concurrent.Futures; | 20 | import com.google.common.util.concurrent.Futures; |
23 | import com.google.common.util.concurrent.ListenableFuture; | 21 | import com.google.common.util.concurrent.ListenableFuture; |
@@ -25,45 +23,30 @@ import lombok.extern.slf4j.Slf4j; | @@ -25,45 +23,30 @@ import lombok.extern.slf4j.Slf4j; | ||
25 | import org.checkerframework.checker.nullness.qual.Nullable; | 23 | import org.checkerframework.checker.nullness.qual.Nullable; |
26 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
27 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
28 | -import org.thingsboard.server.common.data.EdgeUtils; | ||
29 | -import org.thingsboard.server.common.data.EntityType; | ||
30 | -import org.thingsboard.server.common.data.User; | ||
31 | -import org.thingsboard.server.common.data.alarm.Alarm; | ||
32 | import org.thingsboard.server.common.data.edge.Edge; | 26 | import org.thingsboard.server.common.data.edge.Edge; |
33 | import org.thingsboard.server.common.data.edge.EdgeEvent; | 27 | import org.thingsboard.server.common.data.edge.EdgeEvent; |
34 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; | 28 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
35 | import org.thingsboard.server.common.data.edge.EdgeEventType; | 29 | import org.thingsboard.server.common.data.edge.EdgeEventType; |
36 | -import org.thingsboard.server.common.data.id.AlarmId; | ||
37 | -import org.thingsboard.server.common.data.id.CustomerId; | ||
38 | import org.thingsboard.server.common.data.id.EdgeId; | 30 | import org.thingsboard.server.common.data.id.EdgeId; |
39 | import org.thingsboard.server.common.data.id.EntityId; | 31 | import org.thingsboard.server.common.data.id.EntityId; |
40 | -import org.thingsboard.server.common.data.id.EntityIdFactory; | ||
41 | import org.thingsboard.server.common.data.id.RuleChainId; | 32 | import org.thingsboard.server.common.data.id.RuleChainId; |
42 | import org.thingsboard.server.common.data.id.TenantId; | 33 | import org.thingsboard.server.common.data.id.TenantId; |
43 | -import org.thingsboard.server.common.data.page.PageData; | ||
44 | -import org.thingsboard.server.common.data.page.PageLink; | ||
45 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
46 | -import org.thingsboard.server.common.data.relation.EntityRelation; | ||
47 | -import org.thingsboard.server.common.data.rule.RuleChain; | ||
48 | -import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; | ||
49 | import org.thingsboard.server.common.msg.queue.TbCallback; | 34 | import org.thingsboard.server.common.msg.queue.TbCallback; |
50 | -import org.thingsboard.server.dao.alarm.AlarmService; | ||
51 | import org.thingsboard.server.dao.edge.EdgeEventService; | 35 | import org.thingsboard.server.dao.edge.EdgeEventService; |
52 | import org.thingsboard.server.dao.edge.EdgeService; | 36 | import org.thingsboard.server.dao.edge.EdgeService; |
53 | -import org.thingsboard.server.dao.rule.RuleChainService; | ||
54 | -import org.thingsboard.server.dao.user.UserService; | ||
55 | import org.thingsboard.server.gen.transport.TransportProtos; | 37 | import org.thingsboard.server.gen.transport.TransportProtos; |
56 | import org.thingsboard.server.queue.util.TbCoreComponent; | 38 | import org.thingsboard.server.queue.util.TbCoreComponent; |
39 | +import org.thingsboard.server.service.edge.rpc.processor.AlarmEdgeProcessor; | ||
40 | +import org.thingsboard.server.service.edge.rpc.processor.CustomerEdgeProcessor; | ||
41 | +import org.thingsboard.server.service.edge.rpc.processor.EdgeProcessor; | ||
42 | +import org.thingsboard.server.service.edge.rpc.processor.EntityEdgeProcessor; | ||
43 | +import org.thingsboard.server.service.edge.rpc.processor.RelationEdgeProcessor; | ||
57 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; | 44 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
58 | import org.thingsboard.server.service.queue.TbClusterService; | 45 | import org.thingsboard.server.service.queue.TbClusterService; |
59 | 46 | ||
60 | import javax.annotation.PostConstruct; | 47 | import javax.annotation.PostConstruct; |
61 | import javax.annotation.PreDestroy; | 48 | import javax.annotation.PreDestroy; |
62 | import java.io.IOException; | 49 | import java.io.IOException; |
63 | -import java.util.ArrayList; | ||
64 | -import java.util.HashSet; | ||
65 | -import java.util.List; | ||
66 | -import java.util.Set; | ||
67 | import java.util.UUID; | 50 | import java.util.UUID; |
68 | import java.util.concurrent.ExecutorService; | 51 | import java.util.concurrent.ExecutorService; |
69 | import java.util.concurrent.Executors; | 52 | import java.util.concurrent.Executors; |
@@ -73,30 +56,32 @@ import java.util.concurrent.Executors; | @@ -73,30 +56,32 @@ import java.util.concurrent.Executors; | ||
73 | @Slf4j | 56 | @Slf4j |
74 | public class DefaultEdgeNotificationService implements EdgeNotificationService { | 57 | public class DefaultEdgeNotificationService implements EdgeNotificationService { |
75 | 58 | ||
76 | - private static final ObjectMapper mapper = new ObjectMapper(); | 59 | + @Autowired |
60 | + private EdgeService edgeService; | ||
77 | 61 | ||
78 | - private static final int DEFAULT_LIMIT = 100; | 62 | + @Autowired |
63 | + private EdgeEventService edgeEventService; | ||
79 | 64 | ||
80 | @Autowired | 65 | @Autowired |
81 | - private EdgeService edgeService; | 66 | + private TbClusterService clusterService; |
82 | 67 | ||
83 | @Autowired | 68 | @Autowired |
84 | - private AlarmService alarmService; | 69 | + private DbCallbackExecutorService dbCallbackExecutorService; |
85 | 70 | ||
86 | @Autowired | 71 | @Autowired |
87 | - private UserService userService; | 72 | + private EdgeProcessor edgeProcessor; |
88 | 73 | ||
89 | @Autowired | 74 | @Autowired |
90 | - private RuleChainService ruleChainService; | 75 | + private EntityEdgeProcessor entityProcessor; |
91 | 76 | ||
92 | @Autowired | 77 | @Autowired |
93 | - private EdgeEventService edgeEventService; | 78 | + private AlarmEdgeProcessor alarmProcessor; |
94 | 79 | ||
95 | @Autowired | 80 | @Autowired |
96 | - private TbClusterService clusterService; | 81 | + private RelationEdgeProcessor relationProcessor; |
97 | 82 | ||
98 | @Autowired | 83 | @Autowired |
99 | - private DbCallbackExecutorService dbCallbackExecutorService; | 84 | + private CustomerEdgeProcessor customerProcessor; |
100 | 85 | ||
101 | private ExecutorService tsCallBackExecutor; | 86 | private ExecutorService tsCallBackExecutor; |
102 | 87 | ||
@@ -115,7 +100,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -115,7 +100,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
115 | @Override | 100 | @Override |
116 | public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException { | 101 | public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException { |
117 | edge.setRootRuleChainId(ruleChainId); | 102 | edge.setRootRuleChainId(ruleChainId); |
118 | - Edge savedEdge = edgeService.saveEdge(edge); | 103 | + Edge savedEdge = edgeService.saveEdge(edge, true); |
119 | saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.UPDATED, ruleChainId, null); | 104 | saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.UPDATED, ruleChainId, null); |
120 | return savedEdge; | 105 | return savedEdge; |
121 | } | 106 | } |
@@ -160,7 +145,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -160,7 +145,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
160 | EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); | 145 | EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); |
161 | switch (type) { | 146 | switch (type) { |
162 | case EDGE: | 147 | case EDGE: |
163 | - processEdge(tenantId, edgeNotificationMsg); | 148 | + edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg); |
164 | break; | 149 | break; |
165 | case USER: | 150 | case USER: |
166 | case ASSET: | 151 | case ASSET: |
@@ -169,20 +154,20 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -169,20 +154,20 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
169 | case ENTITY_VIEW: | 154 | case ENTITY_VIEW: |
170 | case DASHBOARD: | 155 | case DASHBOARD: |
171 | case RULE_CHAIN: | 156 | case RULE_CHAIN: |
172 | - processEntity(tenantId, edgeNotificationMsg); | 157 | + entityProcessor.processEntityNotification(tenantId, edgeNotificationMsg); |
173 | break; | 158 | break; |
174 | case CUSTOMER: | 159 | case CUSTOMER: |
175 | - processCustomer(tenantId, edgeNotificationMsg); | 160 | + customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg); |
176 | break; | 161 | break; |
177 | case WIDGETS_BUNDLE: | 162 | case WIDGETS_BUNDLE: |
178 | case WIDGET_TYPE: | 163 | case WIDGET_TYPE: |
179 | - processWidgetBundleOrWidgetType(tenantId, edgeNotificationMsg); | 164 | + entityProcessor.processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg); |
180 | break; | 165 | break; |
181 | case ALARM: | 166 | case ALARM: |
182 | - processAlarm(tenantId, edgeNotificationMsg); | 167 | + alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg); |
183 | break; | 168 | break; |
184 | case RELATION: | 169 | case RELATION: |
185 | - processRelation(tenantId, edgeNotificationMsg); | 170 | + relationProcessor.processRelationNotification(tenantId, edgeNotificationMsg); |
186 | break; | 171 | break; |
187 | default: | 172 | default: |
188 | log.debug("Edge event type [{}] is not designed to be pushed to edge", type); | 173 | log.debug("Edge event type [{}] is not designed to be pushed to edge", type); |
@@ -195,311 +180,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -195,311 +180,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
195 | } | 180 | } |
196 | } | 181 | } |
197 | 182 | ||
198 | - private void processEdge(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | ||
199 | - try { | ||
200 | - EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); | ||
201 | - EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); | ||
202 | - ListenableFuture<Edge> edgeFuture; | ||
203 | - switch (actionType) { | ||
204 | - case ASSIGNED_TO_CUSTOMER: | ||
205 | - CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); | ||
206 | - edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); | ||
207 | - Futures.addCallback(edgeFuture, new FutureCallback<Edge>() { | ||
208 | - @Override | ||
209 | - public void onSuccess(@Nullable Edge edge) { | ||
210 | - if (edge != null && !customerId.isNullUid()) { | ||
211 | - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null); | ||
212 | - PageLink pageLink = new PageLink(DEFAULT_LIMIT); | ||
213 | - PageData<User> pageData; | ||
214 | - do { | ||
215 | - pageData = userService.findCustomerUsers(tenantId, customerId, pageLink); | ||
216 | - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
217 | - log.trace("[{}] [{}] user(s) are going to be added to edge.", edge.getId(), pageData.getData().size()); | ||
218 | - for (User user : pageData.getData()) { | ||
219 | - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, EdgeEventActionType.ADDED, user.getId(), null); | ||
220 | - } | ||
221 | - if (pageData.hasNext()) { | ||
222 | - pageLink = pageLink.nextPageLink(); | ||
223 | - } | ||
224 | - } | ||
225 | - } while (pageData != null && pageData.hasNext()); | ||
226 | - } | ||
227 | - } | ||
228 | - | ||
229 | - @Override | ||
230 | - public void onFailure(Throwable t) { | ||
231 | - log.error("Can't find edge by id [{}]", edgeNotificationMsg, t); | ||
232 | - } | ||
233 | - }, dbCallbackExecutorService); | ||
234 | - break; | ||
235 | - case UNASSIGNED_FROM_CUSTOMER: | ||
236 | - CustomerId customerIdToDelete = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); | ||
237 | - edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); | ||
238 | - Futures.addCallback(edgeFuture, new FutureCallback<Edge>() { | ||
239 | - @Override | ||
240 | - public void onSuccess(@Nullable Edge edge) { | ||
241 | - if (edge != null && !customerIdToDelete.isNullUid()) { | ||
242 | - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.DELETED, customerIdToDelete, null); | ||
243 | - } | ||
244 | - } | ||
245 | - | ||
246 | - @Override | ||
247 | - public void onFailure(Throwable t) { | ||
248 | - log.error("Can't find edge by id [{}]", edgeNotificationMsg, t); | ||
249 | - } | ||
250 | - }, dbCallbackExecutorService); | ||
251 | - break; | ||
252 | - } | ||
253 | - } catch (Exception e) { | ||
254 | - log.error("Exception during processing edge event", e); | ||
255 | - } | ||
256 | - } | ||
257 | - | ||
258 | - private void processWidgetBundleOrWidgetType(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | ||
259 | - EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); | ||
260 | - EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); | ||
261 | - EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); | ||
262 | - switch (actionType) { | ||
263 | - case ADDED: | ||
264 | - case UPDATED: | ||
265 | - case DELETED: | ||
266 | - processActionForAllEdges(tenantId, type, actionType, entityId); | ||
267 | - break; | ||
268 | - } | ||
269 | - } | ||
270 | - | ||
271 | - private void processCustomer(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | ||
272 | - EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); | ||
273 | - EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); | ||
274 | - UUID uuid = new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()); | ||
275 | - CustomerId customerId = new CustomerId(EntityIdFactory.getByEdgeEventTypeAndUuid(type, uuid).getId()); | ||
276 | - switch (actionType) { | ||
277 | - case UPDATED: | ||
278 | - PageLink pageLink = new PageLink(DEFAULT_LIMIT); | ||
279 | - PageData<Edge> pageData; | ||
280 | - do { | ||
281 | - pageData = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink); | ||
282 | - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
283 | - for (Edge edge : pageData.getData()) { | ||
284 | - saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null); | ||
285 | - } | ||
286 | - if (pageData.hasNext()) { | ||
287 | - pageLink = pageLink.nextPageLink(); | ||
288 | - } | ||
289 | - } | ||
290 | - } while (pageData != null && pageData.hasNext()); | ||
291 | - break; | ||
292 | - case DELETED: | ||
293 | - EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); | ||
294 | - saveEdgeEvent(tenantId, edgeId, type, actionType, customerId, null); | ||
295 | - break; | ||
296 | - } | ||
297 | - } | ||
298 | - | ||
299 | - private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | ||
300 | - EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); | ||
301 | - EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); | ||
302 | - EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, | ||
303 | - new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); | ||
304 | - EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); | ||
305 | - ListenableFuture<List<EdgeId>> edgeIdsFuture; | ||
306 | - switch (actionType) { | ||
307 | - case ADDED: // used only for USER entity | ||
308 | - case UPDATED: | ||
309 | - case CREDENTIALS_UPDATED: | ||
310 | - edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId); | ||
311 | - Futures.addCallback(edgeIdsFuture, new FutureCallback<List<EdgeId>>() { | ||
312 | - @Override | ||
313 | - public void onSuccess(@Nullable List<EdgeId> edgeIds) { | ||
314 | - if (edgeIds != null && !edgeIds.isEmpty()) { | ||
315 | - for (EdgeId edgeId : edgeIds) { | ||
316 | - saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); | ||
317 | - } | ||
318 | - } | ||
319 | - } | ||
320 | - @Override | ||
321 | - public void onFailure(Throwable throwable) { | ||
322 | - log.error("Failed to find related edge ids [{}]", edgeNotificationMsg, throwable); | ||
323 | - } | ||
324 | - }, dbCallbackExecutorService); | ||
325 | - break; | ||
326 | - case ASSIGNED_TO_CUSTOMER: | ||
327 | - case UNASSIGNED_FROM_CUSTOMER: | ||
328 | - edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId); | ||
329 | - Futures.addCallback(edgeIdsFuture, new FutureCallback<List<EdgeId>>() { | ||
330 | - @Override | ||
331 | - public void onSuccess(@Nullable List<EdgeId> edgeIds) { | ||
332 | - if (edgeIds != null && !edgeIds.isEmpty()) { | ||
333 | - for (EdgeId edgeId : edgeIds) { | ||
334 | - try { | ||
335 | - CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); | ||
336 | - ListenableFuture<Edge> future = edgeService.findEdgeByIdAsync(tenantId, edgeId); | ||
337 | - Futures.addCallback(future, new FutureCallback<Edge>() { | ||
338 | - @Override | ||
339 | - public void onSuccess(@Nullable Edge edge) { | ||
340 | - if (edge != null && edge.getCustomerId() != null && | ||
341 | - !edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(customerId)) { | ||
342 | - saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); | ||
343 | - } | ||
344 | - } | ||
345 | - @Override | ||
346 | - public void onFailure(Throwable throwable) { | ||
347 | - log.error("Failed to find edge by id [{}]", edgeNotificationMsg, throwable); | ||
348 | - } | ||
349 | - }, dbCallbackExecutorService); | ||
350 | - } catch (Exception e) { | ||
351 | - log.error("Can't parse customer id from entity body [{}]", edgeNotificationMsg, e); | ||
352 | - } | ||
353 | - } | ||
354 | - } | ||
355 | - } | ||
356 | - | ||
357 | - @Override | ||
358 | - public void onFailure(Throwable throwable) { | ||
359 | - log.error("Failed to find related edge ids [{}]", edgeNotificationMsg, throwable); | ||
360 | - } | ||
361 | - }, dbCallbackExecutorService); | ||
362 | - break; | ||
363 | - case DELETED: | ||
364 | - saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); | ||
365 | - break; | ||
366 | - case ASSIGNED_TO_EDGE: | ||
367 | - case UNASSIGNED_FROM_EDGE: | ||
368 | - saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); | ||
369 | - if (type.equals(EdgeEventType.RULE_CHAIN)) { | ||
370 | - updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId); | ||
371 | - } | ||
372 | - break; | ||
373 | - } | ||
374 | - } | ||
375 | - | ||
376 | - private void updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) { | ||
377 | - PageLink pageLink = new PageLink(DEFAULT_LIMIT); | ||
378 | - PageData<RuleChain> pageData; | ||
379 | - do { | ||
380 | - pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); | ||
381 | - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
382 | - for (RuleChain ruleChain : pageData.getData()) { | ||
383 | - if (!ruleChain.getId().equals(processingRuleChainId)) { | ||
384 | - List<RuleChainConnectionInfo> connectionInfos = | ||
385 | - ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections(); | ||
386 | - if (connectionInfos != null && !connectionInfos.isEmpty()) { | ||
387 | - for (RuleChainConnectionInfo connectionInfo : connectionInfos) { | ||
388 | - if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) { | ||
389 | - saveEdgeEvent(tenantId, | ||
390 | - edgeId, | ||
391 | - EdgeEventType.RULE_CHAIN_METADATA, | ||
392 | - EdgeEventActionType.UPDATED, | ||
393 | - ruleChain.getId(), | ||
394 | - null); | ||
395 | - } | ||
396 | - } | ||
397 | - } | ||
398 | - } | ||
399 | - } | ||
400 | - if (pageData.hasNext()) { | ||
401 | - pageLink = pageLink.nextPageLink(); | ||
402 | - } | ||
403 | - } | ||
404 | - } while (pageData != null && pageData.hasNext()); | ||
405 | - } | ||
406 | - | ||
407 | - private void processAlarm(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | ||
408 | - AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); | ||
409 | - ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId); | ||
410 | - Futures.addCallback(alarmFuture, new FutureCallback<Alarm>() { | ||
411 | - @Override | ||
412 | - public void onSuccess(@Nullable Alarm alarm) { | ||
413 | - if (alarm != null) { | ||
414 | - EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType()); | ||
415 | - if (type != null) { | ||
416 | - ListenableFuture<List<EdgeId>> relatedEdgeIdsByEntityIdFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator()); | ||
417 | - Futures.addCallback(relatedEdgeIdsByEntityIdFuture, new FutureCallback<List<EdgeId>>() { | ||
418 | - @Override | ||
419 | - public void onSuccess(@Nullable List<EdgeId> relatedEdgeIdsByEntityId) { | ||
420 | - if (relatedEdgeIdsByEntityId != null) { | ||
421 | - for (EdgeId edgeId : relatedEdgeIdsByEntityId) { | ||
422 | - saveEdgeEvent(tenantId, | ||
423 | - edgeId, | ||
424 | - EdgeEventType.ALARM, | ||
425 | - EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()), | ||
426 | - alarmId, | ||
427 | - null); | ||
428 | - } | ||
429 | - } | ||
430 | - } | ||
431 | - | ||
432 | - @Override | ||
433 | - public void onFailure(Throwable t) { | ||
434 | - log.warn("[{}] can't find related edge ids by entity id [{}]", tenantId.getId(), alarm.getOriginator(), t); | ||
435 | - } | ||
436 | - }, dbCallbackExecutorService); | ||
437 | - } | ||
438 | - } | ||
439 | - } | ||
440 | - | ||
441 | - @Override | ||
442 | - public void onFailure(Throwable t) { | ||
443 | - log.warn("[{}] can't find alarm by id [{}]", tenantId.getId(), alarmId.getId(), t); | ||
444 | - } | ||
445 | - }, dbCallbackExecutorService); | ||
446 | - } | ||
447 | - | ||
448 | - private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException { | ||
449 | - EntityRelation relation = mapper.readValue(edgeNotificationMsg.getBody(), EntityRelation.class); | ||
450 | - if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && | ||
451 | - !relation.getTo().getEntityType().equals(EntityType.EDGE)) { | ||
452 | - List<ListenableFuture<List<EdgeId>>> futures = new ArrayList<>(); | ||
453 | - futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getTo())); | ||
454 | - futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom())); | ||
455 | - ListenableFuture<List<List<EdgeId>>> combinedFuture = Futures.allAsList(futures); | ||
456 | - Futures.addCallback(combinedFuture, new FutureCallback<List<List<EdgeId>>>() { | ||
457 | - @Override | ||
458 | - public void onSuccess(@Nullable List<List<EdgeId>> listOfListsEdgeIds) { | ||
459 | - Set<EdgeId> uniqueEdgeIds = new HashSet<>(); | ||
460 | - if (listOfListsEdgeIds != null && !listOfListsEdgeIds.isEmpty()) { | ||
461 | - for (List<EdgeId> listOfListsEdgeId : listOfListsEdgeIds) { | ||
462 | - if (listOfListsEdgeId != null) { | ||
463 | - uniqueEdgeIds.addAll(listOfListsEdgeId); | ||
464 | - } | ||
465 | - } | ||
466 | - } | ||
467 | - if (!uniqueEdgeIds.isEmpty()) { | ||
468 | - for (EdgeId edgeId : uniqueEdgeIds) { | ||
469 | - saveEdgeEvent(tenantId, | ||
470 | - edgeId, | ||
471 | - EdgeEventType.RELATION, | ||
472 | - EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()), | ||
473 | - null, | ||
474 | - mapper.valueToTree(relation)); | ||
475 | - } | ||
476 | - } | ||
477 | - } | ||
478 | - | ||
479 | - @Override | ||
480 | - public void onFailure(Throwable t) { | ||
481 | - log.warn("[{}] can't find related edge ids by relation to id [{}] and relation from id [{}]" , | ||
482 | - tenantId.getId(), relation.getTo().getId(), relation.getFrom().getId(), t); | ||
483 | - } | ||
484 | - }, dbCallbackExecutorService); | ||
485 | - } | ||
486 | - } | ||
487 | - | ||
488 | - private void processActionForAllEdges(TenantId tenantId, EdgeEventType type, EdgeEventActionType actionType, EntityId entityId) { | ||
489 | - PageLink pageLink = new PageLink(DEFAULT_LIMIT); | ||
490 | - PageData<Edge> pageData; | ||
491 | - do { | ||
492 | - pageData = edgeService.findEdgesByTenantId(tenantId, pageLink); | ||
493 | - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
494 | - for (Edge edge : pageData.getData()) { | ||
495 | - saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | ||
496 | - } | ||
497 | - if (pageData.hasNext()) { | ||
498 | - pageLink = pageLink.nextPageLink(); | ||
499 | - } | ||
500 | - } | ||
501 | - } while (pageData != null && pageData.hasNext()); | ||
502 | - } | ||
503 | } | 183 | } |
504 | 184 | ||
505 | 185 |
@@ -16,218 +16,130 @@ | @@ -16,218 +16,130 @@ | ||
16 | package org.thingsboard.server.service.edge; | 16 | package org.thingsboard.server.service.edge; |
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | -import lombok.Getter; | ||
20 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
21 | import org.springframework.context.annotation.Lazy; | 20 | import org.springframework.context.annotation.Lazy; |
22 | import org.springframework.stereotype.Component; | 21 | import org.springframework.stereotype.Component; |
23 | -import org.thingsboard.server.actors.service.ActorService; | ||
24 | -import org.thingsboard.server.dao.alarm.AlarmService; | ||
25 | import org.thingsboard.server.dao.asset.AssetService; | 22 | import org.thingsboard.server.dao.asset.AssetService; |
26 | import org.thingsboard.server.dao.attributes.AttributesService; | 23 | import org.thingsboard.server.dao.attributes.AttributesService; |
27 | -import org.thingsboard.server.dao.customer.CustomerService; | ||
28 | import org.thingsboard.server.dao.dashboard.DashboardService; | 24 | import org.thingsboard.server.dao.dashboard.DashboardService; |
29 | -import org.thingsboard.server.dao.device.DeviceCredentialsService; | ||
30 | import org.thingsboard.server.dao.device.DeviceProfileService; | 25 | import org.thingsboard.server.dao.device.DeviceProfileService; |
31 | -import org.thingsboard.server.dao.device.DeviceService; | ||
32 | import org.thingsboard.server.dao.edge.EdgeEventService; | 26 | import org.thingsboard.server.dao.edge.EdgeEventService; |
33 | import org.thingsboard.server.dao.edge.EdgeService; | 27 | import org.thingsboard.server.dao.edge.EdgeService; |
34 | -import org.thingsboard.server.dao.entityview.EntityViewService; | ||
35 | -import org.thingsboard.server.dao.relation.RelationService; | ||
36 | import org.thingsboard.server.dao.rule.RuleChainService; | 28 | import org.thingsboard.server.dao.rule.RuleChainService; |
29 | +import org.thingsboard.server.dao.settings.AdminSettingsService; | ||
37 | import org.thingsboard.server.dao.user.UserService; | 30 | import org.thingsboard.server.dao.user.UserService; |
38 | -import org.thingsboard.server.dao.widget.WidgetTypeService; | ||
39 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 31 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
40 | -import org.thingsboard.server.queue.discovery.PartitionService; | ||
41 | import org.thingsboard.server.queue.util.TbCoreComponent; | 32 | import org.thingsboard.server.queue.util.TbCoreComponent; |
42 | import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; | 33 | import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; |
43 | -import org.thingsboard.server.service.edge.rpc.constructor.AdminSettingsMsgConstructor; | ||
44 | -import org.thingsboard.server.service.edge.rpc.constructor.AlarmMsgConstructor; | ||
45 | -import org.thingsboard.server.service.edge.rpc.constructor.AssetMsgConstructor; | ||
46 | -import org.thingsboard.server.service.edge.rpc.constructor.CustomerMsgConstructor; | ||
47 | -import org.thingsboard.server.service.edge.rpc.constructor.DashboardMsgConstructor; | ||
48 | -import org.thingsboard.server.service.edge.rpc.constructor.DeviceMsgConstructor; | ||
49 | -import org.thingsboard.server.service.edge.rpc.constructor.DeviceProfileMsgConstructor; | ||
50 | -import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; | ||
51 | -import org.thingsboard.server.service.edge.rpc.constructor.EntityViewMsgConstructor; | ||
52 | -import org.thingsboard.server.service.edge.rpc.constructor.RelationMsgConstructor; | ||
53 | -import org.thingsboard.server.service.edge.rpc.constructor.RuleChainMsgConstructor; | ||
54 | -import org.thingsboard.server.service.edge.rpc.constructor.UserMsgConstructor; | ||
55 | -import org.thingsboard.server.service.edge.rpc.constructor.WidgetTypeMsgConstructor; | ||
56 | -import org.thingsboard.server.service.edge.rpc.constructor.WidgetsBundleMsgConstructor; | ||
57 | -import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; | ||
58 | -import org.thingsboard.server.service.edge.rpc.processor.AlarmProcessor; | ||
59 | -import org.thingsboard.server.service.edge.rpc.processor.DeviceProcessor; | ||
60 | -import org.thingsboard.server.service.edge.rpc.processor.RelationProcessor; | ||
61 | -import org.thingsboard.server.service.edge.rpc.processor.TelemetryProcessor; | 34 | +import org.thingsboard.server.service.edge.rpc.processor.AdminSettingsEdgeProcessor; |
35 | +import org.thingsboard.server.service.edge.rpc.processor.AlarmEdgeProcessor; | ||
36 | +import org.thingsboard.server.service.edge.rpc.processor.AssetEdgeProcessor; | ||
37 | +import org.thingsboard.server.service.edge.rpc.processor.CustomerEdgeProcessor; | ||
38 | +import org.thingsboard.server.service.edge.rpc.processor.DashboardEdgeProcessor; | ||
39 | +import org.thingsboard.server.service.edge.rpc.processor.DeviceEdgeProcessor; | ||
40 | +import org.thingsboard.server.service.edge.rpc.processor.DeviceProfileEdgeProcessor; | ||
41 | +import org.thingsboard.server.service.edge.rpc.processor.EntityEdgeProcessor; | ||
42 | +import org.thingsboard.server.service.edge.rpc.processor.EntityViewEdgeProcessor; | ||
43 | +import org.thingsboard.server.service.edge.rpc.processor.RelationEdgeProcessor; | ||
44 | +import org.thingsboard.server.service.edge.rpc.processor.RuleChainEdgeProcessor; | ||
45 | +import org.thingsboard.server.service.edge.rpc.processor.TelemetryEdgeProcessor; | ||
46 | +import org.thingsboard.server.service.edge.rpc.processor.UserEdgeProcessor; | ||
47 | +import org.thingsboard.server.service.edge.rpc.processor.WidgetBundleEdgeProcessor; | ||
48 | +import org.thingsboard.server.service.edge.rpc.processor.WidgetTypeEdgeProcessor; | ||
49 | +import org.thingsboard.server.service.edge.rpc.sync.EdgeRequestsService; | ||
62 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; | 50 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
63 | -import org.thingsboard.server.service.queue.TbClusterService; | ||
64 | -import org.thingsboard.server.service.state.DeviceStateService; | 51 | +import org.thingsboard.server.service.executors.GrpcCallbackExecutorService; |
65 | 52 | ||
66 | @Component | 53 | @Component |
67 | @TbCoreComponent | 54 | @TbCoreComponent |
68 | @Data | 55 | @Data |
56 | +@Lazy | ||
69 | public class EdgeContextComponent { | 57 | public class EdgeContextComponent { |
70 | 58 | ||
71 | - @Lazy | ||
72 | @Autowired | 59 | @Autowired |
73 | private EdgeService edgeService; | 60 | private EdgeService edgeService; |
74 | 61 | ||
75 | @Autowired | 62 | @Autowired |
76 | - private PartitionService partitionService; | ||
77 | - | ||
78 | - @Lazy | ||
79 | - @Autowired | ||
80 | private EdgeEventService edgeEventService; | 63 | private EdgeEventService edgeEventService; |
81 | 64 | ||
82 | - @Lazy | ||
83 | @Autowired | 65 | @Autowired |
84 | - private AssetService assetService; | 66 | + private AdminSettingsService adminSettingsService; |
85 | 67 | ||
86 | - @Lazy | ||
87 | @Autowired | 68 | @Autowired |
88 | - private DeviceService deviceService; | 69 | + private AssetService assetService; |
89 | 70 | ||
90 | - @Lazy | ||
91 | @Autowired | 71 | @Autowired |
92 | private DeviceProfileService deviceProfileService; | 72 | private DeviceProfileService deviceProfileService; |
93 | 73 | ||
94 | - @Lazy | ||
95 | - @Autowired | ||
96 | - private DeviceCredentialsService deviceCredentialsService; | ||
97 | - | ||
98 | - @Lazy | ||
99 | - @Autowired | ||
100 | - private EntityViewService entityViewService; | ||
101 | - | ||
102 | - @Lazy | ||
103 | @Autowired | 74 | @Autowired |
104 | private AttributesService attributesService; | 75 | private AttributesService attributesService; |
105 | 76 | ||
106 | - @Lazy | ||
107 | - @Autowired | ||
108 | - private CustomerService customerService; | ||
109 | - | ||
110 | - @Lazy | ||
111 | - @Autowired | ||
112 | - private RelationService relationService; | ||
113 | - | ||
114 | - @Lazy | ||
115 | - @Autowired | ||
116 | - private AlarmService alarmService; | ||
117 | - | ||
118 | - @Lazy | ||
119 | @Autowired | 77 | @Autowired |
120 | private DashboardService dashboardService; | 78 | private DashboardService dashboardService; |
121 | 79 | ||
122 | - @Lazy | ||
123 | @Autowired | 80 | @Autowired |
124 | private RuleChainService ruleChainService; | 81 | private RuleChainService ruleChainService; |
125 | 82 | ||
126 | - @Lazy | ||
127 | @Autowired | 83 | @Autowired |
128 | private UserService userService; | 84 | private UserService userService; |
129 | 85 | ||
130 | - @Lazy | ||
131 | - @Autowired | ||
132 | - private ActorService actorService; | ||
133 | - | ||
134 | - @Lazy | ||
135 | @Autowired | 86 | @Autowired |
136 | private WidgetsBundleService widgetsBundleService; | 87 | private WidgetsBundleService widgetsBundleService; |
137 | 88 | ||
138 | - @Lazy | ||
139 | - @Autowired | ||
140 | - private WidgetTypeService widgetTypeService; | ||
141 | - | ||
142 | - @Lazy | ||
143 | - @Autowired | ||
144 | - private DeviceStateService deviceStateService; | ||
145 | - | ||
146 | - @Lazy | ||
147 | - @Autowired | ||
148 | - private TbClusterService tbClusterService; | ||
149 | - | ||
150 | - @Lazy | ||
151 | @Autowired | 89 | @Autowired |
152 | - private SyncEdgeService syncEdgeService; | 90 | + private EdgeRequestsService edgeRequestsService; |
153 | 91 | ||
154 | - @Lazy | ||
155 | @Autowired | 92 | @Autowired |
156 | - private RuleChainMsgConstructor ruleChainMsgConstructor; | 93 | + private AlarmEdgeProcessor alarmProcessor; |
157 | 94 | ||
158 | - @Lazy | ||
159 | @Autowired | 95 | @Autowired |
160 | - private AlarmMsgConstructor alarmMsgConstructor; | 96 | + private DeviceProfileEdgeProcessor deviceProfileProcessor; |
161 | 97 | ||
162 | - @Lazy | ||
163 | @Autowired | 98 | @Autowired |
164 | - private DeviceMsgConstructor deviceMsgConstructor; | 99 | + private DeviceEdgeProcessor deviceProcessor; |
165 | 100 | ||
166 | - @Lazy | ||
167 | @Autowired | 101 | @Autowired |
168 | - private DeviceProfileMsgConstructor deviceProfileMsgConstructor; | 102 | + private EntityEdgeProcessor entityProcessor; |
169 | 103 | ||
170 | - @Lazy | ||
171 | @Autowired | 104 | @Autowired |
172 | - private AssetMsgConstructor assetMsgConstructor; | 105 | + private AssetEdgeProcessor assetProcessor; |
173 | 106 | ||
174 | - @Lazy | ||
175 | @Autowired | 107 | @Autowired |
176 | - private EntityViewMsgConstructor entityViewMsgConstructor; | 108 | + private EntityViewEdgeProcessor entityViewProcessor; |
177 | 109 | ||
178 | - @Lazy | ||
179 | @Autowired | 110 | @Autowired |
180 | - private DashboardMsgConstructor dashboardMsgConstructor; | 111 | + private UserEdgeProcessor userProcessor; |
181 | 112 | ||
182 | - @Lazy | ||
183 | @Autowired | 113 | @Autowired |
184 | - private CustomerMsgConstructor customerMsgConstructor; | 114 | + private RelationEdgeProcessor relationProcessor; |
185 | 115 | ||
186 | - @Lazy | ||
187 | @Autowired | 116 | @Autowired |
188 | - private UserMsgConstructor userMsgConstructor; | 117 | + private TelemetryEdgeProcessor telemetryProcessor; |
189 | 118 | ||
190 | - @Lazy | ||
191 | @Autowired | 119 | @Autowired |
192 | - private RelationMsgConstructor relationMsgConstructor; | 120 | + private DashboardEdgeProcessor dashboardProcessor; |
193 | 121 | ||
194 | - @Lazy | ||
195 | @Autowired | 122 | @Autowired |
196 | - private WidgetsBundleMsgConstructor widgetsBundleMsgConstructor; | 123 | + private RuleChainEdgeProcessor ruleChainProcessor; |
197 | 124 | ||
198 | - @Lazy | ||
199 | @Autowired | 125 | @Autowired |
200 | - private WidgetTypeMsgConstructor widgetTypeMsgConstructor; | 126 | + private CustomerEdgeProcessor customerProcessor; |
201 | 127 | ||
202 | - @Lazy | ||
203 | @Autowired | 128 | @Autowired |
204 | - private AdminSettingsMsgConstructor adminSettingsMsgConstructor; | 129 | + private WidgetBundleEdgeProcessor widgetBundleProcessor; |
205 | 130 | ||
206 | - @Lazy | ||
207 | @Autowired | 131 | @Autowired |
208 | - private EntityDataMsgConstructor entityDataMsgConstructor; | 132 | + private WidgetTypeEdgeProcessor widgetTypeProcessor; |
209 | 133 | ||
210 | - @Lazy | ||
211 | @Autowired | 134 | @Autowired |
212 | - private AlarmProcessor alarmProcessor; | 135 | + private AdminSettingsEdgeProcessor adminSettingsProcessor; |
213 | 136 | ||
214 | - @Lazy | ||
215 | - @Autowired | ||
216 | - private DeviceProcessor deviceProcessor; | ||
217 | - | ||
218 | - @Lazy | ||
219 | - @Autowired | ||
220 | - private RelationProcessor relationProcessor; | ||
221 | - | ||
222 | - @Lazy | ||
223 | - @Autowired | ||
224 | - private TelemetryProcessor telemetryProcessor; | ||
225 | - | ||
226 | - @Lazy | ||
227 | @Autowired | 137 | @Autowired |
228 | private EdgeEventStorageSettings edgeEventStorageSettings; | 138 | private EdgeEventStorageSettings edgeEventStorageSettings; |
229 | 139 | ||
230 | @Autowired | 140 | @Autowired |
231 | - @Getter | ||
232 | private DbCallbackExecutorService dbCallbackExecutor; | 141 | private DbCallbackExecutorService dbCallbackExecutor; |
142 | + | ||
143 | + @Autowired | ||
144 | + private GrpcCallbackExecutorService grpcCallbackExecutorService; | ||
233 | } | 145 | } |
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.fasterxml.jackson.databind.JsonNode; | ||
19 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
20 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
21 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
22 | +import org.thingsboard.server.common.data.id.EdgeId; | ||
23 | +import org.thingsboard.server.common.data.id.EntityId; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | + | ||
26 | +public final class EdgeEventUtils { | ||
27 | + | ||
28 | + private EdgeEventUtils() { | ||
29 | + } | ||
30 | + | ||
31 | + public static EdgeEvent constructEdgeEvent(TenantId tenantId, | ||
32 | + EdgeId edgeId, | ||
33 | + EdgeEventType type, | ||
34 | + EdgeEventActionType action, | ||
35 | + EntityId entityId, | ||
36 | + JsonNode body) { | ||
37 | + EdgeEvent edgeEvent = new EdgeEvent(); | ||
38 | + edgeEvent.setTenantId(tenantId); | ||
39 | + edgeEvent.setEdgeId(edgeId); | ||
40 | + edgeEvent.setType(type); | ||
41 | + edgeEvent.setAction(action); | ||
42 | + if (entityId != null) { | ||
43 | + edgeEvent.setEntityId(entityId.getId()); | ||
44 | + } | ||
45 | + edgeEvent.setBody(body); | ||
46 | + return edgeEvent; | ||
47 | + } | ||
48 | +} |
@@ -16,8 +16,8 @@ | @@ -16,8 +16,8 @@ | ||
16 | package org.thingsboard.server.service.edge.rpc; | 16 | package org.thingsboard.server.service.edge.rpc; |
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.ObjectMapper; | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | -import com.google.common.io.Resources; | ||
20 | import com.google.common.util.concurrent.FutureCallback; | 19 | import com.google.common.util.concurrent.FutureCallback; |
20 | +import com.google.common.util.concurrent.Futures; | ||
21 | import io.grpc.Server; | 21 | import io.grpc.Server; |
22 | import io.grpc.netty.NettyServerBuilder; | 22 | import io.grpc.netty.NettyServerBuilder; |
23 | import io.grpc.stub.StreamObserver; | 23 | import io.grpc.stub.StreamObserver; |
@@ -28,16 +28,16 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | @@ -28,16 +28,16 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
28 | import org.springframework.stereotype.Service; | 28 | import org.springframework.stereotype.Service; |
29 | import org.thingsboard.common.util.ThingsBoardThreadFactory; | 29 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
30 | import org.thingsboard.server.common.data.DataConstants; | 30 | import org.thingsboard.server.common.data.DataConstants; |
31 | -import org.thingsboard.server.common.data.Tenant; | 31 | +import org.thingsboard.server.common.data.ResourceUtils; |
32 | import org.thingsboard.server.common.data.edge.Edge; | 32 | import org.thingsboard.server.common.data.edge.Edge; |
33 | import org.thingsboard.server.common.data.id.EdgeId; | 33 | import org.thingsboard.server.common.data.id.EdgeId; |
34 | import org.thingsboard.server.common.data.id.TenantId; | 34 | import org.thingsboard.server.common.data.id.TenantId; |
35 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | 35 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
36 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; | 36 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
37 | import org.thingsboard.server.common.data.kv.LongDataEntry; | 37 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
38 | -import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc; | ||
39 | -import org.thingsboard.server.gen.edge.RequestMsg; | ||
40 | -import org.thingsboard.server.gen.edge.ResponseMsg; | 38 | +import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc; |
39 | +import org.thingsboard.server.gen.edge.v1.RequestMsg; | ||
40 | +import org.thingsboard.server.gen.edge.v1.ResponseMsg; | ||
41 | import org.thingsboard.server.queue.util.TbCoreComponent; | 41 | import org.thingsboard.server.queue.util.TbCoreComponent; |
42 | import org.thingsboard.server.service.edge.EdgeContextComponent; | 42 | import org.thingsboard.server.service.edge.EdgeContextComponent; |
43 | import org.thingsboard.server.service.state.DefaultDeviceStateService; | 43 | import org.thingsboard.server.service.state.DefaultDeviceStateService; |
@@ -46,9 +46,10 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | @@ -46,9 +46,10 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | ||
46 | import javax.annotation.Nullable; | 46 | import javax.annotation.Nullable; |
47 | import javax.annotation.PostConstruct; | 47 | import javax.annotation.PostConstruct; |
48 | import javax.annotation.PreDestroy; | 48 | import javax.annotation.PreDestroy; |
49 | -import java.io.File; | ||
50 | import java.io.IOException; | 49 | import java.io.IOException; |
50 | +import java.io.InputStream; | ||
51 | import java.util.Collections; | 51 | import java.util.Collections; |
52 | +import java.util.HashMap; | ||
52 | import java.util.Map; | 53 | import java.util.Map; |
53 | import java.util.UUID; | 54 | import java.util.UUID; |
54 | import java.util.concurrent.ConcurrentHashMap; | 55 | import java.util.concurrent.ConcurrentHashMap; |
@@ -57,6 +58,8 @@ import java.util.concurrent.Executors; | @@ -57,6 +58,8 @@ import java.util.concurrent.Executors; | ||
57 | import java.util.concurrent.ScheduledExecutorService; | 58 | import java.util.concurrent.ScheduledExecutorService; |
58 | import java.util.concurrent.ScheduledFuture; | 59 | import java.util.concurrent.ScheduledFuture; |
59 | import java.util.concurrent.TimeUnit; | 60 | import java.util.concurrent.TimeUnit; |
61 | +import java.util.concurrent.locks.Lock; | ||
62 | +import java.util.concurrent.locks.ReentrantLock; | ||
60 | 63 | ||
61 | @Service | 64 | @Service |
62 | @Slf4j | 65 | @Slf4j |
@@ -65,7 +68,8 @@ import java.util.concurrent.TimeUnit; | @@ -65,7 +68,8 @@ import java.util.concurrent.TimeUnit; | ||
65 | public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { | 68 | public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { |
66 | 69 | ||
67 | private final ConcurrentMap<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>(); | 70 | private final ConcurrentMap<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>(); |
68 | - private final ConcurrentMap<EdgeId, Boolean> sessionNewEvents = new ConcurrentHashMap<>(); | 71 | + private final ConcurrentMap<EdgeId, Lock> sessionNewEventsLocks = new ConcurrentHashMap<>(); |
72 | + private final Map<EdgeId, Boolean> sessionNewEvents = new HashMap<>(); | ||
69 | private final ConcurrentMap<EdgeId, ScheduledFuture<?>> sessionEdgeEventChecks = new ConcurrentHashMap<>(); | 73 | private final ConcurrentMap<EdgeId, ScheduledFuture<?>> sessionEdgeEventChecks = new ConcurrentHashMap<>(); |
70 | private static final ObjectMapper mapper = new ObjectMapper(); | 74 | private static final ObjectMapper mapper = new ObjectMapper(); |
71 | 75 | ||
@@ -81,10 +85,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -81,10 +85,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
81 | private boolean persistToTelemetry; | 85 | private boolean persistToTelemetry; |
82 | @Value("${edges.rpc.client_max_keep_alive_time_sec}") | 86 | @Value("${edges.rpc.client_max_keep_alive_time_sec}") |
83 | private int clientMaxKeepAliveTimeSec; | 87 | private int clientMaxKeepAliveTimeSec; |
88 | + @Value("${edges.rpc.max_inbound_message_size:4194304}") | ||
89 | + private int maxInboundMessageSize; | ||
84 | 90 | ||
85 | @Value("${edges.scheduler_pool_size}") | 91 | @Value("${edges.scheduler_pool_size}") |
86 | private int schedulerPoolSize; | 92 | private int schedulerPoolSize; |
87 | 93 | ||
94 | + @Value("${edges.send_scheduler_pool_size}") | ||
95 | + private int sendSchedulerPoolSize; | ||
96 | + | ||
88 | @Autowired | 97 | @Autowired |
89 | private EdgeContextComponent ctx; | 98 | private EdgeContextComponent ctx; |
90 | 99 | ||
@@ -93,19 +102,22 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -93,19 +102,22 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
93 | 102 | ||
94 | private Server server; | 103 | private Server server; |
95 | 104 | ||
96 | - private ScheduledExecutorService scheduler; | 105 | + private ScheduledExecutorService edgeEventProcessingExecutorService; |
106 | + | ||
107 | + private ScheduledExecutorService sendDownlinkExecutorService; | ||
97 | 108 | ||
98 | @PostConstruct | 109 | @PostConstruct |
99 | public void init() { | 110 | public void init() { |
100 | log.info("Initializing Edge RPC service!"); | 111 | log.info("Initializing Edge RPC service!"); |
101 | NettyServerBuilder builder = NettyServerBuilder.forPort(rpcPort) | 112 | NettyServerBuilder builder = NettyServerBuilder.forPort(rpcPort) |
102 | .permitKeepAliveTime(clientMaxKeepAliveTimeSec, TimeUnit.SECONDS) | 113 | .permitKeepAliveTime(clientMaxKeepAliveTimeSec, TimeUnit.SECONDS) |
114 | + .maxInboundMessageSize(maxInboundMessageSize) | ||
103 | .addService(this); | 115 | .addService(this); |
104 | if (sslEnabled) { | 116 | if (sslEnabled) { |
105 | try { | 117 | try { |
106 | - File certFile = new File(Resources.getResource(certFileResource).toURI()); | ||
107 | - File privateKeyFile = new File(Resources.getResource(privateKeyResource).toURI()); | ||
108 | - builder.useTransportSecurity(certFile, privateKeyFile); | 118 | + InputStream certFileIs = ResourceUtils.getInputStream(this, certFileResource); |
119 | + InputStream privateKeyFileIs = ResourceUtils.getInputStream(this, privateKeyResource); | ||
120 | + builder.useTransportSecurity(certFileIs, privateKeyFileIs); | ||
109 | } catch (Exception e) { | 121 | } catch (Exception e) { |
110 | log.error("Unable to set up SSL context. Reason: " + e.getMessage(), e); | 122 | log.error("Unable to set up SSL context. Reason: " + e.getMessage(), e); |
111 | throw new RuntimeException("Unable to set up SSL context!", e); | 123 | throw new RuntimeException("Unable to set up SSL context!", e); |
@@ -119,7 +131,8 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -119,7 +131,8 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
119 | log.error("Failed to start Edge RPC server!", e); | 131 | log.error("Failed to start Edge RPC server!", e); |
120 | throw new RuntimeException("Failed to start Edge RPC server!"); | 132 | throw new RuntimeException("Failed to start Edge RPC server!"); |
121 | } | 133 | } |
122 | - this.scheduler = Executors.newScheduledThreadPool(schedulerPoolSize, ThingsBoardThreadFactory.forName("edge-scheduler")); | 134 | + this.edgeEventProcessingExecutorService = Executors.newScheduledThreadPool(schedulerPoolSize, ThingsBoardThreadFactory.forName("edge-scheduler")); |
135 | + this.sendDownlinkExecutorService = Executors.newScheduledThreadPool(sendSchedulerPoolSize, ThingsBoardThreadFactory.forName("edge-send-scheduler")); | ||
123 | log.info("Edge RPC service initialized!"); | 136 | log.info("Edge RPC service initialized!"); |
124 | } | 137 | } |
125 | 138 | ||
@@ -136,62 +149,84 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -136,62 +149,84 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
136 | sessionEdgeEventChecks.remove(edgeId); | 149 | sessionEdgeEventChecks.remove(edgeId); |
137 | } | 150 | } |
138 | } | 151 | } |
139 | - if (scheduler != null) { | ||
140 | - scheduler.shutdownNow(); | 152 | + if (edgeEventProcessingExecutorService != null) { |
153 | + edgeEventProcessingExecutorService.shutdownNow(); | ||
154 | + } | ||
155 | + if (sendDownlinkExecutorService != null) { | ||
156 | + sendDownlinkExecutorService.shutdownNow(); | ||
141 | } | 157 | } |
142 | } | 158 | } |
143 | 159 | ||
144 | @Override | 160 | @Override |
145 | public StreamObserver<RequestMsg> handleMsgs(StreamObserver<ResponseMsg> outputStream) { | 161 | public StreamObserver<RequestMsg> handleMsgs(StreamObserver<ResponseMsg> outputStream) { |
146 | - return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, mapper).getInputStream(); | 162 | + return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, mapper, sendDownlinkExecutorService).getInputStream(); |
147 | } | 163 | } |
148 | 164 | ||
149 | @Override | 165 | @Override |
150 | - public void updateEdge(Edge edge) { | 166 | + public void updateEdge(TenantId tenantId, Edge edge) { |
151 | EdgeGrpcSession session = sessions.get(edge.getId()); | 167 | EdgeGrpcSession session = sessions.get(edge.getId()); |
152 | if (session != null && session.isConnected()) { | 168 | if (session != null && session.isConnected()) { |
153 | - log.debug("[{}] Updating configuration for edge [{}] [{}]", edge.getTenantId(), edge.getName(), edge.getId()); | 169 | + log.debug("[{}] Updating configuration for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); |
154 | session.onConfigurationUpdate(edge); | 170 | session.onConfigurationUpdate(edge); |
155 | } else { | 171 | } else { |
156 | - log.debug("[{}] Session doesn't exist for edge [{}] [{}]", edge.getTenantId(), edge.getName(), edge.getId()); | 172 | + log.debug("[{}] Session doesn't exist for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); |
157 | } | 173 | } |
158 | } | 174 | } |
159 | 175 | ||
160 | @Override | 176 | @Override |
161 | - public void deleteEdge(EdgeId edgeId) { | 177 | + public void deleteEdge(TenantId tenantId, EdgeId edgeId) { |
162 | EdgeGrpcSession session = sessions.get(edgeId); | 178 | EdgeGrpcSession session = sessions.get(edgeId); |
163 | if (session != null && session.isConnected()) { | 179 | if (session != null && session.isConnected()) { |
164 | - log.info("Closing and removing session for edge [{}]", edgeId); | 180 | + log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId); |
165 | session.close(); | 181 | session.close(); |
166 | sessions.remove(edgeId); | 182 | sessions.remove(edgeId); |
167 | - sessionNewEvents.remove(edgeId); | 183 | + final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); |
184 | + newEventLock.lock(); | ||
185 | + try { | ||
186 | + sessionNewEvents.remove(edgeId); | ||
187 | + } finally { | ||
188 | + newEventLock.unlock(); | ||
189 | + } | ||
168 | cancelScheduleEdgeEventsCheck(edgeId); | 190 | cancelScheduleEdgeEventsCheck(edgeId); |
169 | } | 191 | } |
170 | } | 192 | } |
171 | 193 | ||
172 | @Override | 194 | @Override |
173 | - public void onEdgeEvent(EdgeId edgeId) { | ||
174 | - log.trace("[{}] onEdgeEvent", edgeId.getId()); | ||
175 | - if (Boolean.FALSE.equals(sessionNewEvents.get(edgeId))) { | ||
176 | - log.trace("[{}] set session new events flag to true", edgeId.getId()); | ||
177 | - sessionNewEvents.put(edgeId, true); | 195 | + public void onEdgeEvent(TenantId tenantId, EdgeId edgeId) { |
196 | + log.trace("[{}] onEdgeEvent [{}]", tenantId, edgeId.getId()); | ||
197 | + final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); | ||
198 | + newEventLock.lock(); | ||
199 | + try { | ||
200 | + if (Boolean.FALSE.equals(sessionNewEvents.get(edgeId))) { | ||
201 | + log.trace("[{}] set session new events flag to true [{}]", tenantId, edgeId.getId()); | ||
202 | + sessionNewEvents.put(edgeId, true); | ||
203 | + } | ||
204 | + } finally { | ||
205 | + newEventLock.unlock(); | ||
178 | } | 206 | } |
179 | } | 207 | } |
180 | 208 | ||
181 | private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { | 209 | private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { |
182 | log.info("[{}] edge [{}] connected successfully.", edgeGrpcSession.getSessionId(), edgeId); | 210 | log.info("[{}] edge [{}] connected successfully.", edgeGrpcSession.getSessionId(), edgeId); |
183 | sessions.put(edgeId, edgeGrpcSession); | 211 | sessions.put(edgeId, edgeGrpcSession); |
184 | - sessionNewEvents.put(edgeId, false); | 212 | + final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); |
213 | + newEventLock.lock(); | ||
214 | + try { | ||
215 | + sessionNewEvents.put(edgeId, true); | ||
216 | + } finally { | ||
217 | + newEventLock.unlock(); | ||
218 | + } | ||
185 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); | 219 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); |
186 | save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis()); | 220 | save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis()); |
187 | cancelScheduleEdgeEventsCheck(edgeId); | 221 | cancelScheduleEdgeEventsCheck(edgeId); |
188 | scheduleEdgeEventsCheck(edgeGrpcSession); | 222 | scheduleEdgeEventsCheck(edgeGrpcSession); |
189 | } | 223 | } |
190 | 224 | ||
191 | - public EdgeGrpcSession getEdgeGrpcSessionById(TenantId tenantId, EdgeId edgeId) { | 225 | + @Override |
226 | + public void startSyncProcess(TenantId tenantId, EdgeId edgeId) { | ||
192 | EdgeGrpcSession session = sessions.get(edgeId); | 227 | EdgeGrpcSession session = sessions.get(edgeId); |
193 | if (session != null && session.isConnected()) { | 228 | if (session != null && session.isConnected()) { |
194 | - return session; | 229 | + session.startSyncProcess(tenantId, edgeId); |
195 | } else { | 230 | } else { |
196 | log.error("[{}] Edge is not connected [{}]", tenantId, edgeId); | 231 | log.error("[{}] Edge is not connected [{}]", tenantId, edgeId); |
197 | throw new RuntimeException("Edge is not connected"); | 232 | throw new RuntimeException("Edge is not connected"); |
@@ -202,19 +237,37 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -202,19 +237,37 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
202 | EdgeId edgeId = session.getEdge().getId(); | 237 | EdgeId edgeId = session.getEdge().getId(); |
203 | UUID tenantId = session.getEdge().getTenantId().getId(); | 238 | UUID tenantId = session.getEdge().getTenantId().getId(); |
204 | if (sessions.containsKey(edgeId)) { | 239 | if (sessions.containsKey(edgeId)) { |
205 | - ScheduledFuture<?> schedule = scheduler.schedule(() -> { | 240 | + ScheduledFuture<?> edgeEventCheckTask = edgeEventProcessingExecutorService.schedule(() -> { |
206 | try { | 241 | try { |
207 | - if (Boolean.TRUE.equals(sessionNewEvents.get(edgeId))) { | ||
208 | - log.trace("[{}] Set session new events flag to false", edgeId.getId()); | ||
209 | - sessionNewEvents.put(edgeId, false); | ||
210 | - session.processEdgeEvents(); | 242 | + final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); |
243 | + newEventLock.lock(); | ||
244 | + try { | ||
245 | + if (Boolean.TRUE.equals(sessionNewEvents.get(edgeId))) { | ||
246 | + log.trace("[{}] Set session new events flag to false", edgeId.getId()); | ||
247 | + sessionNewEvents.put(edgeId, false); | ||
248 | + Futures.addCallback(session.processEdgeEvents(), new FutureCallback<>() { | ||
249 | + @Override | ||
250 | + public void onSuccess(Void result) { | ||
251 | + scheduleEdgeEventsCheck(session); | ||
252 | + } | ||
253 | + | ||
254 | + @Override | ||
255 | + public void onFailure(Throwable t) { | ||
256 | + log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), t); | ||
257 | + scheduleEdgeEventsCheck(session); | ||
258 | + } | ||
259 | + }, ctx.getGrpcCallbackExecutorService()); | ||
260 | + } else { | ||
261 | + scheduleEdgeEventsCheck(session); | ||
262 | + } | ||
263 | + } finally { | ||
264 | + newEventLock.unlock(); | ||
211 | } | 265 | } |
212 | } catch (Exception e) { | 266 | } catch (Exception e) { |
213 | log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), e); | 267 | log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), e); |
214 | } | 268 | } |
215 | - scheduleEdgeEventsCheck(session); | ||
216 | }, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); | 269 | }, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); |
217 | - sessionEdgeEventChecks.put(edgeId, schedule); | 270 | + sessionEdgeEventChecks.put(edgeId, edgeEventCheckTask); |
218 | log.trace("[{}] Check edge event scheduled for edge [{}]", tenantId, edgeId.getId()); | 271 | log.trace("[{}] Check edge event scheduled for edge [{}]", tenantId, edgeId.getId()); |
219 | } else { | 272 | } else { |
220 | log.debug("[{}] Session was removed and edge event check schedule must not be started [{}]", | 273 | log.debug("[{}] Session was removed and edge event check schedule must not be started [{}]", |
@@ -236,7 +289,13 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -236,7 +289,13 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
236 | private void onEdgeDisconnect(EdgeId edgeId) { | 289 | private void onEdgeDisconnect(EdgeId edgeId) { |
237 | log.info("[{}] edge disconnected!", edgeId); | 290 | log.info("[{}] edge disconnected!", edgeId); |
238 | sessions.remove(edgeId); | 291 | sessions.remove(edgeId); |
239 | - sessionNewEvents.remove(edgeId); | 292 | + final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); |
293 | + newEventLock.lock(); | ||
294 | + try { | ||
295 | + sessionNewEvents.remove(edgeId); | ||
296 | + } finally { | ||
297 | + newEventLock.unlock(); | ||
298 | + } | ||
240 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false); | 299 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false); |
241 | save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, System.currentTimeMillis()); | 300 | save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, System.currentTimeMillis()); |
242 | cancelScheduleEdgeEventsCheck(edgeId); | 301 | cancelScheduleEdgeEventsCheck(edgeId); |
@@ -16,111 +16,76 @@ | @@ -16,111 +16,76 @@ | ||
16 | package org.thingsboard.server.service.edge.rpc; | 16 | package org.thingsboard.server.service.edge.rpc; |
17 | 17 | ||
18 | import com.datastax.oss.driver.api.core.uuid.Uuids; | 18 | import com.datastax.oss.driver.api.core.uuid.Uuids; |
19 | -import com.fasterxml.jackson.core.JsonProcessingException; | ||
20 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
21 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
22 | import com.google.common.util.concurrent.FutureCallback; | 20 | import com.google.common.util.concurrent.FutureCallback; |
23 | import com.google.common.util.concurrent.Futures; | 21 | import com.google.common.util.concurrent.Futures; |
24 | import com.google.common.util.concurrent.ListenableFuture; | 22 | import com.google.common.util.concurrent.ListenableFuture; |
25 | -import com.google.common.util.concurrent.MoreExecutors; | ||
26 | -import com.google.gson.JsonElement; | 23 | +import com.google.common.util.concurrent.SettableFuture; |
27 | import io.grpc.stub.StreamObserver; | 24 | import io.grpc.stub.StreamObserver; |
28 | import lombok.Data; | 25 | import lombok.Data; |
29 | import lombok.extern.slf4j.Slf4j; | 26 | import lombok.extern.slf4j.Slf4j; |
30 | import org.checkerframework.checker.nullness.qual.Nullable; | 27 | import org.checkerframework.checker.nullness.qual.Nullable; |
31 | -import org.thingsboard.server.common.data.AdminSettings; | ||
32 | -import org.thingsboard.server.common.data.Customer; | ||
33 | -import org.thingsboard.server.common.data.Dashboard; | 28 | +import org.thingsboard.common.util.JacksonUtil; |
34 | import org.thingsboard.server.common.data.DataConstants; | 29 | import org.thingsboard.server.common.data.DataConstants; |
35 | -import org.thingsboard.server.common.data.Device; | ||
36 | -import org.thingsboard.server.common.data.DeviceProfile; | ||
37 | -import org.thingsboard.server.common.data.EntityView; | ||
38 | -import org.thingsboard.server.common.data.HasCustomerId; | ||
39 | -import org.thingsboard.server.common.data.User; | ||
40 | -import org.thingsboard.server.common.data.alarm.Alarm; | ||
41 | -import org.thingsboard.server.common.data.asset.Asset; | 30 | +import org.thingsboard.server.common.data.EdgeUtils; |
42 | import org.thingsboard.server.common.data.edge.Edge; | 31 | import org.thingsboard.server.common.data.edge.Edge; |
43 | import org.thingsboard.server.common.data.edge.EdgeEvent; | 32 | import org.thingsboard.server.common.data.edge.EdgeEvent; |
44 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; | 33 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
45 | -import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
46 | -import org.thingsboard.server.common.data.id.AlarmId; | ||
47 | -import org.thingsboard.server.common.data.id.AssetId; | ||
48 | -import org.thingsboard.server.common.data.id.CustomerId; | ||
49 | -import org.thingsboard.server.common.data.id.DashboardId; | ||
50 | -import org.thingsboard.server.common.data.id.DeviceId; | ||
51 | -import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
52 | import org.thingsboard.server.common.data.id.EdgeId; | 34 | import org.thingsboard.server.common.data.id.EdgeId; |
53 | -import org.thingsboard.server.common.data.id.EntityId; | ||
54 | -import org.thingsboard.server.common.data.id.EntityViewId; | ||
55 | -import org.thingsboard.server.common.data.id.RuleChainId; | ||
56 | import org.thingsboard.server.common.data.id.TenantId; | 35 | import org.thingsboard.server.common.data.id.TenantId; |
57 | -import org.thingsboard.server.common.data.id.UserId; | ||
58 | -import org.thingsboard.server.common.data.id.WidgetTypeId; | ||
59 | -import org.thingsboard.server.common.data.id.WidgetsBundleId; | ||
60 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 36 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
61 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 37 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
62 | import org.thingsboard.server.common.data.kv.LongDataEntry; | 38 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
63 | import org.thingsboard.server.common.data.page.PageData; | 39 | import org.thingsboard.server.common.data.page.PageData; |
64 | -import org.thingsboard.server.common.data.page.SortOrder; | ||
65 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
66 | -import org.thingsboard.server.common.data.relation.EntityRelation; | ||
67 | -import org.thingsboard.server.common.data.rule.RuleChain; | ||
68 | -import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
69 | -import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
70 | -import org.thingsboard.server.common.data.security.UserCredentials; | ||
71 | -import org.thingsboard.server.common.data.widget.WidgetType; | ||
72 | -import org.thingsboard.server.common.data.widget.WidgetsBundle; | ||
73 | -import org.thingsboard.server.common.transport.util.JsonUtils; | ||
74 | -import org.thingsboard.common.util.JacksonUtil; | ||
75 | -import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; | ||
76 | -import org.thingsboard.server.gen.edge.AlarmUpdateMsg; | ||
77 | -import org.thingsboard.server.gen.edge.AssetUpdateMsg; | ||
78 | -import org.thingsboard.server.gen.edge.AttributesRequestMsg; | ||
79 | -import org.thingsboard.server.gen.edge.ConnectRequestMsg; | ||
80 | -import org.thingsboard.server.gen.edge.ConnectResponseCode; | ||
81 | -import org.thingsboard.server.gen.edge.ConnectResponseMsg; | ||
82 | -import org.thingsboard.server.gen.edge.CustomerUpdateMsg; | ||
83 | -import org.thingsboard.server.gen.edge.DashboardUpdateMsg; | ||
84 | -import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; | ||
85 | -import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; | ||
86 | -import org.thingsboard.server.gen.edge.DeviceProfileUpdateMsg; | ||
87 | -import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; | ||
88 | -import org.thingsboard.server.gen.edge.DeviceUpdateMsg; | ||
89 | -import org.thingsboard.server.gen.edge.DownlinkMsg; | ||
90 | -import org.thingsboard.server.gen.edge.DownlinkResponseMsg; | ||
91 | -import org.thingsboard.server.gen.edge.EdgeConfiguration; | ||
92 | -import org.thingsboard.server.gen.edge.EdgeUpdateMsg; | ||
93 | -import org.thingsboard.server.gen.edge.EntityDataProto; | ||
94 | -import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; | ||
95 | -import org.thingsboard.server.gen.edge.RelationRequestMsg; | ||
96 | -import org.thingsboard.server.gen.edge.RelationUpdateMsg; | ||
97 | -import org.thingsboard.server.gen.edge.RequestMsg; | ||
98 | -import org.thingsboard.server.gen.edge.RequestMsgType; | ||
99 | -import org.thingsboard.server.gen.edge.ResponseMsg; | ||
100 | -import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; | ||
101 | -import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; | ||
102 | -import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; | ||
103 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | ||
104 | -import org.thingsboard.server.gen.edge.UplinkMsg; | ||
105 | -import org.thingsboard.server.gen.edge.UplinkResponseMsg; | ||
106 | -import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; | ||
107 | -import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; | ||
108 | -import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; | ||
109 | -import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; | 40 | +import org.thingsboard.server.common.data.page.PageLink; |
41 | +import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; | ||
42 | +import org.thingsboard.server.gen.edge.v1.AttributesRequestMsg; | ||
43 | +import org.thingsboard.server.gen.edge.v1.ConnectRequestMsg; | ||
44 | +import org.thingsboard.server.gen.edge.v1.ConnectResponseCode; | ||
45 | +import org.thingsboard.server.gen.edge.v1.ConnectResponseMsg; | ||
46 | +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg; | ||
47 | +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; | ||
48 | +import org.thingsboard.server.gen.edge.v1.DeviceProfileDevicesRequestMsg; | ||
49 | +import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg; | ||
50 | +import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; | ||
51 | +import org.thingsboard.server.gen.edge.v1.DownlinkMsg; | ||
52 | +import org.thingsboard.server.gen.edge.v1.DownlinkResponseMsg; | ||
53 | +import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; | ||
54 | +import org.thingsboard.server.gen.edge.v1.EdgeUpdateMsg; | ||
55 | +import org.thingsboard.server.gen.edge.v1.EntityDataProto; | ||
56 | +import org.thingsboard.server.gen.edge.v1.EntityViewsRequestMsg; | ||
57 | +import org.thingsboard.server.gen.edge.v1.RelationRequestMsg; | ||
58 | +import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; | ||
59 | +import org.thingsboard.server.gen.edge.v1.RequestMsg; | ||
60 | +import org.thingsboard.server.gen.edge.v1.RequestMsgType; | ||
61 | +import org.thingsboard.server.gen.edge.v1.ResponseMsg; | ||
62 | +import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg; | ||
63 | +import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg; | ||
64 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
65 | +import org.thingsboard.server.gen.edge.v1.UplinkMsg; | ||
66 | +import org.thingsboard.server.gen.edge.v1.UplinkResponseMsg; | ||
67 | +import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg; | ||
68 | +import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg; | ||
110 | import org.thingsboard.server.service.edge.EdgeContextComponent; | 69 | import org.thingsboard.server.service.edge.EdgeContextComponent; |
70 | +import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher; | ||
71 | +import org.thingsboard.server.service.edge.rpc.fetch.GeneralEdgeEventFetcher; | ||
111 | 72 | ||
112 | import java.io.Closeable; | 73 | import java.io.Closeable; |
113 | import java.util.ArrayList; | 74 | import java.util.ArrayList; |
114 | import java.util.Collections; | 75 | import java.util.Collections; |
76 | +import java.util.LinkedHashMap; | ||
115 | import java.util.List; | 77 | import java.util.List; |
78 | +import java.util.Map; | ||
79 | +import java.util.Objects; | ||
116 | import java.util.Optional; | 80 | import java.util.Optional; |
117 | import java.util.UUID; | 81 | import java.util.UUID; |
118 | -import java.util.concurrent.CountDownLatch; | ||
119 | -import java.util.concurrent.ExecutionException; | 82 | +import java.util.concurrent.ScheduledExecutorService; |
83 | +import java.util.concurrent.ScheduledFuture; | ||
120 | import java.util.concurrent.TimeUnit; | 84 | import java.util.concurrent.TimeUnit; |
121 | import java.util.concurrent.locks.ReentrantLock; | 85 | import java.util.concurrent.locks.ReentrantLock; |
122 | import java.util.function.BiConsumer; | 86 | import java.util.function.BiConsumer; |
123 | import java.util.function.Consumer; | 87 | import java.util.function.Consumer; |
88 | +import java.util.stream.Collectors; | ||
124 | 89 | ||
125 | @Slf4j | 90 | @Slf4j |
126 | @Data | 91 | @Data |
@@ -135,27 +100,31 @@ public final class EdgeGrpcSession implements Closeable { | @@ -135,27 +100,31 @@ public final class EdgeGrpcSession implements Closeable { | ||
135 | private final Consumer<EdgeId> sessionCloseListener; | 100 | private final Consumer<EdgeId> sessionCloseListener; |
136 | private final ObjectMapper mapper; | 101 | private final ObjectMapper mapper; |
137 | 102 | ||
103 | + private final EdgeSessionState sessionState = new EdgeSessionState(); | ||
104 | + | ||
138 | private EdgeContextComponent ctx; | 105 | private EdgeContextComponent ctx; |
139 | private Edge edge; | 106 | private Edge edge; |
140 | private StreamObserver<RequestMsg> inputStream; | 107 | private StreamObserver<RequestMsg> inputStream; |
141 | private StreamObserver<ResponseMsg> outputStream; | 108 | private StreamObserver<ResponseMsg> outputStream; |
142 | private boolean connected; | 109 | private boolean connected; |
110 | + private boolean syncCompleted; | ||
143 | 111 | ||
144 | - private CountDownLatch latch; | 112 | + private ScheduledExecutorService sendDownlinkExecutorService; |
145 | 113 | ||
146 | EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver<ResponseMsg> outputStream, BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener, | 114 | EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver<ResponseMsg> outputStream, BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener, |
147 | - Consumer<EdgeId> sessionCloseListener, ObjectMapper mapper) { | 115 | + Consumer<EdgeId> sessionCloseListener, ObjectMapper mapper, ScheduledExecutorService sendDownlinkExecutorService) { |
148 | this.sessionId = UUID.randomUUID(); | 116 | this.sessionId = UUID.randomUUID(); |
149 | this.ctx = ctx; | 117 | this.ctx = ctx; |
150 | this.outputStream = outputStream; | 118 | this.outputStream = outputStream; |
151 | this.sessionOpenListener = sessionOpenListener; | 119 | this.sessionOpenListener = sessionOpenListener; |
152 | this.sessionCloseListener = sessionCloseListener; | 120 | this.sessionCloseListener = sessionCloseListener; |
153 | this.mapper = mapper; | 121 | this.mapper = mapper; |
122 | + this.sendDownlinkExecutorService = sendDownlinkExecutorService; | ||
154 | initInputStream(); | 123 | initInputStream(); |
155 | } | 124 | } |
156 | 125 | ||
157 | private void initInputStream() { | 126 | private void initInputStream() { |
158 | - this.inputStream = new StreamObserver<RequestMsg>() { | 127 | + this.inputStream = new StreamObserver<>() { |
159 | @Override | 128 | @Override |
160 | public void onNext(RequestMsg requestMsg) { | 129 | public void onNext(RequestMsg requestMsg) { |
161 | if (!connected && requestMsg.getMsgType().equals(RequestMsgType.CONNECT_RPC_MESSAGE)) { | 130 | if (!connected && requestMsg.getMsgType().equals(RequestMsgType.CONNECT_RPC_MESSAGE)) { |
@@ -169,15 +138,21 @@ public final class EdgeGrpcSession implements Closeable { | @@ -169,15 +138,21 @@ public final class EdgeGrpcSession implements Closeable { | ||
169 | connected = true; | 138 | connected = true; |
170 | } | 139 | } |
171 | } | 140 | } |
172 | - if (connected && requestMsg.getMsgType().equals(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE)) { | ||
173 | - ctx.getSyncEdgeService().sync(edge.getTenantId(), edge); | ||
174 | - } | ||
175 | if (connected) { | 141 | if (connected) { |
176 | - if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE) && requestMsg.hasUplinkMsg()) { | ||
177 | - onUplinkMsg(requestMsg.getUplinkMsg()); | 142 | + if (requestMsg.getMsgType().equals(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE)) { |
143 | + if (requestMsg.hasSyncRequestMsg() && requestMsg.getSyncRequestMsg().getSyncRequired()) { | ||
144 | + startSyncProcess(edge.getTenantId(), edge.getId()); | ||
145 | + } else { | ||
146 | + syncCompleted = true; | ||
147 | + } | ||
178 | } | 148 | } |
179 | - if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE) && requestMsg.hasDownlinkResponseMsg()) { | ||
180 | - onDownlinkResponse(requestMsg.getDownlinkResponseMsg()); | 149 | + if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE)) { |
150 | + if (requestMsg.hasUplinkMsg()) { | ||
151 | + onUplinkMsg(requestMsg.getUplinkMsg()); | ||
152 | + } | ||
153 | + if (requestMsg.hasDownlinkResponseMsg()) { | ||
154 | + onDownlinkResponse(requestMsg.getDownlinkResponseMsg()); | ||
155 | + } | ||
181 | } | 156 | } |
182 | } | 157 | } |
183 | } | 158 | } |
@@ -198,21 +173,65 @@ public final class EdgeGrpcSession implements Closeable { | @@ -198,21 +173,65 @@ public final class EdgeGrpcSession implements Closeable { | ||
198 | if (edge != null) { | 173 | if (edge != null) { |
199 | try { | 174 | try { |
200 | sessionCloseListener.accept(edge.getId()); | 175 | sessionCloseListener.accept(edge.getId()); |
201 | - } catch (Exception ignored) {} | 176 | + } catch (Exception ignored) { |
177 | + } | ||
202 | } | 178 | } |
203 | try { | 179 | try { |
204 | outputStream.onCompleted(); | 180 | outputStream.onCompleted(); |
205 | - } catch (Exception ignored) {} | 181 | + } catch (Exception ignored) { |
182 | + } | ||
206 | } | 183 | } |
207 | }; | 184 | }; |
208 | } | 185 | } |
209 | 186 | ||
187 | + public void startSyncProcess(TenantId tenantId, EdgeId edgeId) { | ||
188 | + log.trace("[{}][{}] Staring edge sync process", tenantId, edgeId); | ||
189 | + syncCompleted = false; | ||
190 | + doSync(new EdgeSyncCursor(ctx, edge)); | ||
191 | + } | ||
192 | + | ||
193 | + private void doSync(EdgeSyncCursor cursor) { | ||
194 | + if (cursor.hasNext()) { | ||
195 | + log.info("[{}][{}] starting sync process, cursor current idx = {}", edge.getTenantId(), edge.getId(), cursor.getCurrentIdx()); | ||
196 | + ListenableFuture<UUID> uuidListenableFuture = startProcessingEdgeEvents(cursor.getNext()); | ||
197 | + Futures.addCallback(uuidListenableFuture, new FutureCallback<>() { | ||
198 | + @Override | ||
199 | + public void onSuccess(@Nullable UUID result) { | ||
200 | + doSync(cursor); | ||
201 | + } | ||
202 | + | ||
203 | + @Override | ||
204 | + public void onFailure(Throwable t) { | ||
205 | + log.error("[{}][{}] Exception during sync process", edge.getTenantId(), edge.getId(), t); | ||
206 | + } | ||
207 | + }, ctx.getGrpcCallbackExecutorService()); | ||
208 | + } else { | ||
209 | + DownlinkMsg syncCompleteDownlinkMsg = DownlinkMsg.newBuilder() | ||
210 | + .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) | ||
211 | + .setSyncCompletedMsg(SyncCompletedMsg.newBuilder().build()) | ||
212 | + .build(); | ||
213 | + Futures.addCallback(sendDownlinkMsgsPack(Collections.singletonList(syncCompleteDownlinkMsg)), new FutureCallback<Void>() { | ||
214 | + @Override | ||
215 | + public void onSuccess(Void result) { | ||
216 | + syncCompleted = true; | ||
217 | + } | ||
218 | + | ||
219 | + @Override | ||
220 | + public void onFailure(Throwable t) { | ||
221 | + log.error("[{}][{}] Exception during sending sync complete", edge.getTenantId(), edge.getId(), t); | ||
222 | + } | ||
223 | + }, ctx.getGrpcCallbackExecutorService()); | ||
224 | + } | ||
225 | + } | ||
226 | + | ||
210 | private void onUplinkMsg(UplinkMsg uplinkMsg) { | 227 | private void onUplinkMsg(UplinkMsg uplinkMsg) { |
211 | ListenableFuture<List<Void>> future = processUplinkMsg(uplinkMsg); | 228 | ListenableFuture<List<Void>> future = processUplinkMsg(uplinkMsg); |
212 | - Futures.addCallback(future, new FutureCallback<List<Void>>() { | 229 | + Futures.addCallback(future, new FutureCallback<>() { |
213 | @Override | 230 | @Override |
214 | public void onSuccess(@Nullable List<Void> result) { | 231 | public void onSuccess(@Nullable List<Void> result) { |
215 | - UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder().setSuccess(true).build(); | 232 | + UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder() |
233 | + .setUplinkMsgId(uplinkMsg.getUplinkMsgId()) | ||
234 | + .setSuccess(true).build(); | ||
216 | sendDownlinkMsg(ResponseMsg.newBuilder() | 235 | sendDownlinkMsg(ResponseMsg.newBuilder() |
217 | .setUplinkResponseMsg(uplinkResponseMsg) | 236 | .setUplinkResponseMsg(uplinkResponseMsg) |
218 | .build()); | 237 | .build()); |
@@ -220,22 +239,32 @@ public final class EdgeGrpcSession implements Closeable { | @@ -220,22 +239,32 @@ public final class EdgeGrpcSession implements Closeable { | ||
220 | 239 | ||
221 | @Override | 240 | @Override |
222 | public void onFailure(Throwable t) { | 241 | public void onFailure(Throwable t) { |
223 | - UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder().setSuccess(false).setErrorMsg(t.getMessage()).build(); | 242 | + String errorMsg = t.getMessage() != null ? t.getMessage() : ""; |
243 | + UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder() | ||
244 | + .setUplinkMsgId(uplinkMsg.getUplinkMsgId()) | ||
245 | + .setSuccess(false).setErrorMsg(errorMsg).build(); | ||
224 | sendDownlinkMsg(ResponseMsg.newBuilder() | 246 | sendDownlinkMsg(ResponseMsg.newBuilder() |
225 | .setUplinkResponseMsg(uplinkResponseMsg) | 247 | .setUplinkResponseMsg(uplinkResponseMsg) |
226 | .build()); | 248 | .build()); |
227 | } | 249 | } |
228 | - }, MoreExecutors.directExecutor()); | 250 | + }, ctx.getGrpcCallbackExecutorService()); |
229 | } | 251 | } |
230 | 252 | ||
231 | private void onDownlinkResponse(DownlinkResponseMsg msg) { | 253 | private void onDownlinkResponse(DownlinkResponseMsg msg) { |
232 | try { | 254 | try { |
233 | if (msg.getSuccess()) { | 255 | if (msg.getSuccess()) { |
256 | + sessionState.getPendingMsgsMap().remove(msg.getDownlinkMsgId()); | ||
234 | log.debug("[{}] Msg has been processed successfully! {}", edge.getRoutingKey(), msg); | 257 | log.debug("[{}] Msg has been processed successfully! {}", edge.getRoutingKey(), msg); |
235 | } else { | 258 | } else { |
236 | log.error("[{}] Msg processing failed! Error msg: {}", edge.getRoutingKey(), msg.getErrorMsg()); | 259 | log.error("[{}] Msg processing failed! Error msg: {}", edge.getRoutingKey(), msg.getErrorMsg()); |
237 | } | 260 | } |
238 | - latch.countDown(); | 261 | + if (sessionState.getPendingMsgsMap().isEmpty()) { |
262 | + log.debug("[{}] Pending msgs map is empty. Stopping current iteration {}", edge.getRoutingKey(), msg); | ||
263 | + if (sessionState.getScheduledSendDownlinkTask() != null) { | ||
264 | + sessionState.getScheduledSendDownlinkTask().cancel(false); | ||
265 | + } | ||
266 | + sessionState.getSendDownlinkMsgsFuture().set(null); | ||
267 | + } | ||
239 | } catch (Exception e) { | 268 | } catch (Exception e) { |
240 | log.error("[{}] Can't process downlink response message [{}]", this.sessionId, msg, e); | 269 | log.error("[{}] Can't process downlink response message [{}]", this.sessionId, msg, e); |
241 | } | 270 | } |
@@ -244,8 +273,8 @@ public final class EdgeGrpcSession implements Closeable { | @@ -244,8 +273,8 @@ public final class EdgeGrpcSession implements Closeable { | ||
244 | private void sendDownlinkMsg(ResponseMsg downlinkMsg) { | 273 | private void sendDownlinkMsg(ResponseMsg downlinkMsg) { |
245 | log.trace("[{}] Sending downlink msg [{}]", this.sessionId, downlinkMsg); | 274 | log.trace("[{}] Sending downlink msg [{}]", this.sessionId, downlinkMsg); |
246 | if (isConnected()) { | 275 | if (isConnected()) { |
276 | + downlinkMsgLock.lock(); | ||
247 | try { | 277 | try { |
248 | - downlinkMsgLock.lock(); | ||
249 | outputStream.onNext(downlinkMsg); | 278 | outputStream.onNext(downlinkMsg); |
250 | } catch (Exception e) { | 279 | } catch (Exception e) { |
251 | log.error("[{}] Failed to send downlink message [{}]", this.sessionId, downlinkMsg, e); | 280 | log.error("[{}] Failed to send downlink message [{}]", this.sessionId, downlinkMsg, e); |
@@ -269,149 +298,192 @@ public final class EdgeGrpcSession implements Closeable { | @@ -269,149 +298,192 @@ public final class EdgeGrpcSession implements Closeable { | ||
269 | sendDownlinkMsg(edgeConfigMsg); | 298 | sendDownlinkMsg(edgeConfigMsg); |
270 | } | 299 | } |
271 | 300 | ||
272 | - void processEdgeEvents() throws ExecutionException, InterruptedException { | ||
273 | - log.trace("[{}] processHandleMessages started", this.sessionId); | ||
274 | - if (isConnected()) { | 301 | + ListenableFuture<Void> processEdgeEvents() throws Exception { |
302 | + SettableFuture<Void> result = SettableFuture.create(); | ||
303 | + log.trace("[{}] starting processing edge events", this.sessionId); | ||
304 | + if (isConnected() && isSyncCompleted()) { | ||
275 | Long queueStartTs = getQueueStartTs().get(); | 305 | Long queueStartTs = getQueueStartTs().get(); |
276 | - TimePageLink pageLink = new TimePageLink( | ||
277 | - ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), | ||
278 | - 0, | ||
279 | - null, | ||
280 | - new SortOrder("createdTime", SortOrder.Direction.ASC), | 306 | + GeneralEdgeEventFetcher fetcher = new GeneralEdgeEventFetcher( |
281 | queueStartTs, | 307 | queueStartTs, |
282 | - null); | ||
283 | - PageData<EdgeEvent> pageData; | ||
284 | - UUID ifOffset = null; | ||
285 | - boolean success = true; | ||
286 | - do { | ||
287 | - pageData = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), pageLink, true); | ||
288 | - if (isConnected() && !pageData.getData().isEmpty()) { | ||
289 | - log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); | ||
290 | - List<DownlinkMsg> downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData()); | ||
291 | - log.trace("[{}] [{}] downlink msg(s) are going to be send.", this.sessionId, downlinkMsgsPack.size()); | ||
292 | - | ||
293 | - latch = new CountDownLatch(downlinkMsgsPack.size()); | ||
294 | - for (DownlinkMsg downlinkMsg : downlinkMsgsPack) { | ||
295 | - sendDownlinkMsg(ResponseMsg.newBuilder() | ||
296 | - .setDownlinkMsg(downlinkMsg) | ||
297 | - .build()); | 308 | + ctx.getEdgeEventService()); |
309 | + ListenableFuture<UUID> ifOffsetFuture = startProcessingEdgeEvents(fetcher); | ||
310 | + Futures.addCallback(ifOffsetFuture, new FutureCallback<>() { | ||
311 | + @Override | ||
312 | + public void onSuccess(@Nullable UUID ifOffset) { | ||
313 | + if (ifOffset != null) { | ||
314 | + Long newStartTs = Uuids.unixTimestamp(ifOffset); | ||
315 | + ListenableFuture<List<Void>> updateFuture = updateQueueStartTs(newStartTs); | ||
316 | + Futures.addCallback(updateFuture, new FutureCallback<>() { | ||
317 | + @Override | ||
318 | + public void onSuccess(@Nullable List<Void> list) { | ||
319 | + log.debug("[{}] queue offset was updated [{}][{}]", sessionId, ifOffset, newStartTs); | ||
320 | + result.set(null); | ||
321 | + } | ||
322 | + | ||
323 | + @Override | ||
324 | + public void onFailure(Throwable t) { | ||
325 | + log.error("[{}] Failed to update queue offset [{}]", sessionId, ifOffset, t); | ||
326 | + result.setException(t); | ||
327 | + } | ||
328 | + }, ctx.getGrpcCallbackExecutorService()); | ||
329 | + } else { | ||
330 | + log.trace("[{}] ifOffset is null. Skipping iteration without db update", sessionId); | ||
331 | + result.set(null); | ||
298 | } | 332 | } |
333 | + } | ||
299 | 334 | ||
300 | - ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId(); | ||
301 | - | ||
302 | - success = latch.await(10, TimeUnit.SECONDS); | ||
303 | - if (!success) { | ||
304 | - log.warn("[{}] Failed to deliver the batch: {}", this.sessionId, downlinkMsgsPack); | ||
305 | - } | 335 | + @Override |
336 | + public void onFailure(Throwable t) { | ||
337 | + log.error("[{}] Failed to process events", sessionId, t); | ||
338 | + result.setException(t); | ||
306 | } | 339 | } |
307 | - if (isConnected() && (!success || pageData.hasNext())) { | ||
308 | - try { | ||
309 | - Thread.sleep(ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches()); | ||
310 | - } catch (InterruptedException e) { | ||
311 | - log.error("[{}] Error during sleep between batches", this.sessionId, e); | ||
312 | - } | ||
313 | - if (success) { | ||
314 | - pageLink = pageLink.nextPageLink(); | 340 | + }, ctx.getGrpcCallbackExecutorService()); |
341 | + } else { | ||
342 | + log.trace("[{}] edge is not connected or sync is not completed. Skipping iteration", sessionId); | ||
343 | + result.set(null); | ||
344 | + } | ||
345 | + return result; | ||
346 | + } | ||
347 | + | ||
348 | + private ListenableFuture<UUID> startProcessingEdgeEvents(EdgeEventFetcher fetcher) { | ||
349 | + SettableFuture<UUID> result = SettableFuture.create(); | ||
350 | + PageLink pageLink = fetcher.getPageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()); | ||
351 | + processEdgeEvents(fetcher, pageLink, result); | ||
352 | + return result; | ||
353 | + } | ||
354 | + | ||
355 | + private void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture<UUID> result) { | ||
356 | + try { | ||
357 | + PageData<EdgeEvent> pageData = fetcher.fetchEdgeEvents(edge.getTenantId(), edge, pageLink); | ||
358 | + if (isConnected() && !pageData.getData().isEmpty()) { | ||
359 | + log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); | ||
360 | + List<DownlinkMsg> downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData()); | ||
361 | + Futures.addCallback(sendDownlinkMsgsPack(downlinkMsgsPack), new FutureCallback<Void>() { | ||
362 | + @Override | ||
363 | + public void onSuccess(@Nullable Void tmp) { | ||
364 | + if (isConnected() && pageData.hasNext()) { | ||
365 | + processEdgeEvents(fetcher, pageLink.nextPageLink(), result); | ||
366 | + } else { | ||
367 | + UUID ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId(); | ||
368 | + result.set(ifOffset); | ||
369 | + } | ||
315 | } | 370 | } |
316 | - } | ||
317 | - } while (isConnected() && (!success || pageData.hasNext())); | ||
318 | 371 | ||
319 | - if (ifOffset != null) { | ||
320 | - Long newStartTs = Uuids.unixTimestamp(ifOffset); | ||
321 | - updateQueueStartTs(newStartTs); | 372 | + @Override |
373 | + public void onFailure(Throwable t) { | ||
374 | + log.error("[{}] Failed to send downlink msgs pack", sessionId, t); | ||
375 | + result.setException(t); | ||
376 | + } | ||
377 | + }, ctx.getGrpcCallbackExecutorService()); | ||
378 | + } else { | ||
379 | + log.trace("[{}] no event(s) found. Stop processing edge events", this.sessionId); | ||
380 | + result.set(null); | ||
322 | } | 381 | } |
382 | + } catch (Exception e) { | ||
383 | + log.error("[{}] Failed to fetch edge events", this.sessionId, e); | ||
384 | + result.setException(e); | ||
323 | } | 385 | } |
324 | - log.trace("[{}] processHandleMessages finished", this.sessionId); | ||
325 | } | 386 | } |
326 | 387 | ||
327 | - private List<DownlinkMsg> convertToDownlinkMsgsPack(List<EdgeEvent> edgeEvents) { | ||
328 | - List<DownlinkMsg> result = new ArrayList<>(); | ||
329 | - for (EdgeEvent edgeEvent : edgeEvents) { | ||
330 | - log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent); | 388 | + private ListenableFuture<Void> sendDownlinkMsgsPack(List<DownlinkMsg> downlinkMsgsPack) { |
389 | + if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()) { | ||
390 | + String erroMsg = "[" + this.sessionId + "] Previous send downdlink future was not properly completed, stopping it now"; | ||
391 | + log.error(erroMsg); | ||
392 | + sessionState.getSendDownlinkMsgsFuture().setException(new RuntimeException(erroMsg)); | ||
393 | + } | ||
394 | + sessionState.setSendDownlinkMsgsFuture(SettableFuture.create()); | ||
395 | + sessionState.getPendingMsgsMap().clear(); | ||
396 | + downlinkMsgsPack.forEach(msg -> sessionState.getPendingMsgsMap().put(msg.getDownlinkMsgId(), msg)); | ||
397 | + scheduleDownlinkMsgsPackSend(true); | ||
398 | + return sessionState.getSendDownlinkMsgsFuture(); | ||
399 | + } | ||
400 | + | ||
401 | + private void scheduleDownlinkMsgsPackSend(boolean firstRun) { | ||
402 | + Runnable sendDownlinkMsgsTask = () -> { | ||
331 | try { | 403 | try { |
332 | - DownlinkMsg downlinkMsg = null; | ||
333 | - switch (edgeEvent.getAction()) { | ||
334 | - case UPDATED: | ||
335 | - case ADDED: | ||
336 | - case DELETED: | ||
337 | - case ASSIGNED_TO_EDGE: | ||
338 | - case UNASSIGNED_FROM_EDGE: | ||
339 | - case ALARM_ACK: | ||
340 | - case ALARM_CLEAR: | ||
341 | - case CREDENTIALS_UPDATED: | ||
342 | - case RELATION_ADD_OR_UPDATE: | ||
343 | - case RELATION_DELETED: | ||
344 | - case ASSIGNED_TO_CUSTOMER: | ||
345 | - case UNASSIGNED_FROM_CUSTOMER: | ||
346 | - downlinkMsg = processEntityMessage(edgeEvent, edgeEvent.getAction()); | ||
347 | - break; | ||
348 | - case ATTRIBUTES_UPDATED: | ||
349 | - case POST_ATTRIBUTES: | ||
350 | - case ATTRIBUTES_DELETED: | ||
351 | - case TIMESERIES_UPDATED: | ||
352 | - downlinkMsg = processTelemetryMessage(edgeEvent); | ||
353 | - break; | ||
354 | - case CREDENTIALS_REQUEST: | ||
355 | - downlinkMsg = processCredentialsRequestMessage(edgeEvent); | ||
356 | - break; | ||
357 | - case ENTITY_MERGE_REQUEST: | ||
358 | - downlinkMsg = processEntityMergeRequestMessage(edgeEvent); | ||
359 | - break; | ||
360 | - case RPC_CALL: | ||
361 | - downlinkMsg = processRpcCallMsg(edgeEvent); | ||
362 | - break; | ||
363 | - } | ||
364 | - if (downlinkMsg != null) { | ||
365 | - result.add(downlinkMsg); | 404 | + if (isConnected() && sessionState.getPendingMsgsMap().values().size() > 0) { |
405 | + if (!firstRun) { | ||
406 | + log.warn("[{}] Failed to deliver the batch: {}", this.sessionId, sessionState.getPendingMsgsMap().values()); | ||
407 | + } | ||
408 | + log.trace("[{}] [{}] downlink msg(s) are going to be send.", this.sessionId, sessionState.getPendingMsgsMap().values().size()); | ||
409 | + List<DownlinkMsg> copy = new ArrayList<>(sessionState.getPendingMsgsMap().values()); | ||
410 | + for (DownlinkMsg downlinkMsg : copy) { | ||
411 | + sendDownlinkMsg(ResponseMsg.newBuilder() | ||
412 | + .setDownlinkMsg(downlinkMsg) | ||
413 | + .build()); | ||
414 | + } | ||
415 | + scheduleDownlinkMsgsPackSend(false); | ||
416 | + } else { | ||
417 | + sessionState.getSendDownlinkMsgsFuture().set(null); | ||
366 | } | 418 | } |
367 | } catch (Exception e) { | 419 | } catch (Exception e) { |
368 | - log.error("Exception during processing records from queue", e); | 420 | + sessionState.getSendDownlinkMsgsFuture().setException(e); |
369 | } | 421 | } |
422 | + }; | ||
423 | + | ||
424 | + if (firstRun) { | ||
425 | + sendDownlinkExecutorService.submit(sendDownlinkMsgsTask); | ||
426 | + } else { | ||
427 | + sessionState.setScheduledSendDownlinkTask( | ||
428 | + sendDownlinkExecutorService.schedule( | ||
429 | + sendDownlinkMsgsTask, | ||
430 | + ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches(), | ||
431 | + TimeUnit.MILLISECONDS) | ||
432 | + ); | ||
370 | } | 433 | } |
371 | - return result; | 434 | + |
372 | } | 435 | } |
373 | 436 | ||
374 | - private DownlinkMsg processEntityMergeRequestMessage(EdgeEvent edgeEvent) { | 437 | + private DownlinkMsg convertToDownlinkMsg(EdgeEvent edgeEvent) { |
438 | + log.trace("[{}][{}] converting edge event to downlink msg [{}]", edge.getTenantId(), this.sessionId, edgeEvent); | ||
375 | DownlinkMsg downlinkMsg = null; | 439 | DownlinkMsg downlinkMsg = null; |
376 | - if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { | ||
377 | - DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); | ||
378 | - Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); | ||
379 | - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); | ||
380 | - String conflictName = null; | ||
381 | - if(edgeEvent.getBody() != null) { | ||
382 | - conflictName = edgeEvent.getBody().get("conflictName").asText(); | 440 | + try { |
441 | + switch (edgeEvent.getAction()) { | ||
442 | + case UPDATED: | ||
443 | + case ADDED: | ||
444 | + case DELETED: | ||
445 | + case ASSIGNED_TO_EDGE: | ||
446 | + case UNASSIGNED_FROM_EDGE: | ||
447 | + case ALARM_ACK: | ||
448 | + case ALARM_CLEAR: | ||
449 | + case CREDENTIALS_UPDATED: | ||
450 | + case RELATION_ADD_OR_UPDATE: | ||
451 | + case RELATION_DELETED: | ||
452 | + case ASSIGNED_TO_CUSTOMER: | ||
453 | + case UNASSIGNED_FROM_CUSTOMER: | ||
454 | + downlinkMsg = processEntityMessage(edgeEvent, edgeEvent.getAction()); | ||
455 | + log.trace("[{}][{}] entity message processed [{}]", edgeEvent.getTenantId(), this.sessionId, downlinkMsg); | ||
456 | + break; | ||
457 | + case ATTRIBUTES_UPDATED: | ||
458 | + case POST_ATTRIBUTES: | ||
459 | + case ATTRIBUTES_DELETED: | ||
460 | + case TIMESERIES_UPDATED: | ||
461 | + downlinkMsg = ctx.getTelemetryProcessor().processTelemetryMessageToEdge(edgeEvent); | ||
462 | + break; | ||
463 | + case CREDENTIALS_REQUEST: | ||
464 | + downlinkMsg = ctx.getEntityProcessor().processCredentialsRequestMessageToEdge(edgeEvent); | ||
465 | + break; | ||
466 | + case ENTITY_MERGE_REQUEST: | ||
467 | + downlinkMsg = ctx.getEntityProcessor().processEntityMergeRequestMessageToEdge(edge, edgeEvent); | ||
468 | + break; | ||
469 | + case RPC_CALL: | ||
470 | + downlinkMsg = ctx.getDeviceProcessor().processRpcCallMsgToEdge(edgeEvent); | ||
471 | + break; | ||
472 | + default: | ||
473 | + log.warn("[{}][{}] Unsupported action type [{}]", edge.getTenantId(), this.sessionId, edgeEvent.getAction()); | ||
383 | } | 474 | } |
384 | - DeviceUpdateMsg d = ctx.getDeviceMsgConstructor() | ||
385 | - .constructDeviceUpdatedMsg(UpdateMsgType.ENTITY_MERGE_RPC_MESSAGE, device, customerId, conflictName); | ||
386 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
387 | - .addAllDeviceUpdateMsg(Collections.singletonList(d)) | ||
388 | - .build(); | 475 | + } catch (Exception e) { |
476 | + log.error("[{}][{}] Exception during converting edge event to downlink msg", edge.getTenantId(), this.sessionId, e); | ||
389 | } | 477 | } |
390 | return downlinkMsg; | 478 | return downlinkMsg; |
391 | } | 479 | } |
392 | 480 | ||
393 | - private DownlinkMsg processRpcCallMsg(EdgeEvent edgeEvent) { | ||
394 | - log.trace("Executing processRpcCall, edgeEvent [{}]", edgeEvent); | ||
395 | - DeviceRpcCallMsg deviceRpcCallMsg = | ||
396 | - ctx.getDeviceMsgConstructor().constructDeviceRpcCallMsg(edgeEvent.getEntityId(), edgeEvent.getBody()); | ||
397 | - return DownlinkMsg.newBuilder() | ||
398 | - .addAllDeviceRpcCallMsg(Collections.singletonList(deviceRpcCallMsg)) | ||
399 | - .build(); | ||
400 | - } | ||
401 | - | ||
402 | - private DownlinkMsg processCredentialsRequestMessage(EdgeEvent edgeEvent) { | ||
403 | - DownlinkMsg downlinkMsg = null; | ||
404 | - if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { | ||
405 | - DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); | ||
406 | - DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() | ||
407 | - .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) | ||
408 | - .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) | ||
409 | - .build(); | ||
410 | - DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() | ||
411 | - .addAllDeviceCredentialsRequestMsg(Collections.singletonList(deviceCredentialsRequestMsg)); | ||
412 | - downlinkMsg = builder.build(); | ||
413 | - } | ||
414 | - return downlinkMsg; | 481 | + private List<DownlinkMsg> convertToDownlinkMsgsPack(List<EdgeEvent> edgeEvents) { |
482 | + return edgeEvents | ||
483 | + .stream() | ||
484 | + .map(this::convertToDownlinkMsg) | ||
485 | + .filter(Objects::nonNull) | ||
486 | + .collect(Collectors.toList()); | ||
415 | } | 487 | } |
416 | 488 | ||
417 | private ListenableFuture<Long> getQueueStartTs() { | 489 | private ListenableFuture<Long> getQueueStartTs() { |
@@ -424,52 +496,14 @@ public final class EdgeGrpcSession implements Closeable { | @@ -424,52 +496,14 @@ public final class EdgeGrpcSession implements Closeable { | ||
424 | } else { | 496 | } else { |
425 | return 0L; | 497 | return 0L; |
426 | } | 498 | } |
427 | - }, ctx.getDbCallbackExecutor()); | 499 | + }, ctx.getGrpcCallbackExecutorService()); |
428 | } | 500 | } |
429 | 501 | ||
430 | - private void updateQueueStartTs(Long newStartTs) { | 502 | + private ListenableFuture<List<Void>> updateQueueStartTs(Long newStartTs) { |
431 | log.trace("[{}] updating QueueStartTs [{}][{}]", this.sessionId, edge.getId(), newStartTs); | 503 | log.trace("[{}] updating QueueStartTs [{}][{}]", this.sessionId, edge.getId(), newStartTs); |
432 | newStartTs = ++newStartTs; // increments ts by 1 - next edge event search starts from current offset + 1 | 504 | newStartTs = ++newStartTs; // increments ts by 1 - next edge event search starts from current offset + 1 |
433 | List<AttributeKvEntry> attributes = Collections.singletonList(new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_TS_ATTR_KEY, newStartTs), System.currentTimeMillis())); | 505 | List<AttributeKvEntry> attributes = Collections.singletonList(new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_TS_ATTR_KEY, newStartTs), System.currentTimeMillis())); |
434 | - ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); | ||
435 | - } | ||
436 | - | ||
437 | - private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) { | ||
438 | - log.trace("[{}] Executing processTelemetryMessage, edgeEvent [{}]", this.sessionId, edgeEvent); | ||
439 | - EntityId entityId = null; | ||
440 | - switch (edgeEvent.getType()) { | ||
441 | - case DEVICE: | ||
442 | - entityId = new DeviceId(edgeEvent.getEntityId()); | ||
443 | - break; | ||
444 | - case ASSET: | ||
445 | - entityId = new AssetId(edgeEvent.getEntityId()); | ||
446 | - break; | ||
447 | - case ENTITY_VIEW: | ||
448 | - entityId = new EntityViewId(edgeEvent.getEntityId()); | ||
449 | - break; | ||
450 | - case DASHBOARD: | ||
451 | - entityId = new DashboardId(edgeEvent.getEntityId()); | ||
452 | - break; | ||
453 | - case TENANT: | ||
454 | - entityId = new TenantId(edgeEvent.getEntityId()); | ||
455 | - break; | ||
456 | - case CUSTOMER: | ||
457 | - entityId = new CustomerId(edgeEvent.getEntityId()); | ||
458 | - break; | ||
459 | - case EDGE: | ||
460 | - entityId = new EdgeId(edgeEvent.getEntityId()); | ||
461 | - break; | ||
462 | - } | ||
463 | - DownlinkMsg downlinkMsg = null; | ||
464 | - if (entityId != null) { | ||
465 | - log.debug("[{}] Sending telemetry data msg, entityId [{}], body [{}]", this.sessionId, edgeEvent.getEntityId(), edgeEvent.getBody()); | ||
466 | - try { | ||
467 | - downlinkMsg = constructEntityDataProtoMsg(entityId, edgeEvent.getAction(), JsonUtils.parse(mapper.writeValueAsString(edgeEvent.getBody()))); | ||
468 | - } catch (Exception e) { | ||
469 | - log.warn("[{}] Can't send telemetry data msg, entityId [{}], body [{}]", this.sessionId, edgeEvent.getEntityId(), edgeEvent.getBody(), e); | ||
470 | - } | ||
471 | - } | ||
472 | - return downlinkMsg; | 506 | + return ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); |
473 | } | 507 | } |
474 | 508 | ||
475 | private DownlinkMsg processEntityMessage(EdgeEvent edgeEvent, EdgeEventActionType action) { | 509 | private DownlinkMsg processEntityMessage(EdgeEvent edgeEvent, EdgeEventActionType action) { |
@@ -477,411 +511,39 @@ public final class EdgeGrpcSession implements Closeable { | @@ -477,411 +511,39 @@ public final class EdgeGrpcSession implements Closeable { | ||
477 | log.trace("Executing processEntityMessage, edgeEvent [{}], action [{}], msgType [{}]", edgeEvent, action, msgType); | 511 | log.trace("Executing processEntityMessage, edgeEvent [{}], action [{}], msgType [{}]", edgeEvent, action, msgType); |
478 | switch (edgeEvent.getType()) { | 512 | switch (edgeEvent.getType()) { |
479 | case DEVICE: | 513 | case DEVICE: |
480 | - return processDevice(edgeEvent, msgType, action); | 514 | + return ctx.getDeviceProcessor().processDeviceToEdge(edge, edgeEvent, msgType, action); |
481 | case DEVICE_PROFILE: | 515 | case DEVICE_PROFILE: |
482 | - return processDeviceProfile(edgeEvent, msgType, action); | 516 | + return ctx.getDeviceProfileProcessor().processDeviceProfileToEdge(edgeEvent, msgType, action); |
483 | case ASSET: | 517 | case ASSET: |
484 | - return processAsset(edgeEvent, msgType, action); | 518 | + return ctx.getAssetProcessor().processAssetToEdge(edge, edgeEvent, msgType, action); |
485 | case ENTITY_VIEW: | 519 | case ENTITY_VIEW: |
486 | - return processEntityView(edgeEvent, msgType, action); | 520 | + return ctx.getEntityViewProcessor().processEntityViewToEdge(edge, edgeEvent, msgType, action); |
487 | case DASHBOARD: | 521 | case DASHBOARD: |
488 | - return processDashboard(edgeEvent, msgType, action); | 522 | + return ctx.getDashboardProcessor().processDashboardToEdge(edge, edgeEvent, msgType, action); |
489 | case CUSTOMER: | 523 | case CUSTOMER: |
490 | - return processCustomer(edgeEvent, msgType, action); | 524 | + return ctx.getCustomerProcessor().processCustomerToEdge(edgeEvent, msgType, action); |
491 | case RULE_CHAIN: | 525 | case RULE_CHAIN: |
492 | - return processRuleChain(edgeEvent, msgType, action); | 526 | + return ctx.getRuleChainProcessor().processRuleChainToEdge(edge, edgeEvent, msgType, action); |
493 | case RULE_CHAIN_METADATA: | 527 | case RULE_CHAIN_METADATA: |
494 | - return processRuleChainMetadata(edgeEvent, msgType); | 528 | + return ctx.getRuleChainProcessor().processRuleChainMetadataToEdge(edgeEvent, msgType); |
495 | case ALARM: | 529 | case ALARM: |
496 | - return processAlarm(edgeEvent, msgType); | 530 | + return ctx.getAlarmProcessor().processAlarmToEdge(edge, edgeEvent, msgType); |
497 | case USER: | 531 | case USER: |
498 | - return processUser(edgeEvent, msgType, action); | 532 | + return ctx.getUserProcessor().processUserToEdge(edge, edgeEvent, msgType, action); |
499 | case RELATION: | 533 | case RELATION: |
500 | - return processRelation(edgeEvent, msgType); | 534 | + return ctx.getRelationProcessor().processRelationToEdge(edgeEvent, msgType); |
501 | case WIDGETS_BUNDLE: | 535 | case WIDGETS_BUNDLE: |
502 | - return processWidgetsBundle(edgeEvent, msgType, action); | 536 | + return ctx.getWidgetBundleProcessor().processWidgetsBundleToEdge(edgeEvent, msgType, action); |
503 | case WIDGET_TYPE: | 537 | case WIDGET_TYPE: |
504 | - return processWidgetType(edgeEvent, msgType, action); | 538 | + return ctx.getWidgetTypeProcessor().processWidgetTypeToEdge(edgeEvent, msgType, action); |
505 | case ADMIN_SETTINGS: | 539 | case ADMIN_SETTINGS: |
506 | - return processAdminSettings(edgeEvent); | 540 | + return ctx.getAdminSettingsProcessor().processAdminSettingsToEdge(edgeEvent); |
507 | default: | 541 | default: |
508 | log.warn("Unsupported edge event type [{}]", edgeEvent); | 542 | log.warn("Unsupported edge event type [{}]", edgeEvent); |
509 | return null; | 543 | return null; |
510 | } | 544 | } |
511 | } | 545 | } |
512 | 546 | ||
513 | - private DownlinkMsg processDevice(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType edgeEdgeEventActionType) { | ||
514 | - DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); | ||
515 | - DownlinkMsg downlinkMsg = null; | ||
516 | - switch (edgeEdgeEventActionType) { | ||
517 | - case ADDED: | ||
518 | - case UPDATED: | ||
519 | - case ASSIGNED_TO_EDGE: | ||
520 | - case ASSIGNED_TO_CUSTOMER: | ||
521 | - case UNASSIGNED_FROM_CUSTOMER: | ||
522 | - Device device = ctx.getDeviceService().findDeviceById(edgeEvent.getTenantId(), deviceId); | ||
523 | - if (device != null) { | ||
524 | - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); | ||
525 | - DeviceUpdateMsg deviceUpdateMsg = | ||
526 | - ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId, null); | ||
527 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
528 | - .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) | ||
529 | - .build(); | ||
530 | - } | ||
531 | - break; | ||
532 | - case DELETED: | ||
533 | - case UNASSIGNED_FROM_EDGE: | ||
534 | - DeviceUpdateMsg deviceUpdateMsg = | ||
535 | - ctx.getDeviceMsgConstructor().constructDeviceDeleteMsg(deviceId); | ||
536 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
537 | - .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) | ||
538 | - .build(); | ||
539 | - break; | ||
540 | - case CREDENTIALS_UPDATED: | ||
541 | - DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId); | ||
542 | - if (deviceCredentials != null) { | ||
543 | - DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = | ||
544 | - ctx.getDeviceMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials); | ||
545 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
546 | - .addAllDeviceCredentialsUpdateMsg(Collections.singletonList(deviceCredentialsUpdateMsg)) | ||
547 | - .build(); | ||
548 | - } | ||
549 | - break; | ||
550 | - } | ||
551 | - log.trace("[{}] device processed [{}]", this.sessionId, downlinkMsg); | ||
552 | - return downlinkMsg; | ||
553 | - } | ||
554 | - | ||
555 | - private DownlinkMsg processDeviceProfile(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | ||
556 | - DeviceProfileId deviceProfileId = new DeviceProfileId(edgeEvent.getEntityId()); | ||
557 | - DownlinkMsg downlinkMsg = null; | ||
558 | - switch (action) { | ||
559 | - case ADDED: | ||
560 | - case UPDATED: | ||
561 | - DeviceProfile deviceProfile = ctx.getDeviceProfileService().findDeviceProfileById(edgeEvent.getTenantId(), deviceProfileId); | ||
562 | - if (deviceProfile != null) { | ||
563 | - DeviceProfileUpdateMsg deviceProfileUpdateMsg = | ||
564 | - ctx.getDeviceProfileMsgConstructor().constructDeviceProfileUpdatedMsg(msgType, deviceProfile); | ||
565 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
566 | - .addAllDeviceProfileUpdateMsg(Collections.singletonList(deviceProfileUpdateMsg)) | ||
567 | - .build(); | ||
568 | - } | ||
569 | - break; | ||
570 | - case DELETED: | ||
571 | - DeviceProfileUpdateMsg deviceProfileUpdateMsg = | ||
572 | - ctx.getDeviceProfileMsgConstructor().constructDeviceProfileDeleteMsg(deviceProfileId); | ||
573 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
574 | - .addAllDeviceProfileUpdateMsg(Collections.singletonList(deviceProfileUpdateMsg)) | ||
575 | - .build(); | ||
576 | - break; | ||
577 | - } | ||
578 | - log.trace("[{}] device profile processed [{}]", this.sessionId, downlinkMsg); | ||
579 | - return downlinkMsg; | ||
580 | - } | ||
581 | - | ||
582 | - private DownlinkMsg processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | ||
583 | - AssetId assetId = new AssetId(edgeEvent.getEntityId()); | ||
584 | - DownlinkMsg downlinkMsg = null; | ||
585 | - switch (action) { | ||
586 | - case ADDED: | ||
587 | - case UPDATED: | ||
588 | - case ASSIGNED_TO_EDGE: | ||
589 | - case ASSIGNED_TO_CUSTOMER: | ||
590 | - case UNASSIGNED_FROM_CUSTOMER: | ||
591 | - Asset asset = ctx.getAssetService().findAssetById(edgeEvent.getTenantId(), assetId); | ||
592 | - if (asset != null) { | ||
593 | - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(asset); | ||
594 | - AssetUpdateMsg assetUpdateMsg = | ||
595 | - ctx.getAssetMsgConstructor().constructAssetUpdatedMsg(msgType, asset, customerId); | ||
596 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
597 | - .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) | ||
598 | - .build(); | ||
599 | - } | ||
600 | - break; | ||
601 | - case DELETED: | ||
602 | - case UNASSIGNED_FROM_EDGE: | ||
603 | - AssetUpdateMsg assetUpdateMsg = | ||
604 | - ctx.getAssetMsgConstructor().constructAssetDeleteMsg(assetId); | ||
605 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
606 | - .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) | ||
607 | - .build(); | ||
608 | - break; | ||
609 | - } | ||
610 | - log.trace("[{}] asset processed [{}]", this.sessionId, downlinkMsg); | ||
611 | - return downlinkMsg; | ||
612 | - } | ||
613 | - | ||
614 | - private DownlinkMsg processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | ||
615 | - EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId()); | ||
616 | - DownlinkMsg downlinkMsg = null; | ||
617 | - switch (action) { | ||
618 | - case ADDED: | ||
619 | - case UPDATED: | ||
620 | - case ASSIGNED_TO_EDGE: | ||
621 | - case ASSIGNED_TO_CUSTOMER: | ||
622 | - case UNASSIGNED_FROM_CUSTOMER: | ||
623 | - EntityView entityView = ctx.getEntityViewService().findEntityViewById(edgeEvent.getTenantId(), entityViewId); | ||
624 | - if (entityView != null) { | ||
625 | - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(entityView); | ||
626 | - EntityViewUpdateMsg entityViewUpdateMsg = | ||
627 | - ctx.getEntityViewMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView, customerId); | ||
628 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
629 | - .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) | ||
630 | - .build(); | ||
631 | - } | ||
632 | - break; | ||
633 | - case DELETED: | ||
634 | - case UNASSIGNED_FROM_EDGE: | ||
635 | - EntityViewUpdateMsg entityViewUpdateMsg = | ||
636 | - ctx.getEntityViewMsgConstructor().constructEntityViewDeleteMsg(entityViewId); | ||
637 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
638 | - .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) | ||
639 | - .build(); | ||
640 | - break; | ||
641 | - } | ||
642 | - log.trace("[{}] entity view processed [{}]", this.sessionId, downlinkMsg); | ||
643 | - return downlinkMsg; | ||
644 | - } | ||
645 | - | ||
646 | - private DownlinkMsg processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | ||
647 | - DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId()); | ||
648 | - DownlinkMsg downlinkMsg = null; | ||
649 | - switch (action) { | ||
650 | - case ADDED: | ||
651 | - case UPDATED: | ||
652 | - case ASSIGNED_TO_EDGE: | ||
653 | - case ASSIGNED_TO_CUSTOMER: | ||
654 | - case UNASSIGNED_FROM_CUSTOMER: | ||
655 | - Dashboard dashboard = ctx.getDashboardService().findDashboardById(edgeEvent.getTenantId(), dashboardId); | ||
656 | - if (dashboard != null) { | ||
657 | - CustomerId customerId = null; | ||
658 | - if (!edge.getCustomerId().isNullUid() && dashboard.isAssignedToCustomer(edge.getCustomerId())) { | ||
659 | - customerId = edge.getCustomerId(); | ||
660 | - } | ||
661 | - DashboardUpdateMsg dashboardUpdateMsg = | ||
662 | - ctx.getDashboardMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard, customerId); | ||
663 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
664 | - .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) | ||
665 | - .build(); | ||
666 | - } | ||
667 | - break; | ||
668 | - case DELETED: | ||
669 | - case UNASSIGNED_FROM_EDGE: | ||
670 | - DashboardUpdateMsg dashboardUpdateMsg = | ||
671 | - ctx.getDashboardMsgConstructor().constructDashboardDeleteMsg(dashboardId); | ||
672 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
673 | - .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) | ||
674 | - .build(); | ||
675 | - break; | ||
676 | - } | ||
677 | - log.trace("[{}] dashboard processed [{}]", this.sessionId, downlinkMsg); | ||
678 | - return downlinkMsg; | ||
679 | - } | ||
680 | - | ||
681 | - private DownlinkMsg processCustomer(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | ||
682 | - CustomerId customerId = new CustomerId(edgeEvent.getEntityId()); | ||
683 | - DownlinkMsg downlinkMsg = null; | ||
684 | - switch (action) { | ||
685 | - case ADDED: | ||
686 | - case UPDATED: | ||
687 | - Customer customer = ctx.getCustomerService().findCustomerById(edgeEvent.getTenantId(), customerId); | ||
688 | - if (customer != null) { | ||
689 | - CustomerUpdateMsg customerUpdateMsg = | ||
690 | - ctx.getCustomerMsgConstructor().constructCustomerUpdatedMsg(msgType, customer); | ||
691 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
692 | - .addAllCustomerUpdateMsg(Collections.singletonList(customerUpdateMsg)) | ||
693 | - .build(); | ||
694 | - } | ||
695 | - break; | ||
696 | - case DELETED: | ||
697 | - CustomerUpdateMsg customerUpdateMsg = | ||
698 | - ctx.getCustomerMsgConstructor().constructCustomerDeleteMsg(customerId); | ||
699 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
700 | - .addAllCustomerUpdateMsg(Collections.singletonList(customerUpdateMsg)) | ||
701 | - .build(); | ||
702 | - break; | ||
703 | - } | ||
704 | - log.trace("[{}] customer processed [{}]", this.sessionId, downlinkMsg); | ||
705 | - return downlinkMsg; | ||
706 | - } | ||
707 | - | ||
708 | - private DownlinkMsg processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType action) { | ||
709 | - RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); | ||
710 | - DownlinkMsg downlinkMsg = null; | ||
711 | - switch (action) { | ||
712 | - case ADDED: | ||
713 | - case UPDATED: | ||
714 | - case ASSIGNED_TO_EDGE: | ||
715 | - RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); | ||
716 | - if (ruleChain != null) { | ||
717 | - RuleChainUpdateMsg ruleChainUpdateMsg = | ||
718 | - ctx.getRuleChainMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); | ||
719 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
720 | - .addAllRuleChainUpdateMsg(Collections.singletonList(ruleChainUpdateMsg)) | ||
721 | - .build(); | ||
722 | - } | ||
723 | - break; | ||
724 | - case DELETED: | ||
725 | - case UNASSIGNED_FROM_EDGE: | ||
726 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
727 | - .addAllRuleChainUpdateMsg(Collections.singletonList(ctx.getRuleChainMsgConstructor().constructRuleChainDeleteMsg(ruleChainId))) | ||
728 | - .build(); | ||
729 | - break; | ||
730 | - } | ||
731 | - log.trace("[{}] rule chain processed [{}]", this.sessionId, downlinkMsg); | ||
732 | - return downlinkMsg; | ||
733 | - } | ||
734 | - | ||
735 | - private DownlinkMsg processRuleChainMetadata(EdgeEvent edgeEvent, UpdateMsgType msgType) { | ||
736 | - RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); | ||
737 | - RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); | ||
738 | - DownlinkMsg downlinkMsg = null; | ||
739 | - if (ruleChain != null) { | ||
740 | - RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId); | ||
741 | - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = | ||
742 | - ctx.getRuleChainMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData); | ||
743 | - if (ruleChainMetadataUpdateMsg != null) { | ||
744 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
745 | - .addAllRuleChainMetadataUpdateMsg(Collections.singletonList(ruleChainMetadataUpdateMsg)) | ||
746 | - .build(); | ||
747 | - } | ||
748 | - } | ||
749 | - log.trace("[{}] rule chain metadata processed [{}]", this.sessionId, downlinkMsg); | ||
750 | - return downlinkMsg; | ||
751 | - } | ||
752 | - | ||
753 | - private DownlinkMsg processUser(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType edgeEdgeEventActionType) { | ||
754 | - UserId userId = new UserId(edgeEvent.getEntityId()); | ||
755 | - DownlinkMsg downlinkMsg = null; | ||
756 | - switch (edgeEdgeEventActionType) { | ||
757 | - case ADDED: | ||
758 | - case UPDATED: | ||
759 | - User user = ctx.getUserService().findUserById(edgeEvent.getTenantId(), userId); | ||
760 | - if (user != null) { | ||
761 | - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(user); | ||
762 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
763 | - .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserMsgConstructor().constructUserUpdatedMsg(msgType, user, customerId))) | ||
764 | - .build(); | ||
765 | - } | ||
766 | - break; | ||
767 | - case DELETED: | ||
768 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
769 | - .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserMsgConstructor().constructUserDeleteMsg(userId))) | ||
770 | - .build(); | ||
771 | - break; | ||
772 | - case CREDENTIALS_UPDATED: | ||
773 | - UserCredentials userCredentialsByUserId = ctx.getUserService().findUserCredentialsByUserId(edge.getTenantId(), userId); | ||
774 | - if (userCredentialsByUserId != null && userCredentialsByUserId.isEnabled()) { | ||
775 | - UserCredentialsUpdateMsg userCredentialsUpdateMsg = | ||
776 | - ctx.getUserMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); | ||
777 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
778 | - .addAllUserCredentialsUpdateMsg(Collections.singletonList(userCredentialsUpdateMsg)) | ||
779 | - .build(); | ||
780 | - } | ||
781 | - } | ||
782 | - log.trace("[{}] user processed [{}]", this.sessionId, downlinkMsg); | ||
783 | - return downlinkMsg; | ||
784 | - } | ||
785 | - | ||
786 | - private CustomerId getCustomerIdIfEdgeAssignedToCustomer(HasCustomerId hasCustomerIdEntity) { | ||
787 | - if (!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(hasCustomerIdEntity.getCustomerId())) { | ||
788 | - return edge.getCustomerId(); | ||
789 | - } else { | ||
790 | - return null; | ||
791 | - } | ||
792 | - } | ||
793 | - | ||
794 | - private DownlinkMsg processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { | ||
795 | - EntityRelation entityRelation = mapper.convertValue(edgeEvent.getBody(), EntityRelation.class); | ||
796 | - RelationUpdateMsg r = ctx.getRelationMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation); | ||
797 | - DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() | ||
798 | - .addAllRelationUpdateMsg(Collections.singletonList(r)) | ||
799 | - .build(); | ||
800 | - log.trace("[{}] relation processed [{}]", this.sessionId, downlinkMsg); | ||
801 | - return downlinkMsg; | ||
802 | - } | ||
803 | - | ||
804 | - private DownlinkMsg processAlarm(EdgeEvent edgeEvent, UpdateMsgType msgType) { | ||
805 | - DownlinkMsg downlinkMsg = null; | ||
806 | - try { | ||
807 | - AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); | ||
808 | - Alarm alarm = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); | ||
809 | - if (alarm != null) { | ||
810 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
811 | - .addAllAlarmUpdateMsg(Collections.singletonList(ctx.getAlarmMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm))) | ||
812 | - .build(); | ||
813 | - } | ||
814 | - } catch (Exception e) { | ||
815 | - log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e); | ||
816 | - } | ||
817 | - log.trace("[{}] alarm processed [{}]", this.sessionId, downlinkMsg); | ||
818 | - return downlinkMsg; | ||
819 | - } | ||
820 | - | ||
821 | - private DownlinkMsg processWidgetsBundle(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType edgeEdgeEventActionType) { | ||
822 | - WidgetsBundleId widgetsBundleId = new WidgetsBundleId(edgeEvent.getEntityId()); | ||
823 | - DownlinkMsg downlinkMsg = null; | ||
824 | - switch (edgeEdgeEventActionType) { | ||
825 | - case ADDED: | ||
826 | - case UPDATED: | ||
827 | - WidgetsBundle widgetsBundle = ctx.getWidgetsBundleService().findWidgetsBundleById(edgeEvent.getTenantId(), widgetsBundleId); | ||
828 | - if (widgetsBundle != null) { | ||
829 | - WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = | ||
830 | - ctx.getWidgetsBundleMsgConstructor().constructWidgetsBundleUpdateMsg(msgType, widgetsBundle); | ||
831 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
832 | - .addAllWidgetsBundleUpdateMsg(Collections.singletonList(widgetsBundleUpdateMsg)) | ||
833 | - .build(); | ||
834 | - } | ||
835 | - break; | ||
836 | - case DELETED: | ||
837 | - WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = | ||
838 | - ctx.getWidgetsBundleMsgConstructor().constructWidgetsBundleDeleteMsg(widgetsBundleId); | ||
839 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
840 | - .addAllWidgetsBundleUpdateMsg(Collections.singletonList(widgetsBundleUpdateMsg)) | ||
841 | - .build(); | ||
842 | - break; | ||
843 | - } | ||
844 | - log.trace("[{}] widget bundle processed [{}]", this.sessionId, downlinkMsg); | ||
845 | - return downlinkMsg; | ||
846 | - } | ||
847 | - | ||
848 | - private DownlinkMsg processWidgetType(EdgeEvent edgeEvent, UpdateMsgType msgType, EdgeEventActionType edgeEdgeEventActionType) { | ||
849 | - WidgetTypeId widgetTypeId = new WidgetTypeId(edgeEvent.getEntityId()); | ||
850 | - DownlinkMsg downlinkMsg = null; | ||
851 | - switch (edgeEdgeEventActionType) { | ||
852 | - case ADDED: | ||
853 | - case UPDATED: | ||
854 | - WidgetType widgetType = ctx.getWidgetTypeService().findWidgetTypeById(edgeEvent.getTenantId(), widgetTypeId); | ||
855 | - if (widgetType != null) { | ||
856 | - WidgetTypeUpdateMsg widgetTypeUpdateMsg = | ||
857 | - ctx.getWidgetTypeMsgConstructor().constructWidgetTypeUpdateMsg(msgType, widgetType); | ||
858 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
859 | - .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) | ||
860 | - .build(); | ||
861 | - } | ||
862 | - break; | ||
863 | - case DELETED: | ||
864 | - WidgetTypeUpdateMsg widgetTypeUpdateMsg = | ||
865 | - ctx.getWidgetTypeMsgConstructor().constructWidgetTypeDeleteMsg(widgetTypeId); | ||
866 | - downlinkMsg = DownlinkMsg.newBuilder() | ||
867 | - .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) | ||
868 | - .build(); | ||
869 | - break; | ||
870 | - } | ||
871 | - log.trace("[{}] widget type processed [{}]", this.sessionId, downlinkMsg); | ||
872 | - return downlinkMsg; | ||
873 | - } | ||
874 | - | ||
875 | - private DownlinkMsg processAdminSettings(EdgeEvent edgeEvent) { | ||
876 | - AdminSettings adminSettings = mapper.convertValue(edgeEvent.getBody(), AdminSettings.class); | ||
877 | - AdminSettingsUpdateMsg t = ctx.getAdminSettingsMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings); | ||
878 | - DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() | ||
879 | - .addAllAdminSettingsUpdateMsg(Collections.singletonList(t)) | ||
880 | - .build(); | ||
881 | - log.trace("[{}] admin settings processed [{}]", this.sessionId, downlinkMsg); | ||
882 | - return downlinkMsg; | ||
883 | - } | ||
884 | - | ||
885 | private UpdateMsgType getResponseMsgType(EdgeEventActionType actionType) { | 547 | private UpdateMsgType getResponseMsgType(EdgeEventActionType actionType) { |
886 | switch (actionType) { | 548 | switch (actionType) { |
887 | case UPDATED: | 549 | case UPDATED: |
@@ -906,71 +568,77 @@ public final class EdgeGrpcSession implements Closeable { | @@ -906,71 +568,77 @@ public final class EdgeGrpcSession implements Closeable { | ||
906 | } | 568 | } |
907 | } | 569 | } |
908 | 570 | ||
909 | - private DownlinkMsg constructEntityDataProtoMsg(EntityId entityId, EdgeEventActionType actionType, JsonElement entityData) { | ||
910 | - EntityDataProto entityDataProto = ctx.getEntityDataMsgConstructor().constructEntityDataMsg(entityId, actionType, entityData); | ||
911 | - DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() | ||
912 | - .addAllEntityData(Collections.singletonList(entityDataProto)) | ||
913 | - .build(); | ||
914 | - log.trace("[{}] entity data proto processed [{}]", this.sessionId, downlinkMsg); | ||
915 | - return downlinkMsg; | ||
916 | - } | ||
917 | - | ||
918 | private ListenableFuture<List<Void>> processUplinkMsg(UplinkMsg uplinkMsg) { | 571 | private ListenableFuture<List<Void>> processUplinkMsg(UplinkMsg uplinkMsg) { |
919 | List<ListenableFuture<Void>> result = new ArrayList<>(); | 572 | List<ListenableFuture<Void>> result = new ArrayList<>(); |
920 | try { | 573 | try { |
921 | if (uplinkMsg.getEntityDataCount() > 0) { | 574 | if (uplinkMsg.getEntityDataCount() > 0) { |
922 | for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) { | 575 | for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) { |
923 | - result.addAll(ctx.getTelemetryProcessor().onTelemetryUpdate(edge.getTenantId(), edge.getCustomerId(), entityData)); | 576 | + result.addAll(ctx.getTelemetryProcessor().processTelemetryFromEdge(edge.getTenantId(), edge.getCustomerId(), entityData)); |
924 | } | 577 | } |
925 | } | 578 | } |
926 | if (uplinkMsg.getDeviceUpdateMsgCount() > 0) { | 579 | if (uplinkMsg.getDeviceUpdateMsgCount() > 0) { |
927 | for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { | 580 | for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { |
928 | - result.add(ctx.getDeviceProcessor().onDeviceUpdate(edge.getTenantId(), edge, deviceUpdateMsg)); | 581 | + result.add(ctx.getDeviceProcessor().processDeviceFromEdge(edge.getTenantId(), edge, deviceUpdateMsg)); |
929 | } | 582 | } |
930 | } | 583 | } |
931 | if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) { | 584 | if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) { |
932 | for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { | 585 | for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { |
933 | - result.add(ctx.getDeviceProcessor().onDeviceCredentialsUpdate(edge.getTenantId(), deviceCredentialsUpdateMsg)); | 586 | + result.add(ctx.getDeviceProcessor().processDeviceCredentialsFromEdge(edge.getTenantId(), deviceCredentialsUpdateMsg)); |
934 | } | 587 | } |
935 | } | 588 | } |
936 | if (uplinkMsg.getAlarmUpdateMsgCount() > 0) { | 589 | if (uplinkMsg.getAlarmUpdateMsgCount() > 0) { |
937 | for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { | 590 | for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { |
938 | - result.add(ctx.getAlarmProcessor().onAlarmUpdate(edge.getTenantId(), alarmUpdateMsg)); | 591 | + result.add(ctx.getAlarmProcessor().processAlarmFromEdge(edge.getTenantId(), alarmUpdateMsg)); |
939 | } | 592 | } |
940 | } | 593 | } |
941 | if (uplinkMsg.getRelationUpdateMsgCount() > 0) { | 594 | if (uplinkMsg.getRelationUpdateMsgCount() > 0) { |
942 | for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) { | 595 | for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) { |
943 | - result.add(ctx.getRelationProcessor().onRelationUpdate(edge.getTenantId(), relationUpdateMsg)); | 596 | + result.add(ctx.getRelationProcessor().processRelationFromEdge(edge.getTenantId(), relationUpdateMsg)); |
944 | } | 597 | } |
945 | } | 598 | } |
946 | if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) { | 599 | if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) { |
947 | for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { | 600 | for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { |
948 | - result.add(ctx.getSyncEdgeService().processRuleChainMetadataRequestMsg(edge.getTenantId(), edge, ruleChainMetadataRequestMsg)); | 601 | + result.add(ctx.getEdgeRequestsService().processRuleChainMetadataRequestMsg(edge.getTenantId(), edge, ruleChainMetadataRequestMsg)); |
949 | } | 602 | } |
950 | } | 603 | } |
951 | if (uplinkMsg.getAttributesRequestMsgCount() > 0) { | 604 | if (uplinkMsg.getAttributesRequestMsgCount() > 0) { |
952 | for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { | 605 | for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { |
953 | - result.add(ctx.getSyncEdgeService().processAttributesRequestMsg(edge.getTenantId(), edge, attributesRequestMsg)); | 606 | + result.add(ctx.getEdgeRequestsService().processAttributesRequestMsg(edge.getTenantId(), edge, attributesRequestMsg)); |
954 | } | 607 | } |
955 | } | 608 | } |
956 | if (uplinkMsg.getRelationRequestMsgCount() > 0) { | 609 | if (uplinkMsg.getRelationRequestMsgCount() > 0) { |
957 | for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { | 610 | for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { |
958 | - result.add(ctx.getSyncEdgeService().processRelationRequestMsg(edge.getTenantId(), edge, relationRequestMsg)); | 611 | + result.add(ctx.getEdgeRequestsService().processRelationRequestMsg(edge.getTenantId(), edge, relationRequestMsg)); |
959 | } | 612 | } |
960 | } | 613 | } |
961 | if (uplinkMsg.getUserCredentialsRequestMsgCount() > 0) { | 614 | if (uplinkMsg.getUserCredentialsRequestMsgCount() > 0) { |
962 | for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { | 615 | for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { |
963 | - result.add(ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge.getTenantId(), edge, userCredentialsRequestMsg)); | 616 | + result.add(ctx.getEdgeRequestsService().processUserCredentialsRequestMsg(edge.getTenantId(), edge, userCredentialsRequestMsg)); |
964 | } | 617 | } |
965 | } | 618 | } |
966 | if (uplinkMsg.getDeviceCredentialsRequestMsgCount() > 0) { | 619 | if (uplinkMsg.getDeviceCredentialsRequestMsgCount() > 0) { |
967 | for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { | 620 | for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { |
968 | - result.add(ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge.getTenantId(), edge, deviceCredentialsRequestMsg)); | 621 | + result.add(ctx.getEdgeRequestsService().processDeviceCredentialsRequestMsg(edge.getTenantId(), edge, deviceCredentialsRequestMsg)); |
969 | } | 622 | } |
970 | } | 623 | } |
971 | if (uplinkMsg.getDeviceRpcCallMsgCount() > 0) { | 624 | if (uplinkMsg.getDeviceRpcCallMsgCount() > 0) { |
972 | for (DeviceRpcCallMsg deviceRpcCallMsg : uplinkMsg.getDeviceRpcCallMsgList()) { | 625 | for (DeviceRpcCallMsg deviceRpcCallMsg : uplinkMsg.getDeviceRpcCallMsgList()) { |
973 | - result.add(ctx.getDeviceProcessor().processDeviceRpcCallResponseMsg(edge.getTenantId(), deviceRpcCallMsg)); | 626 | + result.add(ctx.getDeviceProcessor().processDeviceRpcCallResponseFromEdge(edge.getTenantId(), deviceRpcCallMsg)); |
627 | + } | ||
628 | + } | ||
629 | + if (uplinkMsg.getDeviceProfileDevicesRequestMsgCount() > 0) { | ||
630 | + for (DeviceProfileDevicesRequestMsg deviceProfileDevicesRequestMsg : uplinkMsg.getDeviceProfileDevicesRequestMsgList()) { | ||
631 | + result.add(ctx.getEdgeRequestsService().processDeviceProfileDevicesRequestMsg(edge.getTenantId(), edge, deviceProfileDevicesRequestMsg)); | ||
632 | + } | ||
633 | + } | ||
634 | + if (uplinkMsg.getWidgetBundleTypesRequestMsgCount() > 0) { | ||
635 | + for (WidgetBundleTypesRequestMsg widgetBundleTypesRequestMsg : uplinkMsg.getWidgetBundleTypesRequestMsgList()) { | ||
636 | + result.add(ctx.getEdgeRequestsService().processWidgetBundleTypesRequestMsg(edge.getTenantId(), edge, widgetBundleTypesRequestMsg)); | ||
637 | + } | ||
638 | + } | ||
639 | + if (uplinkMsg.getEntityViewsRequestMsgCount() > 0) { | ||
640 | + for (EntityViewsRequestMsg entityViewRequestMsg : uplinkMsg.getEntityViewsRequestMsgList()) { | ||
641 | + result.add(ctx.getEdgeRequestsService().processEntityViewsRequestMsg(edge.getTenantId(), edge, entityViewRequestMsg)); | ||
974 | } | 642 | } |
975 | } | 643 | } |
976 | } catch (Exception e) { | 644 | } catch (Exception e) { |
@@ -1026,7 +694,7 @@ public final class EdgeGrpcSession implements Closeable { | @@ -1026,7 +694,7 @@ public final class EdgeGrpcSession implements Closeable { | ||
1026 | .setCloudType("CE"); | 694 | .setCloudType("CE"); |
1027 | if (edge.getCustomerId() != null) { | 695 | if (edge.getCustomerId() != null) { |
1028 | builder.setCustomerIdMSB(edge.getCustomerId().getId().getMostSignificantBits()) | 696 | builder.setCustomerIdMSB(edge.getCustomerId().getId().getMostSignificantBits()) |
1029 | - .setCustomerIdLSB(edge.getCustomerId().getId().getLeastSignificantBits()); | 697 | + .setCustomerIdLSB(edge.getCustomerId().getId().getLeastSignificantBits()); |
1030 | } | 698 | } |
1031 | return builder | 699 | return builder |
1032 | .build(); | 700 | .build(); |
@@ -17,12 +17,15 @@ package org.thingsboard.server.service.edge.rpc; | @@ -17,12 +17,15 @@ package org.thingsboard.server.service.edge.rpc; | ||
17 | 17 | ||
18 | import org.thingsboard.server.common.data.edge.Edge; | 18 | import org.thingsboard.server.common.data.edge.Edge; |
19 | import org.thingsboard.server.common.data.id.EdgeId; | 19 | import org.thingsboard.server.common.data.id.EdgeId; |
20 | +import org.thingsboard.server.common.data.id.TenantId; | ||
20 | 21 | ||
21 | public interface EdgeRpcService { | 22 | public interface EdgeRpcService { |
22 | 23 | ||
23 | - void updateEdge(Edge edge); | 24 | + void updateEdge(TenantId tenantId, Edge edge); |
24 | 25 | ||
25 | - void deleteEdge(EdgeId edgeId); | 26 | + void deleteEdge(TenantId tenantId, EdgeId edgeId); |
26 | 27 | ||
27 | - void onEdgeEvent(EdgeId edgeId); | 28 | + void onEdgeEvent(TenantId tenantId, EdgeId edgeId); |
29 | + | ||
30 | + void startSyncProcess(TenantId tenantId, EdgeId edgeId); | ||
28 | } | 31 | } |
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.common.util.concurrent.SettableFuture; | ||
19 | +import lombok.Data; | ||
20 | +import org.thingsboard.server.gen.edge.v1.DownlinkMsg; | ||
21 | + | ||
22 | +import java.util.LinkedHashMap; | ||
23 | +import java.util.Map; | ||
24 | +import java.util.concurrent.ScheduledFuture; | ||
25 | + | ||
26 | +@Data | ||
27 | +public class EdgeSessionState { | ||
28 | + | ||
29 | + private final Map<Integer, DownlinkMsg> pendingMsgsMap = new LinkedHashMap<>(); | ||
30 | + private SettableFuture<Void> sendDownlinkMsgsFuture; | ||
31 | + private ScheduledFuture<?> scheduledSendDownlinkTask; | ||
32 | +} |
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 org.thingsboard.server.common.data.edge.Edge; | ||
19 | +import org.thingsboard.server.common.data.id.EntityId; | ||
20 | +import org.thingsboard.server.service.edge.EdgeContextComponent; | ||
21 | +import org.thingsboard.server.service.edge.rpc.fetch.AdminSettingsEdgeEventFetcher; | ||
22 | +import org.thingsboard.server.service.edge.rpc.fetch.AssetsEdgeEventFetcher; | ||
23 | +import org.thingsboard.server.service.edge.rpc.fetch.CustomerEdgeEventFetcher; | ||
24 | +import org.thingsboard.server.service.edge.rpc.fetch.CustomerUsersEdgeEventFetcher; | ||
25 | +import org.thingsboard.server.service.edge.rpc.fetch.DashboardsEdgeEventFetcher; | ||
26 | +import org.thingsboard.server.service.edge.rpc.fetch.DeviceProfilesEdgeEventFetcher; | ||
27 | +import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher; | ||
28 | +import org.thingsboard.server.service.edge.rpc.fetch.RuleChainsEdgeEventFetcher; | ||
29 | +import org.thingsboard.server.service.edge.rpc.fetch.SystemWidgetsBundlesEdgeEventFetcher; | ||
30 | +import org.thingsboard.server.service.edge.rpc.fetch.TenantAdminUsersEdgeEventFetcher; | ||
31 | +import org.thingsboard.server.service.edge.rpc.fetch.TenantWidgetsBundlesEdgeEventFetcher; | ||
32 | + | ||
33 | +import java.util.LinkedList; | ||
34 | +import java.util.List; | ||
35 | +import java.util.NoSuchElementException; | ||
36 | + | ||
37 | +public class EdgeSyncCursor { | ||
38 | + | ||
39 | + List<EdgeEventFetcher> fetchers = new LinkedList<>(); | ||
40 | + | ||
41 | + int currentIdx = 0; | ||
42 | + | ||
43 | + public EdgeSyncCursor(EdgeContextComponent ctx, Edge edge) { | ||
44 | + fetchers.add(new SystemWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService())); | ||
45 | + fetchers.add(new TenantWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService())); | ||
46 | + fetchers.add(new DeviceProfilesEdgeEventFetcher(ctx.getDeviceProfileService())); | ||
47 | + fetchers.add(new RuleChainsEdgeEventFetcher(ctx.getRuleChainService())); | ||
48 | + fetchers.add(new TenantAdminUsersEdgeEventFetcher(ctx.getUserService())); | ||
49 | + if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { | ||
50 | + fetchers.add(new CustomerEdgeEventFetcher()); | ||
51 | + fetchers.add(new CustomerUsersEdgeEventFetcher(ctx.getUserService(), edge.getCustomerId())); | ||
52 | + } | ||
53 | + fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService())); | ||
54 | + fetchers.add(new AssetsEdgeEventFetcher(ctx.getAssetService())); | ||
55 | + fetchers.add(new DashboardsEdgeEventFetcher(ctx.getDashboardService())); | ||
56 | + } | ||
57 | + | ||
58 | + public boolean hasNext() { | ||
59 | + return fetchers.size() > currentIdx; | ||
60 | + } | ||
61 | + | ||
62 | + public EdgeEventFetcher getNext() { | ||
63 | + if (!hasNext()) { | ||
64 | + throw new NoSuchElementException(); | ||
65 | + } | ||
66 | + EdgeEventFetcher edgeEventFetcher = fetchers.get(currentIdx); | ||
67 | + currentIdx++; | ||
68 | + return edgeEventFetcher; | ||
69 | + } | ||
70 | + | ||
71 | + public int getCurrentIdx() { | ||
72 | + return currentIdx; | ||
73 | + } | ||
74 | +} |
@@ -18,7 +18,7 @@ package org.thingsboard.server.service.edge.rpc.constructor; | @@ -18,7 +18,7 @@ package org.thingsboard.server.service.edge.rpc.constructor; | ||
18 | import org.springframework.stereotype.Component; | 18 | import org.springframework.stereotype.Component; |
19 | import org.thingsboard.server.common.data.AdminSettings; | 19 | import org.thingsboard.server.common.data.AdminSettings; |
20 | import org.thingsboard.common.util.JacksonUtil; | 20 | import org.thingsboard.common.util.JacksonUtil; |
21 | -import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; | 21 | +import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg; |
22 | import org.thingsboard.server.queue.util.TbCoreComponent; | 22 | import org.thingsboard.server.queue.util.TbCoreComponent; |
23 | 23 | ||
24 | @Component | 24 | @Component |
@@ -26,8 +26,8 @@ import org.thingsboard.server.dao.asset.AssetService; | @@ -26,8 +26,8 @@ import org.thingsboard.server.dao.asset.AssetService; | ||
26 | import org.thingsboard.server.dao.device.DeviceService; | 26 | import org.thingsboard.server.dao.device.DeviceService; |
27 | import org.thingsboard.server.dao.entityview.EntityViewService; | 27 | import org.thingsboard.server.dao.entityview.EntityViewService; |
28 | import org.thingsboard.common.util.JacksonUtil; | 28 | import org.thingsboard.common.util.JacksonUtil; |
29 | -import org.thingsboard.server.gen.edge.AlarmUpdateMsg; | ||
30 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 29 | +import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; |
30 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
31 | import org.thingsboard.server.queue.util.TbCoreComponent; | 31 | import org.thingsboard.server.queue.util.TbCoreComponent; |
32 | 32 | ||
33 | @Component | 33 | @Component |
@@ -20,8 +20,8 @@ import org.thingsboard.server.common.data.asset.Asset; | @@ -20,8 +20,8 @@ import org.thingsboard.server.common.data.asset.Asset; | ||
20 | import org.thingsboard.server.common.data.id.AssetId; | 20 | import org.thingsboard.server.common.data.id.AssetId; |
21 | import org.thingsboard.server.common.data.id.CustomerId; | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | import org.thingsboard.common.util.JacksonUtil; | 22 | import org.thingsboard.common.util.JacksonUtil; |
23 | -import org.thingsboard.server.gen.edge.AssetUpdateMsg; | ||
24 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 23 | +import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; |
24 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
25 | import org.thingsboard.server.queue.util.TbCoreComponent; | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | ||
27 | @Component | 27 | @Component |
@@ -19,8 +19,8 @@ import org.springframework.stereotype.Component; | @@ -19,8 +19,8 @@ import org.springframework.stereotype.Component; | ||
19 | import org.thingsboard.server.common.data.Customer; | 19 | import org.thingsboard.server.common.data.Customer; |
20 | import org.thingsboard.server.common.data.id.CustomerId; | 20 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | import org.thingsboard.common.util.JacksonUtil; | 21 | import org.thingsboard.common.util.JacksonUtil; |
22 | -import org.thingsboard.server.gen.edge.CustomerUpdateMsg; | ||
23 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 22 | +import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; |
23 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
24 | import org.thingsboard.server.queue.util.TbCoreComponent; | 24 | import org.thingsboard.server.queue.util.TbCoreComponent; |
25 | 25 | ||
26 | @Component | 26 | @Component |
@@ -20,8 +20,8 @@ import org.thingsboard.server.common.data.Dashboard; | @@ -20,8 +20,8 @@ import org.thingsboard.server.common.data.Dashboard; | ||
20 | import org.thingsboard.server.common.data.id.CustomerId; | 20 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | import org.thingsboard.server.common.data.id.DashboardId; | 21 | import org.thingsboard.server.common.data.id.DashboardId; |
22 | import org.thingsboard.common.util.JacksonUtil; | 22 | import org.thingsboard.common.util.JacksonUtil; |
23 | -import org.thingsboard.server.gen.edge.DashboardUpdateMsg; | ||
24 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 23 | +import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg; |
24 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
25 | import org.thingsboard.server.queue.util.TbCoreComponent; | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | ||
27 | @Component | 27 | @Component |
@@ -23,11 +23,11 @@ import org.thingsboard.server.common.data.Device; | @@ -23,11 +23,11 @@ import org.thingsboard.server.common.data.Device; | ||
23 | import org.thingsboard.server.common.data.id.CustomerId; | 23 | import org.thingsboard.server.common.data.id.CustomerId; |
24 | import org.thingsboard.server.common.data.id.DeviceId; | 24 | import org.thingsboard.server.common.data.id.DeviceId; |
25 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 25 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
26 | -import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; | ||
27 | -import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; | ||
28 | -import org.thingsboard.server.gen.edge.DeviceUpdateMsg; | ||
29 | -import org.thingsboard.server.gen.edge.RpcRequestMsg; | ||
30 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 26 | +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; |
27 | +import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg; | ||
28 | +import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; | ||
29 | +import org.thingsboard.server.gen.edge.v1.RpcRequestMsg; | ||
30 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
31 | import org.thingsboard.server.queue.util.TbCoreComponent; | 31 | import org.thingsboard.server.queue.util.TbCoreComponent; |
32 | 32 | ||
33 | import java.util.UUID; | 33 | import java.util.UUID; |
@@ -21,8 +21,8 @@ import org.springframework.stereotype.Component; | @@ -21,8 +21,8 @@ import org.springframework.stereotype.Component; | ||
21 | import org.thingsboard.server.common.data.DeviceProfile; | 21 | import org.thingsboard.server.common.data.DeviceProfile; |
22 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 22 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
23 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; | 23 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; |
24 | -import org.thingsboard.server.gen.edge.DeviceProfileUpdateMsg; | ||
25 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 24 | +import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; |
25 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
26 | import org.thingsboard.server.queue.util.TbCoreComponent; | 26 | import org.thingsboard.server.queue.util.TbCoreComponent; |
27 | 27 | ||
28 | @Component | 28 | @Component |
@@ -41,7 +41,7 @@ public class DeviceProfileMsgConstructor { | @@ -41,7 +41,7 @@ public class DeviceProfileMsgConstructor { | ||
41 | .setDefault(deviceProfile.isDefault()) | 41 | .setDefault(deviceProfile.isDefault()) |
42 | .setType(deviceProfile.getType().name()) | 42 | .setType(deviceProfile.getType().name()) |
43 | .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData()))); | 43 | .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData()))); |
44 | - // TODO: voba - should this be always null at the moment?? | 44 | + // TODO: @voba - add possibility to setup edge rule chain as device profile default |
45 | // if (deviceProfile.getDefaultRuleChainId() != null) { | 45 | // if (deviceProfile.getDefaultRuleChainId() != null) { |
46 | // builder.setDefaultRuleChainIdMSB(deviceProfile.getDefaultRuleChainId().getId().getMostSignificantBits()) | 46 | // builder.setDefaultRuleChainIdMSB(deviceProfile.getDefaultRuleChainId().getId().getMostSignificantBits()) |
47 | // .setDefaultRuleChainIdLSB(deviceProfile.getDefaultRuleChainId().getId().getLeastSignificantBits()); | 47 | // .setDefaultRuleChainIdLSB(deviceProfile.getDefaultRuleChainId().getId().getLeastSignificantBits()); |
@@ -25,8 +25,8 @@ import org.springframework.stereotype.Component; | @@ -25,8 +25,8 @@ import org.springframework.stereotype.Component; | ||
25 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; | 25 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
26 | import org.thingsboard.server.common.data.id.EntityId; | 26 | import org.thingsboard.server.common.data.id.EntityId; |
27 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; | 27 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
28 | -import org.thingsboard.server.gen.edge.AttributeDeleteMsg; | ||
29 | -import org.thingsboard.server.gen.edge.EntityDataProto; | 28 | +import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; |
29 | +import org.thingsboard.server.gen.edge.v1.EntityDataProto; | ||
30 | import org.thingsboard.server.gen.transport.TransportProtos; | 30 | import org.thingsboard.server.gen.transport.TransportProtos; |
31 | import org.thingsboard.server.queue.util.TbCoreComponent; | 31 | import org.thingsboard.server.queue.util.TbCoreComponent; |
32 | 32 |
@@ -20,9 +20,9 @@ import org.thingsboard.server.common.data.EntityView; | @@ -20,9 +20,9 @@ import org.thingsboard.server.common.data.EntityView; | ||
20 | import org.thingsboard.server.common.data.id.CustomerId; | 20 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | import org.thingsboard.server.common.data.id.EntityViewId; | 21 | import org.thingsboard.server.common.data.id.EntityViewId; |
22 | import org.thingsboard.common.util.JacksonUtil; | 22 | import org.thingsboard.common.util.JacksonUtil; |
23 | -import org.thingsboard.server.gen.edge.EdgeEntityType; | ||
24 | -import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; | ||
25 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 23 | +import org.thingsboard.server.gen.edge.v1.EdgeEntityType; |
24 | +import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; | ||
25 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
26 | import org.thingsboard.server.queue.util.TbCoreComponent; | 26 | import org.thingsboard.server.queue.util.TbCoreComponent; |
27 | 27 | ||
28 | @Component | 28 | @Component |
@@ -18,8 +18,8 @@ package org.thingsboard.server.service.edge.rpc.constructor; | @@ -18,8 +18,8 @@ package org.thingsboard.server.service.edge.rpc.constructor; | ||
18 | import org.springframework.stereotype.Component; | 18 | import org.springframework.stereotype.Component; |
19 | import org.thingsboard.server.common.data.relation.EntityRelation; | 19 | import org.thingsboard.server.common.data.relation.EntityRelation; |
20 | import org.thingsboard.common.util.JacksonUtil; | 20 | import org.thingsboard.common.util.JacksonUtil; |
21 | -import org.thingsboard.server.gen.edge.RelationUpdateMsg; | ||
22 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 21 | +import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; |
22 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
23 | import org.thingsboard.server.queue.util.TbCoreComponent; | 23 | import org.thingsboard.server.queue.util.TbCoreComponent; |
24 | 24 | ||
25 | @Component | 25 | @Component |
@@ -26,12 +26,12 @@ import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; | @@ -26,12 +26,12 @@ import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; | ||
26 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 26 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
27 | import org.thingsboard.server.common.data.rule.RuleNode; | 27 | import org.thingsboard.server.common.data.rule.RuleNode; |
28 | import org.thingsboard.common.util.JacksonUtil; | 28 | import org.thingsboard.common.util.JacksonUtil; |
29 | -import org.thingsboard.server.gen.edge.NodeConnectionInfoProto; | ||
30 | -import org.thingsboard.server.gen.edge.RuleChainConnectionInfoProto; | ||
31 | -import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; | ||
32 | -import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; | ||
33 | -import org.thingsboard.server.gen.edge.RuleNodeProto; | ||
34 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | 29 | +import org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto; |
30 | +import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto; | ||
31 | +import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg; | ||
32 | +import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg; | ||
33 | +import org.thingsboard.server.gen.edge.v1.RuleNodeProto; | ||
34 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; | ||
35 | import org.thingsboard.server.queue.util.TbCoreComponent; | 35 | import org.thingsboard.server.queue.util.TbCoreComponent; |
36 | 36 | ||
37 | import java.util.ArrayList; | 37 | import java.util.ArrayList; |
@@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
21 | import org.thingsboard.server.common.data.id.UserId; | 21 | import org.thingsboard.server.common.data.id.UserId; |
22 | import org.thingsboard.server.common.data.security.UserCredentials; | 22 | import org.thingsboard.server.common.data.security.UserCredentials; |
23 | import org.thingsboard.common.util.JacksonUtil; | 23 | import org.thingsboard.common.util.JacksonUtil; |
24 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | ||
25 | -import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; | ||
26 | -import org.thingsboard.server.gen.edge.UserUpdateMsg; | 24 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
25 | +import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg; | ||
26 | +import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; | ||
27 | import org.thingsboard.server.queue.util.TbCoreComponent; | 27 | import org.thingsboard.server.queue.util.TbCoreComponent; |
28 | 28 | ||
29 | @Component | 29 | @Component |
@@ -20,8 +20,8 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -20,8 +20,8 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
20 | import org.thingsboard.server.common.data.id.WidgetTypeId; | 20 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
21 | import org.thingsboard.server.common.data.widget.WidgetType; | 21 | import org.thingsboard.server.common.data.widget.WidgetType; |
22 | import org.thingsboard.common.util.JacksonUtil; | 22 | import org.thingsboard.common.util.JacksonUtil; |
23 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | ||
24 | -import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; | 23 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
24 | +import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg; | ||
25 | import org.thingsboard.server.queue.util.TbCoreComponent; | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | ||
27 | @Component | 27 | @Component |
@@ -20,8 +20,8 @@ import org.springframework.stereotype.Component; | @@ -20,8 +20,8 @@ import org.springframework.stereotype.Component; | ||
20 | import org.thingsboard.server.common.data.id.TenantId; | 20 | import org.thingsboard.server.common.data.id.TenantId; |
21 | import org.thingsboard.server.common.data.id.WidgetsBundleId; | 21 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
22 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 22 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
23 | -import org.thingsboard.server.gen.edge.UpdateMsgType; | ||
24 | -import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; | 23 | +import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
24 | +import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg; | ||
25 | import org.thingsboard.server.queue.util.TbCoreComponent; | 25 | import org.thingsboard.server.queue.util.TbCoreComponent; |
26 | 26 | ||
27 | import java.nio.charset.StandardCharsets; | 27 | import java.nio.charset.StandardCharsets; |
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.fetch; | ||
17 | + | ||
18 | +import com.datastax.oss.driver.api.core.uuid.Uuids; | ||
19 | +import com.fasterxml.jackson.databind.JsonNode; | ||
20 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
21 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
22 | +import lombok.AllArgsConstructor; | ||
23 | +import lombok.extern.slf4j.Slf4j; | ||
24 | +import org.apache.commons.io.FileUtils; | ||
25 | +import org.apache.commons.lang3.StringUtils; | ||
26 | +import org.apache.commons.lang3.text.WordUtils; | ||
27 | +import org.springframework.core.io.DefaultResourceLoader; | ||
28 | +import org.thingsboard.server.common.data.AdminSettings; | ||
29 | +import org.thingsboard.server.common.data.edge.Edge; | ||
30 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
31 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
32 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
33 | +import org.thingsboard.server.common.data.id.AdminSettingsId; | ||
34 | +import org.thingsboard.server.common.data.id.TenantId; | ||
35 | +import org.thingsboard.server.common.data.page.PageData; | ||
36 | +import org.thingsboard.server.common.data.page.PageLink; | ||
37 | +import org.thingsboard.server.dao.settings.AdminSettingsService; | ||
38 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
39 | + | ||
40 | +import java.io.File; | ||
41 | +import java.nio.charset.StandardCharsets; | ||
42 | +import java.util.ArrayList; | ||
43 | +import java.util.HashMap; | ||
44 | +import java.util.List; | ||
45 | +import java.util.Map; | ||
46 | +import java.util.regex.Matcher; | ||
47 | +import java.util.regex.Pattern; | ||
48 | + | ||
49 | +@AllArgsConstructor | ||
50 | +@Slf4j | ||
51 | +public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher { | ||
52 | + | ||
53 | + private static final ObjectMapper mapper = new ObjectMapper(); | ||
54 | + | ||
55 | + private final AdminSettingsService adminSettingsService; | ||
56 | + | ||
57 | + @Override | ||
58 | + public PageLink getPageLink(int pageSize) { | ||
59 | + return null; | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public PageData<EdgeEvent> fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) throws Exception { | ||
64 | + List<EdgeEvent> result = new ArrayList<>(); | ||
65 | + | ||
66 | + AdminSettings systemMailSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"); | ||
67 | + result.add(EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS, | ||
68 | + EdgeEventActionType.UPDATED, null, mapper.valueToTree(systemMailSettings))); | ||
69 | + | ||
70 | + AdminSettings tenantMailSettings = convertToTenantAdminSettings(systemMailSettings.getKey(), (ObjectNode) systemMailSettings.getJsonValue()); | ||
71 | + result.add(EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS, | ||
72 | + EdgeEventActionType.UPDATED, null, mapper.valueToTree(tenantMailSettings))); | ||
73 | + | ||
74 | + AdminSettings systemMailTemplates = loadMailTemplates(); | ||
75 | + result.add(EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS, | ||
76 | + EdgeEventActionType.UPDATED, null, mapper.valueToTree(systemMailTemplates))); | ||
77 | + | ||
78 | + AdminSettings tenantMailTemplates = convertToTenantAdminSettings(systemMailTemplates.getKey(), (ObjectNode) systemMailTemplates.getJsonValue()); | ||
79 | + result.add(EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS, | ||
80 | + EdgeEventActionType.UPDATED, null, mapper.valueToTree(tenantMailTemplates))); | ||
81 | + | ||
82 | + // @voba - returns PageData object to be in sync with other fetchers | ||
83 | + return new PageData<>(result, 1, result.size(), false); | ||
84 | + } | ||
85 | + | ||
86 | + private AdminSettings loadMailTemplates() throws Exception { | ||
87 | + Map<String, Object> mailTemplates = new HashMap<>(); | ||
88 | + Pattern startPattern = Pattern.compile("<div class=\"content\".*?>"); | ||
89 | + Pattern endPattern = Pattern.compile("<div class=\"footer\".*?>"); | ||
90 | + File[] files = new DefaultResourceLoader().getResource("classpath:/templates/").getFile().listFiles(); | ||
91 | + for (File file : files) { | ||
92 | + Map<String, String> mailTemplate = new HashMap<>(); | ||
93 | + String name = validateName(file.getName()); | ||
94 | + String stringTemplate = FileUtils.readFileToString(file, StandardCharsets.UTF_8); | ||
95 | + Matcher start = startPattern.matcher(stringTemplate); | ||
96 | + Matcher end = endPattern.matcher(stringTemplate); | ||
97 | + if (start.find() && end.find()) { | ||
98 | + String body = StringUtils.substringBetween(stringTemplate, start.group(), end.group()).replaceAll("\t", ""); | ||
99 | + String subject = StringUtils.substringBetween(body, "<h2>", "</h2>"); | ||
100 | + mailTemplate.put("subject", subject); | ||
101 | + mailTemplate.put("body", body); | ||
102 | + mailTemplates.put(name, mailTemplate); | ||
103 | + } else { | ||
104 | + log.error("Can't load mail template from file {}", file.getName()); | ||
105 | + } | ||
106 | + } | ||
107 | + AdminSettings adminSettings = new AdminSettings(); | ||
108 | + adminSettings.setId(new AdminSettingsId(Uuids.timeBased())); | ||
109 | + adminSettings.setKey("mailTemplates"); | ||
110 | + adminSettings.setJsonValue(mapper.convertValue(mailTemplates, JsonNode.class)); | ||
111 | + return adminSettings; | ||
112 | + } | ||
113 | + | ||
114 | + private String validateName(String name) throws Exception { | ||
115 | + StringBuilder nameBuilder = new StringBuilder(); | ||
116 | + name = name.replace(".vm", ""); | ||
117 | + String[] nameParts = name.split("\\."); | ||
118 | + if (nameParts.length >= 1) { | ||
119 | + nameBuilder.append(nameParts[0]); | ||
120 | + for (int i = 1; i < nameParts.length; i++) { | ||
121 | + String word = WordUtils.capitalize(nameParts[i]); | ||
122 | + nameBuilder.append(word); | ||
123 | + } | ||
124 | + return nameBuilder.toString(); | ||
125 | + } else { | ||
126 | + throw new Exception("Error during filename validation"); | ||
127 | + } | ||
128 | + } | ||
129 | + | ||
130 | + private AdminSettings convertToTenantAdminSettings(String key, ObjectNode jsonValue) { | ||
131 | + AdminSettings tenantMailSettings = new AdminSettings(); | ||
132 | + jsonValue.put("useSystemMailSettings", true); | ||
133 | + tenantMailSettings.setJsonValue(jsonValue); | ||
134 | + tenantMailSettings.setKey(key); | ||
135 | + return tenantMailSettings; | ||
136 | + } | ||
137 | +} |
application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/AssetsEdgeEventFetcher.java
0 → 100644
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.fetch; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.asset.Asset; | ||
21 | +import org.thingsboard.server.common.data.edge.Edge; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
24 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
25 | +import org.thingsboard.server.common.data.id.TenantId; | ||
26 | +import org.thingsboard.server.common.data.page.PageData; | ||
27 | +import org.thingsboard.server.common.data.page.PageLink; | ||
28 | +import org.thingsboard.server.dao.asset.AssetService; | ||
29 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
30 | + | ||
31 | +@AllArgsConstructor | ||
32 | +@Slf4j | ||
33 | +public class AssetsEdgeEventFetcher extends BasePageableEdgeEventFetcher<Asset> { | ||
34 | + | ||
35 | + private final AssetService assetService; | ||
36 | + | ||
37 | + @Override | ||
38 | + PageData<Asset> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
39 | + return assetService.findAssetsByTenantIdAndEdgeId(tenantId, edge.getId(), pageLink); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, Asset asset) { | ||
44 | + return EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ASSET, | ||
45 | + EdgeEventActionType.ADDED, asset.getId(), null); | ||
46 | + } | ||
47 | +} |
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.fetch; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.BaseData; | ||
21 | +import org.thingsboard.server.common.data.edge.Edge; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
24 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
25 | +import org.thingsboard.server.common.data.id.EntityId; | ||
26 | +import org.thingsboard.server.common.data.id.EventId; | ||
27 | +import org.thingsboard.server.common.data.id.HasId; | ||
28 | +import org.thingsboard.server.common.data.id.HasUUID; | ||
29 | +import org.thingsboard.server.common.data.id.IdBased; | ||
30 | +import org.thingsboard.server.common.data.id.RuleChainId; | ||
31 | +import org.thingsboard.server.common.data.id.TenantId; | ||
32 | +import org.thingsboard.server.common.data.id.UUIDBased; | ||
33 | +import org.thingsboard.server.common.data.page.PageData; | ||
34 | +import org.thingsboard.server.common.data.page.PageLink; | ||
35 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
36 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
37 | + | ||
38 | +import java.util.ArrayList; | ||
39 | +import java.util.List; | ||
40 | + | ||
41 | +@Slf4j | ||
42 | +public abstract class BasePageableEdgeEventFetcher<T> implements EdgeEventFetcher { | ||
43 | + | ||
44 | + @Override | ||
45 | + public PageLink getPageLink(int pageSize) { | ||
46 | + return new PageLink(pageSize); | ||
47 | + } | ||
48 | + | ||
49 | + @Override | ||
50 | + public PageData<EdgeEvent> fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
51 | + log.trace("[{}] start fetching edge events [{}]", tenantId, edge.getId()); | ||
52 | + PageData<T> pageData = fetchPageData(tenantId, edge, pageLink); | ||
53 | + List<EdgeEvent> result = new ArrayList<>(); | ||
54 | + if (!pageData.getData().isEmpty()) { | ||
55 | + for (T entity : pageData.getData()) { | ||
56 | + result.add(constructEdgeEvent(tenantId, edge, entity)); | ||
57 | + } | ||
58 | + } | ||
59 | + return new PageData<>(result, pageData.getTotalPages(), pageData.getTotalElements(), pageData.hasNext()); | ||
60 | + } | ||
61 | + | ||
62 | + abstract PageData<T> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink); | ||
63 | + | ||
64 | + abstract EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, T entity); | ||
65 | +} |
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.fetch; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.User; | ||
21 | +import org.thingsboard.server.common.data.edge.Edge; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
24 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
25 | +import org.thingsboard.server.common.data.id.TenantId; | ||
26 | +import org.thingsboard.server.common.data.page.PageData; | ||
27 | +import org.thingsboard.server.common.data.page.PageLink; | ||
28 | +import org.thingsboard.server.dao.user.UserService; | ||
29 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
30 | + | ||
31 | +@Slf4j | ||
32 | +@AllArgsConstructor | ||
33 | +public abstract class BaseUsersEdgeEventFetcher extends BasePageableEdgeEventFetcher<User> { | ||
34 | + | ||
35 | + protected final UserService userService; | ||
36 | + | ||
37 | + @Override | ||
38 | + PageData<User> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
39 | + return findUsers(tenantId, pageLink); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, User user) { | ||
44 | + return EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.USER, | ||
45 | + EdgeEventActionType.ADDED, user.getId(), null); | ||
46 | + } | ||
47 | + | ||
48 | + protected abstract PageData<User> findUsers(TenantId tenantId, PageLink pageLink); | ||
49 | +} |
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.fetch; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.edge.Edge; | ||
21 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | +import org.thingsboard.server.common.data.page.PageData; | ||
26 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | +import org.thingsboard.server.common.data.widget.WidgetsBundle; | ||
28 | +import org.thingsboard.server.dao.widget.WidgetsBundleService; | ||
29 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
30 | + | ||
31 | +@Slf4j | ||
32 | +@AllArgsConstructor | ||
33 | +public abstract class BaseWidgetsBundlesEdgeEventFetcher extends BasePageableEdgeEventFetcher<WidgetsBundle> { | ||
34 | + | ||
35 | + protected final WidgetsBundleService widgetsBundleService; | ||
36 | + | ||
37 | + @Override | ||
38 | + PageData<WidgetsBundle> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
39 | + return findWidgetsBundles(tenantId, pageLink); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, WidgetsBundle widgetsBundle) { | ||
44 | + return EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.WIDGETS_BUNDLE, | ||
45 | + EdgeEventActionType.ADDED, widgetsBundle.getId(), null); | ||
46 | + } | ||
47 | + | ||
48 | + protected abstract PageData<WidgetsBundle> findWidgetsBundles(TenantId tenantId, PageLink pageLink); | ||
49 | +} |
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.fetch; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.edge.Edge; | ||
21 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | +import org.thingsboard.server.common.data.page.PageData; | ||
26 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
28 | + | ||
29 | +import java.util.ArrayList; | ||
30 | +import java.util.List; | ||
31 | + | ||
32 | +@AllArgsConstructor | ||
33 | +@Slf4j | ||
34 | +public class CustomerEdgeEventFetcher implements EdgeEventFetcher { | ||
35 | + | ||
36 | + @Override | ||
37 | + public PageLink getPageLink(int pageSize) { | ||
38 | + return null; | ||
39 | + } | ||
40 | + | ||
41 | + @Override | ||
42 | + public PageData<EdgeEvent> fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
43 | + List<EdgeEvent> result = new ArrayList<>(); | ||
44 | + result.add(EdgeEventUtils.constructEdgeEvent(edge.getTenantId(), edge.getId(), | ||
45 | + EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, edge.getCustomerId(), null)); | ||
46 | + // @voba - returns PageData object to be in sync with other fetchers | ||
47 | + return new PageData<>(result, 1, result.size(), false); | ||
48 | + } | ||
49 | +} |
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.fetch; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.User; | ||
19 | +import org.thingsboard.server.common.data.edge.Edge; | ||
20 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
21 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
22 | +import org.thingsboard.server.common.data.id.TenantId; | ||
23 | +import org.thingsboard.server.common.data.page.PageData; | ||
24 | +import org.thingsboard.server.common.data.page.PageLink; | ||
25 | +import org.thingsboard.server.dao.user.UserService; | ||
26 | + | ||
27 | +public class CustomerUsersEdgeEventFetcher extends BaseUsersEdgeEventFetcher { | ||
28 | + | ||
29 | + private final CustomerId customerId; | ||
30 | + | ||
31 | + public CustomerUsersEdgeEventFetcher(UserService userService, CustomerId customerId) { | ||
32 | + super(userService); | ||
33 | + this.customerId = customerId; | ||
34 | + } | ||
35 | + | ||
36 | + @Override | ||
37 | + protected PageData<User> findUsers(TenantId tenantId, PageLink pageLink) { | ||
38 | + return userService.findCustomerUsers(tenantId, customerId, pageLink); | ||
39 | + } | ||
40 | + | ||
41 | +} |
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.fetch; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.DashboardInfo; | ||
21 | +import org.thingsboard.server.common.data.edge.Edge; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
24 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
25 | +import org.thingsboard.server.common.data.id.TenantId; | ||
26 | +import org.thingsboard.server.common.data.page.PageData; | ||
27 | +import org.thingsboard.server.common.data.page.PageLink; | ||
28 | +import org.thingsboard.server.dao.dashboard.DashboardService; | ||
29 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
30 | + | ||
31 | +@AllArgsConstructor | ||
32 | +@Slf4j | ||
33 | +public class DashboardsEdgeEventFetcher extends BasePageableEdgeEventFetcher<DashboardInfo> { | ||
34 | + | ||
35 | + private final DashboardService dashboardService; | ||
36 | + | ||
37 | + @Override | ||
38 | + PageData<DashboardInfo> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
39 | + return dashboardService.findDashboardsByTenantIdAndEdgeId(tenantId, edge.getId(), pageLink); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, DashboardInfo dashboardInfo) { | ||
44 | + return EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.DASHBOARD, | ||
45 | + EdgeEventActionType.ADDED, dashboardInfo.getId(), null); | ||
46 | + } | ||
47 | +} |
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.fetch; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.data.DeviceProfile; | ||
21 | +import org.thingsboard.server.common.data.edge.Edge; | ||
22 | +import org.thingsboard.server.common.data.edge.EdgeEvent; | ||
23 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
24 | +import org.thingsboard.server.common.data.edge.EdgeEventType; | ||
25 | +import org.thingsboard.server.common.data.id.TenantId; | ||
26 | +import org.thingsboard.server.common.data.page.PageData; | ||
27 | +import org.thingsboard.server.common.data.page.PageLink; | ||
28 | +import org.thingsboard.server.dao.device.DeviceProfileService; | ||
29 | +import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; | ||
30 | + | ||
31 | +@AllArgsConstructor | ||
32 | +@Slf4j | ||
33 | +public class DeviceProfilesEdgeEventFetcher extends BasePageableEdgeEventFetcher<DeviceProfile> { | ||
34 | + | ||
35 | + private final DeviceProfileService deviceProfileService; | ||
36 | + | ||
37 | + @Override | ||
38 | + PageData<DeviceProfile> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { | ||
39 | + return deviceProfileService.findDeviceProfiles(tenantId, pageLink); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, DeviceProfile deviceProfile) { | ||
44 | + return EdgeEventUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE_PROFILE, | ||
45 | + EdgeEventActionType.ADDED, deviceProfile.getId(), null); | ||
46 | + } | ||
47 | +} |