From 66b3b1eca4dc492f7e7264c35a4c555dbea03ed2 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 12 Jun 2020 18:48:21 +0300 Subject: [PATCH 001/156] methods for working with Edge --- .../thingsboard/rest/client/RestClient.java | 200 ++++++++++++++++-- 1 file changed, 187 insertions(+), 13 deletions(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index e14996d12f..1e4fb1088a 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -45,7 +45,9 @@ import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeSearchQuery; +import org.thingsboard.server.common.data.id.*; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; @@ -56,18 +58,6 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.device.DeviceSearchQuery; import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; -import org.thingsboard.server.common.data.id.AssetId; -import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.DashboardId; -import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.EntityViewId; -import org.thingsboard.server.common.data.id.RuleChainId; -import org.thingsboard.server.common.data.id.RuleNodeId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.common.data.id.WidgetTypeId; -import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.kv.Aggregation; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; @@ -1978,6 +1968,190 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } + public Edge saveEdge(Edge edge) { + return restTemplate.postForEntity(baseURL + "/api/edge", edge, Edge.class).getBody(); + } + + public void deleteEdge(EdgeId edgeId) { + restTemplate.delete(baseURL + "/api/edge/{edgeId}", edgeId.getId()); + } + + public Optional getEdgeById(EdgeId edgeId) { + try { + ResponseEntity edge = restTemplate.getForEntity(baseURL + "/api/edge/{edgeId}", Edge.class, edgeId.getId()); + return Optional.ofNullable(edge.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional assignEdgeToCustomer(CustomerId customerId, EdgeId edgeId) { + try { + ResponseEntity edge = restTemplate.postForEntity(baseURL + "/api/customer/{customerId}/edge/{edgeId}", null, Edge.class, customerId.getId(), edgeId.getId()); + return Optional.ofNullable(edge.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional unassignEdgeFromCustomer(EdgeId edgeId) { + try { + ResponseEntity edge = restTemplate.exchange(baseURL + "/api/customer/edge/{edgeId}", HttpMethod.DELETE, HttpEntity.EMPTY, Edge.class, edgeId.getId()); + return Optional.ofNullable(edge.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional assignDeviceToEdge(EdgeId edgeId, DeviceId deviceId) { + try { + ResponseEntity device = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/device/{deviceId}", null, Device.class, edgeId.getId(), deviceId.getId()); + return Optional.ofNullable(device.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional unassignDeviceFromEdge(DeviceId deviceId) { + try { + ResponseEntity device = restTemplate.exchange(baseURL + "/api/edge/device/{deviceId}", HttpMethod.DELETE, HttpEntity.EMPTY, Device.class, deviceId.getId()); + return Optional.ofNullable(device.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TextPageData getEdgeDevices(EdgeId edgeId, String deviceType, TextPageLink pageLink) { + Map params = new HashMap<>(); + params.put("edgeId", edgeId.getId().toString()); + params.put("type", deviceType); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edge/{edgeId}/devices?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + + public Optional assignAssetToEdge(EdgeId edgeId, AssetId assetId) { + try { + ResponseEntity asset = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/asset/{assetId}", null, Asset.class, edgeId.getId(), assetId.getId()); + return Optional.ofNullable(asset.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional unassignAssetFromEdge(AssetId assetId) { + try { + ResponseEntity asset = restTemplate.exchange(baseURL + "/api/edge/asset/{assetId}", HttpMethod.DELETE, HttpEntity.EMPTY, Asset.class, assetId.getId()); + return Optional.ofNullable(asset.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TextPageData getEdgeAssets(EdgeId edgeId, String assetType, TextPageLink pageLink) { + Map params = new HashMap<>(); + params.put("edgeId", edgeId.getId().toString()); + params.put("type", assetType); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edge/{edgeId}/assets?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + + public TextPageData getTenantEdges(String type, TextPageLink pageLink) { + Map params = new HashMap<>(); + params.put("type", type); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/tenant/edges?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + + public Optional getTenantEdge(String edgeName) { + try { + ResponseEntity edge = restTemplate.getForEntity(baseURL + "/api/tenant/edges?edgeName={edgeName}", Edge.class, edgeName); + return Optional.ofNullable(edge.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TextPageData getCustomerEdges(CustomerId customerId, String edgeType, TextPageLink pageLink) { + Map params = new HashMap<>(); + params.put("customerId", customerId.getId().toString()); + params.put("type", edgeType); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/customer/{customerId}/edges?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + + public List getEdgesByIds(List edgeIds) { + return restTemplate.exchange(baseURL + "/api/edges?edgeIds={edgeIds}", + HttpMethod.GET, + HttpEntity.EMPTY, new ParameterizedTypeReference>() { + }, listIdsToString(edgeIds)).getBody(); + } + + public List findByQuery(EdgeSearchQuery query) { + return restTemplate.exchange( + baseURL + "/api/edges", + HttpMethod.POST, + new HttpEntity<>(query), + new ParameterizedTypeReference>() { + }).getBody(); + } + + public List getEdgeTypes() { + return restTemplate.exchange( + baseURL + "/api/edge/types", + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }).getBody(); + } + @Deprecated public Optional getAttributes(String accessToken, String clientKeys, String sharedKeys) { Map params = new HashMap<>(); From c9d995858cb310e0b67cb527c684f0639e6d1397 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Sun, 21 Jun 2020 20:46:56 +0300 Subject: [PATCH 002/156] Dashboard unused edge service deleted --- .../common/data/edge/EdgeQueueEntityType.java | 2 +- msa/js-executor/package-lock.json | 23 +- ui/package-lock.json | 212 ++++++++---------- ui/src/app/api/dashboard.service.js | 44 ---- ui/src/app/api/edge.service.js | 2 +- 5 files changed, 107 insertions(+), 176 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntityType.java index ca268380f4..7ba316a529 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntityType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/msa/js-executor/package-lock.json b/msa/js-executor/package-lock.json index 818b77550e..9a7e7eb76c 100644 --- a/msa/js-executor/package-lock.json +++ b/msa/js-executor/package-lock.json @@ -1872,14 +1872,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1894,20 +1892,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2024,8 +2019,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2037,7 +2031,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2052,7 +2045,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2164,8 +2156,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -2177,7 +2168,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -2299,7 +2289,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/ui/package-lock.json b/ui/package-lock.json index 4de10ff7d8..ea4fcf529c 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1095,12 +1095,12 @@ "@flowjs/ng-flow": { "version": "2.7.8", "resolved": "https://registry.npmjs.org/@flowjs/ng-flow/-/ng-flow-2.7.8.tgz", - "integrity": "sha1-HZ+dH4Ks2lNgMowxW6z9YNv9mBk=" + "integrity": "sha512-zO6jNvz41oMOJj9+1N+vLT0ytitbCtuGABJQRzQDOPXyRMmlSXfJ7om5oYOztyUFrr4jDpE4QFPt+r2/RFceCg==" }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { "call-me-maybe": "^1.0.1", @@ -1424,7 +1424,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.7", @@ -1534,7 +1534,7 @@ "angular-carousel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/angular-carousel/-/angular-carousel-1.1.0.tgz", - "integrity": "sha1-PmlA5ovRio85L8Qx2XGSrDSIMdE=" + "integrity": "sha512-UiLMgT7Ueqk4xpliF1gWt4dYKXezdJA1jyZPNsUWkOGO/dwLuKi284h3BgWl4CnaH7kEBw8L2gsBOyqbYaumNQ==" }, "angular-cookies": { "version": "1.5.8", @@ -1555,7 +1555,7 @@ } }, "angular-fullscreen": { - "version": "git://github.com/fabiobiondi/angular-fullscreen.git#8217174565761d3566807bc60a73b5ca015b8cb6", + "version": "git://github.com/fabiobiondi/angular-fullscreen.git#119b7fbac911d154fd56ace38ebe3432475e8a20", "from": "git://github.com/fabiobiondi/angular-fullscreen.git#master" }, "angular-gridster": { @@ -1629,7 +1629,7 @@ "angular-translate": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.1.tgz", - "integrity": "sha1-sp7Q0vm6xEB156rTKEFmxZ4VB5E=", + "integrity": "sha512-Mw0kFBqsv5j8ItL9IhRZunIlVmIRW6iFsiTmRs9wGr2QTt8z4rehYlWyHos8qnXc/kyOYJiW50iH50CSNHGB9A==", "requires": { "angular": ">=1.2.26 <=1.7" } @@ -1637,7 +1637,7 @@ "angular-translate-handler-log": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate-handler-log/-/angular-translate-handler-log-2.18.1.tgz", - "integrity": "sha1-icu1mCeALYb4EVJ1+/iNbYiWsNQ=", + "integrity": "sha512-TyKzCW4GubNazwCgLpCVXd2212CWdZOckf+aL5+gLuThPhVpOvlg18RSmz8MNPto3kwCcCw3LzShlZ6RX/MQRA==", "requires": { "angular-translate": "~2.18.1" } @@ -1645,7 +1645,7 @@ "angular-translate-interpolation-messageformat": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate-interpolation-messageformat/-/angular-translate-interpolation-messageformat-2.18.1.tgz", - "integrity": "sha1-FsUq4MYcJA8PJBZKBSGUPPi6QI4=", + "integrity": "sha512-SlmyxLB/UUy7FWoGx5QJHrhq8fUu/xzCR0h/ngexOtXZopQjs1vm+TrFZ69d4c/LI7C91sfP4mq4ES29o1xCxA==", "requires": { "angular-translate": "~2.18.1", "messageformat": "~1.0.2" @@ -1654,7 +1654,7 @@ "angular-translate-loader-static-files": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate-loader-static-files/-/angular-translate-loader-static-files-2.18.1.tgz", - "integrity": "sha1-rQw8iDsYsIm9uNsCu9Nm2QP4V8w=", + "integrity": "sha512-5MuyzAROfc493kjLjKlLGLBzXiRmZIFbcWZGutDRxW5SRXSpwrH0u0hh0ENNnUyUQbe2vUspHNPIuZqlq8qIhw==", "requires": { "angular-translate": "~2.18.1" } @@ -1662,7 +1662,7 @@ "angular-translate-storage-cookie": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate-storage-cookie/-/angular-translate-storage-cookie-2.18.1.tgz", - "integrity": "sha1-j8vaspb6gkkOALQorxp0ahf0QVY=", + "integrity": "sha512-wiMaF/0OGN/3ilaYunfsqdLNpfGZEJK0fj4zT8yjD3XPq7Q9kM88xZ4XJiWKgodZShBljGCRzqgQbKMF7d1MLw==", "requires": { "angular-cookies": ">=1.2.26 <1.8", "angular-translate": "~2.18.1" @@ -1671,7 +1671,7 @@ "angular-translate-storage-local": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate-storage-local/-/angular-translate-storage-local-2.18.1.tgz", - "integrity": "sha1-lHQP5NgBq3gpopofBeHDkFTIcwM=", + "integrity": "sha512-zPxcbIJ8tdWXtWNKLtaswynKid0w5le6WPMwiLWhgKPnyzOp/y5WLBW+JEfnZnkGE24yOGhJ6jVPgRNzelLgzg==", "requires": { "angular-translate": "~2.18.1", "angular-translate-storage-cookie": "~2.18.1" @@ -1750,7 +1750,7 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "are-we-there-yet": { @@ -1766,7 +1766,7 @@ "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" @@ -1781,7 +1781,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "arr-union": { @@ -1893,7 +1893,7 @@ }, "util": { "version": "0.10.3", - "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -1958,7 +1958,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, "attr-accept": { @@ -2174,7 +2174,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -2198,7 +2198,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -2207,7 +2207,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -2216,7 +2216,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -2362,7 +2362,7 @@ "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2586,7 +2586,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -2617,7 +2617,7 @@ "dependencies": { "callsites": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true } @@ -2794,7 +2794,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -3121,7 +3121,7 @@ "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -3181,7 +3181,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, "convert-source-map": { @@ -3208,7 +3208,7 @@ "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", "dev": true, "requires": { "aproba": "^1.1.1", @@ -3427,7 +3427,7 @@ "create-react-class": { "version": "15.6.3", "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", - "integrity": "sha1-LXMjf7P5cK5uvgEanmb0bbyoADY=", + "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", "requires": { "fbjs": "^0.8.9", "loose-envify": "^1.3.1", @@ -3555,7 +3555,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" @@ -3633,7 +3633,7 @@ "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -3643,7 +3643,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3652,7 +3652,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3661,7 +3661,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -3724,7 +3724,7 @@ "delegate": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=" + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" }, "delegates": { "version": "1.0.0", @@ -3880,7 +3880,7 @@ "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "domelementtype": { @@ -4035,7 +4035,7 @@ "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { "prr": "~1.0.1" @@ -4554,7 +4554,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { "estraverse": "^4.1.0" @@ -4769,7 +4769,7 @@ "external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "requires": { "chardet": "^0.4.0", "iconv-lite": "^0.4.17", @@ -5197,7 +5197,7 @@ "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha1-4y/AMKLM7kSmtTcTCNpUvgs5fSc=", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", "dev": true }, "fs-write-stream-atomic": { @@ -5259,14 +5259,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5281,20 +5279,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5411,8 +5406,7 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5424,7 +5418,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5439,7 +5432,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5447,14 +5439,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5473,7 +5463,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5563,8 +5552,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5576,7 +5564,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5698,7 +5685,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5785,7 +5771,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "functional-red-black-tree": { @@ -6733,7 +6719,7 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inline-style-prefixer": { "version": "2.0.5", @@ -6783,7 +6769,7 @@ "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { "loose-envify": "^1.0.0" @@ -6885,7 +6871,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-callable": { @@ -6929,7 +6915,7 @@ "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -6940,7 +6926,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } @@ -7048,7 +7034,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "^3.0.1" @@ -7115,7 +7101,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "is-word-character": { @@ -7255,7 +7241,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-schema": { @@ -7272,7 +7258,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -7512,7 +7498,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -8045,7 +8031,7 @@ "messageformat-parser": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-1.1.0.tgz", - "integrity": "sha1-E7oiUKdrvejg/KDbs0dflcWUqQo=" + "integrity": "sha512-Hwem6G3MsKDLS1FtBRGIs8T50P1Q00r3srS6QJePCFbad9fq0nYxwf3rnU2BreApRGhmpKMV7oZI06Sy1c9TPA==" }, "methods": { "version": "1.1.2", @@ -8087,7 +8073,7 @@ "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, "mime-db": { @@ -8108,7 +8094,7 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=" + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "min-document": { "version": "2.19.0", @@ -8165,7 +8151,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" } @@ -8260,7 +8246,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -8338,7 +8324,7 @@ "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -8490,7 +8476,7 @@ } }, "ngFlowchart": { - "version": "git://github.com/thingsboard/ngFlowchart.git#1343a7478961f68280d81f0ecda4e722a2068e0f", + "version": "git://github.com/thingsboard/ngFlowchart.git#ad172c26bb731f4e4e79d05dfa8cdc3f59cd1690", "from": "git://github.com/thingsboard/ngFlowchart.git#master" }, "ngclipboard": { @@ -8550,7 +8536,7 @@ "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { "lower-case": "^1.1.1" @@ -8569,7 +8555,7 @@ "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8=", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", "requires": { "encoding": "^0.1.11", "is-stream": "^1.0.1" @@ -8770,7 +8756,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -9087,7 +9073,7 @@ "osenv": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha1-hc36+uso6Gd/QW4odZK18/SepBA=", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -9515,7 +9501,7 @@ "postcss-loader": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0=", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", "dev": true, "requires": { "loader-utils": "^1.1.0", @@ -9818,7 +9804,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, "process": { @@ -9841,7 +9827,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { "asap": "~2.0.3" } @@ -9921,7 +9907,7 @@ "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "requires": { "duplexify": "^3.6.0", @@ -10086,7 +10072,7 @@ "rc-menu": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-5.1.4.tgz", - "integrity": "sha1-5d8I/ouDPoFGkTX/E7MKuPIf88Y=", + "integrity": "sha512-ZUkUNda70GtTXcQDiO3rSDdk3sgIwDwzPUm5dVM8nRH/j84qv0BVBkIUwIBu8+s+G3G9lWLurRqh22dCqZPeOA==", "requires": { "babel-runtime": "6.x", "classnames": "2.x", @@ -10117,7 +10103,7 @@ "rc-trigger": { "version": "1.11.5", "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-1.11.5.tgz", - "integrity": "sha1-+I+fhODnn44O8cjRv4rCIItxViA=", + "integrity": "sha512-MBuUPw1nFzA4K7jQOwb7uvFaZFjXGd00EofUYiZ+l/fgKVq8wnLC0lkv36kwqM7vfKyftRo2sh7cWVpdPuNnnw==", "requires": { "babel-runtime": "6.x", "create-react-class": "15.x", @@ -10276,7 +10262,7 @@ "react-transition-group": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.1.tgz", - "integrity": "sha1-4R9yslf5IbITIpp3TfRmEjRsfKY=", + "integrity": "sha512-CWaL3laCmgAFdxdKbhhps+c0HRGF4c+hdM4H23+FI1QBNUyx/AMeIJGWorehPNSaKnQNOAxL7PQmqMu78CDj3Q==", "requires": { "chain-function": "^1.0.0", "dom-helpers": "^3.2.0", @@ -10288,7 +10274,7 @@ "reactcss": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", - "integrity": "sha1-wAATh15Vexzw39mjaKHD2rO1SN0=", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", "requires": { "lodash": "^4.0.1" } @@ -10471,7 +10457,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { "version": "0.14.1", @@ -10485,7 +10471,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -10790,7 +10776,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, "retry": { @@ -10894,7 +10880,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass-graph": { "version": "2.2.4", @@ -11228,7 +11214,7 @@ "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { "base": "^0.11.1", @@ -11264,7 +11250,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { "define-property": "^1.0.0", @@ -11284,7 +11270,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -11293,7 +11279,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -11302,7 +11288,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -11315,7 +11301,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -11335,7 +11321,7 @@ "sockjs": { "version": "0.3.19", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha1-2Xa76ACve9IK4IWY1YI5NQiZPA0=", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", "dev": true, "requires": { "faye-websocket": "^0.10.0", @@ -11459,7 +11445,7 @@ "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -11553,7 +11539,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -11693,7 +11679,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -11737,7 +11723,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } @@ -12706,7 +12692,7 @@ "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha1-wiaIrtTqs83C3+rLtWFmBWCgCAQ=" + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" }, "table": { "version": "5.4.6", @@ -12936,7 +12922,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "requires": { "os-tmpdir": "~1.0.2" } @@ -12976,7 +12962,7 @@ "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { "define-property": "^2.0.2", @@ -13178,7 +13164,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -13503,7 +13489,7 @@ "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -13565,7 +13551,7 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, "util": { @@ -14304,7 +14290,7 @@ "websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, "whatwg-fetch": { @@ -14418,7 +14404,7 @@ "ws": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha1-y9nm514J/F0skAFfIfDECHXg3VE=", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", "requires": { "options": ">=0.0.5", "ultron": "1.0.x" diff --git a/ui/src/app/api/dashboard.service.js b/ui/src/app/api/dashboard.service.js index a7f020b164..7280c9d06d 100644 --- a/ui/src/app/api/dashboard.service.js +++ b/ui/src/app/api/dashboard.service.js @@ -25,7 +25,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { stDiffPromise = undefined; }); - var service = { assignDashboardToCustomer: assignDashboardToCustomer, getCustomerDashboards: getCustomerDashboards, @@ -43,9 +42,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { makeDashboardPublic: makeDashboardPublic, makeDashboardPrivate: makeDashboardPrivate, getPublicDashboardLink: getPublicDashboardLink, - updateDashboardEdges: updateDashboardEdges, - addDashboardEdges: addDashboardEdges, - removeDashboardEdges: removeDashboardEdges, getEdgeDashboards: getEdgeDashboards, assignDashboardToEdge: assignDashboardToEdge, unassignDashboardFromEdge: unassignDashboardFromEdge @@ -290,17 +286,10 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { } dashboard.assignedEdgesIds = []; if (dashboard.assignedEdges && dashboard.assignedEdges.length) { - // var assignedEdgesTitles = []; for (var j = 0; j < dashboard.assignedEdges.length; j++) { var assignedEdge = dashboard.assignedEdges[j]; dashboard.assignedEdgesIds.push(assignedEdge.edgeId.id); - // if (assignedCustomer.public) { - // dashboard.publicCustomerId = assignedCustomer.customerId.id; - // } else { - // assignedCustomersTitles.push(assignedCustomer.title); - // } } - // dashboard.assignedCustomersText = assignedCustomersTitles.join(', '); } return dashboard; } @@ -313,39 +302,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { return dashboard; } - function updateDashboardEdges(dashboardId, edgeIds) { - var deferred = $q.defer(); - var url = '/api/dashboard/' + dashboardId + '/edges'; - $http.post(url, edgeIds).then(function success(response) { - deferred.resolve(prepareDashboard(response.data)); - }, function fail() { - deferred.reject(); - }); - return deferred.promise; - } - - function addDashboardEdges(dashboardId, edgeIds) { - var deferred = $q.defer(); - var url = '/api/dashboard/' + dashboardId + '/edges/add'; - $http.post(url, edgeIds).then(function success(response) { - deferred.resolve(prepareDashboard(response.data)); - }, function fail() { - deferred.reject(); - }); - return deferred.promise; - } - - function removeDashboardEdges(dashboardId, edgeIds) { - var deferred = $q.defer(); - var url = '/api/dashboard/' + dashboardId + '/edges/remove'; - $http.post(url, edgeIds).then(function success(response) { - deferred.resolve(prepareDashboard(response.data)); - }, function fail() { - deferred.reject(); - }); - return deferred.promise; - } - function getEdgeDashboards(edgeId, pageLink, config) { var deferred = $q.defer(); var url = '/api/edge/' + edgeId + '/dashboards?limit=' + pageLink.limit; diff --git a/ui/src/app/api/edge.service.js b/ui/src/app/api/edge.service.js index d2123e7576..5e8a9f88a8 100644 --- a/ui/src/app/api/edge.service.js +++ b/ui/src/app/api/edge.service.js @@ -55,7 +55,7 @@ function EdgeService($http, $q, customerService) { deferred.reject(); }); return deferred.promise; - } + } // TODO: deaflynx: check usage in UI function getEdgesByIds(edgeIds, config) { var deferred = $q.defer(); From 1f5752485195303865e9e25ba5537784e48dcd51 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 22 Jun 2020 18:26:00 +0300 Subject: [PATCH 003/156] fixed bug with undefined rule chain type --- ui/src/app/rulechain/rulechain.controller.js | 6 +++--- ui/src/app/rulechain/rulechain.routes.js | 2 +- ui/src/app/rulechain/rulechains.controller.js | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js index 292c3f71c1..ba7c76cc55 100644 --- a/ui/src/app/rulechain/rulechain.controller.js +++ b/ui/src/app/rulechain/rulechain.controller.js @@ -1180,7 +1180,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time var saveRuleChainPromise; if (vm.isImport) { if (angular.isUndefined(vm.ruleChain.type)) { - vm.ruleChain.type = types.systemRuleChainType; + vm.ruleChain.type = types.coreRuleChainType; } saveRuleChainPromise = ruleChainService.saveRuleChain(vm.ruleChain); } else { @@ -1269,7 +1269,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time vm.isDirty = false; vm.isImport = false; $mdUtil.nextTick(() => { - if (vm.ruleChain.type === vm.types.systemRuleChainType) { + if (vm.ruleChain.type === vm.types.coreRuleChainType) { $state.go('home.ruleChains.core.ruleChain', {ruleChainId: vm.ruleChain.id.id}); } else { $state.go('home.ruleChains.edge.ruleChain', {ruleChainId: vm.ruleChain.id.id}); @@ -1293,7 +1293,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time ruleNode.configuration = angular.copy(ruleNode.component.configurationDescriptor.nodeDefinition.defaultConfiguration); var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null; - var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.systemRuleChainType; + var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.coreRuleChainType; vm.enableHotKeys = false; diff --git a/ui/src/app/rulechain/rulechain.routes.js b/ui/src/app/rulechain/rulechain.routes.js index 08dc2f522e..a3f533eb57 100644 --- a/ui/src/app/rulechain/rulechain.routes.js +++ b/ui/src/app/rulechain/rulechain.routes.js @@ -82,7 +82,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider ruleNodeComponents: /*@ngInject*/ function($stateParams, ruleChainService) { - return ruleChainService.getRuleNodeComponents(types.systemRuleChainType); + return ruleChainService.getRuleNodeComponents(types.coreRuleChainType); } }, data: { diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index aba5c3bb2a..01037d77a4 100644 --- a/ui/src/app/rulechain/rulechains.controller.js +++ b/ui/src/app/rulechain/rulechains.controller.js @@ -114,7 +114,7 @@ export default function RuleChainsController(ruleChainService, userService, edge if (vm.ruleChainsScope === 'tenant') { fetchRuleChainsFunction = function (pageLink) { - return fetchRuleChains(pageLink, types.systemRuleChainType); + return fetchRuleChains(pageLink, types.coreRuleChainType); }; deleteRuleChainFunction = function (ruleChainId) { return deleteRuleChain(ruleChainId); @@ -162,9 +162,9 @@ export default function RuleChainsController(ruleChainService, userService, edge }); vm.ruleChainGridConfig.addItemActions.push({ onAction: function ($event) { - importExport.importRuleChain($event, types.systemRuleChainType).then( + importExport.importRuleChain($event, types.coreRuleChainType).then( function(ruleChainImport) { - $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.systemRuleChainType}); + $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.coreRuleChainType}); } ); }, @@ -385,7 +385,7 @@ export default function RuleChainsController(ruleChainService, userService, edge if (vm.ruleChainsScope === 'edges') { ruleChain.type = types.edgeRuleChainType; } else { - ruleChain.type = types.systemRuleChainType; + ruleChain.type = types.coreRuleChainType; } } return ruleChainService.saveRuleChain(ruleChain); From b0e08a263a76aa43688ececc7f4c58c240652d4b Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 22 Jun 2020 19:00:42 +0300 Subject: [PATCH 004/156] Refactoring & renaming --- .../edge/rpc/init/DefaultSyncEdgeService.java | 16 ++++++++++++---- .../service/queue/TbCoreConsumerStats.java | 9 +++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 341cc95d28..306d1bf5f9 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -15,11 +15,13 @@ */ package org.thingsboard.server.service.edge.rpc.init; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import io.grpc.stub.StreamObserver; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Dashboard; @@ -131,10 +133,16 @@ public class DefaultSyncEdgeService implements SyncEdgeService { futures.add(syncAssets(ctx, edge, pushedEntityIds, outputStream)); futures.add(syncEntityViews(ctx, edge, pushedEntityIds, outputStream)); futures.add(syncDashboards(ctx, edge, pushedEntityIds, outputStream)); - ListenableFuture> joinFuture = Futures.allAsList(futures); - Futures.transform(joinFuture, result -> { - syncRelations(ctx, edge, pushedEntityIds, outputStream); - return null; + Futures.addCallback(Futures.allAsList(futures), new FutureCallback>() { + @Override + public void onSuccess(@Nullable List result) { + syncRelations(ctx, edge, pushedEntityIds, outputStream); + } + + @Override + public void onFailure(Throwable t) { + log.warn("Exception during sync entities", t); + } }, MoreExecutors.directExecutor()); } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java b/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java index a8ace962bf..7e5abd9da8 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java @@ -33,7 +33,7 @@ public class TbCoreConsumerStats { private final AtomicInteger claimDeviceCounter = new AtomicInteger(0); private final AtomicInteger deviceStateCounter = new AtomicInteger(0); - private final AtomicInteger edgeNotificationCounter = new AtomicInteger(0); + private final AtomicInteger edgeNotificationMsgCounter = new AtomicInteger(0); private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0); private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0); @@ -69,7 +69,7 @@ public class TbCoreConsumerStats { public void log(TransportProtos.EdgeNotificationMsgProto msg) { totalCounter.incrementAndGet(); - edgeNotificationCounter.incrementAndGet(); + edgeNotificationMsgCounter.incrementAndGet(); } public void log(TransportProtos.SubscriptionMgrMsgProto msg) { @@ -86,12 +86,13 @@ public class TbCoreConsumerStats { int total = totalCounter.getAndSet(0); if (total > 0) { log.info("Total [{}] sessionEvents [{}] getAttr [{}] subToAttr [{}] subToRpc [{}] toDevRpc [{}] subInfo [{}] claimDevice [{}]" + - " deviceState [{}] subMgr [{}] coreNfs [{}]", + " deviceState [{}] subMgr [{}] coreNfs [{}] edgeNfs [{}]", total, sessionEventCounter.getAndSet(0), getAttributesCounter.getAndSet(0), subscribeToAttributesCounter.getAndSet(0), subscribeToRPCCounter.getAndSet(0), toDeviceRPCCallResponseCounter.getAndSet(0), subscriptionInfoCounter.getAndSet(0), claimDeviceCounter.getAndSet(0) - , deviceStateCounter.getAndSet(0), subscriptionMsgCounter.getAndSet(0), toCoreNotificationsCounter.getAndSet(0)); + , deviceStateCounter.getAndSet(0), subscriptionMsgCounter.getAndSet(0), toCoreNotificationsCounter.getAndSet(0), + edgeNotificationMsgCounter.getAndSet(0)); } } From 79bf245932e54ef5ebc4f08d7711ee097043260d Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 23 Jun 2020 19:13:27 +0300 Subject: [PATCH 005/156] Added Relation and Credentials Request Messages --- .../service/edge/rpc/EdgeGrpcService.java | 6 +- .../service/edge/rpc/EdgeGrpcSession.java | 171 ++++---- .../DashboardUpdateMsgConstructor.java | 6 - .../DeviceUpdateMsgConstructor.java | 33 +- .../constructor/UserUpdateMsgConstructor.java | 25 +- .../edge/rpc/init/DefaultSyncEdgeService.java | 412 +++++++++++------- .../edge/rpc/init/SyncEdgeService.java | 17 +- common/edge-api/src/main/proto/edge.proto | 72 ++- .../dao/dashboard/DashboardServiceImpl.java | 2 +- .../server/dao/edge/CassandraEdgeDao.java | 16 +- .../server/dao/rule/BaseRuleChainService.java | 2 +- .../server/dao/sql/edge/JpaEdgeDao.java | 12 +- 12 files changed, 465 insertions(+), 309 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index cb90fa4345..e90ae5c383 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -26,8 +26,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.RuleChainId; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.ResponseMsg; @@ -48,7 +46,7 @@ import java.util.concurrent.Executors; public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { private final Map sessions = new ConcurrentHashMap<>(); - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectMapper mapper = new ObjectMapper(); @Value("${edges.rpc.port}") private int rpcPort; @@ -102,7 +100,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { @Override public StreamObserver handleMsgs(StreamObserver outputStream) { - return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, objectMapper).getInputStream(); + return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, mapper).getInputStream(); } private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 341142e34d..6d2637840a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -18,7 +18,6 @@ package org.thingsboard.server.service.edge.rpc; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -55,7 +54,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; -import org.thingsboard.server.common.data.kv.DataType; import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; @@ -70,14 +68,18 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectResponseCode; import org.thingsboard.server.gen.edge.ConnectResponseMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.EntityUpdateMsg; +import org.thingsboard.server.gen.edge.RelationRequestMsg; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.RequestMsgType; import org.thingsboard.server.gen.edge.ResponseMsg; @@ -86,6 +88,7 @@ import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.service.edge.EdgeContextComponent; @@ -115,7 +118,7 @@ public final class EdgeGrpcSession implements Closeable { private final UUID sessionId; private final BiConsumer sessionOpenListener; private final Consumer sessionCloseListener; - private final ObjectMapper objectMapper; + private final ObjectMapper mapper; private EdgeContextComponent ctx; private Edge edge; @@ -124,13 +127,13 @@ public final class EdgeGrpcSession implements Closeable { private boolean connected; EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener, - Consumer sessionCloseListener, ObjectMapper objectMapper) { + Consumer sessionCloseListener, ObjectMapper mapper) { this.sessionId = UUID.randomUUID(); this.ctx = ctx; this.outputStream = outputStream; this.sessionOpenListener = sessionOpenListener; this.sessionCloseListener = sessionCloseListener; - this.objectMapper = objectMapper; + this.mapper = mapper; initInputStream(); } @@ -147,7 +150,7 @@ public final class EdgeGrpcSession implements Closeable { outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); } if (ConnectResponseCode.ACCEPTED == responseMsg.getResponseCode()) { - ctx.getSyncEdgeService().sync(ctx, edge, outputStream); + ctx.getSyncEdgeService().sync(edge, outputStream); } } if (connected) { @@ -189,9 +192,6 @@ public final class EdgeGrpcSession implements Closeable { processTelemetryMessage(edgeEvent); } else { processEntityCRUDMessage(edgeEvent, msgType); - if (ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) { - pushEntityAttributesToEdge(edgeEvent); - } } } catch (Exception e) { log.error("Exception during processing records from queue", e); @@ -239,58 +239,6 @@ public final class EdgeGrpcSession implements Closeable { ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); } - private void pushEntityAttributesToEdge(EdgeEvent edgeEvent) throws IOException { - EntityId entityId = null; - switch (edgeEvent.getEdgeEventType()) { - case EDGE: - entityId = edge.getId(); - break; - case DEVICE: - entityId = new DeviceId(edgeEvent.getEntityId()); - break; - case ASSET: - entityId = new AssetId(edgeEvent.getEntityId()); - break; - case ENTITY_VIEW: - entityId = new EntityViewId(edgeEvent.getEntityId()); - break; - case DASHBOARD: - entityId = new DashboardId(edgeEvent.getEntityId()); - break; - } - if (entityId != null) { - final EntityId finalEntityId = entityId; - ListenableFuture> ssAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); - Futures.transform(ssAttrFuture, ssAttributes -> { - if (ssAttributes != null && !ssAttributes.isEmpty()) { - try { - ObjectNode entityNode = objectMapper.createObjectNode(); - for (AttributeKvEntry attr : ssAttributes) { - if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getBooleanValue().get()); - } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getDoubleValue().get()); - } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getLongValue().get()); - } else { - entityNode.put(attr.getKey(), attr.getValueAsString()); - } - } - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", finalEntityId, entityNode); - DownlinkMsg value = constructEntityDataProtoMsg(finalEntityId, ActionType.ATTRIBUTES_UPDATED, JsonUtils.parse(objectMapper.writeValueAsString(entityNode))); - outputStream.onNext(ResponseMsg.newBuilder() - .setDownlinkMsg(value).build()); - } catch (Exception e) { - log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); - } - } - return null; - }, MoreExecutors.directExecutor()); - ListenableFuture> shAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); - ListenableFuture> clAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); - } - } - private void processTelemetryMessage(EdgeEvent edgeEvent) throws IOException { log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent); EntityId entityId = null; @@ -311,7 +259,7 @@ public final class EdgeGrpcSession implements Closeable { DownlinkMsg downlinkMsg; try { ActionType actionType = ActionType.valueOf(edgeEvent.getEdgeEventAction()); - downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(objectMapper.writeValueAsString(edgeEvent.getEntityBody()))); + downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(mapper.writeValueAsString(edgeEvent.getEntityBody()))); outputStream.onNext(ResponseMsg.newBuilder() .setDownlinkMsg(downlinkMsg) .build()); @@ -617,7 +565,7 @@ public final class EdgeGrpcSession implements Closeable { } private void processRelationCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { - EntityRelation entityRelation = objectMapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); + EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() .setRelationUpdateMsg(ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation)) .build(); @@ -666,7 +614,7 @@ public final class EdgeGrpcSession implements Closeable { return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE; case ATTRIBUTES_UPDATED: case ATTRIBUTES_DELETED: - case TIMESERIES_DELETED: + case TIMESERIES_UPDATED: return null; default: throw new RuntimeException("Unsupported actionType [" + actionType + "]"); @@ -702,11 +650,17 @@ public final class EdgeGrpcSession implements Closeable { } } } + if (uplinkMsg.getDeviceUpdateMsgList() != null && !uplinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { onDeviceUpdate(deviceUpdateMsg); } } + if (uplinkMsg.getDeviceCredentialsUpdateMsgList() != null && !uplinkMsg.getDeviceCredentialsUpdateMsgList().isEmpty()) { + for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { + onDeviceCredentialsUpdate(deviceCredentialsUpdateMsg); + } + } if (uplinkMsg.getAlarmUpdateMsgList() != null && !uplinkMsg.getAlarmUpdateMsgList().isEmpty()) { for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { onAlarmUpdate(alarmUpdateMsg); @@ -714,7 +668,27 @@ public final class EdgeGrpcSession implements Closeable { } if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { - ctx.getSyncEdgeService().syncRuleChainMetadata(edge, ruleChainMetadataRequestMsg, outputStream); + ctx.getSyncEdgeService().processRuleChainMetadata(edge, ruleChainMetadataRequestMsg, outputStream); + } + } + if (uplinkMsg.getAttributesRequestMsgList() != null && !uplinkMsg.getAttributesRequestMsgList().isEmpty()) { + for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { + ctx.getSyncEdgeService().processAttributesRequestMsg(edge, attributesRequestMsg, outputStream); + } + } + if (uplinkMsg.getRelationRequestMsgList() != null && !uplinkMsg.getRelationRequestMsgList().isEmpty()) { + for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { + ctx.getSyncEdgeService().processRelationRequestMsg(edge, relationRequestMsg, outputStream); + } + } + if (uplinkMsg.getUserCredentialsRequestMsgList() != null && !uplinkMsg.getUserCredentialsRequestMsgList().isEmpty()) { + for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { + ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge, userCredentialsRequestMsg, outputStream); + } + } + if (uplinkMsg.getDeviceCredentialsRequestMsgList() != null && !uplinkMsg.getDeviceCredentialsRequestMsgList().isEmpty()) { + for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { + ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg, outputStream); } } } catch (Exception e) { @@ -850,21 +824,59 @@ public final class EdgeGrpcSession implements Closeable { device.setType(deviceUpdateMsg.getType()); device.setLabel(deviceUpdateMsg.getLabel()); device = ctx.getDeviceService().saveDevice(device); - updateDeviceCredentials(deviceUpdateMsg, device); + + requestDeviceCredentialsFromEdge(device); + } + + private void onDeviceCredentialsUpdate(DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { + log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); + DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); + ListenableFuture deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edge.getTenantId(), deviceId); + + Futures.addCallback(deviceFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable Device device) { + if (device != null) { + log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", + device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); + try { + DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId()); + deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType())); + deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId()); + deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue()); + ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials); + } catch (Exception e) { + log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); + } + log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", + device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); + } + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't update device credentials for deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg, t); + } + }, ctx.getDbCallbackExecutor()); } - private void updateDeviceCredentials(DeviceUpdateMsg deviceUpdateMsg, Device device) { - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", - device.getName(), deviceUpdateMsg.getCredentialsId(), deviceUpdateMsg.getCredentialsValue()); + private void requestDeviceCredentialsFromEdge(Device device) { + log.debug("Executing requestDeviceCredentialsFromEdge device [{}]", device); - DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId()); - deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceUpdateMsg.getCredentialsType())); - deviceCredentials.setCredentialsId(deviceUpdateMsg.getCredentialsId()); - deviceCredentials.setCredentialsValue(deviceUpdateMsg.getCredentialsValue()); - ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials); - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", - device.getName(), deviceUpdateMsg.getCredentialsId(), deviceUpdateMsg.getCredentialsValue()); + DownlinkMsg downlinkMsg = constructDeviceCredentialsRequestMsg(device.getId()); + outputStream.onNext(ResponseMsg.newBuilder() + .setDownlinkMsg(downlinkMsg) + .build()); + } + private DownlinkMsg constructDeviceCredentialsRequestMsg(DeviceId deviceId) { + DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() + .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) + .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) + .build(); + DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() + .addAllDeviceCredentialsRequestMsg(Collections.singletonList(deviceCredentialsRequestMsg)); + return builder.build(); } private Device createDevice(DeviceUpdateMsg deviceUpdateMsg) { @@ -884,7 +896,8 @@ public final class EdgeGrpcSession implements Closeable { createRelationFromEdge(device.getId()); ctx.getRelationService().saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(edge.getId(), device.getId(), "Created")); ctx.getDeviceStateService().onDeviceAdded(device); - updateDeviceCredentials(deviceUpdateMsg, device); + + requestDeviceCredentialsFromEdge(device); } finally { deviceCreationLock.unlock(); } @@ -925,7 +938,7 @@ public final class EdgeGrpcSession implements Closeable { existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); } existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); - existentAlarm.setDetails(objectMapper.readTree(alarmUpdateMsg.getDetails())); + existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails())); ctx.getAlarmService().createOrUpdateAlarm(existentAlarm); break; case ALARM_ACK_RPC_MESSAGE: @@ -935,7 +948,7 @@ public final class EdgeGrpcSession implements Closeable { break; case ALARM_CLEAR_RPC_MESSAGE: if (existentAlarm != null) { - ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), objectMapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); + ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), mapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); } break; case ENTITY_DELETED_RPC_MESSAGE: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java index 6bd24f123b..6c52464326 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java @@ -16,11 +16,9 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.id.DashboardId; -import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -29,11 +27,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Slf4j public class DashboardUpdateMsgConstructor { - @Autowired - private DashboardService dashboardService; - public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) { - dashboard = dashboardService.findDashboardById(dashboard.getTenantId(), dashboard.getId()); DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(dashboard.getId().getId().getMostSignificantBits()) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java index 8d7fbc4c25..dcef0a57c6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java @@ -16,12 +16,11 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.dao.device.DeviceCredentialsService; +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -29,9 +28,6 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Slf4j public class DeviceUpdateMsgConstructor { - @Autowired - private DeviceCredentialsService deviceCredentialsService; - public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) { DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() .setMsgType(msgType) @@ -42,20 +38,19 @@ public class DeviceUpdateMsgConstructor { if (device.getLabel() != null) { builder.setLabel(device.getLabel()); } - if (msgType.equals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE) || - msgType.equals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE) || - msgType.equals(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE)) { - DeviceCredentials deviceCredentials - = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId()); - if (deviceCredentials != null) { - if (deviceCredentials.getCredentialsType() != null) { - builder.setCredentialsType(deviceCredentials.getCredentialsType().name()) - .setCredentialsId(deviceCredentials.getCredentialsId()); - } - if (deviceCredentials.getCredentialsValue() != null) { - builder.setCredentialsValue(deviceCredentials.getCredentialsValue()); - } - } + return builder.build(); + } + + public DeviceCredentialsUpdateMsg constructDeviceCredentialsUpdatedMsg(DeviceCredentials deviceCredentials) { + DeviceCredentialsUpdateMsg.Builder builder = DeviceCredentialsUpdateMsg.newBuilder() + .setDeviceIdMSB(deviceCredentials.getDeviceId().getId().getMostSignificantBits()) + .setDeviceIdLSB(deviceCredentials.getDeviceId().getId().getLeastSignificantBits()); + if (deviceCredentials.getCredentialsType() != null) { + builder.setCredentialsType(deviceCredentials.getCredentialsType().name()) + .setCredentialsId(deviceCredentials.getCredentialsId()); + } + if (deviceCredentials.getCredentialsValue() != null) { + builder.setCredentialsValue(deviceCredentials.getCredentialsValue()); } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java index b994d8fdc4..af42448e19 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java @@ -16,31 +16,26 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.UserCredentials; -import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.UserUpdateMsg; @Component @Slf4j public class UserUpdateMsgConstructor { - @Autowired - private UserService userService; - public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user) { UserUpdateMsg.Builder builder = UserUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(user.getId().getId().getMostSignificantBits()) .setIdLSB(user.getId().getId().getLeastSignificantBits()) .setEmail(user.getEmail()) - .setAuthority(user.getAuthority().name()) - .setEnabled(false); + .setAuthority(user.getAuthority().name()); if (user.getFirstName() != null) { builder.setFirstName(user.getFirstName()); } @@ -53,13 +48,6 @@ public class UserUpdateMsgConstructor { if (user.getAdditionalInfo() != null) { builder.setAdditionalInfo(JacksonUtil.toString(user.getAdditionalInfo())); } - if (msgType.equals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE) || - msgType.equals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE)) { - UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); - if (userCredentials != null) { - builder.setEnabled(userCredentials.isEnabled()).setPassword(userCredentials.getPassword()); - } - } return builder.build(); } @@ -69,4 +57,13 @@ public class UserUpdateMsgConstructor { .setIdMSB(userId.getId().getMostSignificantBits()) .setIdLSB(userId.getId().getLeastSignificantBits()).build(); } + + public UserCredentialsUpdateMsg constructUserCredentialsUpdatedMsg(UserCredentials userCredentials) { + UserCredentialsUpdateMsg.Builder builder = UserCredentialsUpdateMsg.newBuilder() + .setUserIdMSB(userCredentials.getUserId().getId().getMostSignificantBits()) + .setUserIdLSB(userCredentials.getUserId().getId().getLeastSignificantBits()) + .setEnabled(userCredentials.isEnabled()) + .setPassword(userCredentials.getPassword()); + return builder.build(); + } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 306d1bf5f9..c300a3204d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -15,10 +15,11 @@ */ package org.thingsboard.server.service.edge.rpc.init; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; import io.grpc.stub.StreamObserver; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; @@ -26,13 +27,21 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DashboardInfo; +import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.kv.AttributeKvEntry; +import org.thingsboard.server.common.data.kv.DataType; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; @@ -43,44 +52,60 @@ import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.data.security.UserCredentials; +import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.dao.asset.AssetService; +import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.dashboard.DashboardService; +import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; +import org.thingsboard.server.gen.edge.DownlinkMsg; +import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.EntityUpdateMsg; import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; +import org.thingsboard.server.gen.edge.RelationRequestMsg; import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.ResponseMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.gen.edge.UserUpdateMsg; -import org.thingsboard.server.service.edge.EdgeContextComponent; import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor; +import org.thingsboard.server.service.executors.DbCallbackExecutorService; import java.util.ArrayList; -import java.util.HashSet; +import java.util.Collections; import java.util.List; -import java.util.Set; import java.util.UUID; @Service @Slf4j public class DefaultSyncEdgeService implements SyncEdgeService { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + private AttributesService attributesService; + @Autowired private RuleChainService ruleChainService; @@ -90,6 +115,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private DeviceService deviceService; + @Autowired + private DeviceCredentialsService deviceCredentialsService; + @Autowired private AssetService assetService; @@ -123,34 +151,29 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private RelationUpdateMsgConstructor relationUpdateMsgConstructor; - @Override - public void sync(EdgeContextComponent ctx, Edge edge, StreamObserver outputStream) { - Set pushedEntityIds = new HashSet<>(); - syncUsers(ctx, edge, pushedEntityIds, outputStream); - List> futures = new ArrayList<>(); - futures.add(syncRuleChains(ctx, edge, pushedEntityIds, outputStream)); - futures.add(syncDevices(ctx, edge, pushedEntityIds, outputStream)); - futures.add(syncAssets(ctx, edge, pushedEntityIds, outputStream)); - futures.add(syncEntityViews(ctx, edge, pushedEntityIds, outputStream)); - futures.add(syncDashboards(ctx, edge, pushedEntityIds, outputStream)); - Futures.addCallback(Futures.allAsList(futures), new FutureCallback>() { - @Override - public void onSuccess(@Nullable List result) { - syncRelations(ctx, edge, pushedEntityIds, outputStream); - } + @Autowired + private EntityDataMsgConstructor entityDataMsgConstructor; - @Override - public void onFailure(Throwable t) { - log.warn("Exception during sync entities", t); - } - }, MoreExecutors.directExecutor()); + @Autowired + private DbCallbackExecutorService dbCallbackExecutorService; + + @Override + public void sync(Edge edge, StreamObserver outputStream) { + syncUsers(edge, outputStream); + syncRuleChains(edge, outputStream); + syncDevices(edge, outputStream); + syncAssets(edge, outputStream); + syncEntityViews(edge, outputStream); + syncDashboards(edge, outputStream); } - private ListenableFuture syncRuleChains(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void syncRuleChains(Edge edge, StreamObserver outputStream) { try { - ListenableFuture> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); - return Futures.transform(future, pageData -> { - try { + ListenableFuture> future = + ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable TimePageData pageData) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] rule chains(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (RuleChain ruleChain : pageData.getData()) { @@ -165,81 +188,93 @@ public class DefaultSyncEdgeService implements SyncEdgeService { outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) .build()); - pushedEntityIds.add(ruleChain.getId()); } } - } catch (Exception e) { - log.error("Exception during loading edge rule chain(s) on sync!", e); } - return null; - }, ctx.getDbCallbackExecutor()); + + @Override + public void onFailure(Throwable t) { + log.error("Exception during loading edge rule chain(s) on sync!", t); + } + }, dbCallbackExecutorService); } catch (Exception e) { log.error("Exception during loading edge rule chain(s) on sync!", e); - return Futures.immediateFuture(null); } } - private ListenableFuture syncDevices(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void syncDevices(Edge edge, StreamObserver outputStream) { try { - ListenableFuture> future = deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); - return Futures.transform(future, pageData -> { - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); - for (Device device : pageData.getData()) { - DeviceUpdateMsg deviceUpdateMsg = - deviceUpdateMsgConstructor.constructDeviceUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - device); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(deviceUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - pushedEntityIds.add(device.getId()); + ListenableFuture> future = + deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable TimePageData pageData) { + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { + log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); + for (Device device : pageData.getData()) { + DeviceUpdateMsg deviceUpdateMsg = + deviceUpdateMsgConstructor.constructDeviceUpdatedMsg( + UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, + device); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setDeviceUpdateMsg(deviceUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } } - return null; - }, ctx.getDbCallbackExecutor()); + + @Override + public void onFailure(Throwable t) { + log.error("Exception during loading edge device(s) on sync!", t); + } + }, dbCallbackExecutorService); } catch (Exception e) { log.error("Exception during loading edge device(s) on sync!", e); - return Futures.immediateFuture(null); } } - private ListenableFuture syncAssets(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void syncAssets(Edge edge, StreamObserver outputStream) { try { ListenableFuture> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); - return Futures.transform(future, pageData -> { - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - log.trace("[{}] [{}] asset(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); - for (Asset asset : pageData.getData()) { - AssetUpdateMsg assetUpdateMsg = - assetUpdateMsgConstructor.constructAssetUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - asset); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAssetUpdateMsg(assetUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - pushedEntityIds.add(asset.getId()); + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable TimePageData pageData) { + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { + log.trace("[{}] [{}] asset(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); + for (Asset asset : pageData.getData()) { + AssetUpdateMsg assetUpdateMsg = + assetUpdateMsgConstructor.constructAssetUpdatedMsg( + UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, + asset); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setAssetUpdateMsg(assetUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } } - return null; - }, ctx.getDbCallbackExecutor()); + + @Override + public void onFailure(Throwable t) { + log.error("Exception during loading edge asset(s) on sync!", t); + } + }, dbCallbackExecutorService); } catch (Exception e) { log.error("Exception during loading edge asset(s) on sync!", e); - return Futures.immediateFuture(null); } } - private ListenableFuture syncEntityViews(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void syncEntityViews(Edge edge, StreamObserver outputStream) { try { ListenableFuture> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); - return Futures.transform(future, pageData -> { - try { + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable TimePageData pageData) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] entity view(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (EntityView entityView : pageData.getData()) { @@ -253,25 +288,26 @@ public class DefaultSyncEdgeService implements SyncEdgeService { outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) .build()); - pushedEntityIds.add(entityView.getId()); } } - } catch (Exception e) { - log.error("Exception during loading edge entity view(s) on sync!", e); } - return null; - }, ctx.getDbCallbackExecutor()); + + @Override + public void onFailure(Throwable t) { + log.error("Exception during loading edge entity view(s) on sync!", t); + } + }, dbCallbackExecutorService); } catch (Exception e) { log.error("Exception during loading edge entity view(s) on sync!", e); - return Futures.immediateFuture(null); } } - private ListenableFuture syncDashboards(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void syncDashboards(Edge edge, StreamObserver outputStream) { try { ListenableFuture> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); - return Futures.transform(future, pageData -> { - try { + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable TimePageData pageData) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] dashboard(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (DashboardInfo dashboardInfo : pageData.getData()) { @@ -286,34 +322,34 @@ public class DefaultSyncEdgeService implements SyncEdgeService { outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) .build()); - pushedEntityIds.add(dashboard.getId()); } } - } catch (Exception e) { - log.error("Exception during loading edge dashboard(s) on sync!", e); } - return null; - }, ctx.getDbCallbackExecutor()); + + @Override + public void onFailure(Throwable t) { + log.error("Exception during loading edge dashboard(s) on sync!", t); + } + }, dbCallbackExecutorService); } catch (Exception e) { log.error("Exception during loading edge dashboard(s) on sync!", e); - return Futures.immediateFuture(null); } } - private void syncUsers(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void syncUsers(Edge edge, StreamObserver outputStream) { try { TextPageData pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE)); - pushUsersToEdge(pageData, edge, pushedEntityIds, outputStream); + pushUsersToEdge(pageData, edge, outputStream); if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE)); - pushUsersToEdge(pageData, edge, pushedEntityIds, outputStream); + pushUsersToEdge(pageData, edge, outputStream); } } catch (Exception e) { log.error("Exception during loading edge user(s) on sync!", e); } } - private void pushUsersToEdge(TextPageData pageData, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { + private void pushUsersToEdge(TextPageData pageData, Edge edge, StreamObserver outputStream) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (User user : pageData.getData()) { @@ -327,81 +363,161 @@ public class DefaultSyncEdgeService implements SyncEdgeService { outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) .build()); - pushedEntityIds.add(user.getId()); } } } - private ListenableFuture syncRelations(EdgeContextComponent ctx, Edge edge, Set pushedEntityIds, StreamObserver outputStream) { - if (!pushedEntityIds.isEmpty()) { - List>> futures = new ArrayList<>(); - for (EntityId entityId : pushedEntityIds) { - futures.add(syncRelations(edge, entityId, EntitySearchDirection.FROM)); - futures.add(syncRelations(edge, entityId, EntitySearchDirection.TO)); + @Override + public void processRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver outputStream) { + if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { + RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); + RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(edge.getTenantId(), ruleChainId); + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = + ruleChainUpdateMsgConstructor.constructRuleChainMetadataUpdatedMsg( + UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, + ruleChainMetaData); + if (ruleChainMetadataUpdateMsg != null) { + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } + } + + @Override + public void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg, StreamObserver outputStream) { + EntityId entityId = EntityIdFactory.getByTypeAndUuid( + EntityType.valueOf(attributesRequestMsg.getEntityType()), + new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB())); + ListenableFuture> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); + Futures.addCallback(ssAttrFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List ssAttributes) { + if (ssAttributes != null && !ssAttributes.isEmpty()) { + try { + ObjectNode entityNode = mapper.createObjectNode(); + for (AttributeKvEntry attr : ssAttributes) { + if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { + entityNode.put(attr.getKey(), attr.getBooleanValue().get()); + } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { + entityNode.put(attr.getKey(), attr.getDoubleValue().get()); + } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { + entityNode.put(attr.getKey(), attr.getLongValue().get()); + } else { + entityNode.put(attr.getKey(), attr.getValueAsString()); + } + } + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityNode); + + EntityDataProto entityDataProto = + entityDataMsgConstructor.constructEntityDataMsg( + entityId, + ActionType.ATTRIBUTES_UPDATED, + JsonUtils.parse(mapper.writeValueAsString(entityNode))); + DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() + .addAllEntityData(Collections.singletonList(entityDataProto)); + DownlinkMsg value = builder.build(); + + outputStream.onNext(ResponseMsg.newBuilder() + .setDownlinkMsg(value).build()); + } catch (Exception e) { + log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); + } + } + } + + @Override + public void onFailure(Throwable t) { + } - ListenableFuture>> relationsListFuture = Futures.allAsList(futures); - return Futures.transform(relationsListFuture, relationsList -> { + }, dbCallbackExecutorService); + + // TODO: voba - push shared attributes to edge? + ListenableFuture> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); + ListenableFuture> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); + } + + @Override + public void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg, StreamObserver outputStream) { + EntityId entityId = EntityIdFactory.getByTypeAndUuid( + EntityType.valueOf(relationRequestMsg.getEntityType()), + new UUID(relationRequestMsg.getEntityIdMSB(), relationRequestMsg.getEntityIdLSB())); + + List>> futures = new ArrayList<>(); + futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.FROM)); + futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.TO)); + ListenableFuture>> relationsListFuture = Futures.allAsList(futures); + Futures.addCallback(relationsListFuture, new FutureCallback>>() { + @Override + public void onSuccess(@Nullable List> relationsList) { try { - Set uniqueEntityRelations = new HashSet<>(); if (!relationsList.isEmpty()) { for (List entityRelations : relationsList) { - if (!entityRelations.isEmpty()) { - uniqueEntityRelations.addAll(entityRelations); - } - } - } - if (!uniqueEntityRelations.isEmpty()) { - log.trace("[{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), uniqueEntityRelations.size()); - for (EntityRelation relation : uniqueEntityRelations) { - try { - RelationUpdateMsg relationUpdateMsg = - relationUpdateMsgConstructor.constructRelationUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - relation); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRelationUpdateMsg(relationUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } catch (Exception e) { - log.error("Exception during loading relation [{}] to edge on sync!", relation, e); + log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size()); + for (EntityRelation relation : entityRelations) { + try { + RelationUpdateMsg relationUpdateMsg = + relationUpdateMsgConstructor.constructRelationUpdatedMsg( + UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, + relation); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setRelationUpdateMsg(relationUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } catch (Exception e) { + log.error("Exception during loading relation [{}] to edge on sync!", relation, e); + } } } } } catch (Exception e) { log.error("Exception during loading relation(s) to edge on sync!", e); } - return null; - }, ctx.getDbCallbackExecutor()); - } else { - return Futures.immediateFuture(null); - } + } + + @Override + public void onFailure(Throwable t) { + log.error("Exception during loading relation(s) to edge on sync!", t); + } + }, dbCallbackExecutorService); } - private ListenableFuture> syncRelations(Edge edge, EntityId entityId, EntitySearchDirection direction) { + private ListenableFuture> findRelationByQuery(Edge edge, EntityId entityId, EntitySearchDirection direction) { EntityRelationsQuery query = new EntityRelationsQuery(); query.setParameters(new RelationsSearchParameters(entityId, direction, -1, false)); return relationService.findByQuery(edge.getTenantId(), query); } @Override - public void syncRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver outputStream) { - if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { - RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); - RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(edge.getTenantId(), ruleChainId); - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = - ruleChainUpdateMsgConstructor.constructRuleChainMetadataUpdatedMsg( - UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, - ruleChainMetaData); - if (ruleChainMetadataUpdateMsg != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg, StreamObserver outputStream) { + DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId); + if (deviceCredentials != null) { + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setDeviceCredentialsUpdateMsg(deviceUpdateMsgConstructor.constructDeviceCredentialsUpdatedMsg(deviceCredentials)) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } + + @Override + public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg, StreamObserver outputStream) { + UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); + UserCredentials userCredentialsByUserId = userService.findUserCredentialsByUserId(edge.getTenantId(), userId); + if (userCredentialsByUserId != null) { + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setUserCredentialsUpdateMsg(userUpdateMsgConstructor.constructUserCredentialsUpdatedMsg(userCredentialsByUserId)) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); } } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java index 84b4d9ffff..dbcb659daf 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java @@ -17,13 +17,24 @@ package org.thingsboard.server.service.edge.rpc.init; import io.grpc.stub.StreamObserver; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.gen.edge.AttributesRequestMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.RelationRequestMsg; import org.thingsboard.server.gen.edge.ResponseMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; -import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; public interface SyncEdgeService { - void sync(EdgeContextComponent ctx, Edge edge, StreamObserver outputStream); + void sync(Edge edge, StreamObserver outputStream); - void syncRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver outputStream); + void processRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver outputStream); + + void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg, StreamObserver outputStream); + + void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg, StreamObserver outputStream); + + void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg, StreamObserver outputStream); + + void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg, StreamObserver outputStream); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 38cbe7092c..8c33a55a6e 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -48,15 +48,17 @@ message ResponseMsg { message EntityUpdateMsg { DeviceUpdateMsg deviceUpdateMsg = 1; - RuleChainUpdateMsg ruleChainUpdateMsg = 2; - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 3; - DashboardUpdateMsg dashboardUpdateMsg = 4; - AssetUpdateMsg assetUpdateMsg = 5; - EntityViewUpdateMsg entityViewUpdateMsg = 6; - AlarmUpdateMsg alarmUpdateMsg = 7; - UserUpdateMsg userUpdateMsg = 8; - CustomerUpdateMsg customerUpdateMsg = 9; - RelationUpdateMsg relationUpdateMsg = 10; + DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 2; + RuleChainUpdateMsg ruleChainUpdateMsg = 3; + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 4; + DashboardUpdateMsg dashboardUpdateMsg = 5; + AssetUpdateMsg assetUpdateMsg = 6; + EntityViewUpdateMsg entityViewUpdateMsg = 7; + AlarmUpdateMsg alarmUpdateMsg = 8; + UserUpdateMsg userUpdateMsg = 9; + UserCredentialsUpdateMsg userCredentialsUpdateMsg = 10; + CustomerUpdateMsg customerUpdateMsg = 11; + RelationUpdateMsg relationUpdateMsg = 12; } enum RequestMsgType { @@ -169,9 +171,14 @@ message DeviceUpdateMsg { string name = 4; string type = 5; string label = 6; - string credentialsType = 7; - string credentialsId = 8; - string credentialsValue = 9; +} + +message DeviceCredentialsUpdateMsg { + int64 deviceIdMSB = 1; + int64 deviceIdLSB = 2; + string credentialsType = 3; + string credentialsId = 4; + string credentialsValue = 5; } message AssetUpdateMsg { @@ -248,8 +255,13 @@ message UserUpdateMsg { string firstName = 6; string lastName = 7; string additionalInfo = 8; - bool enabled = 9; - string password = 10; +} + +message UserCredentialsUpdateMsg { + int64 userIdMSB = 1; + int64 userIdLSB = 2; + bool enabled = 3; + string password = 4; } message RuleChainMetadataRequestMsg { @@ -257,6 +269,28 @@ message RuleChainMetadataRequestMsg { int64 ruleChainIdLSB = 2; } +message AttributesRequestMsg { + int64 entityIdMSB = 1; + int64 entityIdLSB = 2; + string entityType = 3; +} + +message RelationRequestMsg { + int64 entityIdMSB = 1; + int64 entityIdLSB = 2; + string entityType = 3; +} + +message UserCredentialsRequestMsg { + int64 userIdMSB = 1; + int64 userIdLSB = 2; +} + +message DeviceCredentialsRequestMsg { + int64 deviceIdMSB = 1; + int64 deviceIdLSB = 2; +} + enum EdgeEntityType { DEVICE = 0; ASSET = 1; @@ -270,8 +304,13 @@ message UplinkMsg { int32 uplinkMsgId = 1; repeated EntityDataProto entityData = 2; repeated DeviceUpdateMsg deviceUpdateMsg = 3; - repeated AlarmUpdateMsg alarmUpdateMsg = 4; - repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 5; + repeated DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 4; + repeated AlarmUpdateMsg alarmUpdateMsg = 5; + repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 6; + repeated AttributesRequestMsg attributesRequestMsg = 7; + repeated RelationRequestMsg relationRequestMsg = 8; + repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 9; + repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 10; } message UplinkResponseMsg { @@ -282,5 +321,6 @@ message UplinkResponseMsg { message DownlinkMsg { int32 downlinkMsgId = 1; repeated EntityDataProto entityData = 2; + repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 3; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java index ae3f787e5a..06bf99f5c3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java @@ -232,7 +232,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb if (edge == null) { throw new DataValidationException("Can't assign dashboard to non-existent edge!"); } - if (!edge.getTenantId().getId().equals(dashboard.getTenantId().getId())) { + if (!edge.getTenantId().equals(dashboard.getTenantId())) { throw new DataValidationException("Can't assign dashboard to edge from different tenant!"); } try { diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java index fbe44c2267..ec99c673a6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java @@ -22,17 +22,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntitySubtype; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.DashboardId; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.model.nosql.EdgeEntity; import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; import org.thingsboard.server.dao.relation.RelationDao; @@ -113,19 +109,17 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao> findEdgesByTenantIdAndRuleChainId(UUID tenantId, UUID ruleChainId) { log.debug("Try to find edges by tenantId [{}], ruleChainId [{}]", tenantId, ruleChainId); ListenableFuture> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new RuleChainId(ruleChainId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); - return Futures.transformAsync(relations, input -> { - List> edgeFutures = new ArrayList<>(input.size()); - for (EntityRelation relation : input) { - edgeFutures.add(findByIdAsync(new TenantId(tenantId), relation.getFrom().getId())); - } - return Futures.successfulAsList(edgeFutures); - }, MoreExecutors.directExecutor()); + return transformFromRelationToEdge(tenantId, relations); } @Override public ListenableFuture> findEdgesByTenantIdAndDashboardId(UUID tenantId, UUID dashboardId) { log.debug("Try to find edges by tenantId [{}], dashboardId [{}]", tenantId, dashboardId); ListenableFuture> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new DashboardId(dashboardId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); + return transformFromRelationToEdge(tenantId, relations); + } + + private ListenableFuture> transformFromRelationToEdge(UUID tenantId, ListenableFuture> relations) { return Futures.transformAsync(relations, input -> { List> edgeFutures = new ArrayList<>(input.size()); for (EntityRelation relation : input) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index d07f0704ca..73272c3328 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -414,7 +414,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC if (edge == null) { throw new DataValidationException("Can't assign ruleChain to non-existent edge!"); } - if (!edge.getTenantId().getId().equals(ruleChain.getTenantId().getId())) { + if (!edge.getTenantId().equals(ruleChain.getTenantId())) { throw new DataValidationException("Can't assign ruleChain to edge from different tenant!"); } try { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java index 6a18a4e039..feacf23f5e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java @@ -151,19 +151,17 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao imple public ListenableFuture> findEdgesByTenantIdAndRuleChainId(UUID tenantId, UUID ruleChainId) { log.debug("Try to find edges by tenantId [{}], ruleChainId [{}]", tenantId, ruleChainId); ListenableFuture> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new RuleChainId(ruleChainId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); - return Futures.transformAsync(relations, input -> { - List> edgeFutures = new ArrayList<>(input.size()); - for (EntityRelation relation : input) { - edgeFutures.add(findByIdAsync(new TenantId(tenantId), relation.getFrom().getId())); - } - return Futures.successfulAsList(edgeFutures); - }, MoreExecutors.directExecutor()); + return transformFromRelationToEdge(tenantId, relations); } @Override public ListenableFuture> findEdgesByTenantIdAndDashboardId(UUID tenantId, UUID dashboardId) { log.debug("Try to find edges by tenantId [{}], dashboardId [{}]", tenantId, dashboardId); ListenableFuture> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new DashboardId(dashboardId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); + return transformFromRelationToEdge(tenantId, relations); + } + + private ListenableFuture> transformFromRelationToEdge(UUID tenantId, ListenableFuture> relations) { return Futures.transformAsync(relations, input -> { List> edgeFutures = new ArrayList<>(input.size()); for (EntityRelation relation : input) { From 3d8db0dbc8d21fc53bfe997c39a66d0e644d7e06 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 24 Jun 2020 09:21:23 +0300 Subject: [PATCH 006/156] Removed unused options --- .../thingsboard/server/service/edge/rpc/EdgeGrpcSession.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 6d2637840a..e4b2d761cc 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -350,7 +350,6 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - case DEVICE_CONFLICT_RPC_MESSAGE: ListenableFuture assetFuture = ctx.getAssetService().findAssetByIdAsync(edgeEvent.getTenantId(), assetId); Futures.addCallback(assetFuture, new FutureCallback() { @@ -388,7 +387,6 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - case DEVICE_CONFLICT_RPC_MESSAGE: ListenableFuture entityViewFuture = ctx.getEntityViewService().findEntityViewByIdAsync(edgeEvent.getTenantId(), entityViewId); Futures.addCallback(entityViewFuture, new FutureCallback() { @@ -426,7 +424,6 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - case DEVICE_CONFLICT_RPC_MESSAGE: ListenableFuture dashboardFuture = ctx.getDashboardService().findDashboardByIdAsync(edgeEvent.getTenantId(), dashboardId); Futures.addCallback(dashboardFuture, new FutureCallback() { From cd70b6fb54644c198a1cadb37f03e88142307237 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Wed, 24 Jun 2020 12:39:58 +0300 Subject: [PATCH 007/156] fixed bug + some refractoring --- .../server/common/data/edge/EdgeEvent.java | 1 - .../rule/engine/edge/TbMsgPushToEdgeNode.java | 64 +++++++++++-------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java index 1c9ea9343c..f108db0056 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java @@ -20,7 +20,6 @@ import lombok.Data; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.EdgeEventId; import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import java.util.UUID; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index ad757220b3..97b0c1c8a0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -15,6 +15,7 @@ */ package org.thingsboard.rule.engine.edge; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -77,33 +78,35 @@ public class TbMsgPushToEdgeNode implements TbNode { if (isSupportedOriginator(msg.getOriginator().getEntityType())) { if (isSupportedMsgType(msg.getType())) { ListenableFuture getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator()); - Futures.transform(getEdgeIdFuture, edgeId -> { - EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); - if (edgeEventTypeByEntityType == null) { - log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); - ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); - } - EdgeEvent edgeEvent = new EdgeEvent(); - edgeEvent.setTenantId(ctx.getTenantId()); - edgeEvent.setEdgeId(edgeId); - edgeEvent.setEdgeEventAction(getActionTypeByMsgType(msg.getType()).name()); - edgeEvent.setEntityId(msg.getOriginator().getId()); - edgeEvent.setEdgeEventType(edgeEventTypeByEntityType); - edgeEvent.setEntityBody(json.valueToTree(msg.getData())); - ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); - Futures.addCallback(saveFuture, new FutureCallback() { - @Override - public void onSuccess(@Nullable EdgeEvent event) { - ctx.tellNext(msg, SUCCESS); + Futures.addCallback(getEdgeIdFuture, new FutureCallback() { + @Override + public void onSuccess(@org.checkerframework.checker.nullness.qual.Nullable EdgeId edgeId) { + EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); + if (edgeEventTypeByEntityType == null) { + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); } - - @Override - public void onFailure(Throwable th) { - log.error("Could not save edge event", th); - ctx.tellFailure(msg, th); + EdgeEvent edgeEvent = null; + try { + edgeEvent = buildEdgeEvent(ctx, msg, edgeId, edgeEventTypeByEntityType); + } catch (JsonProcessingException e) { + log.error("Failed to build edge event", e); } - }, ctx.getDbCallbackExecutor()); - return null; + ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); + Futures.addCallback(saveFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent event) { + ctx.tellNext(msg, SUCCESS); + } @Override + public void onFailure(Throwable th) { + log.error("Could not save edge event", th); + ctx.tellFailure(msg, th); + } + }, ctx.getDbCallbackExecutor()); + } @Override + public void onFailure(Throwable t) { + ctx.tellFailure(msg, t); + } }, ctx.getDbCallbackExecutor()); } else { log.debug("Unsupported msg type {}", msg.getType()); @@ -115,6 +118,17 @@ public class TbMsgPushToEdgeNode implements TbNode { } } + private EdgeEvent buildEdgeEvent(TbContext ctx, TbMsg msg, EdgeId edgeId, EdgeEventType edgeEventTypeByEntityType) throws JsonProcessingException { + EdgeEvent edgeEvent = new EdgeEvent(); + edgeEvent.setTenantId(ctx.getTenantId()); + edgeEvent.setEdgeId(edgeId); + edgeEvent.setEdgeEventAction(getActionTypeByMsgType(msg.getType()).name()); + edgeEvent.setEntityId(msg.getOriginator().getId()); + edgeEvent.setEdgeEventType(edgeEventTypeByEntityType); + edgeEvent.setEntityBody(json.readTree(msg.getData())); + return edgeEvent; + } + private ActionType getActionTypeByMsgType(String msgType) { ActionType actionType; if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msgType)) { From 53eb60e67dce00c2af9e71dccebbdf64794fc612 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Wed, 24 Jun 2020 15:58:08 +0300 Subject: [PATCH 008/156] fixes --- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 97b0c1c8a0..7b96bb45f6 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -80,7 +80,7 @@ public class TbMsgPushToEdgeNode implements TbNode { ListenableFuture getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator()); Futures.addCallback(getEdgeIdFuture, new FutureCallback() { @Override - public void onSuccess(@org.checkerframework.checker.nullness.qual.Nullable EdgeId edgeId) { + public void onSuccess(@Nullable EdgeId edgeId) { EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); if (edgeEventTypeByEntityType == null) { log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); @@ -97,16 +97,19 @@ public class TbMsgPushToEdgeNode implements TbNode { @Override public void onSuccess(@Nullable EdgeEvent event) { ctx.tellNext(msg, SUCCESS); - } @Override + } + @Override public void onFailure(Throwable th) { log.error("Could not save edge event", th); ctx.tellFailure(msg, th); } }, ctx.getDbCallbackExecutor()); - } @Override + } + @Override public void onFailure(Throwable t) { ctx.tellFailure(msg, t); } + }, ctx.getDbCallbackExecutor()); } else { log.debug("Unsupported msg type {}", msg.getType()); From 1cfb7fa5017d60c855e42fec8b34c09dd01b9181 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 25 Jun 2020 10:53:12 +0300 Subject: [PATCH 009/156] removed wildcard import --- .../org/thingsboard/rest/client/RestClient.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 1e4fb1088a..11a46055b2 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -47,7 +47,6 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeSearchQuery; -import org.thingsboard.server.common.data.id.*; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; @@ -58,6 +57,20 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.device.DeviceSearchQuery; import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityViewId; +import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.RuleNodeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.id.WidgetTypeId; +import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.kv.Aggregation; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; From d1c1b44499b92bf130886b0aded651017198b9da Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 25 Jun 2020 11:32:55 +0300 Subject: [PATCH 010/156] Fixed multithread issue with gRPC session - push from a single thread --- .../edge/DefaultEdgeNotificationService.java | 12 +- .../service/edge/rpc/EdgeGrpcSession.java | 340 +++++++++--------- .../edge/rpc/init/DefaultSyncEdgeService.java | 299 +++++++-------- .../edge/rpc/init/SyncEdgeService.java | 14 +- .../common/data/edge/EdgeEventType.java | 14 +- 5 files changed, 307 insertions(+), 372 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index ab319fc872..5206a40f6a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -76,9 +76,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @Autowired private EdgeService edgeService; - @Autowired - private RuleChainService ruleChainService; - @Autowired private AlarmService alarmService; @@ -185,10 +182,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { for (EdgeId edgeId : edgeIds) { try { saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); - if (edgeEventType.equals(EdgeEventType.RULE_CHAIN)) { - RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, new RuleChainId(entityId.getId())); - saveEdgeEvent(tenantId, edgeId, EdgeEventType.RULE_CHAIN_METADATA, edgeEventActionType, ruleChainMetaData.getRuleChainId(), null); - } } catch (Exception e) { log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]", tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e); @@ -278,7 +271,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case DEVICE: case ASSET: case ENTITY_VIEW: - ListenableFuture> originatorEdgeRelationsFuture = relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); + ListenableFuture> originatorEdgeRelationsFuture = + relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); @@ -314,7 +308,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case ENTITY_VIEW: return EdgeEventType.ENTITY_VIEW; default: - log.info("Unsupported entity type: [{}]", entityType); + log.debug("Unsupported entity type: [{}]", entityType); return null; } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index e4b2d761cc..1c21599aa8 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -63,15 +63,18 @@ import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; +import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectResponseCode; import org.thingsboard.server.gen.edge.ConnectResponseMsg; +import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; @@ -79,16 +82,19 @@ import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.EntityUpdateMsg; +import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.RequestMsgType; import org.thingsboard.server.gen.edge.ResponseMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.service.edge.EdgeContextComponent; @@ -150,7 +156,7 @@ public final class EdgeGrpcSession implements Closeable { outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); } if (ConnectResponseCode.ACCEPTED == responseMsg.getResponseCode()) { - ctx.getSyncEdgeService().sync(edge, outputStream); + ctx.getSyncEdgeService().sync(edge); } } if (connected) { @@ -279,6 +285,9 @@ public final class EdgeGrpcSession implements Closeable { case DEVICE: processDeviceCRUD(edgeEvent, msgType); break; + case DEVICE_CREDENTIALS: + processDeviceCredentialsCRUD(edgeEvent, msgType); + break; case ASSET: processAssetCRUD(edgeEvent, msgType); break; @@ -300,6 +309,9 @@ public final class EdgeGrpcSession implements Closeable { case USER: processUserCRUD(edgeEvent, msgType); break; + case USER_CREDENTIALS: + processUserCredentialsCRUD(edgeEvent, msgType); + break; case RELATION: processRelationCRUD(edgeEvent, msgType); break; @@ -312,37 +324,48 @@ public final class EdgeGrpcSession implements Closeable { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: case DEVICE_CONFLICT_RPC_MESSAGE: - ListenableFuture deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edgeEvent.getTenantId(), deviceId); - Futures.addCallback(deviceFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable Device device) { - if (device != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processDeviceCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + Device device = ctx.getDeviceService().findDeviceById(edgeEvent.getTenantId(), deviceId); + if (device != null) { + DeviceUpdateMsg deviceUpdateMsg = + ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setDeviceUpdateMsg(deviceUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } break; case ENTITY_DELETED_RPC_MESSAGE: + DeviceUpdateMsg deviceUpdateMsg = + ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId)) + .setDeviceUpdateMsg(deviceUpdateMsg) .build(); outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) .build()); } + } - + private void processDeviceCredentialsCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); + switch (msgType) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId); + if (deviceCredentials != null) { + DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = + ctx.getDeviceUpdateMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setDeviceCredentialsUpdateMsg(deviceCredentialsUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + break; + } } private void processAssetCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { @@ -350,30 +373,23 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - ListenableFuture assetFuture = ctx.getAssetService().findAssetByIdAsync(edgeEvent.getTenantId(), assetId); - Futures.addCallback(assetFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable Asset asset) { - if (asset != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAssetUpdateMsg(ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processAssetCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + Asset asset = ctx.getAssetService().findAssetById(edgeEvent.getTenantId(), assetId); + if (asset != null) { + AssetUpdateMsg assetUpdateMsg = + ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setAssetUpdateMsg(assetUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } break; case ENTITY_DELETED_RPC_MESSAGE: + AssetUpdateMsg assetUpdateMsg = + ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAssetUpdateMsg(ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId)) + .setAssetUpdateMsg(assetUpdateMsg) .build(); outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) @@ -387,30 +403,23 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - ListenableFuture entityViewFuture = ctx.getEntityViewService().findEntityViewByIdAsync(edgeEvent.getTenantId(), entityViewId); - Futures.addCallback(entityViewFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable EntityView entityView) { - if (entityView != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setEntityViewUpdateMsg(ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processEntityViewCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + EntityView entityView = ctx.getEntityViewService().findEntityViewById(edgeEvent.getTenantId(), entityViewId); + if (entityView != null) { + EntityViewUpdateMsg entityViewUpdateMsg = + ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setEntityViewUpdateMsg(entityViewUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } break; case ENTITY_DELETED_RPC_MESSAGE: + EntityViewUpdateMsg entityViewUpdateMsg = + ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setEntityViewUpdateMsg(ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId)) + .setEntityViewUpdateMsg(entityViewUpdateMsg) .build(); outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) @@ -424,30 +433,23 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - ListenableFuture dashboardFuture = ctx.getDashboardService().findDashboardByIdAsync(edgeEvent.getTenantId(), dashboardId); - Futures.addCallback(dashboardFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable Dashboard dashboard) { - if (dashboard != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDashboardUpdateMsg(ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processDashboardCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + Dashboard dashboard = ctx.getDashboardService().findDashboardById(edgeEvent.getTenantId(), dashboardId); + if (dashboard != null) { + DashboardUpdateMsg dashboardUpdateMsg = + ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setDashboardUpdateMsg(dashboardUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } break; case ENTITY_DELETED_RPC_MESSAGE: + DashboardUpdateMsg dashboardUpdateMsg = + ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDashboardUpdateMsg(ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId)) + .setDashboardUpdateMsg(dashboardUpdateMsg) .build(); outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) @@ -461,27 +463,17 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - case DEVICE_CONFLICT_RPC_MESSAGE: - ListenableFuture ruleChainFuture = ctx.getRuleChainService().findRuleChainByIdAsync(edgeEvent.getTenantId(), ruleChainId); - Futures.addCallback(ruleChainFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable RuleChain ruleChain) { - if (ruleChain != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainUpdateMsg(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processRuleChainCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); + if (ruleChain != null) { + RuleChainUpdateMsg ruleChainUpdateMsg = + ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setRuleChainUpdateMsg(ruleChainUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } break; case ENTITY_DELETED_RPC_MESSAGE: EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() @@ -496,31 +488,20 @@ public final class EdgeGrpcSession implements Closeable { private void processRuleChainMetadataCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); - ListenableFuture ruleChainFuture = ctx.getRuleChainService().findRuleChainByIdAsync(edgeEvent.getTenantId(), ruleChainId); - Futures.addCallback(ruleChainFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable RuleChain ruleChain) { - if (ruleChain != null) { - RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId); - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = - ctx.getRuleChainUpdateMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData); - if (ruleChainMetadataUpdateMsg != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processRuleChainMetadataCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); + if (ruleChain != null) { + RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId); + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = + ctx.getRuleChainUpdateMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData); + if (ruleChainMetadataUpdateMsg != null) { + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } } private void processUserCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { @@ -528,27 +509,15 @@ public final class EdgeGrpcSession implements Closeable { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - case DEVICE_CONFLICT_RPC_MESSAGE: - ListenableFuture userFuture = ctx.getUserService().findUserByIdAsync(edgeEvent.getTenantId(), userId); - Futures.addCallback(userFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable User user) { - if (user != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processUserCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + User user = ctx.getUserService().findUserById(edgeEvent.getTenantId(), userId); + if (user != null) { + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user)) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } break; case ENTITY_DELETED_RPC_MESSAGE: EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() @@ -561,6 +530,26 @@ public final class EdgeGrpcSession implements Closeable { } } + private void processUserCredentialsCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + UserId userId = new UserId(edgeEvent.getEntityId()); + switch (msgType) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + UserCredentials userCredentialsByUserId = ctx.getUserService().findUserCredentialsByUserId(edge.getTenantId(), userId); + if (userCredentialsByUserId != null) { + UserCredentialsUpdateMsg userCredentialsUpdateMsg = + ctx.getUserUpdateMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setUserCredentialsUpdateMsg(userCredentialsUpdateMsg) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + break; + } + } + private void processRelationCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() @@ -572,27 +561,20 @@ public final class EdgeGrpcSession implements Closeable { } private void processAlarmCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { - AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); - ListenableFuture alarmFuture = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId); - Futures.addCallback(alarmFuture, - new FutureCallback() { - @Override - public void onSuccess(@Nullable Alarm alarm) { - if (alarm != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAlarmUpdateMsg(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("Can't processAlarmCRUD, edgeEvent [{}]", edgeEvent, t); - } - }, ctx.getDbCallbackExecutor()); + try { + AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); + Alarm alarm = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); + if (alarm != null) { + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setAlarmUpdateMsg(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm)) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } catch (Exception e) { + log.error("Can't process alarm CRUD msg [{}] [{}]", edgeEvent, msgType, e); + } } private UpdateMsgType getResponseMsgType(ActionType actionType) { @@ -665,27 +647,27 @@ public final class EdgeGrpcSession implements Closeable { } if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { - ctx.getSyncEdgeService().processRuleChainMetadata(edge, ruleChainMetadataRequestMsg, outputStream); + ctx.getSyncEdgeService().processRuleChainMetadataRequestMsg(edge, ruleChainMetadataRequestMsg); } } if (uplinkMsg.getAttributesRequestMsgList() != null && !uplinkMsg.getAttributesRequestMsgList().isEmpty()) { for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { - ctx.getSyncEdgeService().processAttributesRequestMsg(edge, attributesRequestMsg, outputStream); + ctx.getSyncEdgeService().processAttributesRequestMsg(edge, attributesRequestMsg); } } if (uplinkMsg.getRelationRequestMsgList() != null && !uplinkMsg.getRelationRequestMsgList().isEmpty()) { for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { - ctx.getSyncEdgeService().processRelationRequestMsg(edge, relationRequestMsg, outputStream); + ctx.getSyncEdgeService().processRelationRequestMsg(edge, relationRequestMsg); } } if (uplinkMsg.getUserCredentialsRequestMsgList() != null && !uplinkMsg.getUserCredentialsRequestMsgList().isEmpty()) { for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { - ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge, userCredentialsRequestMsg, outputStream); + ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge, userCredentialsRequestMsg); } } if (uplinkMsg.getDeviceCredentialsRequestMsgList() != null && !uplinkMsg.getDeviceCredentialsRequestMsgList().isEmpty()) { for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { - ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg, outputStream); + ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg); } } } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index c300a3204d..ac6c5ebd05 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.edge.rpc.init; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; @@ -35,10 +36,14 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.DataType; @@ -60,6 +65,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceService; +import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; @@ -82,6 +88,7 @@ import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.gen.edge.UserUpdateMsg; +import org.thingsboard.server.service.edge.EdgeNotificationService; import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; @@ -103,6 +110,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { private static final ObjectMapper mapper = new ObjectMapper(); + @Autowired + private EdgeEventService edgeEventService; + @Autowired private AttributesService attributesService; @@ -130,21 +140,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private UserService userService; - @Autowired - private RuleChainUpdateMsgConstructor ruleChainUpdateMsgConstructor; - @Autowired private DeviceUpdateMsgConstructor deviceUpdateMsgConstructor; - @Autowired - private AssetUpdateMsgConstructor assetUpdateMsgConstructor; - - @Autowired - private EntityViewUpdateMsgConstructor entityViewUpdateMsgConstructor; - - @Autowired - private DashboardUpdateMsgConstructor dashboardUpdateMsgConstructor; - @Autowired private UserUpdateMsgConstructor userUpdateMsgConstructor; @@ -158,16 +156,20 @@ public class DefaultSyncEdgeService implements SyncEdgeService { private DbCallbackExecutorService dbCallbackExecutorService; @Override - public void sync(Edge edge, StreamObserver outputStream) { - syncUsers(edge, outputStream); - syncRuleChains(edge, outputStream); - syncDevices(edge, outputStream); - syncAssets(edge, outputStream); - syncEntityViews(edge, outputStream); - syncDashboards(edge, outputStream); + public void sync(Edge edge) { + try { + syncUsers(edge); + syncRuleChains(edge); + syncDevices(edge); + syncAssets(edge); + syncEntityViews(edge); + syncDashboards(edge); + } catch (Exception e) { + log.error("Exception during sync process", e); + } } - private void syncRuleChains(Edge edge, StreamObserver outputStream) { + private void syncRuleChains(Edge edge) { try { ListenableFuture> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); @@ -177,17 +179,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] rule chains(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (RuleChain ruleChain : pageData.getData()) { - RuleChainUpdateMsg ruleChainUpdateMsg = - ruleChainUpdateMsgConstructor.constructRuleChainUpdatedMsg( - edge.getRootRuleChainId(), - UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, - ruleChain); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainUpdateMsg(ruleChainUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN, ActionType.ADDED, ruleChain.getId(), null); } } } @@ -202,7 +194,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } - private void syncDevices(Edge edge, StreamObserver outputStream) { + private void syncDevices(Edge edge) { try { ListenableFuture> future = deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); @@ -212,16 +204,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (Device device : pageData.getData()) { - DeviceUpdateMsg deviceUpdateMsg = - deviceUpdateMsgConstructor.constructDeviceUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - device); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(deviceUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.ADDED, device.getId(), null); } } } @@ -236,7 +219,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } - private void syncAssets(Edge edge, StreamObserver outputStream) { + private void syncAssets(Edge edge) { try { ListenableFuture> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); Futures.addCallback(future, new FutureCallback>() { @@ -245,16 +228,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] asset(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (Asset asset : pageData.getData()) { - AssetUpdateMsg assetUpdateMsg = - assetUpdateMsgConstructor.constructAssetUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - asset); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAssetUpdateMsg(assetUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ASSET, ActionType.ADDED, asset.getId(), null); } } } @@ -269,7 +243,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } - private void syncEntityViews(Edge edge, StreamObserver outputStream) { + private void syncEntityViews(Edge edge) { try { ListenableFuture> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); Futures.addCallback(future, new FutureCallback>() { @@ -278,16 +252,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] entity view(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (EntityView entityView : pageData.getData()) { - EntityViewUpdateMsg entityViewUpdateMsg = - entityViewUpdateMsgConstructor.constructEntityViewUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - entityView); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setEntityViewUpdateMsg(entityViewUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ENTITY_VIEW, ActionType.ADDED, entityView.getId(), null); } } } @@ -302,7 +267,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } - private void syncDashboards(Edge edge, StreamObserver outputStream) { + private void syncDashboards(Edge edge) { try { ListenableFuture> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); Futures.addCallback(future, new FutureCallback>() { @@ -311,17 +276,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] dashboard(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (DashboardInfo dashboardInfo : pageData.getData()) { - Dashboard dashboard = dashboardService.findDashboardById(edge.getTenantId(), dashboardInfo.getId()); - DashboardUpdateMsg dashboardUpdateMsg = - dashboardUpdateMsgConstructor.constructDashboardUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - dashboard); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDashboardUpdateMsg(dashboardUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DASHBOARD, ActionType.ADDED, dashboardInfo.getId(), null); } } } @@ -336,112 +291,101 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } - private void syncUsers(Edge edge, StreamObserver outputStream) { + private void syncUsers(Edge edge) { try { TextPageData pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE)); - pushUsersToEdge(pageData, edge, outputStream); + pushUsersToEdge(pageData, edge); if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE)); - pushUsersToEdge(pageData, edge, outputStream); + pushUsersToEdge(pageData, edge); } } catch (Exception e) { log.error("Exception during loading edge user(s) on sync!", e); } } - private void pushUsersToEdge(TextPageData pageData, Edge edge, StreamObserver outputStream) { + private void pushUsersToEdge(TextPageData pageData, Edge edge) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); for (User user : pageData.getData()) { - UserUpdateMsg userUpdateMsg = - userUpdateMsgConstructor.constructUserUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - user); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setUserUpdateMsg(userUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.ADDED, user.getId(), null); } } } @Override - public void processRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver outputStream) { + public void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) { if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); - RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(edge.getTenantId(), ruleChainId); - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = - ruleChainUpdateMsgConstructor.constructRuleChainMetadataUpdatedMsg( - UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, - ruleChainMetaData); - if (ruleChainMetadataUpdateMsg != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null); } } @Override - public void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg, StreamObserver outputStream) { + public void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg) { EntityId entityId = EntityIdFactory.getByTypeAndUuid( EntityType.valueOf(attributesRequestMsg.getEntityType()), new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB())); - ListenableFuture> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); - Futures.addCallback(ssAttrFuture, new FutureCallback>() { - @Override - public void onSuccess(@Nullable List ssAttributes) { - if (ssAttributes != null && !ssAttributes.isEmpty()) { - try { - ObjectNode entityNode = mapper.createObjectNode(); - for (AttributeKvEntry attr : ssAttributes) { - if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getBooleanValue().get()); - } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getDoubleValue().get()); - } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getLongValue().get()); - } else { - entityNode.put(attr.getKey(), attr.getValueAsString()); + final EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(entityId.getEntityType()); + if (edgeEventType != null) { + ListenableFuture> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); + Futures.addCallback(ssAttrFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List ssAttributes) { + if (ssAttributes != null && !ssAttributes.isEmpty()) { + try { + ObjectNode entityNode = mapper.createObjectNode(); + for (AttributeKvEntry attr : ssAttributes) { + if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { + entityNode.put(attr.getKey(), attr.getBooleanValue().get()); + } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { + entityNode.put(attr.getKey(), attr.getDoubleValue().get()); + } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { + entityNode.put(attr.getKey(), attr.getLongValue().get()); + } else { + entityNode.put(attr.getKey(), attr.getValueAsString()); + } } + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityNode); + saveEdgeEvent(edge.getTenantId(), + edge.getId(), + edgeEventType, + ActionType.ATTRIBUTES_UPDATED, + entityId, + entityNode); + } catch (Exception e) { + log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); } - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityNode); - - EntityDataProto entityDataProto = - entityDataMsgConstructor.constructEntityDataMsg( - entityId, - ActionType.ATTRIBUTES_UPDATED, - JsonUtils.parse(mapper.writeValueAsString(entityNode))); - DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() - .addAllEntityData(Collections.singletonList(entityDataProto)); - DownlinkMsg value = builder.build(); - - outputStream.onNext(ResponseMsg.newBuilder() - .setDownlinkMsg(value).build()); - } catch (Exception e) { - log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); } } - } - @Override - public void onFailure(Throwable t) { + @Override + public void onFailure(Throwable t) { - } - }, dbCallbackExecutorService); + } + }, dbCallbackExecutorService); + + // TODO: voba - push shared attributes to edge? + ListenableFuture> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); + ListenableFuture> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); + } + } - // TODO: voba - push shared attributes to edge? - ListenableFuture> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); - ListenableFuture> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); + private EdgeEventType getEdgeQueueTypeByEntityType(EntityType entityType) { + switch (entityType) { + case DEVICE: + return EdgeEventType.DEVICE; + case ASSET: + return EdgeEventType.ASSET; + case ENTITY_VIEW: + return EdgeEventType.ENTITY_VIEW; + default: + return null; + } } @Override - public void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg, StreamObserver outputStream) { + public void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg) { EntityId entityId = EntityIdFactory.getByTypeAndUuid( EntityType.valueOf(relationRequestMsg.getEntityType()), new UUID(relationRequestMsg.getEntityIdMSB(), relationRequestMsg.getEntityIdLSB())); @@ -459,16 +403,12 @@ public class DefaultSyncEdgeService implements SyncEdgeService { log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size()); for (EntityRelation relation : entityRelations) { try { - RelationUpdateMsg relationUpdateMsg = - relationUpdateMsgConstructor.constructRelationUpdatedMsg( - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, - relation); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRelationUpdateMsg(relationUpdateMsg) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + saveEdgeEvent(edge.getTenantId(), + edge.getId(), + EdgeEventType.RELATION, + ActionType.ADDED, + null, + mapper.valueToTree(relation)); } catch (Exception e) { log.error("Exception during loading relation [{}] to edge on sync!", relation, e); } @@ -494,30 +434,39 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } @Override - public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg, StreamObserver outputStream) { - DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); - DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId); - if (deviceCredentials != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceCredentialsUpdateMsg(deviceUpdateMsgConstructor.constructDeviceCredentialsUpdatedMsg(deviceCredentials)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { + if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) { + DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE_CREDENTIALS, ActionType.ADDED, deviceId, null); } } @Override - public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg, StreamObserver outputStream) { - UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); - UserCredentials userCredentialsByUserId = userService.findUserCredentialsByUserId(edge.getTenantId(), userId); - if (userCredentialsByUserId != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setUserCredentialsUpdateMsg(userUpdateMsgConstructor.constructUserCredentialsUpdatedMsg(userCredentialsByUserId)) - .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); + public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { + if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) { + UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER_CREDENTIALS, ActionType.ADDED, userId, null); + } + } + + private void saveEdgeEvent(TenantId tenantId, + EdgeId edgeId, + EdgeEventType edgeEventType, + ActionType edgeEventAction, + EntityId entityId, + JsonNode entityBody) { + log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], edgeEventType [{}], edgeEventAction[{}], entityId [{}], entityBody [{}]", + tenantId, edgeId, edgeEventType, edgeEventAction, entityId, entityBody); + + EdgeEvent edgeEvent = new EdgeEvent(); + edgeEvent.setTenantId(tenantId); + edgeEvent.setEdgeId(edgeId); + edgeEvent.setEdgeEventType(edgeEventType); + edgeEvent.setEdgeEventAction(edgeEventAction.name()); + if (entityId != null) { + edgeEvent.setEntityId(entityId.getId()); } + edgeEvent.setEntityBody(entityBody); + edgeEventService.saveAsync(edgeEvent); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java index dbcb659daf..051af4f6d2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java @@ -15,26 +15,24 @@ */ package org.thingsboard.server.service.edge.rpc.init; -import io.grpc.stub.StreamObserver; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; -import org.thingsboard.server.gen.edge.ResponseMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; public interface SyncEdgeService { - void sync(Edge edge, StreamObserver outputStream); + void sync(Edge edge); - void processRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver outputStream); + void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg); - void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg, StreamObserver outputStream); + void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg); - void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg, StreamObserver outputStream); + void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg); - void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg, StreamObserver outputStream); + void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg); - void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg, StreamObserver outputStream); + void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index ada50c9998..ae47442bd1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -16,5 +16,17 @@ package org.thingsboard.server.common.data.edge; public enum EdgeEventType { - DASHBOARD, ASSET, DEVICE, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA, EDGE, USER, CUSTOMER, RELATION + DASHBOARD, + ASSET, + DEVICE, + DEVICE_CREDENTIALS, + ENTITY_VIEW, + ALARM, + RULE_CHAIN, + RULE_CHAIN_METADATA, + EDGE, + USER, + USER_CREDENTIALS, + CUSTOMER, + RELATION } From 963b2274ec2717aa9eab4035130f88a32e8a4ae9 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 25 Jun 2020 15:47:44 +0300 Subject: [PATCH 011/156] Code clean up --- .../edge/DefaultEdgeNotificationService.java | 2 - .../service/edge/rpc/EdgeGrpcSession.java | 4 +- .../edge/rpc/init/DefaultSyncEdgeService.java | 45 ------------------- 3 files changed, 2 insertions(+), 49 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 5206a40f6a..06dda55555 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -42,13 +42,11 @@ import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.relation.RelationService; -import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.executors.DbCallbackExecutorService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 1c21599aa8..764be973ab 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -28,7 +28,9 @@ import com.google.gson.JsonObject; import io.grpc.stub.StreamObserver; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; +import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -827,8 +829,6 @@ public final class EdgeGrpcSession implements Closeable { } catch (Exception e) { log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); } - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", - device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index ac6c5ebd05..322aef6cb2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -21,12 +21,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import io.grpc.stub.StreamObserver; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -56,51 +54,23 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import org.thingsboard.server.common.data.rule.RuleChain; -import org.thingsboard.server.common.data.rule.RuleChainMetaData; -import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.common.data.security.UserCredentials; -import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.dashboard.DashboardService; -import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; -import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.AttributesRequestMsg; -import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; -import org.thingsboard.server.gen.edge.DeviceUpdateMsg; -import org.thingsboard.server.gen.edge.DownlinkMsg; -import org.thingsboard.server.gen.edge.EntityDataProto; -import org.thingsboard.server.gen.edge.EntityUpdateMsg; -import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; -import org.thingsboard.server.gen.edge.RelationUpdateMsg; -import org.thingsboard.server.gen.edge.ResponseMsg; import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; -import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; -import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; -import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; -import org.thingsboard.server.gen.edge.UserUpdateMsg; -import org.thingsboard.server.service.edge.EdgeNotificationService; -import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.UUID; @@ -125,9 +95,6 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private DeviceService deviceService; - @Autowired - private DeviceCredentialsService deviceCredentialsService; - @Autowired private AssetService assetService; @@ -140,18 +107,6 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private UserService userService; - @Autowired - private DeviceUpdateMsgConstructor deviceUpdateMsgConstructor; - - @Autowired - private UserUpdateMsgConstructor userUpdateMsgConstructor; - - @Autowired - private RelationUpdateMsgConstructor relationUpdateMsgConstructor; - - @Autowired - private EntityDataMsgConstructor entityDataMsgConstructor; - @Autowired private DbCallbackExecutorService dbCallbackExecutorService; From 486ea8e06571957ceedf31347da98c9146c77a0e Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 25 Jun 2020 15:50:57 +0300 Subject: [PATCH 012/156] Renaming --- .../server/service/edge/DefaultEdgeNotificationService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 06dda55555..b7e47183c3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -147,7 +147,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case ENTITY_VIEW: case DASHBOARD: case RULE_CHAIN: - processEntities(tenantId, edgeNotificationMsg); + processEntity(tenantId, edgeNotificationMsg); break; case ALARM: processAlarm(tenantId, edgeNotificationMsg); @@ -166,7 +166,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } } - private void processEntities(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { + private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); From 125130193d9308b87c64aefe95d058347495882a Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 25 Jun 2020 15:58:59 +0300 Subject: [PATCH 013/156] Ignore EDGE relation --- .../server/controller/BaseController.java | 5 +- .../edge/DefaultEdgeNotificationService.java | 49 ++++++++++--------- .../edge/rpc/init/DefaultSyncEdgeService.java | 15 +++--- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 3ec9767793..2a8b32b7de 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -725,7 +725,10 @@ public abstract class BaseController { protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) { try { - sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction); + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && + !relation.getTo().getEntityType().equals(EntityType.EDGE)) { + sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction); + } } catch (Exception e) { log.warn("Failed to push relation to core: {}", relation, e); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index b7e47183c3..77fafc3bc9 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -236,32 +236,35 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { - EntityRelation entityRelation = mapper.convertValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class); - List>> futures = new ArrayList<>(); - futures.add(findRelatedEdgeIdsByEntityId(tenantId, entityRelation.getTo())); - futures.add(findRelatedEdgeIdsByEntityId(tenantId, entityRelation.getFrom())); - ListenableFuture>> combinedFuture = Futures.allAsList(futures); - Futures.transform(combinedFuture, listOfListsEdgeIds -> { - Set uniqueEdgeIds = new HashSet<>(); - if (listOfListsEdgeIds != null && !listOfListsEdgeIds.isEmpty()) { - for (List listOfListsEdgeId : listOfListsEdgeIds) { - if (listOfListsEdgeId != null) { - uniqueEdgeIds.addAll(listOfListsEdgeId); + EntityRelation relation = mapper.convertValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class); + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && + !relation.getTo().getEntityType().equals(EntityType.EDGE)) { + List>> futures = new ArrayList<>(); + futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getTo())); + futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom())); + ListenableFuture>> combinedFuture = Futures.allAsList(futures); + Futures.transform(combinedFuture, listOfListsEdgeIds -> { + Set uniqueEdgeIds = new HashSet<>(); + if (listOfListsEdgeIds != null && !listOfListsEdgeIds.isEmpty()) { + for (List listOfListsEdgeId : listOfListsEdgeIds) { + if (listOfListsEdgeId != null) { + uniqueEdgeIds.addAll(listOfListsEdgeId); + } } } - } - if (!uniqueEdgeIds.isEmpty()) { - for (EdgeId edgeId : uniqueEdgeIds) { - saveEdgeEvent(tenantId, - edgeId, - EdgeEventType.RELATION, - ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()), - null, - mapper.valueToTree(entityRelation)); + if (!uniqueEdgeIds.isEmpty()) { + for (EdgeId edgeId : uniqueEdgeIds) { + saveEdgeEvent(tenantId, + edgeId, + EdgeEventType.RELATION, + ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()), + null, + mapper.valueToTree(relation)); + } } - } - return null; - }, dbCallbackExecutorService); + return null; + }, dbCallbackExecutorService); + } } private ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 322aef6cb2..8a4a0851fc 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -358,12 +358,15 @@ public class DefaultSyncEdgeService implements SyncEdgeService { log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size()); for (EntityRelation relation : entityRelations) { try { - saveEdgeEvent(edge.getTenantId(), - edge.getId(), - EdgeEventType.RELATION, - ActionType.ADDED, - null, - mapper.valueToTree(relation)); + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && + !relation.getTo().getEntityType().equals(EntityType.EDGE)) { + saveEdgeEvent(edge.getTenantId(), + edge.getId(), + EdgeEventType.RELATION, + ActionType.ADDED, + null, + mapper.valueToTree(relation)); + } } catch (Exception e) { log.error("Exception during loading relation [{}] to edge on sync!", relation, e); } From e832759eef0152450d8c8f50a6daa28624ca460a Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 25 Jun 2020 16:48:32 +0300 Subject: [PATCH 014/156] bug by DeviceCredentials creation --- .../server/service/edge/rpc/EdgeGrpcSession.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 764be973ab..bcf4065a26 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -28,9 +28,8 @@ import com.google.gson.JsonObject; import io.grpc.stub.StreamObserver; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; -import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -871,6 +870,7 @@ public final class EdgeGrpcSession implements Closeable { device.setType(deviceUpdateMsg.getType()); device.setLabel(deviceUpdateMsg.getLabel()); device = ctx.getDeviceService().saveDevice(device); + createDeviceCredentials(device); device = ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId()); createRelationFromEdge(device.getId()); ctx.getRelationService().saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(edge.getId(), device.getId(), "Created")); @@ -883,6 +883,14 @@ public final class EdgeGrpcSession implements Closeable { return device; } + private void createDeviceCredentials(Device device) { + DeviceCredentials deviceCredentials = new DeviceCredentials(); + deviceCredentials.setDeviceId(device.getId()); + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); + deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20)); + ctx.getDeviceCredentialsService().createDeviceCredentials(device.getTenantId(), deviceCredentials); + } + private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) { switch (entityType) { case DEVICE: From 4b9642fc11d0675e000866a3e51e35356ef372a9 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 25 Jun 2020 17:32:34 +0300 Subject: [PATCH 015/156] Moved getEdgeEventTypeByEntityType to EdgeUtils --- .../server/controller/BaseController.java | 13 ++-- .../service/queue/TbCoreConsumerStats.java | 2 +- .../server/dao/edge/EdgeEventService.java | 2 - .../server/common/data/EdgeUtils.java | 61 ++++++------------- .../server/dao/edge/BaseEdgeEventService.java | 23 ------- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 3 +- 6 files changed, 24 insertions(+), 80 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 2a8b32b7de..e435ad6bbb 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -26,12 +26,12 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.HasName; @@ -39,14 +39,14 @@ import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.edge.EdgeEventType; -import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; @@ -85,7 +85,6 @@ import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.ClaimDevicesService; import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceService; -import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; @@ -113,7 +112,6 @@ import org.thingsboard.server.service.state.DeviceStateService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import javax.mail.MessagingException; -import javax.management.relation.Relation; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Optional; @@ -209,9 +207,6 @@ public abstract class BaseController { @Autowired protected EdgeNotificationService edgeNotificationService; - @Autowired - protected EdgeEventService edgeEventService; - @Value("${server.log_controller_error_stack_trace}") @Getter private boolean logControllerErrorStackTrace; @@ -735,7 +730,7 @@ public abstract class BaseController { } protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) { - EdgeEventType edgeEventType = edgeEventService.getEdgeEventTypeByEntityType(entityId.getEntityType()); + EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); if (edgeEventType != null) { sendNotificationMsgToEdgeService(tenantId, null, entityId, null, edgeEventType, edgeEventAction); } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java b/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java index 7e5abd9da8..f8407057ba 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java @@ -33,9 +33,9 @@ public class TbCoreConsumerStats { private final AtomicInteger claimDeviceCounter = new AtomicInteger(0); private final AtomicInteger deviceStateCounter = new AtomicInteger(0); - private final AtomicInteger edgeNotificationMsgCounter = new AtomicInteger(0); private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0); private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0); + private final AtomicInteger edgeNotificationMsgCounter = new AtomicInteger(0); public void log(TransportProtos.TransportToDeviceActorMsg msg) { totalCounter.incrementAndGet(); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java index 6c3e189d41..0d65c134f2 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java @@ -26,8 +26,6 @@ import org.thingsboard.server.common.data.page.TimePageLink; public interface EdgeEventService { - EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType); - ListenableFuture saveAsync(EdgeEvent edgeEvent); TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java index 31449a7801..784763f99e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeId; import java.util.Set; @@ -24,50 +25,22 @@ public final class EdgeUtils { private EdgeUtils() { } - public static boolean isAssignedToEdge(Set assignedEdges, EdgeId edgeId) { - return assignedEdges != null && assignedEdges.contains(new ShortEdgeInfo(edgeId, null, null)); - } - - public static ShortEdgeInfo getAssignedEdgeInfo(Set assignedEdges, EdgeId edgeId) { - if (assignedEdges != null) { - for (ShortEdgeInfo edgeInfo : assignedEdges) { - if (edgeInfo.getEdgeId().equals(edgeId)) { - return edgeInfo; - } - } - } - return null; - } - - public static boolean addAssignedEdge(Set assignedEdges, ShortEdgeInfo edgeInfo) { - if (assignedEdges != null && assignedEdges.contains(edgeInfo)) { - return false; - } else { - if (assignedEdges != null) { - assignedEdges.add(edgeInfo); - return true; - } else { - return false; - } - } - } - - public static boolean updateAssignedEdge(Set assignedEdges, ShortEdgeInfo edgeInfo) { - if (assignedEdges != null && assignedEdges.contains(edgeInfo)) { - assignedEdges.remove(edgeInfo); - assignedEdges.add(edgeInfo); - return true; - } else { - return false; - } - } - - public static boolean removeAssignedEdge(Set assignedEdges, ShortEdgeInfo edgeInfo) { - if (assignedEdges != null && assignedEdges.contains(edgeInfo)) { - assignedEdges.remove(edgeInfo); - return true; - } else { - return false; + public static EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType) { + switch (entityType) { + case DEVICE: + return EdgeEventType.DEVICE; + case ASSET: + return EdgeEventType.ASSET; + case ENTITY_VIEW: + return EdgeEventType.ENTITY_VIEW; + case DASHBOARD: + return EdgeEventType.DASHBOARD; + case USER: + return EdgeEventType.USER; + case ALARM: + return EdgeEventType.ALARM; + default: + return null; } } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java index fb8f3a03a4..75bc3046c4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java @@ -20,9 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TimePageData; @@ -39,27 +37,6 @@ public class BaseEdgeEventService implements EdgeEventService { @Autowired public EdgeEventDao edgeEventDao; - @Override - public EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType) { - switch (entityType) { - case DEVICE: - return EdgeEventType.DEVICE; - case ASSET: - return EdgeEventType.ASSET; - case ENTITY_VIEW: - return EdgeEventType.ENTITY_VIEW; - case DASHBOARD: - return EdgeEventType.DASHBOARD; - case USER: - return EdgeEventType.USER; - case ALARM: - return EdgeEventType.ALARM; - default: - log.warn("Failed to push notification to edge service. Unsupported entity type [{}]", entityType); - return null; - } - } - @Override public ListenableFuture saveAsync(EdgeEvent edgeEvent) { edgeEventValidator.validate(edgeEvent, EdgeEvent::getTenantId); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 7b96bb45f6..bda074eee9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -29,6 +29,7 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.EdgeEvent; @@ -81,7 +82,7 @@ public class TbMsgPushToEdgeNode implements TbNode { Futures.addCallback(getEdgeIdFuture, new FutureCallback() { @Override public void onSuccess(@Nullable EdgeId edgeId) { - EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); + EdgeEventType edgeEventTypeByEntityType = EdgeUtils.getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); if (edgeEventTypeByEntityType == null) { log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); From a5d75e380068b8562c1a43d0c66385f40ad10d55 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 25 Jun 2020 18:06:02 +0300 Subject: [PATCH 016/156] Removed CREDENTIALS type. Use action instead --- .../server/controller/AuthController.java | 4 + .../server/controller/UserController.java | 11 +- .../edge/DefaultEdgeNotificationService.java | 1 + .../service/edge/rpc/EdgeGrpcSession.java | 262 +++++++++--------- .../edge/rpc/init/DefaultSyncEdgeService.java | 4 +- .../common/data/edge/EdgeEventType.java | 2 - 6 files changed, 139 insertions(+), 145 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index 9f6c6f3b44..e999320e43 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.RestController; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; @@ -124,6 +125,9 @@ public class AuthController extends BaseController { } userCredentials.setPassword(passwordEncoder.encode(newPassword)); userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials); + + sendNotificationMsgToEdgeService(getTenantId(), null, userCredentials.getUserId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED); + } catch (Exception e) { throw handleException(e); } diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 32ce338a37..8dedc59098 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -35,17 +35,14 @@ import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.common.data.page.TimePageData; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -60,8 +57,6 @@ import org.thingsboard.server.utils.MiscUtils; import javax.servlet.http.HttpServletRequest; -import static org.thingsboard.server.controller.EdgeController.EDGE_ID; - @RestController @TbCoreComponent @RequestMapping("/api") @@ -167,6 +162,8 @@ public class UserController extends BaseController { savedUser.getCustomerId(), user.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); + sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, user.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + return savedUser; } catch (Exception e) { @@ -242,6 +239,8 @@ public class UserController extends BaseController { user.getCustomerId(), ActionType.DELETED, null, strUserId); + sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, ActionType.DELETED); + } catch (Exception e) { logEntityAction(emptyId(EntityType.USER), null, diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 77fafc3bc9..d16082173c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -174,6 +174,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { // TODO: voba - ADDED is not required for CE version ? // case ADDED: case UPDATED: + case CREDENTIALS_UPDATED: ListenableFuture> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); Futures.transform(edgeIdsFuture, edgeIds -> { if (edgeIds != null && !edgeIds.isEmpty()) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 764be973ab..74989530a3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -28,9 +28,7 @@ import com.google.gson.JsonObject; import io.grpc.stub.StreamObserver; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; -import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -195,11 +193,23 @@ public final class EdgeGrpcSession implements Closeable { for (EdgeEvent edgeEvent : pageData.getData()) { log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent); try { - UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction())); - if (msgType == null) { - processTelemetryMessage(edgeEvent); - } else { - processEntityCRUDMessage(edgeEvent, msgType); + ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getEdgeEventAction()); + switch (edgeEventAction) { + case UPDATED: + case ADDED: + case ASSIGNED_TO_EDGE: + case DELETED: + case UNASSIGNED_FROM_EDGE: + case ALARM_ACK: + case ALARM_CLEAR: + case CREDENTIALS_UPDATED: + processEntityMessage(edgeEvent, edgeEventAction); + break; + case ATTRIBUTES_UPDATED: + case ATTRIBUTES_DELETED: + case TIMESERIES_UPDATED: + processTelemetryMessage(edgeEvent); + break; } } catch (Exception e) { log.error("Exception during processing records from queue", e); @@ -278,217 +288,212 @@ public final class EdgeGrpcSession implements Closeable { } } - private void processEntityCRUDMessage(EdgeEvent edgeEvent, UpdateMsgType msgType) { - log.trace("Executing processEntityCRUDMessage, edgeEvent [{}], msgType [{}]", edgeEvent, msgType); + private void processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) { + UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction())); + log.trace("Executing processEntityCRUDMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType); switch (edgeEvent.getEdgeEventType()) { case EDGE: // TODO: voba - add edge update logic break; case DEVICE: - processDeviceCRUD(edgeEvent, msgType); - break; - case DEVICE_CREDENTIALS: - processDeviceCredentialsCRUD(edgeEvent, msgType); + processDevice(edgeEvent, msgType, edgeEventAction); break; case ASSET: - processAssetCRUD(edgeEvent, msgType); + processAsset(edgeEvent, msgType, edgeEventAction); break; case ENTITY_VIEW: - processEntityViewCRUD(edgeEvent, msgType); + processEntityView(edgeEvent, msgType, edgeEventAction); break; case DASHBOARD: - processDashboardCRUD(edgeEvent, msgType); + processDashboard(edgeEvent, msgType, edgeEventAction); break; case RULE_CHAIN: - processRuleChainCRUD(edgeEvent, msgType); + processRuleChain(edgeEvent, msgType, edgeEventAction); break; case RULE_CHAIN_METADATA: - processRuleChainMetadataCRUD(edgeEvent, msgType); + processRuleChainMetadata(edgeEvent, msgType); break; case ALARM: - processAlarmCRUD(edgeEvent, msgType); + processAlarm(edgeEvent, msgType); break; case USER: - processUserCRUD(edgeEvent, msgType); - break; - case USER_CREDENTIALS: - processUserCredentialsCRUD(edgeEvent, msgType); + processUser(edgeEvent, msgType, edgeEventAction); break; case RELATION: - processRelationCRUD(edgeEvent, msgType); + processRelation(edgeEvent, msgType); break; } } - private void processDeviceCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processDevice(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - case DEVICE_CONFLICT_RPC_MESSAGE: + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeActionType) { + case ADDED: + case UPDATED: + case ASSIGNED_TO_EDGE: Device device = ctx.getDeviceService().findDeviceById(edgeEvent.getTenantId(), deviceId); if (device != null) { DeviceUpdateMsg deviceUpdateMsg = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setDeviceUpdateMsg(deviceUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; - case ENTITY_DELETED_RPC_MESSAGE: + case DELETED: + case UNASSIGNED_FROM_EDGE: DeviceUpdateMsg deviceUpdateMsg = ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setDeviceUpdateMsg(deviceUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } - } - - private void processDeviceCredentialsCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { - DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + break; + case CREDENTIALS_UPDATED: DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId); if (deviceCredentials != null) { DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = ctx.getDeviceUpdateMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setDeviceCredentialsUpdateMsg(deviceCredentialsUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } - private void processAssetCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { AssetId assetId = new AssetId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeEventAction) { + case ADDED: + case UPDATED: + case ASSIGNED_TO_EDGE: Asset asset = ctx.getAssetService().findAssetById(edgeEvent.getTenantId(), assetId); if (asset != null) { AssetUpdateMsg assetUpdateMsg = ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setAssetUpdateMsg(assetUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; - case ENTITY_DELETED_RPC_MESSAGE: + case DELETED: + case UNASSIGNED_FROM_EDGE: AssetUpdateMsg assetUpdateMsg = ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setAssetUpdateMsg(assetUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); break; } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } - private void processEntityViewCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeEventAction) { + case ADDED: + case UPDATED: + case ASSIGNED_TO_EDGE: EntityView entityView = ctx.getEntityViewService().findEntityViewById(edgeEvent.getTenantId(), entityViewId); if (entityView != null) { EntityViewUpdateMsg entityViewUpdateMsg = ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setEntityViewUpdateMsg(entityViewUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; - case ENTITY_DELETED_RPC_MESSAGE: + case DELETED: + case UNASSIGNED_FROM_EDGE: EntityViewUpdateMsg entityViewUpdateMsg = ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setEntityViewUpdateMsg(entityViewUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); break; } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } - private void processDashboardCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeEventAction) { + case ADDED: + case UPDATED: + case ASSIGNED_TO_EDGE: Dashboard dashboard = ctx.getDashboardService().findDashboardById(edgeEvent.getTenantId(), dashboardId); if (dashboard != null) { DashboardUpdateMsg dashboardUpdateMsg = ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setDashboardUpdateMsg(dashboardUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; - case ENTITY_DELETED_RPC_MESSAGE: + case DELETED: + case UNASSIGNED_FROM_EDGE: DashboardUpdateMsg dashboardUpdateMsg = ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setDashboardUpdateMsg(dashboardUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); break; } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } - private void processRuleChainCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeEventAction) { + case ADDED: + case UPDATED: + case ASSIGNED_TO_EDGE: RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); if (ruleChain != null) { RuleChainUpdateMsg ruleChainUpdateMsg = ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setRuleChainUpdateMsg(ruleChainUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; - case ENTITY_DELETED_RPC_MESSAGE: - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + case DELETED: + case UNASSIGNED_FROM_EDGE: + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setRuleChainUpdateMsg(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainDeleteMsg(ruleChainId)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); break; } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } } - private void processRuleChainMetadataCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processRuleChainMetadata(EdgeEvent edgeEvent, UpdateMsgType msgType) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); if (ruleChain != null) { @@ -506,53 +511,44 @@ public final class EdgeGrpcSession implements Closeable { } } - private void processUserCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processUser(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { UserId userId = new UserId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeActionType) { + case ADDED: + case UPDATED: + case ASSIGNED_TO_EDGE: User user = ctx.getUserService().findUserById(edgeEvent.getTenantId(), userId); if (user != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } break; - case ENTITY_DELETED_RPC_MESSAGE: - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + case DELETED: + case UNASSIGNED_FROM_EDGE: + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); break; - } - } - - private void processUserCredentialsCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { - UserId userId = new UserId(edgeEvent.getEntityId()); - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + case CREDENTIALS_UPDATED: UserCredentials userCredentialsByUserId = ctx.getUserService().findUserCredentialsByUserId(edge.getTenantId(), userId); if (userCredentialsByUserId != null) { UserCredentialsUpdateMsg userCredentialsUpdateMsg = ctx.getUserUpdateMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setUserCredentialsUpdateMsg(userCredentialsUpdateMsg) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } - break; + } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); } } - private void processRelationCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() .setRelationUpdateMsg(ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation)) @@ -562,7 +558,7 @@ public final class EdgeGrpcSession implements Closeable { .build()); } - private void processAlarmCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private void processAlarm(EdgeEvent edgeEvent, UpdateMsgType msgType) { try { AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); Alarm alarm = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); @@ -593,10 +589,6 @@ public final class EdgeGrpcSession implements Closeable { return UpdateMsgType.ALARM_ACK_RPC_MESSAGE; case ALARM_CLEAR: return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE; - case ATTRIBUTES_UPDATED: - case ATTRIBUTES_DELETED: - case TIMESERIES_UPDATED: - return null; default: throw new RuntimeException("Unsupported actionType [" + actionType + "]"); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 8a4a0851fc..8576f96152 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -395,7 +395,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) { DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE_CREDENTIALS, ActionType.ADDED, deviceId, null); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null); } } @@ -403,7 +403,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) { UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER_CREDENTIALS, ActionType.ADDED, userId, null); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null); } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index ae47442bd1..52259d4507 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -19,14 +19,12 @@ public enum EdgeEventType { DASHBOARD, ASSET, DEVICE, - DEVICE_CREDENTIALS, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA, EDGE, USER, - USER_CREDENTIALS, CUSTOMER, RELATION } From 4cf29e2d89a674b8412685612c8722c411c221ac Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 26 Jun 2020 11:53:16 +0300 Subject: [PATCH 017/156] Added support for dashboard telemetry and attributes update --- .../server/service/edge/rpc/EdgeGrpcSession.java | 11 +++++++---- .../server/common/data/audit/ActionType.java | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 74989530a3..5e077aea67 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -248,7 +248,7 @@ public final class EdgeGrpcSession implements Closeable { } else { return 0L; } - }, MoreExecutors.directExecutor()); + }, ctx.getDbCallbackExecutor()); } private void updateQueueStartTs(Long newStartTs) { @@ -270,7 +270,9 @@ public final class EdgeGrpcSession implements Closeable { case ENTITY_VIEW: entityId = new EntityViewId(edgeEvent.getEntityId()); break; - + case DASHBOARD: + entityId = new DashboardId(edgeEvent.getEntityId()); + break; } if (entityId != null) { log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody()); @@ -290,7 +292,7 @@ public final class EdgeGrpcSession implements Closeable { private void processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) { UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction())); - log.trace("Executing processEntityCRUDMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType); + log.trace("Executing processEntityMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType); switch (edgeEvent.getEdgeEventType()) { case EDGE: // TODO: voba - add edge update logic @@ -571,13 +573,14 @@ public final class EdgeGrpcSession implements Closeable { .build()); } } catch (Exception e) { - log.error("Can't process alarm CRUD msg [{}] [{}]", edgeEvent, msgType, e); + log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e); } } private UpdateMsgType getResponseMsgType(ActionType actionType) { switch (actionType) { case UPDATED: + case CREDENTIALS_UPDATED: return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; case ADDED: case ASSIGNED_TO_EDGE: diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java b/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java index 48de5fedb6..84273148c5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java @@ -43,7 +43,8 @@ public enum ActionType { LOGOUT(false), LOCKOUT(false), ASSIGNED_TO_EDGE(false), // log edge name - UNASSIGNED_FROM_EDGE(false); // log edge name + UNASSIGNED_FROM_EDGE(false), // log edge name + CREDENTIALS_REQUEST(false); // request credentials from edge private final boolean isRead; From b5d99e504fea132d5b1180e0de92b681f22175f1 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 26 Jun 2020 12:57:38 +0300 Subject: [PATCH 018/156] Minor naming change in default edge rule chains --- msa/js-executor/package-lock.json | 18 +++++++++--------- ui/package-lock.json | 13 ++++--------- ui/src/app/rulechain/rulechains.controller.js | 4 ++-- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/msa/js-executor/package-lock.json b/msa/js-executor/package-lock.json index 5636c4f586..23d1ea1558 100644 --- a/msa/js-executor/package-lock.json +++ b/msa/js-executor/package-lock.json @@ -1461,7 +1461,7 @@ }, "enabled": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", "requires": { "env-variable": "0.0.x" @@ -1740,7 +1740,7 @@ }, "fecha": { "version": "2.3.3", - "resolved": "http://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" }, "file-stream-rotator": { @@ -2390,7 +2390,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -2547,7 +2547,7 @@ }, "got": { "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { @@ -2879,7 +2879,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -3241,7 +3241,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mixin-deep": { @@ -3540,7 +3540,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -3979,7 +3979,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -4289,7 +4289,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, diff --git a/ui/package-lock.json b/ui/package-lock.json index a76c853921..6bc1035b88 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -5238,8 +5238,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -5650,8 +5649,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -5706,7 +5704,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5750,14 +5747,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index aba5c3bb2a..0590bc718b 100644 --- a/ui/src/app/rulechain/rulechains.controller.js +++ b/ui/src/app/rulechain/rulechains.controller.js @@ -335,7 +335,7 @@ export default function RuleChainsController(ruleChainService, userService, edge vm.grid = grid; } - function getDefaultEdges(ruleChains) { + function mapRuleChainsWithDefaultEdges(ruleChains) { var deferred = $q.defer(); ruleChainService.getDefaultEdgeRuleChains(null).then( function success(response) { @@ -365,7 +365,7 @@ export default function RuleChainsController(ruleChainService, userService, edge var deferred = $q.defer(); ruleChainService.getRuleChains(pageLink, null, type).then( function success(ruleChains) { - getDefaultEdges(ruleChains).then( + mapRuleChainsWithDefaultEdges(ruleChains).then( function success(response) { deferred.resolve(response); }, function fail() { From d76b9eff68a10ba5ba6b8238b26126e3b477bc19 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 26 Jun 2020 13:13:59 +0300 Subject: [PATCH 019/156] Changed default rule chain types on nodes --- .../org/thingsboard/rule/engine/api/RuleNode.java | 2 +- .../rule/engine/action/TbAssignToCustomerNode.java | 4 +--- .../rule/engine/action/TbClearAlarmNode.java | 4 +--- .../action/TbCopyAttributesToEntityViewNode.java | 4 +--- .../rule/engine/action/TbCreateAlarmNode.java | 4 +--- .../rule/engine/action/TbCreateRelationNode.java | 4 +--- .../rule/engine/action/TbDeleteRelationNode.java | 4 +--- .../org/thingsboard/rule/engine/action/TbLogNode.java | 5 +---- .../rule/engine/action/TbMsgCountNode.java | 4 +--- .../action/TbSaveToCustomCassandraTableNode.java | 3 ++- .../engine/action/TbUnassignFromCustomerNode.java | 11 +++++++---- .../thingsboard/rule/engine/aws/sns/TbSnsNode.java | 3 +-- .../thingsboard/rule/engine/aws/sqs/TbSqsNode.java | 3 +-- .../rule/engine/debug/TbMsgGeneratorNode.java | 3 +-- .../thingsboard/rule/engine/delay/TbMsgDelayNode.java | 3 +-- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 4 +++- .../rule/engine/filter/TbCheckMessageNode.java | 3 +-- .../rule/engine/filter/TbCheckRelationNode.java | 3 +-- .../rule/engine/filter/TbJsFilterNode.java | 3 +-- .../rule/engine/filter/TbJsSwitchNode.java | 3 +-- .../rule/engine/filter/TbMsgTypeFilterNode.java | 3 +-- .../rule/engine/filter/TbMsgTypeSwitchNode.java | 3 +-- .../engine/filter/TbOriginatorTypeFilterNode.java | 3 +-- .../engine/filter/TbOriginatorTypeSwitchNode.java | 3 +-- .../rule/engine/gcp/pubsub/TbPubSubNode.java | 3 +-- .../rule/engine/geo/TbGpsGeofencingActionNode.java | 3 +-- .../rule/engine/geo/TbGpsGeofencingFilterNode.java | 3 +-- .../thingsboard/rule/engine/kafka/TbKafkaNode.java | 3 +-- .../rule/engine/mail/TbMsgToEmailNode.java | 3 +-- .../thingsboard/rule/engine/mail/TbSendEmailNode.java | 3 +-- .../rule/engine/metadata/TbGetAttributesNode.java | 3 +-- .../engine/metadata/TbGetCustomerAttributeNode.java | 3 +-- .../engine/metadata/TbGetCustomerDetailsNode.java | 3 +-- .../rule/engine/metadata/TbGetDeviceAttrNode.java | 3 +-- .../engine/metadata/TbGetOriginatorFieldsNode.java | 3 +-- .../engine/metadata/TbGetRelatedAttributeNode.java | 3 +-- .../rule/engine/metadata/TbGetTelemetryNode.java | 3 +-- .../engine/metadata/TbGetTenantAttributeNode.java | 3 +-- .../rule/engine/metadata/TbGetTenantDetailsNode.java | 3 +-- .../org/thingsboard/rule/engine/mqtt/TbMqttNode.java | 3 +-- .../rule/engine/rabbitmq/TbRabbitMqNode.java | 3 +-- .../rule/engine/rest/TbRestApiCallNode.java | 3 +-- .../rule/engine/rpc/TbSendRPCReplyNode.java | 3 +-- .../rule/engine/rpc/TbSendRPCRequestNode.java | 3 +-- .../rule/engine/telemetry/TbMsgAttributesNode.java | 3 +-- .../rule/engine/telemetry/TbMsgTimeseriesNode.java | 3 +-- .../transaction/TbSynchronizationBeginNode.java | 3 +-- .../engine/transaction/TbSynchronizationEndNode.java | 3 +-- .../rule/engine/transform/TbChangeOriginatorNode.java | 3 +-- .../rule/engine/transform/TbTransformMsgNode.java | 3 +-- 50 files changed, 59 insertions(+), 108 deletions(-) diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java index 1efe0081d7..0272b3b372 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java @@ -58,6 +58,6 @@ public @interface RuleNode { boolean customRelations() default false; - RuleChainType[] ruleChainTypes() default RuleChainType.CORE; + RuleChainType[] ruleChainTypes() default {RuleChainType.CORE, RuleChainType.EDGE}; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java index 5d0fe87fa9..5e68409362 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java @@ -37,9 +37,7 @@ import org.thingsboard.server.common.msg.TbMsg; "Will create new Customer if it doesn't exists and 'Create new Customer if not exists' is set to true.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeAssignToCustomerConfig", - icon = "add_circle", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + icon = "add_circle") public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java index b7f7b8ca04..e2a1aba779 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java @@ -45,9 +45,7 @@ import org.thingsboard.server.common.msg.TbMsg; "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeClearAlarmConfig", - icon = "notifications_off", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + icon = "notifications_off") public class TbClearAlarmNode extends TbAbstractAlarmNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java index 96595eb845..c8cd6b7b53 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java @@ -57,9 +57,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "Changes message originator to related entity view and produces new messages according to count of updated entity views", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig", - icon = "content_copy", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + icon = "content_copy") public class TbCopyAttributesToEntityViewNode implements TbNode { EmptyNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java index 4bd56be6be..45a8f4b0d2 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java @@ -51,9 +51,7 @@ import java.util.List; "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCreateAlarmConfig", - icon = "notifications_active", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + icon = "notifications_active") public class TbCreateAlarmNode extends TbAbstractAlarmNode { private static ObjectMapper mapper = new ObjectMapper(); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java index c9c0edd96f..7a3364d55a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java @@ -54,9 +54,7 @@ import java.util.List; nodeDetails = "If the relation already exists or successfully created - Message send via Success chain, otherwise Failure chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCreateRelationConfig", - icon = "add_circle", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + icon = "add_circle") public class TbCreateRelationNode extends TbAbstractRelationActionNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java index 2ea2264dad..d5bc429cd7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java @@ -44,9 +44,7 @@ import java.util.List; nodeDetails = "If the relation(s) successfully deleted - Message send via Success chain, otherwise Failure chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeDeleteRelationConfig", - icon = "remove_circle", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + icon = "remove_circle") public class TbDeleteRelationNode extends TbAbstractRelationActionNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java index 393cc72b0b..05391b0a7a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java @@ -37,10 +37,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeLogConfig", - icon = "menu", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) - + icon = "menu") public class TbLogNode implements TbNode { private TbLogNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java index 1569eff98e..01ed0c9499 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java @@ -44,9 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDetails = "Count incoming messages for specified interval and produces POST_TELEMETRY_REQUEST msg with messages count", icon = "functions", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbActionNodeMsgCountConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} -) + configDirective = "tbActionNodeMsgCountConfig") public class TbMsgCountNode implements TbNode { private static final String TB_MSG_COUNT_NODE_MSG = "TbMsgCountNodeMsg"; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java index c86cb91b49..c1e9d7152f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java @@ -78,7 +78,8 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; " otherwise, the message will be routed via success chain.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCustomTableConfig", - icon = "file_upload" + icon = "file_upload", + ruleChainTypes = RuleChainType.CORE ) public class TbSaveToCustomCassandraTableNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java index 79513c728d..3f2b17157d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java @@ -21,9 +21,13 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.*; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @RuleNode( @@ -34,8 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDetails = "Finds target Entity Customer by Customer name pattern and then unassign Originator Entity from this customer.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeUnAssignToCustomerConfig", - icon = "remove_circle", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "remove_circle" ) public class TbUnassignFromCustomerNode extends TbAbstractCustomerActionNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java index bfc9a0c865..9b013740a8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java @@ -46,8 +46,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "For example requestId field can be accessed with metadata.requestId.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeSnsConfig", - iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+" ) public class TbSnsNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java index 27359dc8f3..9a53a1307a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java @@ -51,8 +51,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; " For example requestId field can be accessed with metadata.requestId.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeSqsConfig", - iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+" ) public class TbSqsNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java index 696b606f2c..cd4e912a10 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java @@ -45,8 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; inEnabled = false, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbActionNodeGeneratorConfig", - icon = "repeat", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "repeat" ) public class TbMsgGeneratorNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java index 0b806465b0..e6a79eb5f6 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java @@ -46,8 +46,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDetails = "Delays messages for configurable period. Please note, this node acknowledges the message from the current queue (message will be removed from queue)", icon = "pause", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbActionNodeMsgDelayConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbActionNodeMsgDelayConfig" ) public class TbMsgDelayNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index bda074eee9..0e1ba938e3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; @@ -57,7 +58,8 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDetails = "Pushes messages to edge, if Message Originator assigned to particular edge or is EDGE entity. This node is used only on Cloud instances to push messages from Cloud to Edge. Supports only DEVICE, ENTITY_VIEW, ASSET and EDGE Message Originator(s).", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbNodeEmptyConfig", - icon = "cloud_download" + icon = "cloud_download", + ruleChainTypes = RuleChainType.CORE ) public class TbMsgPushToEdgeNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java index e9d54de5de..23025f836f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java @@ -40,8 +40,7 @@ import java.util.Map; nodeDetails = "If selected checkbox 'Check that all selected keys are present'\" and all keys in message data and metadata are exist - send Message via True chain, otherwise False chain is used.\n" + "Else if the checkbox is not selected, and at least one of the keys from data or metadata of the message exists - send Message via True chain, otherwise, False chain is used. ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeCheckMessageConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeCheckMessageConfig" ) public class TbCheckMessageNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java index f5912d1e5b..21f4222689 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java @@ -52,8 +52,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; " any relation to the originator of the message by type and direction.", nodeDetails = "If at least one relation exists - send Message via True chain, otherwise False chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeCheckRelationConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeCheckRelationConfig" ) public class TbCheckRelationNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java index 997a872a4a..7656cb6ead 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java @@ -37,8 +37,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
" + "Message type can be accessed via msgType property.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeScriptConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeScriptConfig" ) public class TbJsFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java index fa8f332d69..8f4f466d85 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java @@ -40,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
" + "Message type can be accessed via msgType property.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeSwitchConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeSwitchConfig" ) public class TbJsSwitchNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java index f0dac68130..1e77943c49 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java @@ -34,8 +34,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Filter incoming messages by Message Type", nodeDetails = "If incoming MessageType is expected - send Message via True chain, otherwise False chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbFilterNodeMessageTypeConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeMessageTypeConfig" ) public class TbMsgTypeFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java index 0973b49a97..27b069bc5b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java @@ -35,8 +35,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; nodeDescription = "Route incoming messages by Message Type", nodeDetails = "Sends messages with message types \"Post attributes\", \"Post telemetry\", \"RPC Request\" etc. via corresponding chain, otherwise Other chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbNodeEmptyConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbNodeEmptyConfig" ) public class TbMsgTypeSwitchNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java index 6687ae461e..dd01f67383 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java @@ -32,8 +32,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Filter incoming messages by message Originator Type", nodeDetails = "If Originator Type of incoming message is expected - send Message via True chain, otherwise False chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbFilterNodeOriginatorTypeConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeOriginatorTypeConfig" ) public class TbOriginatorTypeFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java index 9bd2109746..6f01e02c5c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java @@ -32,8 +32,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Route incoming messages by Message Originator Type", nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbNodeEmptyConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbNodeEmptyConfig" ) public class TbOriginatorTypeSwitchNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java index 036bfbd762..9b10cad9d8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java @@ -50,8 +50,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "messageId field can be accessed with metadata.messageId.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodePubSubConfig", - iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=" ) public class TbPubSubNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java index bb2e0bbca9..ca9f890032 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java @@ -52,8 +52,7 @@ import java.util.concurrent.TimeoutException; nodeDescription = "Produces incoming messages using GPS based geofencing", nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbActionNodeGpsGeofencingConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbActionNodeGpsGeofencingConfig" ) public class TbGpsGeofencingActionNode extends AbstractGeofencingNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java index a40f416f92..61a08736f8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java @@ -53,8 +53,7 @@ import java.util.List; nodeDescription = "Filter incoming messages by GPS based geofencing", nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeGpsGeofencingConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbFilterNodeGpsGeofencingConfig" ) public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java index 2945b09ab8..12807bbf19 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java @@ -52,8 +52,7 @@ import java.util.Properties; " from the Kafka in the Message Metadata. For example partition field can be accessed with metadata.partition.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeKafkaConfig", - iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==" ) public class TbKafkaNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java index 1a4fb244b3..758d818fe5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java @@ -41,8 +41,7 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE; "Set 'SEND_EMAIL' output message type.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeToEmailConfig", - icon = "email", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "email" ) public class TbMsgToEmailNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java index 043b5008c4..23d2485bc4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java @@ -47,8 +47,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "with to Email Node using Successful chain.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeSendEmailConfig", - icon = "send", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "send" ) public class TbSendEmailNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java index 92aca60332..2d9a2b4be0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java @@ -41,8 +41,7 @@ import org.thingsboard.server.common.msg.TbMsg; "To access those attributes in other nodes this template can be used " + "metadata.cs_temperature or metadata.shared_limit ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeOriginatorAttributesConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeOriginatorAttributesConfig" ) public class TbGetAttributesNode extends TbAbstractGetAttributesNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java index 1b0e0b7efb..bb8b642f83 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java @@ -34,8 +34,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; "To access those attributes in other nodes this template can be used " + "metadata.temperature.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbEnrichmentNodeCustomerAttributesConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeCustomerAttributesConfig" ) public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java index 93a03498d7..a486ae5007 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java @@ -43,8 +43,7 @@ import org.thingsboard.server.common.msg.TbMsg; "Note: only Device, Asset, and Entity View type are allowed.

" + "If the originator of the message is not assigned to Customer, or originator type is not supported - Message will be forwarded to Failure chain, otherwise, Success chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeEntityDetailsConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeEntityDetailsConfig" ) public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java index af6cbf9265..97b4918db9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java @@ -39,8 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg; "To access those attributes in other nodes this template can be used " + "metadata.cs_temperature or metadata.shared_limit ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeDeviceAttributesConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeDeviceAttributesConfig" ) public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java index 6f240d2df6..ec6d57f5c5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java @@ -44,8 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDescription = "Add Message Originator fields values into Message Metadata", nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeOriginatorFieldsConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeOriginatorFieldsConfig" ) public class TbGetOriginatorFieldsNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java index 44cf94163e..fadf8b9366 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java @@ -36,8 +36,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; "To access those attributes in other nodes this template can be used " + "metadata.temperature.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbEnrichmentNodeRelatedAttributesConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeRelatedAttributesConfig" ) public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 009870e404..485d6f083a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -67,8 +67,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE; "Also, the rule node allows you to select telemetry sampling order: ASC or DESC.
" + "Note: The maximum size of the fetched array is 1000 records.\n ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase" ) public class TbGetTelemetryNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java index 1d31a6bc0d..e9ba41acd7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java @@ -36,8 +36,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; "To access those attributes in other nodes this template can be used " + "metadata.temperature.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbEnrichmentNodeTenantAttributesConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeTenantAttributesConfig" ) public class TbGetTenantAttributeNode extends TbEntityGetAttrNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java index cf4bcaf064..2098dc4fc0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java @@ -38,8 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg; "Note: only Device, Asset, and Entity View type are allowed.

" + "If the originator of the message is not assigned to Tenant, or originator type is not supported - Message will be forwarded to Failure chain, otherwise, Success chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeEntityDetailsConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbEnrichmentNodeEntityDetailsConfig" ) public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java index b7d76f8968..57e1b09258 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java @@ -50,8 +50,7 @@ import java.util.concurrent.TimeoutException; nodeDetails = "Will publish message payload to the MQTT broker with QoS AT_LEAST_ONCE.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbActionNodeMqttConfig", - icon = "call_split", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "call_split" ) public class TbMqttNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java index 78ac75a642..b260fa8cef 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java @@ -40,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; nodeDetails = "Will publish message payload to RabbitMQ queue.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeRabbitMqConfig", - iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=" ) public class TbRabbitMqNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index eee1b8627f..0db4989b07 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -42,8 +42,7 @@ import org.thingsboard.server.common.msg.TbMsg; "and if your proxy with auth, the next ones should be added: \"tb.proxy.user\" and \"tb.proxy.password\" to the thingsboard.conf file.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeRestApiCallConfig", - iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+" ) public class TbRestApiCallNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java index 2fc84e1c32..9c824a104c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java @@ -40,8 +40,7 @@ import java.util.UUID; nodeDetails = "Expects messages with any message type. Will forward message body to the device.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeRpcReplyConfig", - icon = "call_merge", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "call_merge" ) public class TbSendRPCReplyNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java index eac01929b6..301c7cd36c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java @@ -51,8 +51,7 @@ import java.util.concurrent.TimeUnit; "If the RPC call request is originated by REST API call from user, will forward the response to user immediately.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeRpcRequestConfig", - icon = "call_made", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "call_made" ) public class TbSendRPCRequestNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index cb536714e7..e776fa4dbd 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -45,8 +45,7 @@ import java.util.Set; nodeDetails = "Saves entity attributes based on configurable scope parameter. Expects messages with 'POST_ATTRIBUTES_REQUEST' message type", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbActionNodeAttributesConfig", - icon = "file_upload", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "file_upload" ) public class TbMsgAttributesNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java index 24ba417b89..3b25e4d9f2 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java @@ -46,8 +46,7 @@ import java.util.Map; nodeDetails = "Saves timeseries telemetry data based on configurable TTL parameter. Expects messages with 'POST_TELEMETRY_REQUEST' message type", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbActionNodeTimeseriesConfig", - icon = "file_upload", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "file_upload" ) public class TbMsgTimeseriesNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java index c66cbc1652..8b376ae977 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java @@ -39,8 +39,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "Subsequent messages will not be processed until the previous message processing is completed or timeout event occurs.\n" + "Size of the queue per originator and timeout values are configurable on a system level", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbNodeEmptyConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbNodeEmptyConfig" ) @Deprecated public class TbSynchronizationBeginNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java index 83d221285a..068aefe862 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java @@ -39,8 +39,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDescription = "This Node is now deprecated. Use \"Checkpoint\" instead.", nodeDetails = "", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = ("tbNodeEmptyConfig"), - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = ("tbNodeEmptyConfig") ) @Deprecated public class TbSynchronizationEndNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java index 0a0de55a46..8b65c9ca0c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java @@ -47,8 +47,7 @@ import java.util.HashSet; "Alarm Originator found only in case original Originator is Alarm entity.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbTransformationNodeChangeOriginatorConfig", - icon = "find_replace", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + icon = "find_replace" ) public class TbChangeOriginatorNode extends TbAbstractTransformNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java index 434a5ce61a..15937d6cd5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java @@ -38,8 +38,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "{ msg: new payload,
   metadata: new metadata,
   msgType: new msgType }

" + "All fields in resulting object are optional and will be taken from original message if not specified.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbTransformationNodeScriptConfig", - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} + configDirective = "tbTransformationNodeScriptConfig" ) public class TbTransformMsgNode extends TbAbstractTransformNode { From b2f4a08209b4efecf645a51d11461ef2370ae45c Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 26 Jun 2020 17:04:36 +0300 Subject: [PATCH 020/156] Added set default edge root rule chain test --- .../dao/service/BaseRuleChainServiceTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java index 2ab0fa4067..f9ec01a00a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java @@ -332,6 +332,21 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest { Assert.assertEquals(1, result.size()); } + @Test + public void setDefaultRootEdgeRuleChain() throws Exception { + RuleChainId ruleChainId1 = saveRuleChainAndSetDefaultEdge("Default Edge Rule Chain 1"); + RuleChainId ruleChainId2 = saveRuleChainAndSetDefaultEdge("Default Edge Rule Chain 2"); + + ruleChainService.setDefaultRootEdgeRuleChain(tenantId, ruleChainId1); + ruleChainService.setDefaultRootEdgeRuleChain(tenantId, ruleChainId2); + + RuleChain ruleChainById = ruleChainService.findRuleChainById(tenantId, ruleChainId1); + Assert.assertFalse(ruleChainById.isRoot()); + + ruleChainById = ruleChainService.findRuleChainById(tenantId, ruleChainId2); + Assert.assertTrue(ruleChainById.isRoot()); + } + private RuleChainId saveRuleChainAndSetDefaultEdge(String name) { RuleChain edgeRuleChain = new RuleChain(); edgeRuleChain.setTenantId(tenantId); From b38f8b61f429ca16a02c68253b320ffdceccd90d Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 30 Jun 2020 18:19:25 +0300 Subject: [PATCH 021/156] added all methods for working with Edge --- .../thingsboard/rest/client/RestClient.java | 167 ++++++++++++++++-- 1 file changed, 157 insertions(+), 10 deletions(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 11a46055b2..cd9a51e1f7 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -2015,6 +2015,42 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } + public Optional assignEdgeToPublicCustomer(EdgeId edgeId) { + try { + ResponseEntity edge = restTemplate.postForEntity(baseURL + "/api/customer/public/edge/{edgeId}", null, Edge.class, edgeId.getId()); + return Optional.ofNullable(edge.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional setRootRuleChain(RuleChainId ruleChainId, EdgeId edgeId) { + try { + ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/{ruleChainId}/root", null, RuleChain.class, edgeId.getId(), ruleChainId.getId()); + return Optional.ofNullable(ruleChain.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TextPageData getEdges(TextPageLink pageLink) { + Map params = new HashMap<>(); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edges?" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + public Optional unassignEdgeFromCustomer(EdgeId edgeId) { try { ResponseEntity edge = restTemplate.exchange(baseURL + "/api/customer/edge/{edgeId}", HttpMethod.DELETE, HttpEntity.EMPTY, Edge.class, edgeId.getId()); @@ -2041,9 +2077,9 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public Optional unassignDeviceFromEdge(DeviceId deviceId) { + public Optional unassignDeviceFromEdge(EdgeId edgeId, DeviceId deviceId) { try { - ResponseEntity device = restTemplate.exchange(baseURL + "/api/edge/device/{deviceId}", HttpMethod.DELETE, HttpEntity.EMPTY, Device.class, deviceId.getId()); + ResponseEntity device = restTemplate.exchange(baseURL + "/api/edge/{edgeId}/device/{deviceId}", HttpMethod.DELETE, HttpEntity.EMPTY, Device.class, edgeId.getId(), deviceId.getId()); return Optional.ofNullable(device.getBody()); } catch (HttpClientErrorException exception) { if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { @@ -2054,13 +2090,12 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public TextPageData getEdgeDevices(EdgeId edgeId, String deviceType, TextPageLink pageLink) { + public TextPageData getEdgeDevices(EdgeId edgeId, TextPageLink pageLink) { Map params = new HashMap<>(); params.put("edgeId", edgeId.getId().toString()); - params.put("type", deviceType); addPageLinkToParam(params, pageLink); return restTemplate.exchange( - baseURL + "/api/edge/{edgeId}/devices?type={type}&" + getUrlParams(pageLink), + baseURL + "/api/edge/{edgeId}/devices?" + getUrlParams(pageLink), HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference>() { }, params).getBody(); @@ -2079,9 +2114,9 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public Optional unassignAssetFromEdge(AssetId assetId) { + public Optional unassignAssetFromEdge(EdgeId edgeId, AssetId assetId) { try { - ResponseEntity asset = restTemplate.exchange(baseURL + "/api/edge/asset/{assetId}", HttpMethod.DELETE, HttpEntity.EMPTY, Asset.class, assetId.getId()); + ResponseEntity asset = restTemplate.exchange(baseURL + "/api/edge/{edgeId}/asset/{assetId}", HttpMethod.DELETE, HttpEntity.EMPTY, Asset.class, edgeId.getId(), assetId.getId()); return Optional.ofNullable(asset.getBody()); } catch (HttpClientErrorException exception) { if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { @@ -2092,18 +2127,130 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public TextPageData getEdgeAssets(EdgeId edgeId, String assetType, TextPageLink pageLink) { + public TextPageData getEdgeAssets(EdgeId edgeId, TextPageLink pageLink) { Map params = new HashMap<>(); params.put("edgeId", edgeId.getId().toString()); - params.put("type", assetType); addPageLinkToParam(params, pageLink); return restTemplate.exchange( - baseURL + "/api/edge/{edgeId}/assets?type={type}&" + getUrlParams(pageLink), + baseURL + "/api/edge/{edgeId}/assets?" + getUrlParams(pageLink), HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference>() { }, params).getBody(); } + public Optional assignDashboardToEdge(EdgeId edgeId, DashboardId dashboardId) { + try { + ResponseEntity dashboard = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/dashboard/{dashboardId}", null, Dashboard.class, edgeId.getId(), dashboardId.getId()); + return Optional.ofNullable(dashboard.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional unassignDashboardFromEdge(EdgeId edgeId, DashboardId dashboardId) { + try { + ResponseEntity dashboard = restTemplate.exchange(baseURL + "/api/edge/{edgeId}/dashboard/{dashboardId}", HttpMethod.DELETE, HttpEntity.EMPTY, Dashboard.class, edgeId.getId(), dashboardId.getId()); + return Optional.ofNullable(dashboard.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TimePageData getEdgeDashboards(EdgeId edgeId, TimePageLink pageLink) { + Map params = new HashMap<>(); + params.put("edgeId", edgeId.getId().toString()); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edge/{edgeId}/dashboards?" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + + public Optional assignEntityViewToEdge(EdgeId edgeId, EntityViewId entityViewId) { + try { + ResponseEntity entityView = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/entityView/{entityViewId}", null, EntityView.class, edgeId.getId(), entityViewId.getId()); + return Optional.ofNullable(entityView.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional unassignEntityViewFromEdge(EdgeId edgeId, EntityViewId entityViewId) { + try { + ResponseEntity entityView = restTemplate.exchange(baseURL + "/api/edge/{edgeId}/entityView/{entityViewId}", HttpMethod.DELETE, HttpEntity.EMPTY, EntityView.class, edgeId.getId(), entityViewId.getId()); + return Optional.ofNullable(entityView.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TextPageData getEdgeEntityViews(EdgeId edgeId, String entityViewType, TextPageLink pageLink) { + Map params = new HashMap<>(); + params.put("edgeId", edgeId.getId().toString()); + params.put("type", entityViewType); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edge/{edgeId}/entityViews?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + + public Optional assignRuleChainToEdge(EdgeId edgeId, RuleChainId ruleChainId) { + try { + ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/ruleChain/{ruleChainId}", null, RuleChain.class, edgeId.getId(), ruleChainId.getId()); + return Optional.ofNullable(ruleChain.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional unassignRuleChainFromEdge(EdgeId edgeId, RuleChainId ruleChainId) { + try { + ResponseEntity ruleChain = restTemplate.exchange(baseURL + "/api/edge/{edgeId}/ruleChain/{ruleChainId}", HttpMethod.DELETE, HttpEntity.EMPTY, RuleChain.class, edgeId.getId(), ruleChainId.getId()); + return Optional.ofNullable(ruleChain.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public TimePageData getEdgeRuleChains(EdgeId edgeId, TimePageLink pageLink) { + Map params = new HashMap<>(); + params.put("edgeId", edgeId.getId().toString()); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edge/{edgeId}/ruleChains?" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + public TextPageData getTenantEdges(String type, TextPageLink pageLink) { Map params = new HashMap<>(); params.put("type", type); From bf5f90d2712b2d01553a3829150abfb2079cd3cb Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 1 Jul 2020 09:27:16 +0300 Subject: [PATCH 022/156] Added support for user update. Push notification to rule engine in case device was created --- .../edge/DefaultEdgeNotificationService.java | 18 +++++ .../service/edge/EdgeContextComponent.java | 11 +++ .../service/edge/rpc/EdgeGrpcSession.java | 67 +++++++++++++++++-- 3 files changed, 89 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index d16082173c..eb5fcdad9e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -23,12 +23,14 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; @@ -36,6 +38,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.IdBased; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; @@ -46,7 +49,9 @@ import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; +import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.relation.RelationService; +import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.executors.DbCallbackExecutorService; @@ -77,6 +82,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @Autowired private AlarmService alarmService; + @Autowired + private UserService userService; + @Autowired private RelationService relationService; @@ -142,6 +150,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { switch (edgeEventType) { // TODO: voba - handle edge updates // case EDGE: + case USER: case ASSET: case DEVICE: case ENTITY_VIEW: @@ -286,6 +295,15 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); case RULE_CHAIN: return convertToEdgeIds(edgeService.findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); + case USER: + User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); + TextPageData edges; + if (userById.getCustomerId() == null || userById.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { + edges = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + } else { + edges = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); + } + return convertToEdgeIds(Futures.immediateFuture(edges.getData())); default: return Futures.immediateFuture(Collections.emptyList()); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index 32f38d2621..c21c1ebc9c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -33,6 +33,9 @@ import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; +import org.thingsboard.server.queue.discovery.PartitionService; +import org.thingsboard.server.queue.provider.TbQueueProducerProvider; +import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; @@ -49,6 +52,7 @@ import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.state.DeviceStateService; @Component +@TbCoreComponent @Data public class EdgeContextComponent { @@ -56,6 +60,13 @@ public class EdgeContextComponent { @Autowired private EdgeService edgeService; + @Autowired + private PartitionService partitionService; + + @Autowired + @Lazy + private TbQueueProducerProvider producerProvider; + @Lazy @Autowired private EdgeNotificationService edgeNotificationService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 5e077aea67..cca61aa28e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -18,10 +18,10 @@ package org.thingsboard.server.service.edge.rpc; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; @@ -66,6 +67,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.queue.ServiceType; +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; @@ -96,6 +99,10 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.TbQueueCallback; +import org.thingsboard.server.queue.TbQueueMsgMetadata; +import org.thingsboard.server.queue.TbQueueProducer; +import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.service.edge.EdgeContextComponent; import java.io.Closeable; @@ -132,6 +139,8 @@ public final class EdgeGrpcSession implements Closeable { private StreamObserver outputStream; private boolean connected; + private TbQueueProducer> ruleEngineMsgProducer; + EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener, Consumer sessionCloseListener, ObjectMapper mapper) { this.sessionId = UUID.randomUUID(); @@ -140,6 +149,7 @@ public final class EdgeGrpcSession implements Closeable { this.sessionOpenListener = sessionOpenListener; this.sessionCloseListener = sessionCloseListener; this.mapper = mapper; + this.ruleEngineMsgProducer = ctx.getProducerProvider().getRuleEngineMsgProducer(); initInputStream(); } @@ -767,17 +777,19 @@ public final class EdgeGrpcSession implements Closeable { Device deviceById = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId); if (deviceById != null) { // this ID already used by other device - create new device and update ID on the edge - Device savedDevice = createDevice(deviceUpdateMsg); + device = createDevice(deviceUpdateMsg); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, savedDevice)) + .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device)) .build(); outputStream.onNext(ResponseMsg.newBuilder() .setEntityUpdateMsg(entityUpdateMsg) .build()); } else { - createDevice(deviceUpdateMsg); + device = createDevice(deviceUpdateMsg); } } + // TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment + ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId()); break; case ENTITY_UPDATED_RPC_MESSAGE: updateDevice(deviceUpdateMsg); @@ -866,11 +878,9 @@ public final class EdgeGrpcSession implements Closeable { device.setType(deviceUpdateMsg.getType()); device.setLabel(deviceUpdateMsg.getLabel()); device = ctx.getDeviceService().saveDevice(device); - device = ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId()); createRelationFromEdge(device.getId()); - ctx.getRelationService().saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(edge.getId(), device.getId(), "Created")); ctx.getDeviceStateService().onDeviceAdded(device); - + pushDeviceCreatedEventToRuleEngine(device); requestDeviceCredentialsFromEdge(device); } finally { deviceCreationLock.unlock(); @@ -878,6 +888,49 @@ public final class EdgeGrpcSession implements Closeable { return device; } + private void pushDeviceCreatedEventToRuleEngine(Device device) { + try { + ObjectNode entityNode = mapper.valueToTree(device); + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, device.getId(), getActionTbMsgMetaData(device.getCustomerId()), mapper.writeValueAsString(entityNode)); + sendToRuleEngine(edge.getTenantId(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + // TODO: voba - handle success + } + + @Override + public void onFailure(Throwable t) { + // TODO: voba - handle failure + } + }); + } catch (JsonProcessingException | IllegalArgumentException e) { + log.warn("[{}] Failed to push device action to rule engine: {}", device.getId(), DataConstants.ENTITY_CREATED, e); + } + } + + protected void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) { + TopicPartitionInfo tpi = ctx.getPartitionService().resolve(ServiceType.TB_RULE_ENGINE, tenantId, tbMsg.getOriginator()); + TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder().setTbMsg(TbMsg.toByteString(tbMsg)) + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()).build(); + ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), callback); + } + + private TbMsgMetaData getActionTbMsgMetaData(CustomerId customerId) { + TbMsgMetaData metaData = getTbMsgMetaData(edge); + if (customerId != null && !customerId.isNullUid()) { + metaData.putValue("customerId", customerId.toString()); + } + return metaData; + } + + private TbMsgMetaData getTbMsgMetaData(Edge edge) { + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("edgeId", edge.getId().toString()); + metaData.putValue("edgeName", edge.getName()); + return metaData; + } + private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) { switch (entityType) { case DEVICE: From 15b6574bf2c9c42194944b30ee87e35aa3ce2842 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Wed, 1 Jul 2020 18:58:21 +0300 Subject: [PATCH 023/156] fix in getEdgeEntityViews --- .../main/java/org/thingsboard/rest/client/RestClient.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index cd9a51e1f7..a89d88959a 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -2201,13 +2201,12 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public TextPageData getEdgeEntityViews(EdgeId edgeId, String entityViewType, TextPageLink pageLink) { + public TextPageData getEdgeEntityViews(EdgeId edgeId, TextPageLink pageLink) { Map params = new HashMap<>(); params.put("edgeId", edgeId.getId().toString()); - params.put("type", entityViewType); addPageLinkToParam(params, pageLink); return restTemplate.exchange( - baseURL + "/api/edge/{edgeId}/entityViews?type={type}&" + getUrlParams(pageLink), + baseURL + "/api/edge/{edgeId}/entityViews?" + getUrlParams(pageLink), HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference>() { From 79020736a66d04511e1520a02be8f8e0a1784551 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 3 Jul 2020 15:33:43 +0300 Subject: [PATCH 024/156] getEdgeEvents method --- .../org/thingsboard/rest/client/RestClient.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index a89d88959a..ab04b16b66 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeSearchQuery; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; @@ -2311,6 +2312,19 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { }).getBody(); } + public TimePageData getEdgeEvents(EdgeId edgeId, TimePageLink pageLink) { + Map params = new HashMap<>(); + params.put("edgeId", edgeId.toString()); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/edge/{edgeId}/events?" + getUrlParams(pageLink), + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, + params).getBody(); + } + @Deprecated public Optional getAttributes(String accessToken, String clientKeys, String sharedKeys) { Map params = new HashMap<>(); From 3c3da12e29a0b89d6188a7c7a01cfc41c872f9b3 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 3 Jul 2020 15:42:07 +0300 Subject: [PATCH 025/156] added EdgeEventController --- .../controller/EdgeEventController.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java new file mode 100644 index 0000000000..b58d1eeb71 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -0,0 +1,53 @@ +package org.thingsboard.server.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TimePageData; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.edge.EdgeEventService; +import org.thingsboard.server.queue.util.TbCoreComponent; + +@Slf4j +@RestController +@TbCoreComponent +@RequestMapping("/api") +public class EdgeEventController extends BaseController { + + @Autowired + private EdgeEventService edgeEventService; + + public static final String EDGE_ID = "edgeId"; + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/edge/{edgeId}/events", method = RequestMethod.GET) + @ResponseBody + public TimePageData getEdgeEvents( + @PathVariable(EDGE_ID) String strEdgeId, + @RequestParam int limit, + @RequestParam(required = false) Long startTime, + @RequestParam(required = false) Long endTime, + @RequestParam(required = false, defaultValue = "false") boolean ascOrder, + @RequestParam(required = false) String offset) throws ThingsboardException { + checkParameter(EDGE_ID, strEdgeId); + try { + TenantId tenantId = getCurrentUser().getTenantId(); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); + return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink)); + } catch (Exception e) { + throw handleException(e); + } + } +} + From 0cf800d0a87401aadef991aa527b0c47c23cfaa1 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 6 Jul 2020 12:25:15 +0300 Subject: [PATCH 026/156] test, license --- .../controller/EdgeEventController.java | 15 +++ .../BaseEdgeEventControllerTest.java | 127 ++++++++++++++++++ .../nosql/EdgeEventControllerNoSqlTest.java | 23 ++++ .../sql/EdgeEventControllerSqlTest.java | 23 ++++ 4 files changed, 188 insertions(+) create mode 100644 application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java create mode 100644 application/src/test/java/org/thingsboard/server/controller/nosql/EdgeEventControllerNoSqlTest.java create mode 100644 application/src/test/java/org/thingsboard/server/controller/sql/EdgeEventControllerSqlTest.java diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java index b58d1eeb71..8558c194b2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.controller; import lombok.extern.slf4j.Slf4j; diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java new file mode 100644 index 0000000000..6c78aa1626 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java @@ -0,0 +1,127 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller; + +import com.fasterxml.jackson.core.type.TypeReference; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TimePageData; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.data.security.Authority; + +import java.util.List; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class BaseEdgeEventControllerTest extends AbstractControllerTest { + + private Tenant savedTenant; + private TenantId tenantId; + private User tenantAdmin; + + @Before + public void beforeTest() throws Exception { + loginSysAdmin(); + + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + savedTenant = doPost("/api/tenant", tenant, Tenant.class); + tenantId = savedTenant.getId(); + Assert.assertNotNull(savedTenant); + + tenantAdmin = new User(); + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); + tenantAdmin.setTenantId(savedTenant.getId()); + tenantAdmin.setEmail("tenant2@thingsboard.org"); + tenantAdmin.setFirstName("Joe"); + tenantAdmin.setLastName("Downs"); + + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); + } + + @After + public void afterTest() throws Exception { + loginSysAdmin(); + + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) + .andExpect(status().isOk()); + } + + @Test + public void testGetEdgeEvents() throws Exception { + Edge edge = constructEdge("TestEdge", "default"); + edge = doPost("/api/edge", edge, Edge.class); + + Device device = constructDevice("TestDevice", "default"); + Asset asset = constructAsset("TestAsset", "default"); + + Device savedDevice = doPost("/api/device", device, Device.class); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + + doPost("/api/edge/" + edge.getId().toString() + "/device/" + savedDevice.getId().toString(), Device.class); + doPost("/api/edge/" + edge.getId().toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); + + Thread.sleep(500); + + List edgeEvents = doGetTypedWithTimePageLink("/api/edge/" + edge.getId().toString() + "/events?", + new TypeReference>() { + }, new TimePageLink(5)).getData(); + + Assert.assertFalse(edgeEvents.isEmpty()); + Assert.assertEquals(3, edgeEvents.size()); + Assert.assertEquals(edgeEvents.get(0).getEdgeEventType(), EdgeEventType.DEVICE); + Assert.assertEquals(edgeEvents.get(1).getEdgeEventType(), EdgeEventType.ASSET); + Assert.assertEquals(edgeEvents.get(2).getEdgeEventType(), EdgeEventType.RULE_CHAIN); + } + + private Edge constructEdge(String name, String type) { + Edge edge = new Edge(); + edge.setTenantId(tenantId); + edge.setName(name); + edge.setType(type); + edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); + edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); + return edge; + } + + private Device constructDevice(String name, String type) { + Device device = new Device(); + device.setName(name); + device.setType(type); + return device; + } + + private Asset constructAsset(String name, String type) { + Asset asset = new Asset(); + asset.setName(name); + asset.setType(type); + return asset; + } + + +} diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/EdgeEventControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/EdgeEventControllerNoSqlTest.java new file mode 100644 index 0000000000..8cb88c83f6 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/nosql/EdgeEventControllerNoSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller.nosql; + +import org.thingsboard.server.controller.BaseEdgeEventControllerTest; +import org.thingsboard.server.dao.service.DaoNoSqlTest; + +@DaoNoSqlTest +public class EdgeEventControllerNoSqlTest extends BaseEdgeEventControllerTest { +} diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/EdgeEventControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/EdgeEventControllerSqlTest.java new file mode 100644 index 0000000000..84b37970ed --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/sql/EdgeEventControllerSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller.sql; + +import org.thingsboard.server.controller.BaseEdgeEventControllerTest; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +public class EdgeEventControllerSqlTest extends BaseEdgeEventControllerTest { +} From 5ac2ca3a26292f38f143875b7c728e20cd82fc36 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Mon, 6 Jul 2020 13:27:04 +0300 Subject: [PATCH 027/156] Added Downlink edge tab. UI data implementation --- ui/src/app/common/types.constant.js | 4 +++ .../event/event-header-edge-event.tpl.html | 23 ++++++++++++ ui/src/app/event/event-header.directive.js | 4 +++ .../app/event/event-row-edge-event.tpl.html | 36 +++++++++++++++++++ ui/src/app/event/event-row.directive.js | 36 ++++++++++++++++++- ui/src/app/event/event-table.directive.js | 31 ++++++++++++++-- ui/src/app/locale/locale.constant-en_US.json | 7 +++- 7 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 ui/src/app/event/event-header-edge-event.tpl.html create mode 100644 ui/src/app/event/event-row-edge-event.tpl.html diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index a4036362c9..960527f3b3 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -600,6 +600,10 @@ export default angular.module('thingsboard.types', []) stats: { value: "STATS", name: "event.type-stats" + }, + edgeEvent: { + value: "EDGE_EVENT", + name: "event.type-edge-event" } }, debugEventType: { diff --git a/ui/src/app/event/event-header-edge-event.tpl.html b/ui/src/app/event/event-header-edge-event.tpl.html new file mode 100644 index 0000000000..cdd9dfb20f --- /dev/null +++ b/ui/src/app/event/event-header-edge-event.tpl.html @@ -0,0 +1,23 @@ + +
event.event-time
+
event.event-type
+
edge.entity-id
+
edge.event-action
+
event.success
+
edge.entity-info
diff --git a/ui/src/app/event/event-header.directive.js b/ui/src/app/event/event-header.directive.js index ce0fe4e81c..efe3dab21c 100644 --- a/ui/src/app/event/event-header.directive.js +++ b/ui/src/app/event/event-header.directive.js @@ -19,6 +19,7 @@ import eventHeaderLcEventTemplate from './event-header-lc-event.tpl.html'; import eventHeaderStatsTemplate from './event-header-stats.tpl.html'; import eventHeaderErrorTemplate from './event-header-error.tpl.html'; import eventHeaderDebugRuleNodeTemplate from './event-header-debug-rulenode.tpl.html'; +import eventHeaderEdgeEventTemplate from './event-header-edge-event.tpl.html' /* eslint-enable import/no-unresolved, import/default */ @@ -45,6 +46,9 @@ export default function EventHeaderDirective($compile, $templateCache, types) { case types.debugEventType.debugRuleChain.value: template = eventHeaderDebugRuleNodeTemplate; break; + case types.eventType.edgeEvent.value: + template = eventHeaderEdgeEventTemplate; + break; } return $templateCache.get(template); } diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html new file mode 100644 index 0000000000..a42e39d811 --- /dev/null +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -0,0 +1,36 @@ + +
{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}
+
{{event.edgeEventAction}}
+
{{event.entityId}}
+
{{event.entityType}}
+
{{event.success ? 'event.success' : 'event.failed'}}
+
+ + + {{ 'action.view' | translate }} + + + more_horiz + + +
+ diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index eec8a1aff6..ae337cfb38 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -21,11 +21,12 @@ import eventRowLcEventTemplate from './event-row-lc-event.tpl.html'; import eventRowStatsTemplate from './event-row-stats.tpl.html'; import eventRowErrorTemplate from './event-row-error.tpl.html'; import eventRowDebugRuleNodeTemplate from './event-row-debug-rulenode.tpl.html'; +import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, types) { +export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, types, toast, entityService) { var linker = function (scope, element, attrs) { @@ -47,6 +48,9 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ case types.debugEventType.debugRuleChain.value: template = eventRowDebugRuleNodeTemplate; break; + case types.eventType.edgeEvent.value: + template = eventRowEdgeEventTemplate; + break; } return $templateCache.get(template); } @@ -86,6 +90,36 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ }); } + scope.showEdgeEntityContent = function($event, title, contentType) { + var onShowingCallback = { + onShowing: function(){} + } + if (!contentType) { + contentType = null; + } + entityService.getEntity(scope.event.entityType, scope.event.entityId, {}).then( + function success(info) { + var content = angular.toJson(info); + $mdDialog.show({ + controller: 'EventContentDialogController', + controllerAs: 'vm', + templateUrl: eventErrorDialogTemplate, + locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, + parent: angular.element($document[0].body), + fullscreen: true, + targetEvent: $event, + multiple: true, + onShowing: function(scope, element) { + onShowingCallback.onShowing(scope, element); + } + }); + }, + function fail() { + toast.showError($translate.instant('edge.load-entity-error')); + } + ); + } + scope.checkTooltip = function($event) { var el = $event.target; var $el = angular.element(el); diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index ff002f069e..7f21dfd57f 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -24,6 +24,27 @@ import eventTableTemplate from './event-table.tpl.html'; /*@ngInject*/ export default function EventTableDirective($compile, $templateCache, $rootScope, types, eventService) { + var edgeData = [ + { + "createdTime": 1593592774537, + "tenantId": "63746950-bb76-11ea-9f96-69d7782607f7", + "edgeId": "85bb84b0-bb78-11ea-8472-c3dbdeb0fd97", + "edgeEventAction": "ASSIGNED_TO_EDGE", + "entityId": "640055a0-bb76-11ea-9f96-69d7782607f7", + "entityType": "DEVICE", + "success": true, + }, + { + "createdTime": 1593592774538, + "tenantId": "63746950-bb76-11ea-9f96-69d7782607f7", + "edgeId": "85bb84b0-bb78-11ea-8472-c3dbdeb0fd97", + "edgeEventAction": "CREDENTIALS_UPDATED", + "entityId": "640055a0-bb76-11ea-9f96-69d7782607f8", + "entityType": "DEVICE", + "success": false + } + ] + var linker = function (scope, element, attrs) { var template = $templateCache.get(eventTableTemplate); @@ -98,7 +119,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope }, fetchMoreItems_: function () { - if (scope.events.hasNext && !scope.events.pending) { + if (scope.events.hasNext && !scope.events.pending && scope.eventType !== "EDGE_EVENT") { if (scope.entityType && scope.entityId && scope.eventType && scope.tenantId) { var promise = eventService.getEvents(scope.entityType, scope.entityId, scope.eventType, scope.tenantId, scope.events.nextPageLink); @@ -125,12 +146,16 @@ export default function EventTableDirective($compile, $templateCache, $rootScope scope.events.hasNext = false; } } + if (scope.eventType === "EDGE_EVENT") { + scope.events.data = edgeData; + scope.events.nextPageLink = false; + scope.events.hasNext = null; + } } }; scope.$watch("entityId", function(newVal, prevVal) { if (newVal && !angular.equals(newVal, prevVal)) { - scope.resetFilter(); scope.reload(); } }); @@ -141,7 +166,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope } }); - scope.$watch("timewindow", function(newVal, prevVal) { + scope.$watch("createdTime", function(newVal, prevVal) { if (newVal && !angular.equals(newVal, prevVal)) { scope.reload(); } diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index d6b186c42e..57c54c2556 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -791,14 +791,17 @@ "name": "Name", "name-required": "Name is required.", "description": "Description", - "events": "Events", + "entity-info": "Entity info", "details": "Details", + "events": "Events", "copy-id": "Copy Edge Id", "id-copied-message": "Edge Id has been copied to clipboard", "permissions": "Permissions", "edge-required": "Edge required", "edge-type": "Edge type", "edge-type-required": "Edge type is required.", + "event-action": "Event action", + "entity-id": "Entity ID", "select-edge-type": "Select edge type", "assign-to-customer": "Assign to customer", "assign-to-customer-text": "Please select the customer to assign the edge(s)", @@ -818,6 +821,7 @@ "make-private-edge-text": "After the confirmation the edge and all its data will be made private and won't be accessible by others.", "import": "Import edge", "label": "Label", + "load-entity-error": "Could not load entity info", "assign-new-edge": "Assign new edge", "manage-edge-dashboards": "Manage edge dashboards", "unassign-from-edge": "Unassign from edge", @@ -1082,6 +1086,7 @@ "type-debug-rule-chain": "Debug", "no-events-prompt": "No events found", "error": "Error", + "type-edge-event": "Downlink", "alarm": "Alarm", "event-time": "Event time", "server": "Server", From 51bfc91f14ae835e35489a9f6c28d40b093acfdf Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 6 Jul 2020 19:12:21 +0300 Subject: [PATCH 028/156] fixes in EdgeEventControllerTest and in relation processing --- .../paho27873734058141-tcplocalhost1883/.lck | 0 .../edge/DefaultEdgeNotificationService.java | 5 ++-- .../BaseEdgeEventControllerTest.java | 30 ++++++++++++++----- 3 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 application/paho27873734058141-tcplocalhost1883/.lck diff --git a/application/paho27873734058141-tcplocalhost1883/.lck b/application/paho27873734058141-tcplocalhost1883/.lck new file mode 100644 index 0000000000..e69de29bb2 diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index eb5fcdad9e..47c6ece48f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.edge; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.Futures; @@ -245,8 +246,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { }, dbCallbackExecutorService); } - private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { - EntityRelation relation = mapper.convertValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class); + private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException { + EntityRelation relation = mapper.readValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class); if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && !relation.getTo().getEntityType().equals(EntityType.EDGE)) { List>> futures = new ArrayList<>(); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java index 6c78aa1626..72e6f149ec 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java @@ -16,12 +16,16 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.web.client.RestTemplate; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; @@ -32,18 +36,23 @@ import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.security.Authority; import java.util.List; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@Slf4j public class BaseEdgeEventControllerTest extends AbstractControllerTest { private Tenant savedTenant; private TenantId tenantId; private User tenantAdmin; + private RestTemplate restTemplate; + @Before public void beforeTest() throws Exception { loginSysAdmin(); @@ -78,25 +87,31 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { edge = doPost("/api/edge", edge, Edge.class); Device device = constructDevice("TestDevice", "default"); - Asset asset = constructAsset("TestAsset", "default"); - Device savedDevice = doPost("/api/device", device, Device.class); - Asset savedAsset = doPost("/api/asset", asset, Asset.class); doPost("/api/edge/" + edge.getId().toString() + "/device/" + savedDevice.getId().toString(), Device.class); + + Asset asset = constructAsset("TestAsset", "default"); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + doPost("/api/edge/" + edge.getId().toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); - Thread.sleep(500); + EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE); + + doPost("/api/relation", relation); + + Thread.sleep(1000); List edgeEvents = doGetTypedWithTimePageLink("/api/edge/" + edge.getId().toString() + "/events?", new TypeReference>() { }, new TimePageLink(5)).getData(); Assert.assertFalse(edgeEvents.isEmpty()); - Assert.assertEquals(3, edgeEvents.size()); - Assert.assertEquals(edgeEvents.get(0).getEdgeEventType(), EdgeEventType.DEVICE); + Assert.assertEquals(4, edgeEvents.size()); + Assert.assertEquals(edgeEvents.get(0).getEdgeEventType(), EdgeEventType.RELATION); Assert.assertEquals(edgeEvents.get(1).getEdgeEventType(), EdgeEventType.ASSET); - Assert.assertEquals(edgeEvents.get(2).getEdgeEventType(), EdgeEventType.RULE_CHAIN); + Assert.assertEquals(edgeEvents.get(2).getEdgeEventType(), EdgeEventType.DEVICE); + Assert.assertEquals(edgeEvents.get(3).getEdgeEventType(), EdgeEventType.RULE_CHAIN); } private Edge constructEdge(String name, String type) { @@ -123,5 +138,4 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { return asset; } - } From 9e124cf9b174fd509b29a91a77de0403f3a67270 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 6 Jul 2020 19:18:15 +0300 Subject: [PATCH 029/156] deleted .lck file --- application/paho27873734058141-tcplocalhost1883/.lck | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 application/paho27873734058141-tcplocalhost1883/.lck diff --git a/application/paho27873734058141-tcplocalhost1883/.lck b/application/paho27873734058141-tcplocalhost1883/.lck deleted file mode 100644 index e69de29bb2..0000000000 From 1fe848b04248da55e9665017a7322a2ee83a0984 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 6 Jul 2020 19:32:10 +0300 Subject: [PATCH 030/156] deleted unused imports --- .../server/controller/BaseEdgeEventControllerTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java index 72e6f149ec..ac5ea446d2 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java @@ -16,15 +16,12 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.web.client.RestTemplate; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Tenant; @@ -41,7 +38,6 @@ import org.thingsboard.server.common.data.security.Authority; import java.util.List; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @Slf4j From 4621d28e33c83122a1d6459cb3f4231dde2b6e0f Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 6 Jul 2020 19:34:31 +0300 Subject: [PATCH 031/156] deleted unused fields --- .../server/controller/BaseEdgeEventControllerTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java index ac5ea446d2..b079be6357 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java @@ -22,7 +22,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.springframework.web.client.RestTemplate; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; @@ -47,8 +46,6 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { private TenantId tenantId; private User tenantAdmin; - private RestTemplate restTemplate; - @Before public void beforeTest() throws Exception { loginSysAdmin(); From 1545a8cd762cff70428dcb1ba0b502c0b67c488e Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 7 Jul 2020 11:28:15 +0300 Subject: [PATCH 032/156] Fixed EDGE_EVENT events fetch by edgeId --- ui/src/app/api/edge.service.js | 23 ++++++++- .../event/event-header-edge-event.tpl.html | 5 +- .../app/event/event-row-edge-event.tpl.html | 7 ++- ui/src/app/event/event-row.directive.js | 50 +++++++++++-------- ui/src/app/event/event-table.directive.js | 43 ++++------------ 5 files changed, 68 insertions(+), 60 deletions(-) diff --git a/ui/src/app/api/edge.service.js b/ui/src/app/api/edge.service.js index 5e8a9f88a8..858dff3d18 100644 --- a/ui/src/app/api/edge.service.js +++ b/ui/src/app/api/edge.service.js @@ -32,7 +32,8 @@ function EdgeService($http, $q, customerService) { assignEdgeToCustomer: assignEdgeToCustomer, unassignEdgeFromCustomer: unassignEdgeFromCustomer, makeEdgePublic: makeEdgePublic, - setRootRuleChain: setRootRuleChain + setRootRuleChain: setRootRuleChain, + getEdgeEvents: getEdgeEvents }; return service; @@ -241,4 +242,24 @@ function EdgeService($http, $q, customerService) { }); return deferred.promise; } + + function getEdgeEvents(edgeId, pageLink) { + var deferred = $q.defer(); + var url = '/api/edge/' + edgeId + '/events' + '?limit=' + pageLink.limit; + if (angular.isDefined(pageLink.startTime) && pageLink.startTime != null) { + url += '&startTime=' + pageLink.startTime; + } + if (angular.isDefined(pageLink.endTime) && pageLink.endTime != null) { + url += '&endTime=' + pageLink.endTime; + } + if (angular.isDefined(pageLink.idOffset) && pageLink.idOffset != null) { + url += '&offset=' + pageLink.idOffset; + } + $http.get(url, null).then(function success(response) { + deferred.resolve(response.data); + }, function fail(response) { + deferred.reject(response.data); + }); + return deferred.promise; + } } diff --git a/ui/src/app/event/event-header-edge-event.tpl.html b/ui/src/app/event/event-header-edge-event.tpl.html index cdd9dfb20f..f0d2daa53b 100644 --- a/ui/src/app/event/event-header-edge-event.tpl.html +++ b/ui/src/app/event/event-header-edge-event.tpl.html @@ -15,9 +15,8 @@ limitations under the License. --> -
event.event-time
+
event.event-time
event.event-type
-
edge.entity-id
edge.event-action
-
event.success
+
edge.entity-id
edge.entity-info
diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html index a42e39d811..5c3a7a8576 100644 --- a/ui/src/app/event/event-row-edge-event.tpl.html +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -15,11 +15,10 @@ limitations under the License. --> -
{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}
+
{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}
+
{{event.edgeEventType}}
{{event.edgeEventAction}}
-
{{event.entityId}}
-
{{event.entityType}}
-
{{event.success ? 'event.success' : 'event.failed'}}
+
{{event.entityId}}
Date: Tue, 7 Jul 2020 11:31:16 +0300 Subject: [PATCH 033/156] Added EdgeEventController.java --- .../controller/EdgeEventController.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java new file mode 100644 index 0000000000..5af0d3516a --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -0,0 +1,67 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TimePageData; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.edge.EdgeEventService; +import org.thingsboard.server.queue.util.TbCoreComponent; + +@Slf4j +@RestController +@TbCoreComponent +@RequestMapping("/api") +public class EdgeEventController extends BaseController { + + @Autowired + private EdgeEventService edgeEventService; + + public static final String EDGE_ID = "edgeId"; + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/edge/{edgeId}/events", method = RequestMethod.GET) + @ResponseBody + public TimePageData getEdgeEvents( + @PathVariable(EDGE_ID) String strEdgeId, + @RequestParam int limit, + @RequestParam(required = false) Long startTime, + @RequestParam(required = false) Long endTime, + @RequestParam(required = false, defaultValue = "false") boolean ascOrder, + @RequestParam(required = false) String offset) throws ThingsboardException { + checkParameter(EDGE_ID, strEdgeId); + try { + TenantId tenantId = getCurrentUser().getTenantId(); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); + return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink)); + } catch (Exception e) { + throw handleException(e); + } + } +} From 35429c942b5e448423b1839cdad313fb88aed8b6 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 7 Jul 2020 12:32:29 +0300 Subject: [PATCH 034/156] Refactored EdgeEvents, cleaned mistakes in code --- ui/src/app/event/event-row.directive.js | 37 +++++++++++++---------- ui/src/app/event/event-table.directive.js | 10 +++--- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index 9e8a5f8bb5..2690323d0a 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -98,22 +98,27 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ if (!contentType) { contentType = null; } - if (scope.event.edgeEventType === 'RELATION') { - var content = angular.toJson(scope.event.entityBody); - } else if (scope.event.edgeEventType === 'RULE_CHAIN_METADATA') { - content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {}).then( - function success(info) { - return angular.toJson(info); - }, function fail() { - toast.showError($translate.instant('edge.load-entity-error')); - }); - } else { - content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {}).then( - function success(info) { - return angular.toJson(info); - }, function fail() { - toast.showError($translate.instant('edge.load-entity-error')); - }); + var content = ''; + switch(scope.event.edgeEventType) { + case 'RELATION': + content = angular.toJson(scope.event.entityBody); + break; + case 'RULE_CHAIN_METADATA': + content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {}).then( + function success(info) { + return angular.toJson(info); + }, function fail() { + toast.showError($translate.instant('edge.load-entity-error')); + }); + break; + default: + content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {}).then( + function success(info) { + return angular.toJson(info); + }, function fail() { + toast.showError($translate.instant('edge.load-entity-error')); + }); + break; } $mdDialog.show({ controller: 'EventContentDialogController', diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index 812a8afd23..38ae0d162b 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -22,9 +22,9 @@ import eventTableTemplate from './event-table.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function EventTableDirective($compile, $templateCache, $rootScope, $stateParams, types, eventService, edgeService) { +export default function EventTableDirective($compile, $templateCache, $rootScope, types, eventService, edgeService) { - var linker = function (scope, element, attrs) { + var linker = function (scope, element, attrs) { var template = $templateCache.get(eventTableTemplate); @@ -134,6 +134,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope scope.$watch("entityId", function(newVal, prevVal) { if (newVal && !angular.equals(newVal, prevVal)) { + scope.resetFilter(); scope.reload(); } }); @@ -144,7 +145,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope } }); - scope.$watch("createdTime", function(newVal, prevVal) { + scope.$watch("timewindow", function(newVal, prevVal) { if (newVal && !angular.equals(newVal, prevVal)) { scope.reload(); } @@ -221,8 +222,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope scope: { entityType: '=', entityId: '=', - tenantId: '=', - edge: '=?' + tenantId: '=' } }; } From 9fdcd6a4291656a05cd96a885a1e59b0fe7501cb Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 7 Jul 2020 13:47:10 +0300 Subject: [PATCH 035/156] check permissions --- .../org/thingsboard/server/controller/EdgeEventController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java index 8558c194b2..4d689eb5e9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.security.permission.Operation; @Slf4j @RestController @@ -58,6 +59,7 @@ public class EdgeEventController extends BaseController { try { TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink)); } catch (Exception e) { From 6c3d2d986ee57b06f3718e35fbfc1830bac6d58b Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 7 Jul 2020 17:59:12 +0300 Subject: [PATCH 036/156] Added edge state. Added edge id and cloud type to proto --- .../service/edge/rpc/EdgeGrpcService.java | 61 +++++++++++++++++++ .../service/edge/rpc/EdgeGrpcSession.java | 3 + .../src/main/resources/thingsboard.yml | 2 + common/edge-api/src/main/proto/edge.proto | 14 +++-- .../server/dao/user/UserServiceImpl.java | 4 -- 5 files changed, 74 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index e90ae5c383..3792fbdf73 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.io.Resources; +import com.google.common.util.concurrent.FutureCallback; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; @@ -25,16 +26,24 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.kv.BasicTsKvEntry; +import org.thingsboard.server.common.data.kv.BooleanDataEntry; +import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.ResponseMsg; import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.service.state.DefaultDeviceStateService; +import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -56,10 +65,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { private String certFileResource; @Value("${edges.rpc.ssl.private_key}") private String privateKeyResource; + @Value("${edges.state.persistToTelemetry:false}") + private boolean persistToTelemetry; @Autowired private EdgeContextComponent ctx; + @Autowired + private TelemetrySubscriptionService tsSubService; + private Server server; private ExecutorService executor; @@ -105,6 +119,8 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { sessions.put(edgeId, edgeGrpcSession); + save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); + save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis()); } private void processHandleMessages() { @@ -123,6 +139,51 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { private void onEdgeDisconnect(EdgeId edgeId) { sessions.remove(edgeId); + save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false); + save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, System.currentTimeMillis()); + } + + private void save(EdgeId edgeId, String key, long value) { + if (persistToTelemetry) { + tsSubService.saveAndNotify( + TenantId.SYS_TENANT_ID, edgeId, + Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new LongDataEntry(key, value))), + new AttributeSaveCallback(edgeId, key, value)); + } else { + tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, edgeId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(edgeId, key, value)); + } + } + + private void save(EdgeId edgeId, String key, boolean value) { + if (persistToTelemetry) { + tsSubService.saveAndNotify( + TenantId.SYS_TENANT_ID, edgeId, + Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new BooleanDataEntry(key, value))), + new AttributeSaveCallback(edgeId, key, value)); + } else { + tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, edgeId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(edgeId, key, value)); + } } + private static class AttributeSaveCallback implements FutureCallback { + private final EdgeId edgeId; + private final String key; + private final Object value; + + AttributeSaveCallback(EdgeId edgeId, String key, Object value) { + this.edgeId = edgeId; + this.key = key; + this.value = value; + } + + @Override + public void onSuccess(@javax.annotation.Nullable Void result) { + log.trace("[{}] Successfully updated attribute [{}] with value [{}]", edgeId, key, value); + } + + @Override + public void onFailure(Throwable t) { + log.warn("[{}] Failed to update attribute [{}] with value [{}]", edgeId, key, value, t); + } + } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index f1f4aa1f95..7c7912f176 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -1042,11 +1042,14 @@ public final class EdgeGrpcSession implements Closeable { private EdgeConfiguration constructEdgeConfigProto(Edge edge) throws JsonProcessingException { return EdgeConfiguration.newBuilder() + .setEdgeIdMSB(edge.getId().getId().getMostSignificantBits()) + .setEdgeIdLSB(edge.getId().getId().getLeastSignificantBits()) .setTenantIdMSB(edge.getTenantId().getId().getMostSignificantBits()) .setTenantIdLSB(edge.getTenantId().getId().getLeastSignificantBits()) .setName(edge.getName()) .setRoutingKey(edge.getRoutingKey()) .setType(edge.getType()) + .setCloudType("CE") .build(); } diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 089953e81b..613533002f 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -591,6 +591,8 @@ edges: max_read_records_count: "${EDGES_RPC_STORAGE_MAX_READ_RECORDS_COUNT:50}" no_read_records_sleep: "${EDGES_RPC_NO_READ_RECORDS_SLEEP:1000}" sleep_between_batches: "${EDGES_RPC_SLEEP_BETWEEN_BATCHES:1000}" + state: + persistToTelemetry: "${EDGES_PERSIST_STATE_TO_TELEMETRY:false}" swagger: api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}" diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 8c33a55a6e..2cdbd241d1 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -84,12 +84,14 @@ message ConnectResponseMsg { } message EdgeConfiguration { - int64 tenantIdMSB = 1; - int64 tenantIdLSB = 2; - string name = 3; - string routingKey = 4; - string type = 5; - string cloudType = 6; + int64 edgeIdMSB = 1; + int64 edgeIdLSB = 2; + int64 tenantIdMSB = 3; + int64 tenantIdLSB = 4; + string name = 5; + string routingKey = 6; + string type = 7; + string cloudType = 8; } enum UpdateMsgType { diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index a5e3495c9e..914ba5d3ec 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -37,7 +37,6 @@ import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.customer.CustomerDao; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; @@ -86,9 +85,6 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic @Autowired private CustomerDao customerDao; - @Autowired - private EdgeService edgeService; - @Override public User findUserByEmail(TenantId tenantId, String email) { log.trace("Executing findUserByEmail [{}]", email); From 12d650c4002bd58a9f570a419c4dffc15a2c11e1 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 7 Jul 2020 18:30:29 +0300 Subject: [PATCH 037/156] Added edgeEventType constants, changed hardcoded values --- ui/src/app/common/types.constant.js | 13 +++++++++++++ ui/src/app/event/event-row.directive.js | 4 ++-- ui/src/app/event/event-table.directive.js | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 960527f3b3..7b37ada832 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -376,6 +376,19 @@ export default angular.module('thingsboard.types', []) entityView: "ENTITY_VIEW", edge: "EDGE" }, + edgeEventType:{ + dashboard: "DASHBOARD", + asset: "ASSET", + device: "DEVICE", + entityView: "ENTITY_VIEW", + alarm: "ALARM", + rulechain: "RULE_CHAIN", + ruleChainMetaData: "RULE_CHAIN_METADATA", + edge: "EDGE", + user: "USER", + customer: "CUSTOMER", + relation: "RELATION" + }, importEntityColumnType: { name: { name: 'import.column-type.name', diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index 2690323d0a..0ba533d5f1 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -100,10 +100,10 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ } var content = ''; switch(scope.event.edgeEventType) { - case 'RELATION': + case types.edgeEventType.relation: content = angular.toJson(scope.event.entityBody); break; - case 'RULE_CHAIN_METADATA': + case types.edgeEventType.ruleChainMetaData: content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {}).then( function success(info) { return angular.toJson(info); diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index 38ae0d162b..7ee1286638 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -100,7 +100,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope fetchMoreItems_: function () { if (scope.events.hasNext && !scope.events.pending) { if (scope.entityType && scope.entityId && scope.eventType && scope.tenantId) { - if (scope.eventType !== "EDGE_EVENT") { + if (scope.eventType !== types.eventType.edgeEvent.value) { var promise = eventService.getEvents(scope.entityType, scope.entityId, scope.eventType, scope.tenantId, scope.events.nextPageLink); } else { From a30618752ff7129523d0ec42aca0cf97c1dfeaae Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 7 Jul 2020 18:34:49 +0300 Subject: [PATCH 038/156] Minor code refactor in EventTableDirective --- ui/src/app/event/event-table.directive.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index 7ee1286638..4e8ae226b7 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -100,8 +100,9 @@ export default function EventTableDirective($compile, $templateCache, $rootScope fetchMoreItems_: function () { if (scope.events.hasNext && !scope.events.pending) { if (scope.entityType && scope.entityId && scope.eventType && scope.tenantId) { + var promise = ''; if (scope.eventType !== types.eventType.edgeEvent.value) { - var promise = eventService.getEvents(scope.entityType, scope.entityId, + promise = eventService.getEvents(scope.entityType, scope.entityId, scope.eventType, scope.tenantId, scope.events.nextPageLink); } else { promise = edgeService.getEdgeEvents(scope.entityId, scope.events.nextPageLink); From 6b153ee2addb5ab993a6c8367efe202b60560511 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 9 Jul 2020 13:57:04 +0300 Subject: [PATCH 039/156] bug with alarms fixed --- .../service/edge/rpc/EdgeGrpcSession.java | 6 +-- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 51 ++++++++++++------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index f1f4aa1f95..85cddcf750 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -962,18 +962,18 @@ public final class EdgeGrpcSession implements Closeable { switch (alarmUpdateMsg.getMsgType()) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - if (existentAlarm == null) { + if (existentAlarm == null || existentAlarm.getStatus().isCleared()) { existentAlarm = new Alarm(); existentAlarm.setTenantId(edge.getTenantId()); existentAlarm.setType(alarmUpdateMsg.getName()); existentAlarm.setOriginator(originatorId); existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity())); - existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus())); existentAlarm.setStartTs(alarmUpdateMsg.getStartTs()); - existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); existentAlarm.setClearTs(alarmUpdateMsg.getClearTs()); existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); } + existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus())); + existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails())); ctx.getAlarmService().createOrUpdateAlarm(existentAlarm); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 0e1ba938e3..6208976e55 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.edge; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -46,6 +47,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; import javax.annotation.Nullable; import java.util.List; +import java.util.UUID; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -84,14 +86,10 @@ public class TbMsgPushToEdgeNode implements TbNode { Futures.addCallback(getEdgeIdFuture, new FutureCallback() { @Override public void onSuccess(@Nullable EdgeId edgeId) { - EdgeEventType edgeEventTypeByEntityType = EdgeUtils.getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); - if (edgeEventTypeByEntityType == null) { - log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); - ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); - } EdgeEvent edgeEvent = null; try { - edgeEvent = buildEdgeEvent(ctx, msg, edgeId, edgeEventTypeByEntityType); + edgeEvent = buildEdgeEvent(msg, ctx); + edgeEvent.setEdgeId(edgeId); } catch (JsonProcessingException e) { log.error("Failed to build edge event", e); } @@ -124,17 +122,35 @@ public class TbMsgPushToEdgeNode implements TbNode { } } - private EdgeEvent buildEdgeEvent(TbContext ctx, TbMsg msg, EdgeId edgeId, EdgeEventType edgeEventTypeByEntityType) throws JsonProcessingException { + private EdgeEvent buildEdgeEvent(TbMsg msg, TbContext ctx) throws JsonProcessingException { + if (DataConstants.ALARM.equals(msg.getType())) { + return buildEdgeEvent(ctx.getTenantId(), ActionType.ADDED, getUUIDFromMsgData(msg), EdgeEventType.ALARM, null); + } else { + EdgeEventType edgeEventTypeByEntityType = EdgeUtils.getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); + if (edgeEventTypeByEntityType == null) { + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); + } + return buildEdgeEvent(ctx.getTenantId(), getActionTypeByMsgType(msg.getType()), msg.getOriginator().getId(), edgeEventTypeByEntityType, json.readTree(msg.getData())); + } + } + + private EdgeEvent buildEdgeEvent(TenantId tenantId, ActionType edgeEventAction, UUID entityId, EdgeEventType edgeEventType, JsonNode entityBody) { EdgeEvent edgeEvent = new EdgeEvent(); - edgeEvent.setTenantId(ctx.getTenantId()); - edgeEvent.setEdgeId(edgeId); - edgeEvent.setEdgeEventAction(getActionTypeByMsgType(msg.getType()).name()); - edgeEvent.setEntityId(msg.getOriginator().getId()); - edgeEvent.setEdgeEventType(edgeEventTypeByEntityType); - edgeEvent.setEntityBody(json.readTree(msg.getData())); + edgeEvent.setTenantId(tenantId); + edgeEvent.setEdgeEventAction(edgeEventAction.name()); + edgeEvent.setEntityId(entityId); + edgeEvent.setEdgeEventType(edgeEventType); + edgeEvent.setEntityBody(entityBody); return edgeEvent; } + private UUID getUUIDFromMsgData(TbMsg msg) throws JsonProcessingException { + JsonNode data = json.readTree(msg.getData()).get("id"); + String id = json.treeToValue(data.get("id"), String.class); + return UUID.fromString(id); + } + private ActionType getActionTypeByMsgType(String msgType) { ActionType actionType; if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msgType)) { @@ -161,14 +177,11 @@ public class TbMsgPushToEdgeNode implements TbNode { } private boolean isSupportedMsgType(String msgType) { - if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msgType) + return SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msgType) || SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msgType) || DataConstants.ATTRIBUTES_UPDATED.equals(msgType) - || DataConstants.ATTRIBUTES_DELETED.equals(msgType)) { - return true; - } else { - return false; - } + || DataConstants.ATTRIBUTES_DELETED.equals(msgType) + || DataConstants.ALARM.equals(msgType); } private ListenableFuture getEdgeIdByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) { From 2fffa660ab2a7436c0a2fe9944b1664134d4e335 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 9 Jul 2020 17:48:46 +0300 Subject: [PATCH 040/156] Refacroting to handle null cases --- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 6208976e55..eef30d5d22 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -86,26 +86,33 @@ public class TbMsgPushToEdgeNode implements TbNode { Futures.addCallback(getEdgeIdFuture, new FutureCallback() { @Override public void onSuccess(@Nullable EdgeId edgeId) { - EdgeEvent edgeEvent = null; try { - edgeEvent = buildEdgeEvent(msg, ctx); - edgeEvent.setEdgeId(edgeId); + EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx); + if (edgeEvent == null) { + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); + } else { + edgeEvent.setEdgeId(edgeId); + ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); + Futures.addCallback(saveFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent event) { + ctx.tellNext(msg, SUCCESS); + } + + @Override + public void onFailure(Throwable th) { + log.error("Could not save edge event", th); + ctx.tellFailure(msg, th); + } + }, ctx.getDbCallbackExecutor()); + } } catch (JsonProcessingException e) { log.error("Failed to build edge event", e); + ctx.tellFailure(msg, e); } - ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); - Futures.addCallback(saveFuture, new FutureCallback() { - @Override - public void onSuccess(@Nullable EdgeEvent event) { - ctx.tellNext(msg, SUCCESS); - } - @Override - public void onFailure(Throwable th) { - log.error("Could not save edge event", th); - ctx.tellFailure(msg, th); - } - }, ctx.getDbCallbackExecutor()); } + @Override public void onFailure(Throwable t) { ctx.tellFailure(msg, t); @@ -128,8 +135,7 @@ public class TbMsgPushToEdgeNode implements TbNode { } else { EdgeEventType edgeEventTypeByEntityType = EdgeUtils.getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); if (edgeEventTypeByEntityType == null) { - log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); - ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); + return null; } return buildEdgeEvent(ctx.getTenantId(), getActionTypeByMsgType(msg.getType()), msg.getOriginator().getId(), edgeEventTypeByEntityType, json.readTree(msg.getData())); } From 35a17efc71249eb157b96bcf5689173e43348666 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Sat, 11 Jul 2020 00:29:42 +0300 Subject: [PATCH 041/156] For edgeEvents added Status of data received by Edge v.1.0 --- .../event/event-header-edge-event.tpl.html | 1 + .../app/event/event-row-edge-event.tpl.html | 1 + ui/src/app/event/event-row.directive.js | 28 +++++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/ui/src/app/event/event-header-edge-event.tpl.html b/ui/src/app/event/event-header-edge-event.tpl.html index f0d2daa53b..e9770f42bd 100644 --- a/ui/src/app/event/event-header-edge-event.tpl.html +++ b/ui/src/app/event/event-header-edge-event.tpl.html @@ -20,3 +20,4 @@
edge.event-action
edge.entity-id
edge.entity-info
+
event.status
diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html index 5c3a7a8576..7dea0aa804 100644 --- a/ui/src/app/event/event-row-edge-event.tpl.html +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -32,4 +32,5 @@
+
{{receiveStatus(event.createdTime)}}
diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index 0ba533d5f1..7bec6c28dd 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -26,11 +26,13 @@ import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, - types, toast, entityService, ruleChainService) { +export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, $log, + types, toast, entityService, ruleChainService, userService, attributeService) { var linker = function (scope, element, attrs) { + var lastDisconnectTime; + var getTemplate = function(eventType) { var template = ''; switch(eventType) { @@ -50,6 +52,7 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ template = eventRowDebugRuleNodeTemplate; break; case types.eventType.edgeEvent.value: + getLastDisconnectTime(); template = eventRowEdgeEventTemplate; break; } @@ -135,6 +138,27 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ }); } + function getLastDisconnectTime() { + let params = { + entityType: types.entityType.edge, + entityId: scope.entityId, + attributeScope: types.attributesScope.server.value, + query: {order: '', limit: 1, page: 1, search: "active"} + }; + attributeService.getEntityAttributes(params.entityType, params.entityId, params.attributeScope, params.query, + function (attribute) { + if (attribute && attribute.data) { + $log.log("attribute", attribute); + lastDisconnectTime = attribute.data[0].lastUpdateTs; + $log.log("lastDisconnectTime", lastDisconnectTime, typeof(lastDisconnectTime)); + } + }); + } + + scope.receiveStatus = function(eventCreatedTime) { + return (eventCreatedTime <= lastDisconnectTime) ? $translate.instant('event.success') : $translate.instant('event.failed'); + } + scope.checkTooltip = function($event) { var el = $event.target; var $el = angular.element(el); From df62957780e50b67e589b8feeef2bd6b4b73e902 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Sat, 11 Jul 2020 00:34:00 +0300 Subject: [PATCH 042/156] For edgeEvents added Status of data received by Edge v.1.0 --- ui/src/app/event/event-row.directive.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index 7bec6c28dd..2e4163d694 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -26,7 +26,7 @@ import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, $log, +export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, types, toast, entityService, ruleChainService, userService, attributeService) { var linker = function (scope, element, attrs) { @@ -148,9 +148,7 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ attributeService.getEntityAttributes(params.entityType, params.entityId, params.attributeScope, params.query, function (attribute) { if (attribute && attribute.data) { - $log.log("attribute", attribute); lastDisconnectTime = attribute.data[0].lastUpdateTs; - $log.log("lastDisconnectTime", lastDisconnectTime, typeof(lastDisconnectTime)); } }); } From 5ab81b98a6c5f53d8691cd811c4d23b5fdd573cc Mon Sep 17 00:00:00 2001 From: deaflynx Date: Mon, 13 Jul 2020 17:13:18 +0300 Subject: [PATCH 043/156] Edge Events Status Update --- ui/src/app/api/edge.service.js | 2 +- .../app/event/event-row-edge-event.tpl.html | 2 +- ui/src/app/event/event-row.directive.js | 30 +++-------- ui/src/app/event/event-table.directive.js | 52 ++++++++++++++++++- 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/ui/src/app/api/edge.service.js b/ui/src/app/api/edge.service.js index 858dff3d18..7814e1d826 100644 --- a/ui/src/app/api/edge.service.js +++ b/ui/src/app/api/edge.service.js @@ -56,7 +56,7 @@ function EdgeService($http, $q, customerService) { deferred.reject(); }); return deferred.promise; - } // TODO: deaflynx: check usage in UI + } function getEdgesByIds(edgeIds, config) { var deferred = $q.defer(); diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html index 7dea0aa804..0b088d8570 100644 --- a/ui/src/app/event/event-row-edge-event.tpl.html +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -32,5 +32,5 @@ -
{{receiveStatus(event.createdTime)}}
+
{{updateStatus(event.createdTime)}}
diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index 2e4163d694..fd9756a697 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -27,12 +27,10 @@ import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; /*@ngInject*/ export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, - types, toast, entityService, ruleChainService, userService, attributeService) { + types, toast, entityService, ruleChainService) { var linker = function (scope, element, attrs) { - var lastDisconnectTime; - var getTemplate = function(eventType) { var template = ''; switch(eventType) { @@ -52,7 +50,6 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ template = eventRowDebugRuleNodeTemplate; break; case types.eventType.edgeEvent.value: - getLastDisconnectTime(); template = eventRowEdgeEventTemplate; break; } @@ -138,25 +135,6 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ }); } - function getLastDisconnectTime() { - let params = { - entityType: types.entityType.edge, - entityId: scope.entityId, - attributeScope: types.attributesScope.server.value, - query: {order: '', limit: 1, page: 1, search: "active"} - }; - attributeService.getEntityAttributes(params.entityType, params.entityId, params.attributeScope, params.query, - function (attribute) { - if (attribute && attribute.data) { - lastDisconnectTime = attribute.data[0].lastUpdateTs; - } - }); - } - - scope.receiveStatus = function(eventCreatedTime) { - return (eventCreatedTime <= lastDisconnectTime) ? $translate.instant('event.success') : $translate.instant('event.failed'); - } - scope.checkTooltip = function($event) { var el = $event.target; var $el = angular.element(el); @@ -166,6 +144,12 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ } $compile(element.contents())(scope); + + scope.updateStatus = function(eventCreatedTime) { + if (scope.queueStartTs) { + return (eventCreatedTime < scope.queueStartTs) ? $translate.instant('event.success') : $translate.instant('event.failed'); + } + } } return { diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index 4e8ae226b7..df300dd8e1 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -22,7 +22,8 @@ import eventTableTemplate from './event-table.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function EventTableDirective($compile, $templateCache, $rootScope, types, eventService, edgeService) { +export default function EventTableDirective($compile, $templateCache, $rootScope, types, eventService, edgeService, + attributeService) { var linker = function (scope, element, attrs) { @@ -106,6 +107,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope scope.eventType, scope.tenantId, scope.events.nextPageLink); } else { promise = edgeService.getEdgeEvents(scope.entityId, scope.events.nextPageLink); + scope.loadEdgeInfo(); } if (promise) { scope.events.pending = true; @@ -135,6 +137,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope scope.$watch("entityId", function(newVal, prevVal) { if (newVal && !angular.equals(newVal, prevVal)) { + scope.loadEdgeInfo(); scope.resetFilter(); scope.reload(); } @@ -212,6 +215,53 @@ export default function EventTableDirective($compile, $templateCache, $rootScope return false; } + scope.subscriptionId = null; + scope.queueStartTs; + + scope.loadEdgeInfo = function() { + attributeService.getEntityAttributesValues(scope.entityType, scope.entityId, types.attributesScope.server.value, + ["queueStartTs"], {}) + .then(function success(attributes) { + scope.onUpdate(attributes); + }); + + scope.checkSubscription(); + + attributeService.getEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value, {order: '', limit: 1, page: 1, search: ''}, + function (attributes) { + if (attributes && attributes.data) { + scope.onUpdate(attributes.data); + } + }); + } + + scope.onUpdate = function(attributes) { + let edge = attributes.reduce(function (map, attribute) { + map[attribute.key] = attribute; + return map; + }, {}); + if (edge.queueStartTs) { + scope.queueStartTs = edge.queueStartTs.lastUpdateTs; + } + } + + scope.checkSubscription = function() { + var newSubscriptionId = null; + if (scope.entityId && scope.entityType && types.attributesScope.server.value) { + newSubscriptionId = attributeService.subscribeForEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value); + } + if (scope.subscriptionId && scope.subscriptionId != newSubscriptionId) { + attributeService.unsubscribeForEntityAttributes(scope.subscriptionId); + } + scope.subscriptionId = newSubscriptionId; + } + + scope.$on('$destroy', function () { + if (scope.subscriptionId) { + attributeService.unsubscribeForEntityAttributes(scope.subscriptionId); + } + }); + scope.reload(); $compile(element.contents())(scope); From 63de68f6952d7e2f2d3d927b51486ea4ae5330b6 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 14 Jul 2020 10:57:34 +0300 Subject: [PATCH 044/156] Added eventTypeScope for edgeEvents --- ui/src/app/event/event-table.directive.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index df300dd8e1..205a686fe3 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -23,7 +23,7 @@ import eventTableTemplate from './event-table.tpl.html'; /*@ngInject*/ export default function EventTableDirective($compile, $templateCache, $rootScope, types, eventService, edgeService, - attributeService) { + attributeService, $log) { var linker = function (scope, element, attrs) { @@ -31,11 +31,16 @@ export default function EventTableDirective($compile, $templateCache, $rootScope element.html(template); + scope.eventTypeScope = angular.copy(types.eventType); + if (scope.entityType !== types.entityType.edge) { + delete scope.eventTypeScope.edgeEvent; + } + if (attrs.disabledEventTypes) { var disabledEventTypes = attrs.disabledEventTypes.split(','); scope.eventTypes = {}; - for (var type in types.eventType) { - var eventType = types.eventType[type]; + for (var type in scope.eventTypeScope) { + var eventType = scope.eventTypeScope[type]; var enabled = true; for (var i=0;i Date: Tue, 14 Jul 2020 15:38:21 +0300 Subject: [PATCH 045/156] fixed bug with saving server attributes in client scope --- .../edge/rpc/init/DefaultSyncEdgeService.java | 20 ++++++++++++------- common/queue/src/main/proto/queue.proto | 1 + .../transport/adaptor/JsonConverter.java | 3 ++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 8576f96152..1a2a3d3177 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -71,7 +71,9 @@ import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; @Service @@ -289,25 +291,29 @@ public class DefaultSyncEdgeService implements SyncEdgeService { public void onSuccess(@Nullable List ssAttributes) { if (ssAttributes != null && !ssAttributes.isEmpty()) { try { - ObjectNode entityNode = mapper.createObjectNode(); + Map entityData = new HashMap<>(); + ObjectNode attributes = mapper.createObjectNode(); for (AttributeKvEntry attr : ssAttributes) { if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getBooleanValue().get()); + attributes.put(attr.getKey(), attr.getBooleanValue().get()); } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getDoubleValue().get()); + attributes.put(attr.getKey(), attr.getDoubleValue().get()); } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { - entityNode.put(attr.getKey(), attr.getLongValue().get()); + attributes.put(attr.getKey(), attr.getLongValue().get()); } else { - entityNode.put(attr.getKey(), attr.getValueAsString()); + attributes.put(attr.getKey(), attr.getValueAsString()); } } - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityNode); + entityData.put("kv", attributes); + entityData.put("scope", DataConstants.SERVER_SCOPE); + JsonNode entityBody = mapper.valueToTree(entityData); + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody); saveEdgeEvent(edge.getTenantId(), edge.getId(), edgeEventType, ActionType.ATTRIBUTES_UPDATED, entityId, - entityNode); + entityBody); } catch (Exception e) { log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); } diff --git a/common/queue/src/main/proto/queue.proto b/common/queue/src/main/proto/queue.proto index 921a096df0..c302a30b8c 100644 --- a/common/queue/src/main/proto/queue.proto +++ b/common/queue/src/main/proto/queue.proto @@ -115,6 +115,7 @@ message PostTelemetryMsg { message PostAttributeMsg { repeated KeyValueProto kv = 1; + string scope = 2; } message GetAttributeRequestMsg { diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java index 8375b84ffa..2836f05164 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java @@ -136,8 +136,9 @@ public class JsonConverter { public static PostAttributeMsg convertToAttributesProto(JsonElement jsonObject) throws JsonSyntaxException { if (jsonObject.isJsonObject()) { PostAttributeMsg.Builder result = PostAttributeMsg.newBuilder(); - List keyValueList = parseProtoValues(jsonObject.getAsJsonObject()); + List keyValueList = parseProtoValues(jsonObject.getAsJsonObject().getAsJsonObject("kv")); result.addAllKv(keyValueList); + result.setScope(jsonObject.getAsJsonObject().getAsJsonPrimitive("scope").getAsString()); return result.build(); } else { throw new JsonSyntaxException(CAN_T_PARSE_VALUE + jsonObject); From 37cb35c99baba90b72c313aa9e6681c8a293bce9 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 14 Jul 2020 17:06:21 +0300 Subject: [PATCH 046/156] fix + refactoring --- .../common/transport/adaptor/JsonConverter.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java index 2836f05164..42b4b2a77c 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java @@ -133,15 +133,21 @@ public class JsonConverter { .build(); } - public static PostAttributeMsg convertToAttributesProto(JsonElement jsonObject) throws JsonSyntaxException { - if (jsonObject.isJsonObject()) { + public static PostAttributeMsg convertToAttributesProto(JsonElement jsonElement) throws JsonSyntaxException { + if (jsonElement.isJsonObject()) { PostAttributeMsg.Builder result = PostAttributeMsg.newBuilder(); - List keyValueList = parseProtoValues(jsonObject.getAsJsonObject().getAsJsonObject("kv")); + List keyValueList = null; + JsonObject jsonObject = jsonElement.getAsJsonObject(); + if (jsonObject.has("kv") && jsonObject.has("scope")) { + keyValueList = parseProtoValues(jsonObject.getAsJsonObject("kv")); + result.setScope(jsonObject.getAsJsonPrimitive("scope").getAsString()); + } else { + keyValueList = parseProtoValues(jsonObject); + } result.addAllKv(keyValueList); - result.setScope(jsonObject.getAsJsonObject().getAsJsonPrimitive("scope").getAsString()); return result.build(); } else { - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + jsonObject); + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + jsonElement); } } From d81804ac8ddc517f15d94be393316e525dac0efc Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 14 Jul 2020 19:22:31 +0300 Subject: [PATCH 047/156] scope replaced to EntityDataProto --- .../rpc/constructor/EntityDataMsgConstructor.java | 9 ++++++++- common/edge-api/src/main/proto/edge.proto | 1 + common/queue/src/main/proto/queue.proto | 1 - .../common/transport/adaptor/JsonConverter.java | 15 ++++----------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index d9a06655c5..e83c197690 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -16,6 +16,7 @@ package org.thingsboard.server.service.edge.rpc.constructor; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.audit.ActionType; @@ -42,7 +43,13 @@ public class EntityDataMsgConstructor { break; case ATTRIBUTES_UPDATED: try { - builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(entityData)); + JsonObject data = entityData.getAsJsonObject(); + if (data.has("scope") && data.has("kv")) { + builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv"))); + builder.setPostAttributeScope(data.getAsJsonPrimitive("scope").getAsString()); + } else { + builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(data)); + } } catch (Exception e) { log.warn("Can't convert to attributes proto, entityData [{}]", entityData, e); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 2cdbd241d1..9713cd754f 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -109,6 +109,7 @@ message EntityDataProto { string entityType = 3; transport.PostTelemetryMsg postTelemetryMsg = 4; transport.PostAttributeMsg postAttributesMsg = 5; + string postAttributeScope = 6; // transport.ToDeviceRpcRequestMsg ??? } diff --git a/common/queue/src/main/proto/queue.proto b/common/queue/src/main/proto/queue.proto index c302a30b8c..921a096df0 100644 --- a/common/queue/src/main/proto/queue.proto +++ b/common/queue/src/main/proto/queue.proto @@ -115,7 +115,6 @@ message PostTelemetryMsg { message PostAttributeMsg { repeated KeyValueProto kv = 1; - string scope = 2; } message GetAttributeRequestMsg { diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java index 42b4b2a77c..8375b84ffa 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java @@ -133,21 +133,14 @@ public class JsonConverter { .build(); } - public static PostAttributeMsg convertToAttributesProto(JsonElement jsonElement) throws JsonSyntaxException { - if (jsonElement.isJsonObject()) { + public static PostAttributeMsg convertToAttributesProto(JsonElement jsonObject) throws JsonSyntaxException { + if (jsonObject.isJsonObject()) { PostAttributeMsg.Builder result = PostAttributeMsg.newBuilder(); - List keyValueList = null; - JsonObject jsonObject = jsonElement.getAsJsonObject(); - if (jsonObject.has("kv") && jsonObject.has("scope")) { - keyValueList = parseProtoValues(jsonObject.getAsJsonObject("kv")); - result.setScope(jsonObject.getAsJsonPrimitive("scope").getAsString()); - } else { - keyValueList = parseProtoValues(jsonObject); - } + List keyValueList = parseProtoValues(jsonObject.getAsJsonObject()); result.addAllKv(keyValueList); return result.build(); } else { - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + jsonElement); + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + jsonObject); } } From 6ede96ef48531ffec5fca2c3fd26b5ae47cf8ff2 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Wed, 15 Jul 2020 14:54:25 +0300 Subject: [PATCH 048/156] fix for POST_ATTRIBUTES_REQUEST --- .../rpc/constructor/EntityDataMsgConstructor.java | 8 ++------ .../rule/engine/edge/TbMsgPushToEdgeNode.java | 14 +++++++++++++- .../rule/engine/telemetry/TbMsgAttributesNode.java | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index e83c197690..2c4694d25d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -44,12 +44,8 @@ public class EntityDataMsgConstructor { case ATTRIBUTES_UPDATED: try { JsonObject data = entityData.getAsJsonObject(); - if (data.has("scope") && data.has("kv")) { - builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv"))); - builder.setPostAttributeScope(data.getAsJsonPrimitive("scope").getAsString()); - } else { - builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(data)); - } + builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv"))); + builder.setPostAttributeScope(data.getAsJsonPrimitive("scope").getAsString()); } catch (Exception e) { log.warn("Can't convert to attributes proto, entityData [{}]", entityData, e); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index eef30d5d22..b383ae0a1a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -46,7 +46,9 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import javax.annotation.Nullable; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -137,7 +139,17 @@ public class TbMsgPushToEdgeNode implements TbNode { if (edgeEventTypeByEntityType == null) { return null; } - return buildEdgeEvent(ctx.getTenantId(), getActionTypeByMsgType(msg.getType()), msg.getOriginator().getId(), edgeEventTypeByEntityType, json.readTree(msg.getData())); + JsonNode entityBody = null; + JsonNode data = json.readTree(msg.getData()); + if (SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msg.getType())) { + Map entityData = new HashMap<>(); + entityData.put("kv", data); + entityData.put("scope", msg.getMetaData().getData().get("scope")); + entityBody = json.valueToTree(entityData); + } else { + entityBody = data; + } + return buildEdgeEvent(ctx.getTenantId(), getActionTypeByMsgType(msg.getType()), msg.getOriginator().getId(), edgeEventTypeByEntityType, entityBody); } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index e776fa4dbd..b6e9e4a292 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -64,6 +64,7 @@ public class TbMsgAttributesNode implements TbNode { } String src = msg.getData(); Set attributes = JsonConverter.convertToAttributes(new JsonParser().parse(src)); + msg.getMetaData().putValue("scope", config.getScope()); ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), config.getScope(), new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); } From e571bf24b6ad2f8b1bdee0a728adf90a54e9a41e Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Wed, 15 Jul 2020 19:37:01 +0300 Subject: [PATCH 049/156] complited attributes update and attributes delete feature --- .../constructor/EntityDataMsgConstructor.java | 20 +++++++++++++-- common/edge-api/src/main/proto/edge.proto | 6 +++++ .../rule/engine/edge/TbMsgPushToEdgeNode.java | 25 ++++++++++++++----- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index 2c4694d25d..07f7ffb02a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.service.edge.rpc.constructor; +import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; @@ -22,8 +24,11 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.gen.edge.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.EntityDataProto; +import java.util.List; + @Component @Slf4j public class EntityDataMsgConstructor { @@ -50,8 +55,19 @@ public class EntityDataMsgConstructor { log.warn("Can't convert to attributes proto, entityData [{}]", entityData, e); } break; - // TODO: voba - add support for attribute delete - // case ATTRIBUTES_DELETED: + case ATTRIBUTES_DELETED: + try { + AttributeDeleteMsg.Builder attributeDeleteMsg = AttributeDeleteMsg.newBuilder(); + attributeDeleteMsg.setScope(entityData.getAsJsonObject().getAsJsonPrimitive("scope").getAsString()); + JsonArray jsonArray = entityData.getAsJsonObject().getAsJsonArray("keys"); + List keys = new Gson().fromJson(jsonArray.toString(), List.class); + attributeDeleteMsg.addAllAttributeNames(keys); + attributeDeleteMsg.build(); + builder.setAttributeDeleteMsg(attributeDeleteMsg); + } catch (Exception e) { + log.warn("Can't convert to AttributeDeleteMsg proto, entityData [{}]", entityData, e); + } + break; } return builder.build(); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 9713cd754f..181ebff531 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -110,9 +110,15 @@ message EntityDataProto { transport.PostTelemetryMsg postTelemetryMsg = 4; transport.PostAttributeMsg postAttributesMsg = 5; string postAttributeScope = 6; + AttributeDeleteMsg attributeDeleteMsg = 7; // transport.ToDeviceRpcRequestMsg ??? } +message AttributeDeleteMsg { + string scope = 1; + repeated string attributeNames = 2; +} + message RuleChainUpdateMsg { UpdateMsgType msgType = 1; int64 idMSB = 2; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index b383ae0a1a..f1134078c1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -139,17 +139,15 @@ public class TbMsgPushToEdgeNode implements TbNode { if (edgeEventTypeByEntityType == null) { return null; } + ActionType actionType = getActionTypeByMsgType(msg.getType()); JsonNode entityBody = null; JsonNode data = json.readTree(msg.getData()); - if (SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msg.getType())) { - Map entityData = new HashMap<>(); - entityData.put("kv", data); - entityData.put("scope", msg.getMetaData().getData().get("scope")); - entityBody = json.valueToTree(entityData); + if (actionType.equals(ActionType.ATTRIBUTES_UPDATED) || actionType.equals(ActionType.ATTRIBUTES_DELETED)) { + entityBody = getAttributeEntityBody(actionType, data, msg.getMetaData().getData()); } else { entityBody = data; } - return buildEdgeEvent(ctx.getTenantId(), getActionTypeByMsgType(msg.getType()), msg.getOriginator().getId(), edgeEventTypeByEntityType, entityBody); + return buildEdgeEvent(ctx.getTenantId(), actionType, msg.getOriginator().getId(), edgeEventTypeByEntityType, entityBody); } } @@ -163,6 +161,21 @@ public class TbMsgPushToEdgeNode implements TbNode { return edgeEvent; } + private JsonNode getAttributeEntityBody(ActionType actionType, JsonNode data, Map metadata) throws JsonProcessingException { + Map entityData = new HashMap<>(); + switch (actionType) { + case ATTRIBUTES_UPDATED: + entityData.put("kv", data); + break; + case ATTRIBUTES_DELETED: + List keys = json.treeToValue(data.get("attributes"), List.class); + entityData.put("keys", keys); + break; + } + entityData.put("scope", metadata.get("scope")); + return json.valueToTree(entityData); + } + private UUID getUUIDFromMsgData(TbMsg msg) throws JsonProcessingException { JsonNode data = json.readTree(msg.getData()).get("id"); String id = json.treeToValue(data.get("id"), String.class); From daeb9631950028d6f2a5979720dcd05bceab2047 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 16 Jul 2020 16:34:18 +0300 Subject: [PATCH 050/156] fix in EntityViewUpdateMsg constructing --- .../edge/rpc/constructor/EntityViewUpdateMsgConstructor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java index 75301c7ed9..2ca0b4fcbe 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java @@ -45,8 +45,8 @@ public class EntityViewUpdateMsgConstructor { .setIdLSB(entityView.getId().getId().getLeastSignificantBits()) .setName(entityView.getName()) .setType(entityView.getType()) - .setIdMSB(entityView.getEntityId().getId().getMostSignificantBits()) - .setIdLSB(entityView.getEntityId().getId().getLeastSignificantBits()) + .setEntityIdMSB(entityView.getEntityId().getId().getMostSignificantBits()) + .setEntityIdLSB(entityView.getEntityId().getId().getLeastSignificantBits()) .setEntityType(entityType); return builder.build(); } From c989c31f1f3d7cb2004d332a0c2c1bf769773874 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 21 Jul 2020 08:19:16 +0300 Subject: [PATCH 051/156] Added Edge Fieldset manage... buttons. In EdgeEvents updated table columns width, status labels --- ui/src/app/edge/edge-fieldset.tpl.html | 15 +++++++++++++++ ui/src/app/edge/edge.controller.js | 5 +++++ ui/src/app/edge/edge.directive.js | 5 +++++ ui/src/app/edge/edges.tpl.html | 5 +++++ ui/src/app/event/event-header-edge-event.tpl.html | 8 ++++---- ui/src/app/event/event-row-edge-event.tpl.html | 9 +++++---- ui/src/app/event/event-row.directive.js | 10 +++++++++- ui/src/app/locale/locale.constant-en_US.json | 5 ++++- 8 files changed, 52 insertions(+), 10 deletions(-) diff --git a/ui/src/app/edge/edge-fieldset.tpl.html b/ui/src/app/edge/edge-fieldset.tpl.html index b54e1cb651..c151c03f10 100644 --- a/ui/src/app/edge/edge-fieldset.tpl.html +++ b/ui/src/app/edge/edge-fieldset.tpl.html @@ -21,6 +21,21 @@ {{ isPublic ? 'edge.make-private' : 'edge.unassign-from-customer' | translate }} +{{ 'edge.manage-edge-assets' | translate }} +{{ 'edge.manage-edge-devices' | translate }} +{{ 'edge.manage-edge-entity-views' | translate }} +{{ 'edge.manage-edge-dashboards' | translate }} +{{ 'edge.manage-edge-rulechains' | translate }} {{ 'edge.delete' | translate }} diff --git a/ui/src/app/edge/edge.controller.js b/ui/src/app/edge/edge.controller.js index 51269ea753..7e57fce6a6 100644 --- a/ui/src/app/edge/edge.controller.js +++ b/ui/src/app/edge/edge.controller.js @@ -129,6 +129,11 @@ export function EdgeController($rootScope, userService, edgeService, customerSer vm.assignToCustomer = assignToCustomer; vm.makePublic = makePublic; vm.unassignFromCustomer = unassignFromCustomer; + vm.openEdgeAssets = openEdgeAssets; + vm.openEdgeDevices = openEdgeDevices; + vm.openEdgeEntityViews = openEdgeEntityViews; + vm.openEdgeDashboards = openEdgeDashboards; + vm.openEdgeRuleChains = openEdgeRuleChains; initController(); diff --git a/ui/src/app/edge/edge.directive.js b/ui/src/app/edge/edge.directive.js index 0cbe32f79e..d96dfa4b4d 100644 --- a/ui/src/app/edge/edge.directive.js +++ b/ui/src/app/edge/edge.directive.js @@ -96,6 +96,11 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD onAssignToCustomer: '&', onMakePublic: '&', onUnassignFromCustomer: '&', + onManageEdgeAssets: '&', + onManageEdgeDevices: '&', + onManageEdgeEntityViews: '&', + onManageEdgeDashboards: '&', + onManageEdgeRuleChains: '&', onDeleteEdge: '&' } }; diff --git a/ui/src/app/edge/edges.tpl.html b/ui/src/app/edge/edges.tpl.html index 4fc3f5d75e..2600413255 100644 --- a/ui/src/app/edge/edges.tpl.html +++ b/ui/src/app/edge/edges.tpl.html @@ -29,6 +29,11 @@ on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])" on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)" on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)" + on-manage-edge-assets="vm.openEdgeAssets(event, vm.grid.detailsConfig.currentItem)" + on-manage-edge-devices="vm.openEdgeDevices(event, vm.grid.detailsConfig.currentItem)" + on-manage-edge-entity-views="vm.openEdgeEntityViews(event, vm.grid.detailsConfig.currentItem)" + on-manage-edge-dashboards="vm.openEdgeDashboards(event, vm.grid.detailsConfig.currentItem)" + on-manage-edge-rule-chains="vm.openEdgeRuleChains(event, vm.grid.detailsConfig.currentItem)" on-delete-edge="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"> diff --git a/ui/src/app/event/event-header-edge-event.tpl.html b/ui/src/app/event/event-header-edge-event.tpl.html index e9770f42bd..e84922f6a5 100644 --- a/ui/src/app/event/event-header-edge-event.tpl.html +++ b/ui/src/app/event/event-header-edge-event.tpl.html @@ -17,7 +17,7 @@ -->
event.event-time
event.event-type
-
edge.event-action
-
edge.entity-id
-
edge.entity-info
-
event.status
+
edge.event-action
+
edge.entity-id
+
edge.status
+
edge.entity-info
diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html index 0b088d8570..ef5efee956 100644 --- a/ui/src/app/event/event-row-edge-event.tpl.html +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -17,9 +17,10 @@ -->
{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}
{{event.edgeEventType}}
-
{{event.edgeEventAction}}
-
{{event.entityId}}
-
+
{{event.edgeEventAction}}
+
{{event.entityId}}
+
{{updateStatus(event.createdTime)}}
+
@@ -32,5 +33,5 @@
-
{{updateStatus(event.createdTime)}}
+ diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index fd9756a697..11af155176 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -147,7 +147,15 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ scope.updateStatus = function(eventCreatedTime) { if (scope.queueStartTs) { - return (eventCreatedTime < scope.queueStartTs) ? $translate.instant('event.success') : $translate.instant('event.failed'); + var status; + if (eventCreatedTime < scope.queueStartTs) { + status = 'edge.success'; + scope.isPending = false; + } else { + status = 'edge.failed'; + scope.isPending = true; + } + return $translate.instant(status); } } } diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 57c54c2556..bea55fd30e 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -843,7 +843,10 @@ "entity-views": "Edge entity views", "set-root-rule-chain-text": "Please select root rule chain for edge(s)", "set-root-rule-chain-to-edges": "Set root rule chain for Edge(s)", - "set-root-rule-chain-to-edges-text": "Set root rule chain for { count, plural, 1 {1 edge} other {# edges} }" + "set-root-rule-chain-to-edges-text": "Set root rule chain for { count, plural, 1 {1 edge} other {# edges} }", + "status": "Received by edge", + "success": "Deployed", + "failed": "Pending" }, "error": { "unable-to-connect": "Unable to connect to the server! Please check your internet connection.", From 8c9aa0c8dfe47f4b3bbf1f9660f563ef6945cca9 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 21 Jul 2020 08:44:49 +0300 Subject: [PATCH 052/156] Minor code cleaning --- ui/src/app/event/event-row-edge-event.tpl.html | 10 +++++----- ui/src/app/event/event-row.directive.js | 6 +++--- ui/src/app/event/event-table.directive.js | 6 ++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html index ef5efee956..d47ca55b81 100644 --- a/ui/src/app/event/event-row-edge-event.tpl.html +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -15,11 +15,11 @@ limitations under the License. --> -
{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}
-
{{event.edgeEventType}}
-
{{event.edgeEventAction}}
-
{{event.entityId}}
-
{{updateStatus(event.createdTime)}}
+
{{ event.createdTime | date : 'yyyy-MM-dd HH:mm:ss' }}
+
{{ event.edgeEventType }}
+
{{ event.edgeEventAction }}
+
{{ event.entityId }}
+
{{ updateStatus(event.createdTime) | translate }}
Date: Tue, 21 Jul 2020 11:56:19 +0300 Subject: [PATCH 053/156] EdgeEvents: added toast.showError() for deleted entities --- ui/src/app/common/types.constant.js | 13 ++++++ ui/src/app/event/event-row.directive.js | 42 ++++++++++++-------- ui/src/app/locale/locale.constant-en_US.json | 2 +- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 7b37ada832..f48f3e9f03 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -389,6 +389,19 @@ export default angular.module('thingsboard.types', []) customer: "CUSTOMER", relation: "RELATION" }, + edgeEventAction: { + updated: "UPDATED", + added: "ADDED", + assignedToEdge: "ASSIGNED_TO_EDGE", + deleted: "DELETED", + unassignedFromEdge: "UNASSIGNED_FROM_EDGE", + alarmAck: "ALARM_ACK", + alarmClear: "ALARM_CLEAR", + credentialsUpdated: "CREDENTIALS_UPDATED", + attributesUpdated: "ATTRIBUTES_UPDATED", + attributesDeleted: "ATTRIBUTES_DELETED", + timeseriesUpdated: "TIMESERIES_UPDATED" + }, importEntityColumnType: { name: { name: 'import.column-type.name', diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index e5908d88b0..b1b6311e5e 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -102,37 +102,45 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ switch(scope.event.edgeEventType) { case types.edgeEventType.relation: content = angular.toJson(scope.event.entityBody); + showDialog(); break; case types.edgeEventType.ruleChainMetaData: - content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {}).then( + content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then( function success(info) { + showDialog(); return angular.toJson(info); }, function fail() { - toast.showError($translate.instant('edge.load-entity-error')); + showError(); }); break; default: - content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {}).then( + content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {ignoreLoading: true, ignoreErrors: true}).then( function success(info) { + showDialog(); return angular.toJson(info); }, function fail() { - toast.showError($translate.instant('edge.load-entity-error')); + showError(); }); break; } - $mdDialog.show({ - controller: 'EventContentDialogController', - controllerAs: 'vm', - templateUrl: eventErrorDialogTemplate, - locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, - parent: angular.element($document[0].body), - fullscreen: true, - targetEvent: $event, - multiple: true, - onShowing: function(scope, element) { - onShowingCallback.onShowing(scope, element); - } - }); + function showDialog() { + $mdDialog.show({ + controller: 'EventContentDialogController', + controllerAs: 'vm', + templateUrl: eventErrorDialogTemplate, + locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, + parent: angular.element($document[0].body), + fullscreen: true, + targetEvent: $event, + multiple: true, + onShowing: function(scope, element) { + onShowingCallback.onShowing(scope, element); + } + }); + } + function showError() { + toast.showError($translate.instant('edge.load-entity-error')); + } } scope.checkTooltip = function($event) { diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index bea55fd30e..f8d1c8568a 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -821,7 +821,7 @@ "make-private-edge-text": "After the confirmation the edge and all its data will be made private and won't be accessible by others.", "import": "Import edge", "label": "Label", - "load-entity-error": "Could not load entity info", + "load-entity-error": "Entity not found. Failed to load info", "assign-new-edge": "Assign new edge", "manage-edge-dashboards": "Manage edge dashboards", "unassign-from-edge": "Unassign from edge", From 48cced2d0c5a89fabe2d249701d4e95f40d2ba95 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 21 Jul 2020 11:59:04 +0300 Subject: [PATCH 054/156] Minor code fix --- ui/src/app/event/event-row.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index b1b6311e5e..92da9c06b9 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -114,7 +114,7 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ }); break; default: - content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {ignoreLoading: true, ignoreErrors: true}).then( + content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {ignoreErrors: true}).then( function success(info) { showDialog(); return angular.toJson(info); From d34c54b31cba5f5812738ad9d88f3b2d3f79abd2 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 28 Jul 2020 18:00:14 +0300 Subject: [PATCH 055/156] Check for scope in the metadata --- .../rule/engine/telemetry/TbMsgAttributesNode.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index b6e9e4a292..17c66dd36f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -17,6 +17,7 @@ package org.thingsboard.rule.engine.telemetry; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; @@ -51,6 +52,8 @@ public class TbMsgAttributesNode implements TbNode { private TbMsgAttributesNodeConfiguration config; + private static final String SCOPE = "scope"; + @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { this.config = TbNodeUtils.convert(configuration, TbMsgAttributesNodeConfiguration.class); @@ -64,8 +67,12 @@ public class TbMsgAttributesNode implements TbNode { } String src = msg.getData(); Set attributes = JsonConverter.convertToAttributes(new JsonParser().parse(src)); - msg.getMetaData().putValue("scope", config.getScope()); - ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), config.getScope(), new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); + String scope = msg.getMetaData().getValue(SCOPE); + if (StringUtils.isEmpty(scope)) { + scope = config.getScope(); + msg.getMetaData().putValue("scope", scope); + } + ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), scope, new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); } @Override From ac18f1aa95a18ee03c72b2a9eff7fb5d03f9e64f Mon Sep 17 00:00:00 2001 From: deaflynx Date: Wed, 29 Jul 2020 12:36:48 +0300 Subject: [PATCH 056/156] Added edgeAttributeKeys constants --- ui/src/app/common/types.constant.js | 6 ++++++ ui/src/app/event/event-table.directive.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index f48f3e9f03..59f1111ab4 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -402,6 +402,12 @@ export default angular.module('thingsboard.types', []) attributesDeleted: "ATTRIBUTES_DELETED", timeseriesUpdated: "TIMESERIES_UPDATED" }, + edgeAttributeKeys: { + active: "active", + lastConnectTime: "lastConnectTime", + lastDisconnectTime: "lastDisconnectTime", + queueStartTs: "queueStartTs" + }, importEntityColumnType: { name: { name: 'import.column-type.name', diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js index 1cd61c888e..9c7c57d5d7 100644 --- a/ui/src/app/event/event-table.directive.js +++ b/ui/src/app/event/event-table.directive.js @@ -225,7 +225,7 @@ export default function EventTableDirective($compile, $templateCache, $rootScope scope.loadEdgeInfo = function() { attributeService.getEntityAttributesValues(scope.entityType, scope.entityId, types.attributesScope.server.value, - ["queueStartTs"], {}) + types.edgeAttributeKeys.queueStartTs, {}) .then(function success(attributes) { scope.onUpdate(attributes); }); From 5af7eb822140f526aeaea8f1580288ec4ccc2496 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 30 Jul 2020 18:58:04 +0300 Subject: [PATCH 057/156] WidgetsBundles fetch feature --- .../controller/WidgetsBundleController.java | 10 +++- .../edge/DefaultEdgeNotificationService.java | 34 ++++++++----- .../service/edge/EdgeContextComponent.java | 19 +++---- .../service/edge/rpc/EdgeGrpcSession.java | 36 +++++++++++++ .../WidgetsBundleUpdateMsgConstructor.java | 50 +++++++++++++++++++ .../server/common/data/EdgeUtils.java | 5 +- .../common/data/edge/EdgeEventType.java | 3 +- .../common/data/id/EntityIdFactory.java | 2 + common/edge-api/src/main/proto/edge.proto | 10 ++++ 9 files changed, 143 insertions(+), 26 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 1b6b371297..2527df1077 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; @@ -68,7 +69,11 @@ public class WidgetsBundleController extends BaseController { } checkEntity(widgetsBundle.getId(), widgetsBundle, Resource.WIDGETS_BUNDLE); - return checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle)); + WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); + + sendNotificationMsgToEdgeService(savedWidgetsBundle.getTenantId(), savedWidgetsBundle.getId(), ActionType.UPDATED); + + return checkNotNull(savedWidgetsBundle); } catch (Exception e) { throw handleException(e); } @@ -83,6 +88,9 @@ public class WidgetsBundleController extends BaseController { WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); checkWidgetsBundleId(widgetsBundleId, Operation.DELETE); widgetsBundleService.deleteWidgetsBundle(getTenantId(), widgetsBundleId); + + sendNotificationMsgToEdgeService(getTenantId(), widgetsBundleId, ActionType.DELETED); + } catch (Exception e) { throw handleException(e); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 47c6ece48f..b686cffa58 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -157,6 +157,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case ENTITY_VIEW: case DASHBOARD: case RULE_CHAIN: + case WIDGETS_BUNDLE: processEntity(tenantId, edgeNotificationMsg); break; case ALARM: @@ -185,20 +186,29 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { // case ADDED: case UPDATED: case CREDENTIALS_UPDATED: - ListenableFuture> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); - Futures.transform(edgeIdsFuture, edgeIds -> { - if (edgeIds != null && !edgeIds.isEmpty()) { - for (EdgeId edgeId : edgeIds) { - try { - saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); - } catch (Exception e) { - log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]", - tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e); - } + if (edgeEventType.equals(EdgeEventType.WIDGETS_BUNDLE)) { + TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { + for (Edge edge : edgesByTenantId.getData()) { + saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); } } - return null; - }, dbCallbackExecutorService); + } else { + ListenableFuture> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); + Futures.transform(edgeIdsFuture, edgeIds -> { + if (edgeIds != null && !edgeIds.isEmpty()) { + for (EdgeId edgeId : edgeIds) { + try { + saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + } catch (Exception e) { + log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]", + tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e); + } + } + } + return null; + }, dbCallbackExecutorService); + } break; case DELETED: TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index c21c1ebc9c..e62ff527cf 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -33,19 +33,12 @@ import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; +import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; -import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.*; import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.queue.TbClusterService; @@ -119,6 +112,10 @@ public class EdgeContextComponent { @Autowired private ActorService actorService; + @Lazy + @Autowired + private WidgetsBundleService widgetsBundleService; + @Lazy @Autowired private DeviceStateService deviceStateService; @@ -163,6 +160,10 @@ public class EdgeContextComponent { @Autowired private RelationUpdateMsgConstructor relationUpdateMsgConstructor; + @Lazy + @Autowired + private WidgetsBundleUpdateMsgConstructor widgetsBundleUpdateMsgConstructor; + @Lazy @Autowired private EntityDataMsgConstructor entityDataMsgConstructor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 9a5632bde4..a65abef536 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -54,6 +54,7 @@ import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; @@ -66,6 +67,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.UserCredentials; +import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.ServiceType; @@ -99,6 +101,7 @@ import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; @@ -335,6 +338,9 @@ public final class EdgeGrpcSession implements Closeable { case RELATION: processRelation(edgeEvent, msgType); break; + case WIDGETS_BUNDLE: + processWidgetsBundle(edgeEvent, msgType, edgeEventAction); + break; } } @@ -588,6 +594,36 @@ public final class EdgeGrpcSession implements Closeable { } } + private void processWidgetsBundle(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { + WidgetsBundleId widgetsBundleId = new WidgetsBundleId(edgeEvent.getEntityId()); + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeActionType) { + case ADDED: + case UPDATED: + WidgetsBundle widgetsBundle = ctx.getWidgetsBundleService().findWidgetsBundleById(edgeEvent.getTenantId(), widgetsBundleId); + if (widgetsBundle != null) { + WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = + ctx.getWidgetsBundleUpdateMsgConstructor().constructWidgetsBundleUpdateMsg(msgType, widgetsBundle); + entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setWidgetsBundleUpdateMsg(widgetsBundleUpdateMsg) + .build(); + } + break; + case DELETED: + WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = + ctx.getWidgetsBundleUpdateMsgConstructor().constructWidgetsBundleDeleteMsg(widgetsBundleId); + entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setWidgetsBundleUpdateMsg(widgetsBundleUpdateMsg) + .build(); + break; + } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } + private UpdateMsgType getResponseMsgType(ActionType actionType) { switch (actionType) { case UPDATED: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java new file mode 100644 index 0000000000..867f42dcfb --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java @@ -0,0 +1,50 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.constructor; + +import com.google.protobuf.ByteString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.WidgetsBundleId; +import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; + +@Component +@Slf4j +public class WidgetsBundleUpdateMsgConstructor { + + public WidgetsBundleUpdateMsg constructWidgetsBundleUpdateMsg(UpdateMsgType msgType, WidgetsBundle widgetsBundle) { + WidgetsBundleUpdateMsg.Builder builder = WidgetsBundleUpdateMsg.newBuilder() + .setMsgType(msgType) + .setIdMSB(widgetsBundle.getId().getId().getMostSignificantBits()) + .setIdLSB(widgetsBundle.getId().getId().getLeastSignificantBits()) + .setTitle(widgetsBundle.getTitle()) + .setAlias(widgetsBundle.getAlias()); + if (widgetsBundle.getImage() != null) { + builder.setImage(ByteString.copyFrom(widgetsBundle.getImage())); + } + return builder.build(); + } + + public WidgetsBundleUpdateMsg constructWidgetsBundleDeleteMsg(WidgetsBundleId widgetsBundleId) { + return WidgetsBundleUpdateMsg.newBuilder() + .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE) + .setIdMSB(widgetsBundleId.getId().getMostSignificantBits()) + .setIdLSB(widgetsBundleId.getId().getLeastSignificantBits()) + .build(); + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java index 784763f99e..9189fb7d37 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java @@ -16,9 +16,6 @@ package org.thingsboard.server.common.data; import org.thingsboard.server.common.data.edge.EdgeEventType; -import org.thingsboard.server.common.data.id.EdgeId; - -import java.util.Set; public final class EdgeUtils { @@ -39,6 +36,8 @@ public final class EdgeUtils { return EdgeEventType.USER; case ALARM: return EdgeEventType.ALARM; + case WIDGETS_BUNDLE: + return EdgeEventType.WIDGETS_BUNDLE; default: return null; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index 52259d4507..2b76395e7a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -26,5 +26,6 @@ public enum EdgeEventType { EDGE, USER, CUSTOMER, - RELATION + RELATION, + WIDGETS_BUNDLE } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java index 17d86e26ec..3b4f20d5dd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java @@ -87,6 +87,8 @@ public class EntityIdFactory { return new RuleChainId(uuid); case ENTITY_VIEW: return new EntityViewId(uuid); + case WIDGETS_BUNDLE: + return new WidgetsBundleId(uuid); case EDGE: return new EdgeId(uuid); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 181ebff531..62e21ea5e8 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -59,6 +59,7 @@ message EntityUpdateMsg { UserCredentialsUpdateMsg userCredentialsUpdateMsg = 10; CustomerUpdateMsg customerUpdateMsg = 11; RelationUpdateMsg relationUpdateMsg = 12; + WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 13; } enum RequestMsgType { @@ -266,6 +267,15 @@ message UserUpdateMsg { string additionalInfo = 8; } +message WidgetsBundleUpdateMsg { + UpdateMsgType msgType = 1; + int64 idMSB = 2; + int64 idLSB = 3; + string title = 4; + string alias = 5; + bytes image = 6; +} + message UserCredentialsUpdateMsg { int64 userIdMSB = 1; int64 userIdLSB = 2; From c4d7f52cf3e0c552286b1848074b0e6d2c1713b8 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 30 Jul 2020 19:46:33 +0300 Subject: [PATCH 058/156] filtering EdgeEvents with TIMESERIES_UPDATE --- .../server/controller/EdgeEventController.java | 2 +- .../thingsboard/server/dao/edge/EdgeEventService.java | 3 +-- .../server/dao/edge/BaseEdgeEventService.java | 9 +++++++-- .../server/dao/edge/CassandraEdgeEventDao.java | 2 +- .../org/thingsboard/server/dao/edge/EdgeEventDao.java | 2 +- .../server/dao/sql/edge/JpaBaseEdgeEventDao.java | 11 ++++++++--- 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java index 097b8d0f5c..15578b8593 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -61,7 +61,7 @@ public class EdgeEventController extends BaseController { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); - return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink)); + return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, false)); } catch (Exception e) { throw handleException(e); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java index 0d65c134f2..8ab877dd83 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java @@ -16,9 +16,7 @@ package org.thingsboard.server.dao.edge; import com.google.common.util.concurrent.ListenableFuture; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TimePageData; @@ -30,4 +28,5 @@ public interface EdgeEventService { TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); + TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java index 75bc3046c4..efb2c7198a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java @@ -35,7 +35,7 @@ import java.util.List; public class BaseEdgeEventService implements EdgeEventService { @Autowired - public EdgeEventDao edgeEventDao; + private EdgeEventDao edgeEventDao; @Override public ListenableFuture saveAsync(EdgeEvent edgeEvent) { @@ -45,7 +45,12 @@ public class BaseEdgeEventService implements EdgeEventService { @Override public TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) { - List events = edgeEventDao.findEdgeEvents(tenantId.getId(), edgeId, pageLink); + return findEdgeEvents(tenantId, edgeId, pageLink, true); + } + + @Override + public TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate) { + List events = edgeEventDao.findEdgeEvents(tenantId.getId(), edgeId, pageLink, withTsUpdate); return new TimePageData<>(events, pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java index 8483197f1b..e127abad39 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java @@ -53,7 +53,7 @@ public class CassandraEdgeEventDao extends CassandraAbstractSearchTimeDao findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink) { + public List findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate) { return null; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeEventDao.java index 426bada645..bf7b263e44 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeEventDao.java @@ -46,6 +46,6 @@ public interface EdgeEventDao extends Dao { * @param pageLink the pageLink * @return the event list */ - List findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink); + List findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java index 11a4a1dc64..4408b8ebae 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java @@ -26,6 +26,7 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.UUIDConverter; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.EdgeEventId; import org.thingsboard.server.common.data.id.EdgeId; @@ -75,9 +76,9 @@ public class JpaBaseEdgeEventDao extends JpaAbstractSearchTimeDao findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink) { + public List findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate) { Specification timeSearchSpec = JpaAbstractSearchTimeDao.getTimeSearchPageSpec(pageLink, "id"); - Specification fieldsSpec = getEntityFieldsSpec(tenantId, edgeId); + Specification fieldsSpec = getEntityFieldsSpec(tenantId, edgeId, withTsUpdate); Sort.Direction sortDirection = pageLink.isAscOrder() ? Sort.Direction.ASC : Sort.Direction.DESC; Pageable pageable = PageRequest.of(0, pageLink.getLimit(), sortDirection, ID_PROPERTY); return DaoUtil.convertDataList(edgeEventRepository.findAll(Specification.where(timeSearchSpec).and(fieldsSpec), pageable).getContent()); @@ -95,7 +96,7 @@ public class JpaBaseEdgeEventDao extends JpaAbstractSearchTimeDao getEntityFieldsSpec(UUID tenantId, EdgeId edgeId) { + private Specification getEntityFieldsSpec(UUID tenantId, EdgeId edgeId, boolean withTsUpdate) { return (root, criteriaQuery, criteriaBuilder) -> { List predicates = new ArrayList<>(); if (tenantId != null) { @@ -106,6 +107,10 @@ public class JpaBaseEdgeEventDao extends JpaAbstractSearchTimeDao Date: Fri, 31 Jul 2020 10:13:03 +0300 Subject: [PATCH 059/156] Introduced Edge Lifecycle. Update Edge session configuration --- .../server/actors/ActorSystemContext.java | 16 ++++---- .../server/actors/tenant/TenantActor.java | 17 +++++++- .../server/controller/EdgeController.java | 9 ++++ .../service/edge/rpc/EdgeGrpcService.java | 20 ++++++++- .../service/edge/rpc/EdgeGrpcSession.java | 14 +++++++ .../service/edge/rpc/EdgeRpcService.java | 41 +++++++++++++++++++ 6 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 78caa4a626..3f4dcb3c0b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -66,6 +66,7 @@ import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.service.component.ComponentDiscoveryService; +import org.thingsboard.server.service.edge.rpc.EdgeRpcService; import org.thingsboard.server.service.encoding.DataDecodingEncodingService; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.executors.ExternalCallExecutorService; @@ -254,15 +255,14 @@ public class ActorSystemContext { @Getter private TbCoreDeviceRpcService tbCoreDeviceRpcService; - @Lazy - @Autowired - @Getter - private EdgeService edgeService; + @Autowired(required = false) + @Getter private EdgeService edgeService; - @Lazy - @Autowired - @Getter - private EdgeEventService edgeEventService; + @Autowired(required = false) + @Getter private EdgeEventService edgeEventService; + + @Autowired(required = false) + @Getter private EdgeRpcService edgeRpcService; @Value("${actors.session.max_concurrent_sessions_per_device:1}") @Getter diff --git a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java index 7ce5fb3206..fde6f688c5 100644 --- a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java @@ -31,10 +31,13 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; import org.thingsboard.server.actors.service.DefaultActorService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.MsgType; @@ -47,6 +50,7 @@ import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; import org.thingsboard.server.common.msg.queue.RuleEngineException; import org.thingsboard.server.common.msg.queue.ServiceType; +import org.thingsboard.server.service.edge.rpc.EdgeRpcService; import java.util.List; import java.util.Optional; @@ -202,7 +206,18 @@ public class TenantActor extends RuleChainManagerActor { } private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { - if (isRuleEngineForCurrentTenant) { + if (msg.getEntityId().getEntityType() == EntityType.EDGE) { + EdgeId edgeId = new EdgeId(msg.getEntityId().getId()); + EdgeRpcService edgeRpcService = systemContext.getEdgeRpcService(); + if (msg.getEvent() == ComponentLifecycleEvent.DELETED) { + edgeRpcService.deleteEdge(edgeId); + } else { + Edge edge = systemContext.getEdgeService().findEdgeById(tenantId, edgeId); + if (msg.getEvent() == ComponentLifecycleEvent.UPDATED) { + edgeRpcService.updateEdge(edge); + } + } + } else if (isRuleEngineForCurrentTenant) { TbActorRef target = getEntityActorRef(msg.getEntityId()); if (target != null) { if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) { diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index b6f2c31561..3c17176b88 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; @@ -101,6 +102,9 @@ public class EdgeController extends BaseController { edgeService.assignDefaultRuleChainsToEdge(tenantId, savedEdge.getId()); } + tbClusterService.onEntityStateChange(savedEdge.getTenantId(), savedEdge.getId(), + created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); + logEntityAction(savedEdge.getId(), savedEdge, null, created ? ActionType.ADDED : ActionType.UPDATED, null); return savedEdge; } catch (Exception e) { @@ -120,6 +124,9 @@ public class EdgeController extends BaseController { Edge edge = checkEdgeId(edgeId, Operation.DELETE); edgeService.deleteEdge(getTenantId(), edgeId); + tbClusterService.onEntityStateChange(getTenantId(), edgeId, + ComponentLifecycleEvent.DELETED); + logEntityAction(edgeId, edge, null, ActionType.DELETED, null, strEdgeId); @@ -284,6 +291,8 @@ public class EdgeController extends BaseController { Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId); + tbClusterService.onEntityStateChange(updatedEdge.getTenantId(), updatedEdge.getId(), ComponentLifecycleEvent.UPDATED); + logEntityAction(updatedEdge.getId(), updatedEdge, null, ActionType.UPDATED, null); return updatedEdge; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index 3792fbdf73..8e2990c75f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; @@ -52,7 +53,7 @@ import java.util.concurrent.Executors; @Service @Slf4j @ConditionalOnProperty(prefix = "edges.rpc", value = "enabled", havingValue = "true") -public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { +public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { private final Map sessions = new ConcurrentHashMap<>(); private static final ObjectMapper mapper = new ObjectMapper(); @@ -117,6 +118,23 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, mapper).getInputStream(); } + @Override + public void updateEdge(Edge edge) { + EdgeGrpcSession session = sessions.get(edge.getId()); + if (session != null && session.isConnected()) { + session.onConfigurationUpdate(edge); + } + } + + @Override + public void deleteEdge(EdgeId edgeId) { + EdgeGrpcSession session = sessions.get(edgeId); + if (session != null && session.isConnected()) { + session.close(); + sessions.remove(edgeId); + } + } + private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { sessions.put(edgeId, edgeGrpcSession); save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 9a5632bde4..72014cf1c9 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -192,6 +192,20 @@ public final class EdgeGrpcSession implements Closeable { }; } + void onConfigurationUpdate(Edge edge) { + try { + this.edge = edge; + // TODO: voba - push edge configuration update to edge +// outputStream.onNext(org.thingsboard.server.gen.integration.ResponseMsg.newBuilder() +// .setIntegrationUpdateMsg(IntegrationUpdateMsg.newBuilder() +// .setConfiguration(constructIntegrationConfigProto(configuration, defaultConverterProto, downLinkConverterProto)) +// .build()) +// .build()); + } catch (Exception e) { + log.error("Failed to construct proto objects!", e); + } + } + void processHandleMessages() throws ExecutionException, InterruptedException { Long queueStartTs = getQueueStartTs().get(); TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java new file mode 100644 index 0000000000..27cd81250b --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java @@ -0,0 +1,41 @@ +/** + * ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL + * + * Copyright © 2016-2020 ThingsBoard, Inc. All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of ThingsBoard, Inc. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to ThingsBoard, Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, + * patents in process, and are protected by trade secret or copyright law. + * + * Dissemination of this information or reproduction of this material is strictly forbidden + * unless prior written permission is obtained from COMPANY. + * + * Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees, + * managers or contractors who have executed Confidentiality and Non-disclosure agreements + * explicitly covering such access. + * + * The copyright notice above does not evidence any actual or intended publication + * or disclosure of this source code, which includes + * information that is confidential and/or proprietary, and is a trade secret, of COMPANY. + * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, + * OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT + * THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, + * AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. + * THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION + * DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, + * OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART. + */ +package org.thingsboard.server.service.edge.rpc; + +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.id.EdgeId; + +public interface EdgeRpcService { + + void updateEdge(Edge edge); + + void deleteEdge(EdgeId edgeId); +} From ce746b4f91b0bff088e18869825b30012846a1bf Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 31 Jul 2020 11:13:07 +0300 Subject: [PATCH 060/156] Fixed license header --- .../service/edge/rpc/EdgeRpcService.java | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java index 27cd81250b..2355a2e49a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java @@ -1,32 +1,17 @@ /** - * ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL + * Copyright © 2016-2020 The Thingsboard Authors * - * Copyright © 2016-2020 ThingsBoard, Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * NOTICE: All information contained herein is, and remains - * the property of ThingsBoard, Inc. and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to ThingsBoard, Inc. - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. + * http://www.apache.org/licenses/LICENSE-2.0 * - * Dissemination of this information or reproduction of this material is strictly forbidden - * unless prior written permission is obtained from COMPANY. - * - * Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees, - * managers or contractors who have executed Confidentiality and Non-disclosure agreements - * explicitly covering such access. - * - * The copyright notice above does not evidence any actual or intended publication - * or disclosure of this source code, which includes - * information that is confidential and/or proprietary, and is a trade secret, of COMPANY. - * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, - * OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT - * THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, - * AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. - * THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION - * DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, - * OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.thingsboard.server.service.edge.rpc; From 71a3fa68f1c987447965b277c0d2a35b3aea774f Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 31 Jul 2020 11:38:25 +0300 Subject: [PATCH 061/156] fixes --- .../server/service/edge/DefaultEdgeNotificationService.java | 2 +- .../org/thingsboard/server/dao/edge/EdgeEventService.java | 2 -- .../thingsboard/server/dao/edge/BaseEdgeEventService.java | 5 ----- .../server/dao/service/BaseEdgeEventServiceTest.java | 4 ++-- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 47c6ece48f..c90c05746f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -111,7 +111,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @Override public TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) { - return edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink); + return edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, true); } @Override diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java index 8ab877dd83..1c65c34a08 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java @@ -26,7 +26,5 @@ public interface EdgeEventService { ListenableFuture saveAsync(EdgeEvent edgeEvent); - TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); - TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java index efb2c7198a..08e5d2570f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java @@ -43,11 +43,6 @@ public class BaseEdgeEventService implements EdgeEventService { return edgeEventDao.saveAsync(edgeEvent); } - @Override - public TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) { - return findEdgeEvents(tenantId, edgeId, pageLink, true); - } - @Override public TimePageData findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate) { List events = edgeEventDao.findEdgeEvents(tenantId.getId(), edgeId, pageLink, withTsUpdate); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java index f4d622daa5..aa0a3c79e4 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java @@ -82,7 +82,7 @@ public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest { EdgeEvent savedEdgeEvent3 = saveEdgeEventWithProvidedTime(eventTime + 2, edgeId, deviceId, tenantId); saveEdgeEventWithProvidedTime(timeAfterEndTime, edgeId, deviceId, tenantId); - TimePageData edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, new TimePageLink(2, startTime, endTime, false)); + TimePageData edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, new TimePageLink(2, startTime, endTime, false), true); Assert.assertNotNull(edgeEvents.getData()); Assert.assertTrue(edgeEvents.getData().size() == 2); @@ -91,7 +91,7 @@ public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest { Assert.assertTrue(edgeEvents.hasNext()); Assert.assertNotNull(edgeEvents.getNextPageLink()); - edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, edgeEvents.getNextPageLink()); + edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, edgeEvents.getNextPageLink(), true); Assert.assertNotNull(edgeEvents.getData()); Assert.assertTrue(edgeEvents.getData().size() == 1); From 76b35010c75dd0e19df21b3ed2faff4e2dc56e3a Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 31 Jul 2020 15:53:22 +0300 Subject: [PATCH 062/156] WidgetTypes fetch feature --- .../controller/WidgetTypeController.java | 11 ++- .../edge/DefaultEdgeNotificationService.java | 3 +- .../service/edge/EdgeContextComponent.java | 9 +++ .../service/edge/rpc/EdgeGrpcSession.java | 76 +++++++++---------- .../WidgetTypeUpdateMsgConstructor.java | 57 ++++++++++++++ .../server/common/data/EdgeUtils.java | 2 + .../common/data/edge/EdgeEventType.java | 3 +- .../common/data/id/EntityIdFactory.java | 2 + common/edge-api/src/main/proto/edge.proto | 11 +++ 9 files changed, 131 insertions(+), 43 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index ffff90536f..aa21593929 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.controller; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -25,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; @@ -37,6 +39,7 @@ import org.thingsboard.server.service.security.permission.Resource; import java.util.List; +@Slf4j @RestController @TbCoreComponent @RequestMapping("/api") @@ -67,8 +70,11 @@ public class WidgetTypeController extends BaseController { } checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE); + WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); - return checkNotNull(widgetTypeService.saveWidgetType(widgetType)); + sendNotificationMsgToEdgeService(savedWidgetType.getTenantId(), savedWidgetType.getId(), ActionType.UPDATED); + + return checkNotNull(savedWidgetType); } catch (Exception e) { throw handleException(e); } @@ -83,6 +89,9 @@ public class WidgetTypeController extends BaseController { WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); checkWidgetTypeId(widgetTypeId, Operation.DELETE); widgetTypeService.deleteWidgetType(getCurrentUser().getTenantId(), widgetTypeId); + + sendNotificationMsgToEdgeService(getTenantId(), widgetTypeId, ActionType.DELETED); + } catch (Exception e) { throw handleException(e); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index b686cffa58..cc46427b85 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -158,6 +158,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case DASHBOARD: case RULE_CHAIN: case WIDGETS_BUNDLE: + case WIDGET_TYPE: processEntity(tenantId, edgeNotificationMsg); break; case ALARM: @@ -186,7 +187,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { // case ADDED: case UPDATED: case CREDENTIALS_UPDATED: - if (edgeEventType.equals(EdgeEventType.WIDGETS_BUNDLE)) { + if (edgeEventType.equals(EdgeEventType.WIDGETS_BUNDLE) || edgeEventType.equals(EdgeEventType.WIDGET_TYPE)) { TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { for (Edge edge : edgesByTenantId.getData()) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index e62ff527cf..e87bdbdef3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -33,6 +33,7 @@ import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; +import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; @@ -116,6 +117,10 @@ public class EdgeContextComponent { @Autowired private WidgetsBundleService widgetsBundleService; + @Lazy + @Autowired + private WidgetTypeService widgetTypeService; + @Lazy @Autowired private DeviceStateService deviceStateService; @@ -164,6 +169,10 @@ public class EdgeContextComponent { @Autowired private WidgetsBundleUpdateMsgConstructor widgetsBundleUpdateMsgConstructor; + @Lazy + @Autowired + private WidgetTypeUpdateMsgConstructor widgetTypeUpdateMsgConstructor; + @Lazy @Autowired private EntityDataMsgConstructor entityDataMsgConstructor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index a65abef536..471f34a33c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -43,18 +43,7 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.id.AlarmId; -import org.thingsboard.server.common.data.id.AssetId; -import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.DashboardId; -import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.EntityViewId; -import org.thingsboard.server.common.data.id.RuleChainId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.common.data.id.WidgetsBundleId; +import org.thingsboard.server.common.data.id.*; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; @@ -67,6 +56,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.UserCredentials; +import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -74,34 +64,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; -import org.thingsboard.server.gen.edge.AlarmUpdateMsg; -import org.thingsboard.server.gen.edge.AssetUpdateMsg; -import org.thingsboard.server.gen.edge.AttributesRequestMsg; -import org.thingsboard.server.gen.edge.ConnectRequestMsg; -import org.thingsboard.server.gen.edge.ConnectResponseCode; -import org.thingsboard.server.gen.edge.ConnectResponseMsg; -import org.thingsboard.server.gen.edge.DashboardUpdateMsg; -import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; -import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; -import org.thingsboard.server.gen.edge.DeviceUpdateMsg; -import org.thingsboard.server.gen.edge.DownlinkMsg; -import org.thingsboard.server.gen.edge.EdgeConfiguration; -import org.thingsboard.server.gen.edge.EntityDataProto; -import org.thingsboard.server.gen.edge.EntityUpdateMsg; -import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; -import org.thingsboard.server.gen.edge.RelationRequestMsg; -import org.thingsboard.server.gen.edge.RequestMsg; -import org.thingsboard.server.gen.edge.RequestMsgType; -import org.thingsboard.server.gen.edge.ResponseMsg; -import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; -import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; -import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; -import org.thingsboard.server.gen.edge.UpdateMsgType; -import org.thingsboard.server.gen.edge.UplinkMsg; -import org.thingsboard.server.gen.edge.UplinkResponseMsg; -import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; -import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; -import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; +import org.thingsboard.server.gen.edge.*; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; @@ -341,6 +304,9 @@ public final class EdgeGrpcSession implements Closeable { case WIDGETS_BUNDLE: processWidgetsBundle(edgeEvent, msgType, edgeEventAction); break; + case WIDGET_TYPE: + processWidgetType(edgeEvent, msgType, edgeEventAction); + break; } } @@ -624,6 +590,36 @@ public final class EdgeGrpcSession implements Closeable { } } + private void processWidgetType(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { + WidgetTypeId widgetTypeId = new WidgetTypeId(edgeEvent.getEntityId()); + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeActionType) { + case ADDED: + case UPDATED: + WidgetType widgetType = ctx.getWidgetTypeService().findWidgetTypeById(edgeEvent.getTenantId(), widgetTypeId); + if (widgetType != null) { + WidgetTypeUpdateMsg widgetTypeUpdateMsg = + ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeUpdateMsg(msgType, widgetType); + entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setWidgetTypeUpdateMsg(widgetTypeUpdateMsg) + .build(); + } + break; + case DELETED: + WidgetTypeUpdateMsg widgetTypeUpdateMsg = + ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeUpdateMsg(widgetTypeId); + entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setWidgetTypeUpdateMsg(widgetTypeUpdateMsg) + .build(); + break; + } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } + private UpdateMsgType getResponseMsgType(ActionType actionType) { switch (actionType) { case UPDATED: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java new file mode 100644 index 0000000000..dc7b8b704b --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java @@ -0,0 +1,57 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.constructor; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.WidgetTypeId; +import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; +import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; + +@Component +@Slf4j +public class WidgetTypeUpdateMsgConstructor { + + public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(UpdateMsgType msgType, WidgetType widgetType) { + WidgetTypeUpdateMsg.Builder builder = WidgetTypeUpdateMsg.newBuilder() + .setMsgType(msgType) + .setIdMSB(widgetType.getId().getId().getMostSignificantBits()) + .setIdLSB(widgetType.getId().getId().getLeastSignificantBits()); + if (widgetType.getBundleAlias() != null) { + builder.setBundleAlias(widgetType.getBundleAlias()); + } + if (widgetType.getAlias() != null) { + builder.setAlias(widgetType.getAlias()); + } + if (widgetType.getName() != null) { + builder.setName(widgetType.getName()); + } + if (widgetType.getDescriptor() != null) { + builder.setDescriptorJson(JacksonUtil.toString(widgetType.getDescriptor())); + } + return builder.build(); + } + + public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(WidgetTypeId widgetTypeId) { + return WidgetTypeUpdateMsg.newBuilder() + .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE) + .setIdMSB(widgetTypeId.getId().getMostSignificantBits()) + .setIdLSB(widgetTypeId.getId().getLeastSignificantBits()) + .build(); + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java index 9189fb7d37..9385698d24 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java @@ -38,6 +38,8 @@ public final class EdgeUtils { return EdgeEventType.ALARM; case WIDGETS_BUNDLE: return EdgeEventType.WIDGETS_BUNDLE; + case WIDGET_TYPE: + return EdgeEventType.WIDGET_TYPE; default: return null; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index 2b76395e7a..41ef5782de 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -27,5 +27,6 @@ public enum EdgeEventType { USER, CUSTOMER, RELATION, - WIDGETS_BUNDLE + WIDGETS_BUNDLE, + WIDGET_TYPE } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java index 3b4f20d5dd..9297ed5e0b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java @@ -89,6 +89,8 @@ public class EntityIdFactory { return new EntityViewId(uuid); case WIDGETS_BUNDLE: return new WidgetsBundleId(uuid); + case WIDGET_TYPE: + return new WidgetTypeId(uuid); case EDGE: return new EdgeId(uuid); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 62e21ea5e8..bd6bc81728 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -60,6 +60,7 @@ message EntityUpdateMsg { CustomerUpdateMsg customerUpdateMsg = 11; RelationUpdateMsg relationUpdateMsg = 12; WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 13; + WidgetTypeUpdateMsg widgetTypeUpdateMsg = 14; } enum RequestMsgType { @@ -276,6 +277,16 @@ message WidgetsBundleUpdateMsg { bytes image = 6; } +message WidgetTypeUpdateMsg { + UpdateMsgType msgType = 1; + int64 idMSB = 2; + int64 idLSB = 3; + string bundleAlias = 4; + string alias = 5; + string name = 6; + string descriptorJson = 7; +} + message UserCredentialsUpdateMsg { int64 userIdMSB = 1; int64 userIdLSB = 2; From c56c2c4c5d0b9c510e88ee4dfa1951c65bc363a6 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 31 Jul 2020 17:10:35 +0300 Subject: [PATCH 063/156] added test --- .../dao/service/BaseEdgeEventServiceTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java index aa0a3c79e4..5da642d254 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java @@ -19,6 +19,7 @@ import com.datastax.driver.core.utils.UUIDs; import org.junit.Assert; import org.junit.Test; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.DeviceId; @@ -100,6 +101,26 @@ public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest { Assert.assertNull(edgeEvents.getNextPageLink()); } + @Test + public void findEdgeEventsWithTsUpdateAndWithout() throws Exception { + EdgeId edgeId = new EdgeId(UUIDs.timeBased()); + DeviceId deviceId = new DeviceId(UUIDs.timeBased()); + TenantId tenantId = new TenantId(UUIDs.timeBased()); + TimePageLink pageLink = new TimePageLink(1); + + EdgeEvent edgeEventWithTsUpdate = generateEdgeEvent(tenantId, edgeId, deviceId, ActionType.TIMESERIES_UPDATED.name()); + edgeEventService.saveAsync(edgeEventWithTsUpdate); + + TimePageData allEdgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, true); + TimePageData edgeEventsWithoutTsUpdate = edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, false); + + Assert.assertNotNull(allEdgeEvents.getData()); + Assert.assertNotNull(edgeEventsWithoutTsUpdate.getData()); + Assert.assertEquals(1, allEdgeEvents.getData().size()); + Assert.assertEquals(allEdgeEvents.getData().get(0).getUuidId(), edgeEventWithTsUpdate.getUuidId()); + Assert.assertTrue(edgeEventsWithoutTsUpdate.getData().isEmpty()); + } + private EdgeEvent saveEdgeEventWithProvidedTime(long time, EdgeId edgeId, EntityId entityId, TenantId tenantId) throws Exception { EdgeEvent edgeEvent = generateEdgeEvent(tenantId, edgeId, entityId, DataConstants.ENTITY_CREATED); edgeEvent.setId(new EdgeEventId(UUIDs.startOf(time))); From f17a4d2bc26f68a121d818c6c141906c7cd621e3 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 31 Jul 2020 17:45:26 +0300 Subject: [PATCH 064/156] fixes --- .../controller/WidgetTypeController.java | 2 +- .../controller/WidgetsBundleController.java | 2 +- .../service/edge/EdgeContextComponent.java | 12 ++++- .../service/edge/rpc/EdgeGrpcSession.java | 46 +++++++++++++++++-- .../WidgetTypeUpdateMsgConstructor.java | 2 +- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index aa21593929..492b512312 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -72,7 +72,7 @@ public class WidgetTypeController extends BaseController { checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE); WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); - sendNotificationMsgToEdgeService(savedWidgetType.getTenantId(), savedWidgetType.getId(), ActionType.UPDATED); + sendNotificationMsgToEdgeService(savedWidgetType.getTenantId(), savedWidgetType.getId(), savedWidgetType.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return checkNotNull(savedWidgetType); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 2527df1077..213de07d9f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -71,7 +71,7 @@ public class WidgetsBundleController extends BaseController { checkEntity(widgetsBundle.getId(), widgetsBundle, Resource.WIDGETS_BUNDLE); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - sendNotificationMsgToEdgeService(savedWidgetsBundle.getTenantId(), savedWidgetsBundle.getId(), ActionType.UPDATED); + sendNotificationMsgToEdgeService(savedWidgetsBundle.getTenantId(), savedWidgetsBundle.getId(), savedWidgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return checkNotNull(savedWidgetsBundle); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index e87bdbdef3..fcbc8ff756 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -39,7 +39,17 @@ import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; -import org.thingsboard.server.service.edge.rpc.constructor.*; +import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.WidgetTypeUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.WidgetsBundleUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.queue.TbClusterService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 471f34a33c..ec3633a7c4 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -43,7 +43,19 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.id.*; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityViewId; +import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.id.WidgetTypeId; +import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; @@ -64,7 +76,35 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; -import org.thingsboard.server.gen.edge.*; +import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.AttributesRequestMsg; +import org.thingsboard.server.gen.edge.ConnectRequestMsg; +import org.thingsboard.server.gen.edge.ConnectResponseCode; +import org.thingsboard.server.gen.edge.ConnectResponseMsg; +import org.thingsboard.server.gen.edge.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceUpdateMsg; +import org.thingsboard.server.gen.edge.DownlinkMsg; +import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.edge.EntityUpdateMsg; +import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; +import org.thingsboard.server.gen.edge.RelationRequestMsg; +import org.thingsboard.server.gen.edge.RequestMsg; +import org.thingsboard.server.gen.edge.RequestMsgType; +import org.thingsboard.server.gen.edge.ResponseMsg; +import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; +import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; +import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.edge.UplinkMsg; +import org.thingsboard.server.gen.edge.UplinkResponseMsg; +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; @@ -607,7 +647,7 @@ public final class EdgeGrpcSession implements Closeable { break; case DELETED: WidgetTypeUpdateMsg widgetTypeUpdateMsg = - ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeUpdateMsg(widgetTypeId); + ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeDeleteMsg(widgetTypeId); entityUpdateMsg = EntityUpdateMsg.newBuilder() .setWidgetTypeUpdateMsg(widgetTypeUpdateMsg) .build(); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java index dc7b8b704b..52470240d7 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java @@ -47,7 +47,7 @@ public class WidgetTypeUpdateMsgConstructor { return builder.build(); } - public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(WidgetTypeId widgetTypeId) { + public WidgetTypeUpdateMsg constructWidgetTypeDeleteMsg(WidgetTypeId widgetTypeId) { return WidgetTypeUpdateMsg.newBuilder() .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE) .setIdMSB(widgetTypeId.getId().getMostSignificantBits()) From 9980a72ee98c45a23f2ba6dcd317ddfafacd6cfd Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 31 Jul 2020 18:05:15 +0300 Subject: [PATCH 065/156] Fix connection if edge removed --- .../src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 38b377c4a8..917cc3fa02 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -155,6 +155,7 @@ public class EdgeGrpcClient implements EdgeRpcClient { @Override public void onCompleted() { log.debug("[{}] The rpc session was closed!", edgeKey); + onError.accept(new EdgeConnectionException("[" + edgeKey + "] The rpc session was closed!")); } }; } From 869a492c2cce2dd1a9f6c6e496c3f9468ea3bc9e Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 3 Aug 2020 20:05:21 +0300 Subject: [PATCH 066/156] Added support for Tenant Entity --- .../service/edge/rpc/EdgeGrpcSession.java | 10 +++ .../server/common/data/EdgeUtils.java | 4 + .../common/data/edge/EdgeEventType.java | 3 +- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 85 +++++++++++-------- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 72014cf1c9..7220075e77 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -298,6 +298,12 @@ public final class EdgeGrpcSession implements Closeable { case DASHBOARD: entityId = new DashboardId(edgeEvent.getEntityId()); break; + case TENANT: + entityId = new TenantId(edgeEvent.getEntityId()); + break; + case CUSTOMER: + entityId = new CustomerId(edgeEvent.getEntityId()); + break; } if (entityId != null) { log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody()); @@ -748,6 +754,10 @@ public final class EdgeGrpcSession implements Closeable { return new EntityViewId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); case DASHBOARD: return new DashboardId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case TENANT: + return new TenantId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case CUSTOMER: + return new CustomerId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); default: log.warn("Unsupported entity type [{}] during construct of entity id. EntityDataProto [{}]", entityData.getEntityType(), entityData); return null; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java index 784763f99e..eff437a4a5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java @@ -39,6 +39,10 @@ public final class EdgeUtils { return EdgeEventType.USER; case ALARM: return EdgeEventType.ALARM; + case TENANT: + return EdgeEventType.TENANT; + case CUSTOMER: + return EdgeEventType.CUSTOMER; default: return null; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index 52259d4507..cc77b629bd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -26,5 +26,6 @@ public enum EdgeEventType { EDGE, USER, CUSTOMER, - RELATION + RELATION, + TENANT } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index f1134078c1..013ade7480 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -33,11 +33,15 @@ import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.IdBased; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TextPageData; +import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; @@ -46,10 +50,12 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -84,34 +90,38 @@ public class TbMsgPushToEdgeNode implements TbNode { } if (isSupportedOriginator(msg.getOriginator().getEntityType())) { if (isSupportedMsgType(msg.getType())) { - ListenableFuture getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator()); - Futures.addCallback(getEdgeIdFuture, new FutureCallback() { + ListenableFuture> getEdgeIdsFuture = getEdgeIdsByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator()); + Futures.addCallback(getEdgeIdsFuture, new FutureCallback>() { @Override - public void onSuccess(@Nullable EdgeId edgeId) { - try { - EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx); - if (edgeEvent == null) { - log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); - ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); - } else { - edgeEvent.setEdgeId(edgeId); - ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); - Futures.addCallback(saveFuture, new FutureCallback() { - @Override - public void onSuccess(@Nullable EdgeEvent event) { - ctx.tellNext(msg, SUCCESS); + public void onSuccess(@Nullable List edgeIds) { + if (edgeIds != null && !edgeIds.isEmpty()) { + for (EdgeId edgeId : edgeIds) { + try { + EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx); + if (edgeEvent == null) { + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); + } else { + edgeEvent.setEdgeId(edgeId); + ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); + Futures.addCallback(saveFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent event) { + ctx.tellNext(msg, SUCCESS); + } + + @Override + public void onFailure(Throwable th) { + log.error("Could not save edge event", th); + ctx.tellFailure(msg, th); + } + }, ctx.getDbCallbackExecutor()); } - - @Override - public void onFailure(Throwable th) { - log.error("Could not save edge event", th); - ctx.tellFailure(msg, th); - } - }, ctx.getDbCallbackExecutor()); + } catch (JsonProcessingException e) { + log.error("Failed to build edge event", e); + ctx.tellFailure(msg, e); + } } - } catch (JsonProcessingException e) { - log.error("Failed to build edge event", e); - ctx.tellFailure(msg, e); } } @@ -201,6 +211,8 @@ public class TbMsgPushToEdgeNode implements TbNode { case ASSET: case ENTITY_VIEW: case DASHBOARD: + case TENANT: + case CUSTOMER: return true; default: return false; @@ -215,15 +227,20 @@ public class TbMsgPushToEdgeNode implements TbNode { || DataConstants.ALARM.equals(msgType); } - private ListenableFuture getEdgeIdByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) { - ListenableFuture> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); - return Futures.transform(future, relations -> { - if (relations != null && relations.size() > 0) { - return new EdgeId(relations.get(0).getFrom().getId()); - } else { - return null; - } - }, ctx.getDbCallbackExecutor()); + private ListenableFuture> getEdgeIdsByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) { + if (EntityType.TENANT.equals(originatorId.getEntityType())) { + TextPageData edgesByTenantId = ctx.getEdgeService().findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); + } else { + ListenableFuture> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); + return Futures.transform(future, relations -> { + List result = new ArrayList<>(); + if (relations != null && relations.size() > 0) { + result.add(new EdgeId(relations.get(0).getFrom().getId())); + } + return result; + }, ctx.getDbCallbackExecutor()); + } } @Override From 23e0fc7fb2afa9d0732d0245f70aa8f27dc04b27 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 4 Aug 2020 14:26:06 +0300 Subject: [PATCH 067/156] fetch system widgets bundles --- .../WidgetTypeUpdateMsgConstructor.java | 6 +++- .../WidgetsBundleUpdateMsgConstructor.java | 4 +++ .../edge/rpc/init/DefaultSyncEdgeService.java | 29 +++++++++++++++++++ common/edge-api/src/main/proto/edge.proto | 2 ++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java index 52470240d7..784bfd6fdc 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java @@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.dao.util.mapping.JacksonUtil; @@ -44,7 +45,10 @@ public class WidgetTypeUpdateMsgConstructor { if (widgetType.getDescriptor() != null) { builder.setDescriptorJson(JacksonUtil.toString(widgetType.getDescriptor())); } - return builder.build(); + if (widgetType.getTenantId().equals(TenantId.SYS_TENANT_ID)) { + builder.setIsSystem(true); + } + return builder.build(); } public WidgetTypeUpdateMsg constructWidgetTypeDeleteMsg(WidgetTypeId widgetTypeId) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java index 867f42dcfb..4d26e0be59 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java @@ -18,6 +18,7 @@ package org.thingsboard.server.service.edge.rpc.constructor; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -37,6 +38,9 @@ public class WidgetsBundleUpdateMsgConstructor { if (widgetsBundle.getImage() != null) { builder.setImage(ByteString.copyFrom(widgetsBundle.getImage())); } + if (widgetsBundle.getTenantId().equals(TenantId.SYS_TENANT_ID)) { + builder.setIsSystem(true); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 1a2a3d3177..0667da992a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -54,6 +54,8 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.dashboard.DashboardService; @@ -63,6 +65,8 @@ import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; +import org.thingsboard.server.dao.widget.WidgetTypeService; +import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; @@ -109,6 +113,12 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private UserService userService; + @Autowired + private WidgetsBundleService widgetsBundleService; + + @Autowired + private WidgetTypeService widgetTypeService; + @Autowired private DbCallbackExecutorService dbCallbackExecutorService; @@ -121,6 +131,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { syncAssets(edge); syncEntityViews(edge); syncDashboards(edge); + syncWidgetsBundleAndWidgetTypes(edge); } catch (Exception e) { log.error("Exception during sync process", e); } @@ -261,6 +272,24 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } + private void syncWidgetsBundleAndWidgetTypes(Edge edge) { + List widgetsBundlesToPush = new ArrayList<>(); + List widgetTypesToPush = new ArrayList<>(); + widgetsBundlesToPush.addAll(widgetsBundleService.findAllTenantWidgetsBundlesByTenantId(edge.getTenantId())); + widgetsBundlesToPush.addAll(widgetsBundleService.findSystemWidgetsBundles(edge.getTenantId())); + try { + for (WidgetsBundle widgetsBundle: widgetsBundlesToPush) { + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.WIDGETS_BUNDLE, ActionType.ADDED, widgetsBundle.getId(), null); + widgetTypesToPush.addAll(widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(widgetsBundle.getTenantId(), widgetsBundle.getAlias())); + } + for (WidgetType widgetType: widgetTypesToPush) { + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.WIDGET_TYPE, ActionType.ADDED, widgetType.getId(), null); + } + } catch (Exception e) { + log.error("Exception during loading widgets bundle(s) and widget type(s) on sync!", e); + } + } + private void pushUsersToEdge(TextPageData pageData, Edge edge) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index bd6bc81728..fb9ff9dbbf 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -275,6 +275,7 @@ message WidgetsBundleUpdateMsg { string title = 4; string alias = 5; bytes image = 6; + bool isSystem = 7; } message WidgetTypeUpdateMsg { @@ -285,6 +286,7 @@ message WidgetTypeUpdateMsg { string alias = 5; string name = 6; string descriptorJson = 7; + bool isSystem = 8; } message UserCredentialsUpdateMsg { From 7f848b3242fff91b26f3ec8d0129237cd41ddfe5 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Wed, 5 Aug 2020 15:43:02 +0300 Subject: [PATCH 068/156] fixes in controller --- .../org/thingsboard/server/controller/WidgetTypeController.java | 2 +- .../thingsboard/server/controller/WidgetsBundleController.java | 2 +- .../server/service/edge/DefaultEdgeNotificationService.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index 492b512312..62ceec3144 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -72,7 +72,7 @@ public class WidgetTypeController extends BaseController { checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE); WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); - sendNotificationMsgToEdgeService(savedWidgetType.getTenantId(), savedWidgetType.getId(), savedWidgetType.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedWidgetType.getId(), widgetType.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return checkNotNull(savedWidgetType); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 213de07d9f..6adc003284 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -71,7 +71,7 @@ public class WidgetsBundleController extends BaseController { checkEntity(widgetsBundle.getId(), widgetsBundle, Resource.WIDGETS_BUNDLE); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - sendNotificationMsgToEdgeService(savedWidgetsBundle.getTenantId(), savedWidgetsBundle.getId(), savedWidgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedWidgetsBundle.getId(), widgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return checkNotNull(savedWidgetsBundle); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index cc46427b85..c2a9cc223e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -184,7 +184,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); switch (edgeEventActionType) { // TODO: voba - ADDED is not required for CE version ? - // case ADDED: + case ADDED: case UPDATED: case CREDENTIALS_UPDATED: if (edgeEventType.equals(EdgeEventType.WIDGETS_BUNDLE) || edgeEventType.equals(EdgeEventType.WIDGET_TYPE)) { From 05a835f698dc5895218042fda7288489a2d3cb9a Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 6 Aug 2020 12:06:40 +0300 Subject: [PATCH 069/156] short fix in EdgeEventType --- .../org/thingsboard/server/common/data/edge/EdgeEventType.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index 0a38225f0e..12630b0154 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -27,8 +27,7 @@ public enum EdgeEventType { USER, CUSTOMER, RELATION, - TENANT - RELATION, + TENANT, WIDGETS_BUNDLE, WIDGET_TYPE } From 117547ae6b239f728406860c2230bb748678e8b9 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 7 Aug 2020 17:44:06 +0300 Subject: [PATCH 070/156] Fixed relation propagation to edge. Code review improvements --- .../server/controller/AlarmController.java | 3 ++- .../server/controller/AssetController.java | 13 ++++++------- .../server/controller/AuthController.java | 2 +- .../server/controller/BaseController.java | 10 +++++----- .../server/controller/DashboardController.java | 12 +++++------- .../server/controller/DeviceController.java | 12 ++++++------ .../controller/EntityViewController.java | 12 +++++------- .../server/controller/RuleChainController.java | 18 ++++++------------ .../server/controller/UserController.java | 5 +++-- .../controller/WidgetTypeController.java | 3 ++- .../controller/WidgetsBundleController.java | 3 ++- .../service/edge/rpc/EdgeGrpcSession.java | 4 ++++ 12 files changed, 47 insertions(+), 50 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 01c5ea28ae..4aaeb58fd5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -92,7 +92,8 @@ public class AlarmController extends BaseController { getCurrentUser().getCustomerId(), alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(getTenantId(), savedAlarm.getId(), alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedAlarm.getId(), + alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return savedAlarm; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 20fae1e4c6..0877937afa 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -88,13 +88,13 @@ public class AssetController extends BaseController { Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); - sendNotificationMsgToEdgeService(savedAsset.getTenantId(), null, - savedAsset.getId(), EdgeEventType.ASSET, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED); - logEntityAction(savedAsset.getId(), savedAsset, savedAsset.getCustomerId(), asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); + sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(), + asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + return savedAsset; } catch (Exception e) { logEntityAction(emptyId(EntityType.ASSET), asset, @@ -117,7 +117,7 @@ public class AssetController extends BaseController { asset.getCustomerId(), ActionType.DELETED, null, strAssetId); - sendNotificationMsgToEdgeService(getTenantId(), null, assetId, EdgeEventType.ASSET, ActionType.DELETED); + sendNotificationMsgToEdgeService(getTenantId(), assetId, ActionType.DELETED); } catch (Exception e) { logEntityAction(emptyId(EntityType.ASSET), null, @@ -360,7 +360,7 @@ public class AssetController extends BaseController { savedAsset.getCustomerId(), ActionType.ASSIGNED_TO_EDGE, null, strAssetId, strEdgeId, edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), EdgeEventType.ASSET, ActionType.ASSIGNED_TO_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), ActionType.ASSIGNED_TO_EDGE); return savedAsset; } catch (Exception e) { @@ -393,8 +393,7 @@ public class AssetController extends BaseController { asset.getCustomerId(), ActionType.UNASSIGNED_FROM_EDGE, null, strAssetId, edge.getId().toString(), edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), - EdgeEventType.ASSET, ActionType.UNASSIGNED_FROM_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), ActionType.UNASSIGNED_FROM_EDGE); return savedAsset; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index e999320e43..e00ee733b1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -126,7 +126,7 @@ public class AuthController extends BaseController { userCredentials.setPassword(passwordEncoder.encode(newPassword)); userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials); - sendNotificationMsgToEdgeService(getTenantId(), null, userCredentials.getUserId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), userCredentials.getUserId(), ActionType.CREDENTIALS_UPDATED); } catch (Exception e) { throw handleException(e); diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index e435ad6bbb..c2c6771cf1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -730,16 +730,16 @@ public abstract class BaseController { } protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) { + sendNotificationMsgToEdgeService(tenantId, null, entityId, edgeEventAction); + } + + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, ActionType edgeEventAction) { EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); if (edgeEventType != null) { - sendNotificationMsgToEdgeService(tenantId, null, entityId, null, edgeEventType, edgeEventAction); + sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, edgeEventType, edgeEventAction); } } - protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, EdgeEventType edgeEventType, ActionType edgeEventAction) { - sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, edgeEventType, edgeEventAction); - } - private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String entityBody, EdgeEventType edgeEventType, ActionType edgeEventAction) { TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder(); builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index 22674b6ced..0ae455d8f4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -117,8 +117,8 @@ public class DashboardController extends BaseController { null, dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), null, savedDashboard.getId(), - EdgeEventType.DASHBOARD, savedDashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), + dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return savedDashboard; } catch (Exception e) { @@ -143,7 +143,7 @@ public class DashboardController extends BaseController { null, ActionType.DELETED, null, strDashboardId); - sendNotificationMsgToEdgeService(getTenantId(), null, dashboardId, EdgeEventType.DASHBOARD, ActionType.DELETED); + sendNotificationMsgToEdgeService(getTenantId(), dashboardId, ActionType.DELETED); } catch (Exception e) { logEntityAction(emptyId(EntityType.DASHBOARD), @@ -500,8 +500,7 @@ public class DashboardController extends BaseController { null, ActionType.ASSIGNED_TO_EDGE, null, strDashboardId, strEdgeId, edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(), - EdgeEventType.DASHBOARD, ActionType.ASSIGNED_TO_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(), ActionType.ASSIGNED_TO_EDGE); return savedDashboard; } catch (Exception e) { @@ -533,8 +532,7 @@ public class DashboardController extends BaseController { null, ActionType.UNASSIGNED_FROM_EDGE, null, strDashboardId, edge.getId().toString(), edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(), - EdgeEventType.DASHBOARD, ActionType.UNASSIGNED_FROM_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(), ActionType.UNASSIGNED_FROM_EDGE); return savedDashboard; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 6c7391127d..b65d6387c2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -108,8 +108,8 @@ public class DeviceController extends BaseController { tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(), savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null); - sendNotificationMsgToEdgeService(savedDevice.getTenantId(), null, savedDevice.getId(), - EdgeEventType.DEVICE, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(), + device.getId() == null ? ActionType.ADDED : ActionType.UPDATED); logEntityAction(savedDevice.getId(), savedDevice, savedDevice.getCustomerId(), @@ -142,7 +142,7 @@ public class DeviceController extends BaseController { device.getCustomerId(), ActionType.DELETED, null, strDeviceId); - sendNotificationMsgToEdgeService(getTenantId(), null, deviceId, EdgeEventType.DEVICE, ActionType.DELETED); + sendNotificationMsgToEdgeService(getTenantId(), deviceId, ActionType.DELETED); deviceStateService.onDeviceDeleted(device); } catch (Exception e) { @@ -267,7 +267,7 @@ public class DeviceController extends BaseController { tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null); - sendNotificationMsgToEdgeService(getTenantId(), null, device.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), device.getId(), ActionType.CREDENTIALS_UPDATED); logEntityAction(device.getId(), device, device.getCustomerId(), @@ -518,7 +518,7 @@ public class DeviceController extends BaseController { savedDevice.getCustomerId(), ActionType.ASSIGNED_TO_EDGE, null, strDeviceId, strEdgeId, edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), EdgeEventType.DEVICE, ActionType.ASSIGNED_TO_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), ActionType.ASSIGNED_TO_EDGE); return savedDevice; } catch (Exception e) { @@ -549,7 +549,7 @@ public class DeviceController extends BaseController { device.getCustomerId(), ActionType.UNASSIGNED_FROM_EDGE, null, strDeviceId, edge.getId().toString(), edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), EdgeEventType.DEVICE, ActionType.UNASSIGNED_FROM_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), ActionType.UNASSIGNED_FROM_EDGE); return savedDevice; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index f2b95963f5..821dbcbd70 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -118,8 +118,8 @@ public class EntityViewController extends BaseController { logEntityAction(savedEntityView.getId(), savedEntityView, null, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(getTenantId(), null, savedEntityView.getId(), - EdgeEventType.ENTITY_VIEW, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), + entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return savedEntityView; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, @@ -190,7 +190,7 @@ public class EntityViewController extends BaseController { logEntityAction(entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED, null, strEntityViewId); - sendNotificationMsgToEdgeService(getTenantId(), null, entityViewId, EdgeEventType.ENTITY_VIEW, ActionType.DELETED); + sendNotificationMsgToEdgeService(getTenantId(), entityViewId, ActionType.DELETED); } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, @@ -396,8 +396,7 @@ public class EntityViewController extends BaseController { savedEntityView.getCustomerId(), ActionType.ASSIGNED_TO_EDGE, null, strEntityViewId, strEdgeId, edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(), - EdgeEventType.ENTITY_VIEW, ActionType.ASSIGNED_TO_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(), ActionType.ASSIGNED_TO_EDGE); return savedEntityView; } catch (Exception e) { @@ -427,8 +426,7 @@ public class EntityViewController extends BaseController { entityView.getCustomerId(), ActionType.UNASSIGNED_FROM_EDGE, null, strEntityViewId, edge.getId().toString(), edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(), - EdgeEventType.ENTITY_VIEW, ActionType.UNASSIGNED_FROM_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(), ActionType.UNASSIGNED_FROM_EDGE); return savedEntityView; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 463934b4ab..4d2e78bc67 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -145,9 +145,8 @@ public class RuleChainController extends BaseController { created ? ActionType.ADDED : ActionType.UPDATED, null); if (RuleChainType.EDGE.equals(savedRuleChain.getType())) { - sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(), null, - savedRuleChain.getId(), EdgeEventType.RULE_CHAIN, - savedRuleChain.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(), savedRuleChain.getId(), + created ? ActionType.ADDED : ActionType.UPDATED); } return savedRuleChain; @@ -226,9 +225,7 @@ public class RuleChainController extends BaseController { if (RuleChainType.EDGE.equals(ruleChain.getType())) { sendNotificationMsgToEdgeService(ruleChain.getTenantId(), - null, - ruleChain.getId(), EdgeEventType.RULE_CHAIN, - ActionType.UPDATED); + ruleChain.getId(), ActionType.UPDATED); } return savedRuleChainMetaData; @@ -293,8 +290,7 @@ public class RuleChainController extends BaseController { ActionType.DELETED, null, strRuleChainId); if (RuleChainType.EDGE.equals(ruleChain.getType())) { - sendNotificationMsgToEdgeService(ruleChain.getTenantId(), null, - ruleChain.getId(), EdgeEventType.RULE_CHAIN, ActionType.DELETED); + sendNotificationMsgToEdgeService(ruleChain.getTenantId(), ruleChain.getId(), ActionType.DELETED); } } catch (Exception e) { @@ -426,8 +422,7 @@ public class RuleChainController extends BaseController { null, ActionType.ASSIGNED_TO_EDGE, null, strRuleChainId, strEdgeId, edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(), - EdgeEventType.RULE_CHAIN, ActionType.ASSIGNED_TO_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(), ActionType.ASSIGNED_TO_EDGE); return savedRuleChain; } catch (Exception e) { @@ -459,8 +454,7 @@ public class RuleChainController extends BaseController { null, ActionType.UNASSIGNED_FROM_EDGE, null, strRuleChainId, edge.getId().toString(), edge.getName()); - sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(), - EdgeEventType.RULE_CHAIN, ActionType.UNASSIGNED_FROM_EDGE); + sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(), ActionType.UNASSIGNED_FROM_EDGE); return savedRuleChain; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 8dedc59098..25e68d3571 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -162,7 +162,8 @@ public class UserController extends BaseController { savedUser.getCustomerId(), user.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, user.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedUser.getId(), + user.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return savedUser; } catch (Exception e) { @@ -239,7 +240,7 @@ public class UserController extends BaseController { user.getCustomerId(), ActionType.DELETED, null, strUserId); - sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, ActionType.DELETED); + sendNotificationMsgToEdgeService(getTenantId(), user.getId(), ActionType.DELETED); } catch (Exception e) { logEntityAction(emptyId(EntityType.USER), diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index 62ceec3144..45316f77c5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -72,7 +72,8 @@ public class WidgetTypeController extends BaseController { checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE); WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); - sendNotificationMsgToEdgeService(getTenantId(), savedWidgetType.getId(), widgetType.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedWidgetType.getId(), + widgetType.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return checkNotNull(savedWidgetType); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 6adc003284..d6442a3dc2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -71,7 +71,8 @@ public class WidgetsBundleController extends BaseController { checkEntity(widgetsBundle.getId(), widgetsBundle, Resource.WIDGETS_BUNDLE); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - sendNotificationMsgToEdgeService(getTenantId(), savedWidgetsBundle.getId(), widgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + sendNotificationMsgToEdgeService(getTenantId(), savedWidgetsBundle.getId(), + widgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED); return checkNotNull(savedWidgetsBundle); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 9290316366..2586d4cb7d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -234,6 +234,8 @@ public final class EdgeGrpcSession implements Closeable { case ALARM_ACK: case ALARM_CLEAR: case CREDENTIALS_UPDATED: + case RELATION_ADD_OR_UPDATE: + case RELATION_DELETED: processEntityMessage(edgeEvent, edgeEventAction); break; case ATTRIBUTES_UPDATED: @@ -687,9 +689,11 @@ public final class EdgeGrpcSession implements Closeable { return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; case ADDED: case ASSIGNED_TO_EDGE: + case RELATION_ADD_OR_UPDATE: return ENTITY_CREATED_RPC_MESSAGE; case DELETED: case UNASSIGNED_FROM_EDGE: + case RELATION_DELETED: return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; case ALARM_ACK: return UpdateMsgType.ALARM_ACK_RPC_MESSAGE; From 908bb8be7cc759d48aa43b3521d847f0c3c928db Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 10 Aug 2020 18:44:46 +0300 Subject: [PATCH 071/156] Added .run folder to ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index da8569baa3..c0628fd2e3 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ pom.xml.versionsBackup **/.env .instance_id rebuild-docker.sh +.run/ \ No newline at end of file From 224c0d87e44984eae1962b55749c093fe162ba61 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 11 Aug 2020 15:41:09 +0300 Subject: [PATCH 072/156] fixed incorrect ts in timeseries update msgs from cloud --- .../constructor/EntityDataMsgConstructor.java | 4 ++- .../transport/adaptor/JsonConverter.java | 8 +++-- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 29 ++++++++++--------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index 07f7ffb02a..ff342faaa0 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -41,7 +41,9 @@ public class EntityDataMsgConstructor { switch (actionType) { case TIMESERIES_UPDATED: try { - builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(entityData)); + JsonObject data = entityData.getAsJsonObject(); + long ts = data.getAsJsonPrimitive("ts").getAsLong(); + builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data.getAsJsonObject("data"), ts)); } catch (Exception e) { log.warn("Can't convert to telemetry proto, entityData [{}]", entityData, e); } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java index 8375b84ffa..8ddfe0f580 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java @@ -68,12 +68,16 @@ public class JsonConverter { private static int maxStringValueLength = 0; - public static PostTelemetryMsg convertToTelemetryProto(JsonElement jsonElement) throws JsonSyntaxException { + public static PostTelemetryMsg convertToTelemetryProto(JsonElement jsonElement, long ts) throws JsonSyntaxException { PostTelemetryMsg.Builder builder = PostTelemetryMsg.newBuilder(); - convertToTelemetry(jsonElement, System.currentTimeMillis(), null, builder); + convertToTelemetry(jsonElement, ts, null, builder); return builder.build(); } + public static PostTelemetryMsg convertToTelemetryProto(JsonElement jsonElement) throws JsonSyntaxException { + return convertToTelemetryProto(jsonElement, System.currentTimeMillis()); + } + private static void convertToTelemetry(JsonElement jsonElement, long systemTs, Map> result, PostTelemetryMsg.Builder builder) { if (jsonElement.isJsonObject()) { parseObject(systemTs, result, builder, jsonElement.getAsJsonObject()); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 013ade7480..378fc785a3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.edge; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.FutureCallback; @@ -150,13 +151,7 @@ public class TbMsgPushToEdgeNode implements TbNode { return null; } ActionType actionType = getActionTypeByMsgType(msg.getType()); - JsonNode entityBody = null; - JsonNode data = json.readTree(msg.getData()); - if (actionType.equals(ActionType.ATTRIBUTES_UPDATED) || actionType.equals(ActionType.ATTRIBUTES_DELETED)) { - entityBody = getAttributeEntityBody(actionType, data, msg.getMetaData().getData()); - } else { - entityBody = data; - } + JsonNode entityBody = getEntityBody(actionType, msg.getData(), msg.getMetaData().getData()); return buildEdgeEvent(ctx.getTenantId(), actionType, msg.getOriginator().getId(), edgeEventTypeByEntityType, entityBody); } } @@ -171,19 +166,25 @@ public class TbMsgPushToEdgeNode implements TbNode { return edgeEvent; } - private JsonNode getAttributeEntityBody(ActionType actionType, JsonNode data, Map metadata) throws JsonProcessingException { - Map entityData = new HashMap<>(); + private JsonNode getEntityBody(ActionType actionType, String data, Map metadata) throws JsonProcessingException { + Map entityBody = new HashMap<>(); + JsonNode dataJson = json.readTree(data); switch (actionType) { case ATTRIBUTES_UPDATED: - entityData.put("kv", data); + entityBody.put("kv", dataJson); + entityBody.put("scope", metadata.get("scope")); break; case ATTRIBUTES_DELETED: - List keys = json.treeToValue(data.get("attributes"), List.class); - entityData.put("keys", keys); + List keys = json.treeToValue(dataJson.get("attributes"), List.class); + entityBody.put("keys", keys); + entityBody.put("scope", metadata.get("scope")); + break; + case TIMESERIES_UPDATED: + entityBody.put("data", dataJson); + entityBody.put("ts", metadata.get("ts")); break; } - entityData.put("scope", metadata.get("scope")); - return json.valueToTree(entityData); + return json.valueToTree(entityBody); } private UUID getUUIDFromMsgData(TbMsg msg) throws JsonProcessingException { From 9f5a9d02f10aee13803d14fe799971a1d21dbab4 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 11 Aug 2020 15:44:13 +0300 Subject: [PATCH 073/156] deleted unused imports --- .../org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 378fc785a3..be265ebc19 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -16,7 +16,6 @@ package org.thingsboard.rule.engine.edge; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.FutureCallback; From d0db49a2cb826a7b31760ab2809b7450bae6988d Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 12 Aug 2020 14:05:08 +0300 Subject: [PATCH 074/156] Fixed assign rule chain. Added sync of related rule chains --- .../edge/DefaultEdgeNotificationService.java | 45 +++++++++++++++++++ .../server/common/data/EdgeUtils.java | 2 + pom.xml | 1 + 3 files changed, 48 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 0304205008..b4be8a8e82 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -18,9 +18,11 @@ package org.thingsboard.server.service.edge; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; @@ -46,12 +48,15 @@ import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.relation.RelationService; +import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -86,6 +91,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @Autowired private UserService userService; + @Autowired + private RuleChainService ruleChainService; + @Autowired private RelationService relationService; @@ -223,6 +231,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case UNASSIGNED_FROM_EDGE: EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + if (edgeEventType.equals(EdgeEventType.RULE_CHAIN)) { + updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId); + } break; case RELATIONS_DELETED: // TODO: voba - add support for relations deleted @@ -230,6 +241,40 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } } + private void updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) { + ListenableFuture> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, new TimePageLink(Integer.MAX_VALUE)); + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable TimePageData pageData) { + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { + for (RuleChain ruleChain : pageData.getData()) { + if (!ruleChain.getId().equals(processingRuleChainId)) { + List connectionInfos = + ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections(); + if (connectionInfos != null && !connectionInfos.isEmpty()) { + for (RuleChainConnectionInfo connectionInfo : connectionInfos) { + if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) { + saveEdgeEvent(tenantId, + edgeId, + EdgeEventType.RULE_CHAIN_METADATA, + ActionType.UPDATED, + ruleChain.getId(), + null); + } + } + } + } + } + } + } + + @Override + public void onFailure(Throwable t) { + log.error("Exception during updating dependent rule chains on sync!", t); + } + }, dbCallbackExecutorService); + } + private void processAlarm(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); ListenableFuture alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java index 1badf5e158..2394ea0047 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java @@ -34,6 +34,8 @@ public final class EdgeUtils { return EdgeEventType.DASHBOARD; case USER: return EdgeEventType.USER; + case RULE_CHAIN: + return EdgeEventType.RULE_CHAIN; case ALARM: return EdgeEventType.ALARM; case TENANT: diff --git a/pom.xml b/pom.xml index b86c3096b0..7b9e8fbf10 100755 --- a/pom.xml +++ b/pom.xml @@ -725,6 +725,7 @@ **/*.proto.js docker/haproxy/** docker/tb-node/** + .run/** JAVADOC_STYLE From bf21ff3c09ca6a902c2a16126036b0270d1364c4 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 12 Aug 2020 16:31:45 +0300 Subject: [PATCH 075/156] Added TTL for edge events --- .../data/upgrade/2.6.0/schema_update_ttl.sql | 32 +++++++++++ .../ttl/edge/EdgeEventsCleanUpService.java | 56 +++++++++++++++++++ .../src/main/resources/thingsboard.yml | 4 ++ .../main/resources/sql/schema-entities.sql | 17 ++++++ 4 files changed, 109 insertions(+) create mode 100644 application/src/main/data/upgrade/2.6.0/schema_update_ttl.sql create mode 100644 application/src/main/java/org/thingsboard/server/service/ttl/edge/EdgeEventsCleanUpService.java diff --git a/application/src/main/data/upgrade/2.6.0/schema_update_ttl.sql b/application/src/main/data/upgrade/2.6.0/schema_update_ttl.sql new file mode 100644 index 0000000000..7c1075059f --- /dev/null +++ b/application/src/main/data/upgrade/2.6.0/schema_update_ttl.sql @@ -0,0 +1,32 @@ +-- +-- Copyright © 2016-2020 The Thingsboard Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +CREATE OR REPLACE PROCEDURE cleanup_edge_events_by_ttl(IN ttl bigint, INOUT deleted bigint) + LANGUAGE plpgsql AS +$$ +DECLARE + ttl_ts bigint; + ttl_deleted_count bigint DEFAULT 0; +BEGIN + IF ttl > 0 THEN + ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint; + EXECUTE format( + 'WITH deleted AS (DELETE FROM edge_event WHERE ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', ttl_ts) into ttl_deleted_count; + END IF; + RAISE NOTICE 'Edge events removed by ttl: %', ttl_deleted_count; + deleted := ttl_deleted_count; +END +$$; diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/edge/EdgeEventsCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/edge/EdgeEventsCleanUpService.java new file mode 100644 index 0000000000..308feb7304 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/ttl/edge/EdgeEventsCleanUpService.java @@ -0,0 +1,56 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.ttl.edge; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.thingsboard.server.dao.util.PsqlDao; +import org.thingsboard.server.service.ttl.AbstractCleanUpService; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +@PsqlDao +@Slf4j +@Service +public class EdgeEventsCleanUpService extends AbstractCleanUpService { + + @Value("${sql.ttl.edge_events.edge_events_ttl}") + private long ttl; + + @Value("${sql.ttl.edge_events.enabled}") + private boolean ttlTaskExecutionEnabled; + + @Scheduled(initialDelayString = "${sql.ttl.edge_events.execution_interval_ms}", fixedDelayString = "${sql.ttl.edge_events.execution_interval_ms}") + public void cleanUp() { + if (ttlTaskExecutionEnabled) { + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { + doCleanUp(conn); + } catch (SQLException e) { + log.error("SQLException occurred during TTL task execution ", e); + } + } + } + + @Override + protected void doCleanUp(Connection connection) { + long totalEdgeEventsRemoved = executeQuery(connection, "call cleanup_edge_events_by_ttl(" + ttl + ", 0);"); + log.info("Total edge events removed by TTL: [{}]", totalEdgeEventsRemoved); + } +} \ No newline at end of file diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 3152d9939e..08817dd9e3 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -282,6 +282,10 @@ sql: execution_interval_ms: "${SQL_TTL_EVENTS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day events_ttl: "${SQL_TTL_EVENTS_EVENTS_TTL:0}" # Number of seconds debug_events_ttl: "${SQL_TTL_EVENTS_DEBUG_EVENTS_TTL:604800}" # Number of seconds. The current value corresponds to one week + edge_events: + enabled: "${SQL_TTL_EDGE_EVENTS_ENABLED:true}" + execution_interval_ms: "${SQL_TTL_EDGE_EVENTS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day + edge_events_ttl: "${SQL_TTL_EDGE_EVENTS_TTL:2628000}" # Number of seconds. The current value corresponds to one month # Actor system parameters actors: diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 606dd0c8a7..04346b4ed3 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -307,3 +307,20 @@ BEGIN deleted := ttl_deleted_count + debug_ttl_deleted_count; END $$; + +CREATE OR REPLACE PROCEDURE cleanup_edge_events_by_ttl(IN ttl bigint, INOUT deleted bigint) + LANGUAGE plpgsql AS +$$ +DECLARE + ttl_ts bigint; + ttl_deleted_count bigint DEFAULT 0; +BEGIN + IF ttl > 0 THEN + ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint; + EXECUTE format( + 'WITH deleted AS (DELETE FROM edge_event WHERE ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', ttl_ts) into ttl_deleted_count; + END IF; + RAISE NOTICE 'Edge events removed by ttl: %', ttl_deleted_count; + deleted := ttl_deleted_count; +END +$$; From cc645a938e9a44f582a82f699967d1deed695d66 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Thu, 13 Aug 2020 16:53:10 +0300 Subject: [PATCH 076/156] Code cleaning from PE comparison of master vs. develop/2.5.3 --- ui/src/app/api/dashboard.service.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ui/src/app/api/dashboard.service.js b/ui/src/app/api/dashboard.service.js index 7280c9d06d..9d59e24ebc 100644 --- a/ui/src/app/api/dashboard.service.js +++ b/ui/src/app/api/dashboard.service.js @@ -284,13 +284,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { } dashboard.assignedCustomersText = assignedCustomersTitles.join(', '); } - dashboard.assignedEdgesIds = []; - if (dashboard.assignedEdges && dashboard.assignedEdges.length) { - for (var j = 0; j < dashboard.assignedEdges.length; j++) { - var assignedEdge = dashboard.assignedEdges[j]; - dashboard.assignedEdgesIds.push(assignedEdge.edgeId.id); - } - } return dashboard; } @@ -298,7 +291,6 @@ function DashboardService($rootScope, $http, $q, $location, $filter) { delete dashboard.publicCustomerId; delete dashboard.assignedCustomersText; delete dashboard.assignedCustomersIds; - delete dashboard.assignedEdgesIds; return dashboard; } From f29d15d8b7dab6061d7c306defca36827dd41cee Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 14 Aug 2020 12:25:57 +0300 Subject: [PATCH 077/156] Add/delete users to edge on assign/unassign to/from customer --- .../server/controller/BaseController.java | 8 +++ .../server/controller/EdgeController.java | 6 ++ .../edge/DefaultEdgeNotificationService.java | 43 ++++++++++- .../service/edge/EdgeContextComponent.java | 5 ++ .../service/edge/rpc/EdgeGrpcSession.java | 35 +++++++++ .../CustomerUpdateMsgConstructor.java | 72 +++++++++++++++++++ .../constructor/EntityDataMsgConstructor.java | 6 +- .../constructor/UserUpdateMsgConstructor.java | 4 ++ .../edge/rpc/init/DefaultSyncEdgeService.java | 1 + common/edge-api/src/main/proto/edge.proto | 12 ++-- 10 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index c2c6771cf1..390b2187fa 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -718,6 +718,14 @@ public abstract class BaseController { return result; } + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, CustomerId customerId, ActionType edgeEventAction) { + try { + sendNotificationMsgToEdgeService(tenantId, edgeId, null, json.writeValueAsString(customerId), EdgeEventType.EDGE, edgeEventAction); + } catch (Exception e) { + log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); + } + } + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) { try { if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 3c17176b88..19b82b3b85 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -178,6 +178,9 @@ public class EdgeController extends BaseController { savedEdge.getCustomerId(), ActionType.ASSIGNED_TO_CUSTOMER, null, strEdgeId, strCustomerId, customer.getName()); + sendNotificationMsgToEdgeService(savedEdge.getTenantId(), savedEdge.getId(), + customerId, ActionType.ASSIGNED_TO_CUSTOMER); + return savedEdge; } catch (Exception e) { logEntityAction(emptyId(EntityType.EDGE), null, @@ -206,6 +209,9 @@ public class EdgeController extends BaseController { edge.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEdgeId, customer.getId().toString(), customer.getName()); + sendNotificationMsgToEdgeService(savedEdge.getTenantId(), savedEdge.getId(), + edge.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER); + return savedEdge; } catch (Exception e) { logEntityAction(emptyId(EntityType.EDGE), null, diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index b4be8a8e82..279ec96064 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -157,8 +157,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { TenantId tenantId = new TenantId(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB())); EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); switch (edgeEventType) { - // TODO: voba - handle edge updates - // case EDGE: + case EDGE: + processEdge(tenantId, edgeNotificationMsg); + break; case USER: case ASSET: case DEVICE: @@ -186,6 +187,44 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } } + private void processEdge(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { + // TODO: voba - handle edge updates + try { + ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); + EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); + switch (edgeEventActionType) { + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: + CustomerId customerId = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); + ListenableFuture edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); + Futures.addCallback(edgeFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable Edge edge) { + if (edge != null && customerId != null && !EntityId.NULL_UUID.equals(customerId.getId())) { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER.equals(edgeEventActionType) ? ActionType.ADDED : ActionType.DELETED; + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, actionType, customerId, null); + TextPageData pageData = userService.findCustomerUsers(tenantId, customerId, new TextPageLink(Integer.MAX_VALUE)); + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { + log.trace("[{}] [{}] user(s) are going to be {} to edge.", edge.getId(), pageData.getData().size(), actionType.name()); + for (User user : pageData.getData()) { + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, actionType, user.getId(), null); + } + } + } + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't find edge by id [{}]", edgeNotificationMsg, t); + } + }, dbCallbackExecutorService); + break; + } + } catch (Exception e) { + log.error("Exception during processing edge event", e); + } + } + private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index fcbc8ff756..2b756cefc4 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -41,6 +41,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.CustomerUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; @@ -167,6 +168,10 @@ public class EdgeContextComponent { @Autowired private DashboardUpdateMsgConstructor dashboardUpdateMsgConstructor; + @Lazy + @Autowired + private CustomerUpdateMsgConstructor customerUpdateMsgConstructor; + @Lazy @Autowired private UserUpdateMsgConstructor userUpdateMsgConstructor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 2586d4cb7d..8dcecfb36d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -30,6 +30,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; +import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -82,6 +83,7 @@ import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectResponseCode; import org.thingsboard.server.gen.edge.ConnectResponseMsg; +import org.thingsboard.server.gen.edge.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; @@ -348,6 +350,9 @@ public final class EdgeGrpcSession implements Closeable { case DASHBOARD: processDashboard(edgeEvent, msgType, edgeEventAction); break; + case CUSTOMER: + processCustomer(edgeEvent, msgType, edgeEventAction); + break; case RULE_CHAIN: processRuleChain(edgeEvent, msgType, edgeEventAction); break; @@ -510,6 +515,36 @@ public final class EdgeGrpcSession implements Closeable { } } + private void processCustomer(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + CustomerId customerId = new CustomerId(edgeEvent.getEntityId()); + EntityUpdateMsg entityUpdateMsg = null; + switch (edgeEventAction) { + case ADDED: + case UPDATED: + Customer customer = ctx.getCustomerService().findCustomerById(edgeEvent.getTenantId(), customerId); + if (customer != null) { + CustomerUpdateMsg customerUpdateMsg = + ctx.getCustomerUpdateMsgConstructor().constructCustomerUpdatedMsg(msgType, customer); + entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setCustomerUpdateMsg(customerUpdateMsg) + .build(); + } + break; + case DELETED: + CustomerUpdateMsg customerUpdateMsg = + ctx.getCustomerUpdateMsgConstructor().constructCustomerDeleteMsg(customerId); + entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setCustomerUpdateMsg(customerUpdateMsg) + .build(); + break; + } + if (entityUpdateMsg != null) { + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + } + private void processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); EntityUpdateMsg entityUpdateMsg = null; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java new file mode 100644 index 0000000000..a5f54fb443 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java @@ -0,0 +1,72 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.constructor; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; +import org.thingsboard.server.gen.edge.CustomerUpdateMsg; +import org.thingsboard.server.gen.edge.UpdateMsgType; + +@Component +@Slf4j +public class CustomerUpdateMsgConstructor { + + public CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer) { + CustomerUpdateMsg.Builder builder = CustomerUpdateMsg.newBuilder() + .setMsgType(msgType) + .setIdMSB(customer.getId().getId().getMostSignificantBits()) + .setIdLSB(customer.getId().getId().getLeastSignificantBits()) + .setTitle(customer.getTitle()); + if (customer.getCountry() != null) { + builder.setCountry(customer.getCountry()); + } + if (customer.getState() != null) { + builder.setState(customer.getState()); + } + if (customer.getCity() != null) { + builder.setCity(customer.getCity()); + } + if (customer.getAddress() != null) { + builder.setAddress(customer.getAddress()); + } + if (customer.getAddress2() != null) { + builder.setAddress2(customer.getAddress2()); + } + if (customer.getZip() != null) { + builder.setZip(customer.getZip()); + } + if (customer.getPhone() != null) { + builder.setPhone(customer.getPhone()); + } + if (customer.getEmail() != null) { + builder.setEmail(customer.getEmail()); + } + if (customer.getAdditionalInfo() != null) { + builder.setAdditionalInfo(JacksonUtil.toString(customer.getAdditionalInfo())); + } + return builder.build(); + } + + public CustomerUpdateMsg constructCustomerDeleteMsg(CustomerId customerId) { + return CustomerUpdateMsg.newBuilder() + .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE) + .setIdMSB(customerId.getId().getMostSignificantBits()) + .setIdLSB(customerId.getId().getLeastSignificantBits()).build(); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index ff342faaa0..c1d211af58 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -18,6 +18,7 @@ package org.thingsboard.server.service.edge.rpc.constructor; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonNull; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -42,7 +43,10 @@ public class EntityDataMsgConstructor { case TIMESERIES_UPDATED: try { JsonObject data = entityData.getAsJsonObject(); - long ts = data.getAsJsonPrimitive("ts").getAsLong(); + long ts = System.currentTimeMillis(); + if (data.get("ts") != null && !data.get("ts").isJsonNull()) { + ts = data.getAsJsonObject("ts").getAsLong(); + } builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data.getAsJsonObject("data"), ts)); } catch (Exception e) { log.warn("Can't convert to telemetry proto, entityData [{}]", entityData, e); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java index af42448e19..b50e0c2b5e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java @@ -36,6 +36,10 @@ public class UserUpdateMsgConstructor { .setIdLSB(user.getId().getId().getLeastSignificantBits()) .setEmail(user.getEmail()) .setAuthority(user.getAuthority().name()); + if (user.getCustomerId() != null) { + builder.setCustomerIdMSB(user.getCustomerId().getId().getMostSignificantBits()); + builder.setCustomerIdLSB(user.getCustomerId().getId().getLeastSignificantBits()); + } if (user.getFirstName() != null) { builder.setFirstName(user.getFirstName()); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 0667da992a..bf20fc2051 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -264,6 +264,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { TextPageData pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE)); pushUsersToEdge(pageData, edge); if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, ActionType.ADDED, edge.getCustomerId(), null); pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE)); pushUsersToEdge(pageData, edge); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index fb9ff9dbbf..872af2a529 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -261,11 +261,13 @@ message UserUpdateMsg { UpdateMsgType msgType = 1; int64 idMSB = 2; int64 idLSB = 3; - string email = 4; - string authority = 5; - string firstName = 6; - string lastName = 7; - string additionalInfo = 8; + int64 customerIdMSB = 4; + int64 customerIdLSB = 5; + string email = 6; + string authority = 7; + string firstName = 8; + string lastName = 9; + string additionalInfo = 10; } message WidgetsBundleUpdateMsg { From 79f77ebbbac8ba80b8816da2f03a9978962b2436 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 14 Aug 2020 13:52:40 +0300 Subject: [PATCH 078/156] fetch admin settings --- .../service/edge/EdgeContextComponent.java | 5 ++++ .../service/edge/rpc/EdgeGrpcSession.java | 14 ++++++++++ .../AdminSettingsUpdateMsgConstructor.java | 26 +++++++++++++++++++ .../edge/rpc/init/DefaultSyncEdgeService.java | 15 +++++++++++ .../common/data/edge/EdgeEventType.java | 3 ++- common/edge-api/src/main/proto/edge.proto | 8 ++++++ 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index 2b756cefc4..f5a97e2326 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -39,6 +39,7 @@ import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; +import org.thingsboard.server.service.edge.rpc.constructor.AdminSettingsUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.CustomerUpdateMsgConstructor; @@ -188,6 +189,10 @@ public class EdgeContextComponent { @Autowired private WidgetTypeUpdateMsgConstructor widgetTypeUpdateMsgConstructor; + @Lazy + @Autowired + private AdminSettingsUpdateMsgConstructor adminSettingsUpdateMsgConstructor; + @Lazy @Autowired private EntityDataMsgConstructor entityDataMsgConstructor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 8dcecfb36d..85e29f6802 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -30,6 +30,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; +import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; @@ -374,6 +375,9 @@ public final class EdgeGrpcSession implements Closeable { case WIDGET_TYPE: processWidgetType(edgeEvent, msgType, edgeEventAction); break; + case ADMIN_SETTINGS: + processAdminSettings(edgeEvent); + break; } } @@ -717,6 +721,16 @@ public final class EdgeGrpcSession implements Closeable { } } + private void processAdminSettings(EdgeEvent edgeEvent) { + AdminSettings adminSettings = mapper.convertValue(edgeEvent.getEntityBody(), AdminSettings.class); + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() + .setAdminSettingsUpdateMsg(ctx.getAdminSettingsUpdateMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings)) + .build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEntityUpdateMsg(entityUpdateMsg) + .build()); + } + private UpdateMsgType getResponseMsgType(ActionType actionType) { switch (actionType) { case UPDATED: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java new file mode 100644 index 0000000000..97acc749f8 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java @@ -0,0 +1,26 @@ +package org.thingsboard.server.service.edge.rpc.constructor; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.AdminSettings; +import org.thingsboard.server.common.data.id.AdminSettingsId; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; +import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; + +@Slf4j +@Component +public class AdminSettingsUpdateMsgConstructor { + + public AdminSettingsUpdateMsg constructAdminSettingsUpdateMsg(AdminSettings adminSettings) { + AdminSettingsUpdateMsg.Builder builder = AdminSettingsUpdateMsg.newBuilder() + .setKey(adminSettings.getKey()) + .setJsonValue(JacksonUtil.toString(adminSettings.getJsonValue())); + AdminSettingsId adminSettingsId = adminSettings.getId(); + if (adminSettingsId != null) { + builder.setIdMSB(adminSettingsId.getId().getMostSignificantBits()); + builder.setIdLSB(adminSettingsId.getId().getLeastSignificantBits()); + } + return builder.build(); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index bf20fc2051..9ee5879996 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -64,6 +65,7 @@ import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; +import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; @@ -119,6 +121,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Autowired private WidgetTypeService widgetTypeService; + @Autowired + private AdminSettingsService adminSettingsService; + @Autowired private DbCallbackExecutorService dbCallbackExecutorService; @@ -132,6 +137,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { syncEntityViews(edge); syncDashboards(edge); syncWidgetsBundleAndWidgetTypes(edge); + syncAdminSettings(edge); } catch (Exception e) { log.error("Exception during sync process", e); } @@ -291,6 +297,15 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } } + private void syncAdminSettings(Edge edge) { + try { + AdminSettings mailSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(mailSettings)); + } catch (Exception e) { + log.error("Can't load admin settings", e); + } + } + private void pushUsersToEdge(TextPageData pageData, Edge edge) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java index 12630b0154..cc295546a8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java @@ -29,5 +29,6 @@ public enum EdgeEventType { RELATION, TENANT, WIDGETS_BUNDLE, - WIDGET_TYPE + WIDGET_TYPE, + ADMIN_SETTINGS } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 872af2a529..8be4be9956 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -61,6 +61,7 @@ message EntityUpdateMsg { RelationUpdateMsg relationUpdateMsg = 12; WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 13; WidgetTypeUpdateMsg widgetTypeUpdateMsg = 14; + AdminSettingsUpdateMsg adminSettingsUpdateMsg = 15; } enum RequestMsgType { @@ -291,6 +292,13 @@ message WidgetTypeUpdateMsg { bool isSystem = 8; } +message AdminSettingsUpdateMsg { + int64 idMSB = 1; + int64 idLSB = 2; + string key = 3; + string jsonValue = 4; +} + message UserCredentialsUpdateMsg { int64 userIdMSB = 1; int64 userIdLSB = 2; From 444681655e7c0be3d0cbaf28b7121e210544a81a Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 14 Aug 2020 15:43:46 +0300 Subject: [PATCH 079/156] existing license --- .../AdminSettingsUpdateMsgConstructor.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java index 97acc749f8..1b0d188198 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; From 279718017643cb99b9bef28a914501f7b109185d Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 14 Aug 2020 16:42:43 +0300 Subject: [PATCH 080/156] Added isFullAccess check --- .../service/edge/rpc/EdgeGrpcSession.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 8dcecfb36d..8434c41190 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -17,7 +17,9 @@ package org.thingsboard.server.service.edge.rpc; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -66,6 +68,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; +import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.UserCredentials; @@ -602,6 +605,9 @@ public final class EdgeGrpcSession implements Closeable { case ASSIGNED_TO_EDGE: User user = ctx.getUserService().findUserById(edgeEvent.getTenantId(), userId); if (user != null) { + boolean fullAccess = Authority.TENANT_ADMIN.equals(user.getAuthority()); + setFullAccess(user, fullAccess); + entityUpdateMsg = EntityUpdateMsg.newBuilder() .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user)) .build(); @@ -615,7 +621,7 @@ public final class EdgeGrpcSession implements Closeable { break; case CREDENTIALS_UPDATED: UserCredentials userCredentialsByUserId = ctx.getUserService().findUserCredentialsByUserId(edge.getTenantId(), userId); - if (userCredentialsByUserId != null) { + if (userCredentialsByUserId != null && userCredentialsByUserId.isEnabled()) { UserCredentialsUpdateMsg userCredentialsUpdateMsg = ctx.getUserUpdateMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); entityUpdateMsg = EntityUpdateMsg.newBuilder() @@ -630,6 +636,15 @@ public final class EdgeGrpcSession implements Closeable { } } + private void setFullAccess(User user, boolean isFullAccess) { + JsonNode additionalInfo = user.getAdditionalInfo(); + if (additionalInfo == null || additionalInfo instanceof NullNode) { + additionalInfo = mapper.createObjectNode(); + } + ((ObjectNode) additionalInfo).put("isFullAccess", isFullAccess); + user.setAdditionalInfo(additionalInfo); + } + private void processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() From 2b2a513cd49227188f44443b395c0c9bad83f0fd Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 18 Aug 2020 15:46:49 +0300 Subject: [PATCH 081/156] propagate relations delete/update --- .../service/edge/rpc/EdgeGrpcSession.java | 63 +++++++++++++++++++ common/edge-api/src/main/proto/edge.proto | 11 ++-- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 519f4529f1..9b3c565092 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -47,6 +47,8 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; @@ -54,6 +56,7 @@ import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; @@ -98,6 +101,7 @@ import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.EntityUpdateMsg; import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; +import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.RequestMsgType; import org.thingsboard.server.gen.edge.ResponseMsg; @@ -813,6 +817,11 @@ public final class EdgeGrpcSession implements Closeable { onAlarmUpdate(alarmUpdateMsg); } } + if (uplinkMsg.getRelationUpdateMsgList() != null && !uplinkMsg.getRelationUpdateMsgList().isEmpty()) { + for (RelationUpdateMsg relationUpdateMsg: uplinkMsg.getRelationUpdateMsgList()) { + onRelationUpdate(relationUpdateMsg); + } + } if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { ctx.getSyncEdgeService().processRuleChainMetadataRequestMsg(edge, ruleChainMetadataRequestMsg); @@ -1164,6 +1173,60 @@ public final class EdgeGrpcSession implements Closeable { } } + private void onRelationUpdate(RelationUpdateMsg relationUpdateMsg) { + log.info("onRelationUpdate {}", relationUpdateMsg); + try { + EntityRelation entityRelation = new EntityRelation(); + + UUID fromUUID = new UUID(relationUpdateMsg.getFromIdMSB(), relationUpdateMsg.getFromIdLSB()); + EntityId fromId = EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(relationUpdateMsg.getFromEntityType()), fromUUID); + entityRelation.setFrom(fromId); + + UUID toUUID = new UUID(relationUpdateMsg.getToIdMSB(), relationUpdateMsg.getToIdLSB()); + EntityId toId = EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(relationUpdateMsg.getToEntityType()), toUUID); + entityRelation.setTo(toId); + + entityRelation.setType(relationUpdateMsg.getType()); + entityRelation.setTypeGroup(RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup())); + entityRelation.setAdditionalInfo(mapper.readTree(relationUpdateMsg.getAdditionalInfo())); + switch (relationUpdateMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + if (isEntityExists(edge.getTenantId(), entityRelation.getTo()) + && isEntityExists(edge.getTenantId(), entityRelation.getFrom())) { + ctx.getRelationService().saveRelationAsync(edge.getTenantId(), entityRelation); + } + break; + case ENTITY_DELETED_RPC_MESSAGE: + ctx.getRelationService().deleteRelation(edge.getTenantId(), entityRelation); + break; + case UNRECOGNIZED: + log.error("Unsupported msg type"); + } + } catch (Exception e) { + log.error("Error during relation update msg", e); + } + } + + private boolean isEntityExists(TenantId tenantId, EntityId entityId) throws ThingsboardException { + switch (entityId.getEntityType()) { + case DEVICE: + return ctx.getDeviceService().findDeviceById(tenantId, new DeviceId(entityId.getId())) != null; + case ASSET: + return ctx.getAssetService().findAssetById(tenantId, new AssetId(entityId.getId())) != null; + case ENTITY_VIEW: + return ctx.getEntityViewService().findEntityViewById(tenantId, new EntityViewId(entityId.getId())) != null; + case CUSTOMER: + return ctx.getCustomerService().findCustomerById(tenantId, new CustomerId(entityId.getId())) != null; + case USER: + return ctx.getUserService().findUserById(tenantId, new UserId(entityId.getId())) != null; + case DASHBOARD: + return ctx.getDashboardService().findDashboardById(tenantId, new DashboardId(entityId.getId())) != null; + default: + throw new ThingsboardException("Unsupported entity type " + entityId.getEntityType(), ThingsboardErrorCode.INVALID_ARGUMENTS); + } + } + private ConnectResponseMsg processConnect(ConnectRequestMsg request) { Optional optional = ctx.getEdgeService().findEdgeByRoutingKey(TenantId.SYS_TENANT_ID, request.getEdgeRoutingKey()); if (optional.isPresent()) { diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 8be4be9956..cce4bef73a 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -348,11 +348,12 @@ message UplinkMsg { repeated DeviceUpdateMsg deviceUpdateMsg = 3; repeated DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 4; repeated AlarmUpdateMsg alarmUpdateMsg = 5; - repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 6; - repeated AttributesRequestMsg attributesRequestMsg = 7; - repeated RelationRequestMsg relationRequestMsg = 8; - repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 9; - repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 10; + repeated RelationUpdateMsg relationUpdateMsg = 6; + repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 7; + repeated AttributesRequestMsg attributesRequestMsg = 8; + repeated RelationRequestMsg relationRequestMsg = 9; + repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 10; + repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 11; } message UplinkResponseMsg { From 3e42f00cf789797737e21d9504d8fc14fd91e631 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 18 Aug 2020 17:52:11 +0300 Subject: [PATCH 082/156] Ack cloud messages --- .../service/edge/rpc/EdgeGrpcSession.java | 674 +++++++++--------- .../edge/rpc/init/DefaultSyncEdgeService.java | 142 ++-- .../edge/rpc/init/SyncEdgeService.java | 11 +- .../thingsboard/edge/rpc/EdgeGrpcClient.java | 38 +- .../thingsboard/edge/rpc/EdgeRpcClient.java | 7 +- common/edge-api/src/main/proto/edge.proto | 43 +- 6 files changed, 474 insertions(+), 441 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 519f4529f1..26849faeec 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -81,6 +82,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; +import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.AttributesRequestMsg; @@ -93,11 +95,12 @@ import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; +import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EntityDataProto; -import org.thingsboard.server.gen.edge.EntityUpdateMsg; import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; +import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.RequestMsgType; import org.thingsboard.server.gen.edge.ResponseMsg; @@ -120,11 +123,14 @@ import org.thingsboard.server.service.edge.EdgeContextComponent; import java.io.Closeable; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -137,6 +143,8 @@ public final class EdgeGrpcSession implements Closeable { private static final ReentrantLock deviceCreationLock = new ReentrantLock(); + private static final ReentrantLock responseMsgLock = new ReentrantLock(); + private final Gson gson = new Gson(); private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs"; @@ -152,6 +160,8 @@ public final class EdgeGrpcSession implements Closeable { private StreamObserver outputStream; private boolean connected; + private CountDownLatch latch; + private TbQueueProducer> ruleEngineMsgProducer; EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener, @@ -172,7 +182,7 @@ public final class EdgeGrpcSession implements Closeable { public void onNext(RequestMsg requestMsg) { if (!connected && requestMsg.getMsgType().equals(RequestMsgType.CONNECT_RPC_MESSAGE)) { ConnectResponseMsg responseMsg = processConnect(requestMsg.getConnectRequestMsg()); - outputStream.onNext(ResponseMsg.newBuilder() + sendResponseMsg(ResponseMsg.newBuilder() .setConnectResponseMsg(responseMsg) .build()); if (ConnectResponseCode.ACCEPTED != responseMsg.getResponseCode()) { @@ -184,9 +194,10 @@ public final class EdgeGrpcSession implements Closeable { } if (connected) { if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE) && requestMsg.hasUplinkMsg()) { - outputStream.onNext(ResponseMsg.newBuilder() - .setUplinkResponseMsg(processUplinkMsg(requestMsg.getUplinkMsg())) - .build()); + onUplinkMsg(requestMsg.getUplinkMsg()); + } + if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE) && requestMsg.hasDownlinkResponseMsg()) { + onDownlinkResponse(requestMsg.getDownlinkResponseMsg()); } } } @@ -204,11 +215,54 @@ public final class EdgeGrpcSession implements Closeable { }; } + private void onUplinkMsg(UplinkMsg uplinkMsg) { + ListenableFuture> future = processUplinkMsg(uplinkMsg); + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List result) { + UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder().setSuccess(true).build(); + sendResponseMsg(ResponseMsg.newBuilder() + .setUplinkResponseMsg(uplinkResponseMsg) + .build()); + } + + @Override + public void onFailure(Throwable t) { + UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder().setSuccess(false).setErrorMsg(t.getMessage()).build(); + sendResponseMsg(ResponseMsg.newBuilder() + .setUplinkResponseMsg(uplinkResponseMsg) + .build()); + } + }, MoreExecutors.directExecutor()); + } + + private void onDownlinkResponse(DownlinkResponseMsg msg) { + try { + if (msg.getSuccess()) { + log.debug("[{}] Msg has been processed successfully! {}", edge.getRoutingKey(), msg); + } else { + log.error("[{}] Msg processing failed! Error msg: {}", edge.getRoutingKey(), msg.getErrorMsg()); + } + latch.countDown(); + } catch (Exception e) { + log.error("Can't process downlink response message [{}]", msg, e); + } + } + + private void sendResponseMsg(ResponseMsg responseMsg) { + try { + responseMsgLock.lock(); + outputStream.onNext(responseMsg); + } finally { + responseMsgLock.unlock(); + } + } + void onConfigurationUpdate(Edge edge) { try { this.edge = edge; // TODO: voba - push edge configuration update to edge -// outputStream.onNext(org.thingsboard.server.gen.integration.ResponseMsg.newBuilder() +// sendResponseMsg(org.thingsboard.server.gen.integration.ResponseMsg.newBuilder() // .setIntegrationUpdateMsg(IntegrationUpdateMsg.newBuilder() // .setConfiguration(constructIntegrationConfigProto(configuration, defaultConverterProto, downLinkConverterProto)) // .build()) @@ -223,48 +277,39 @@ public final class EdgeGrpcSession implements Closeable { TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true); TimePageData pageData; UUID ifOffset = null; + boolean success = true; do { pageData = ctx.getEdgeNotificationService().findEdgeEvents(edge.getTenantId(), edge.getId(), pageLink); if (isConnected() && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); - for (EdgeEvent edgeEvent : pageData.getData()) { - log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent); - try { - ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getEdgeEventAction()); - switch (edgeEventAction) { - case UPDATED: - case ADDED: - case ASSIGNED_TO_EDGE: - case DELETED: - case UNASSIGNED_FROM_EDGE: - case ALARM_ACK: - case ALARM_CLEAR: - case CREDENTIALS_UPDATED: - case RELATION_ADD_OR_UPDATE: - case RELATION_DELETED: - processEntityMessage(edgeEvent, edgeEventAction); - break; - case ATTRIBUTES_UPDATED: - case ATTRIBUTES_DELETED: - case TIMESERIES_UPDATED: - processTelemetryMessage(edgeEvent); - break; - } - } catch (Exception e) { - log.error("Exception during processing records from queue", e); - } - ifOffset = edgeEvent.getUuidId(); + List downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData()); + log.trace("[{}] downlink msg(s) are going to be send.", downlinkMsgsPack.size()); + + latch = new CountDownLatch(downlinkMsgsPack.size()); + for (DownlinkMsg downlinkMsg : downlinkMsgsPack) { + sendResponseMsg(ResponseMsg.newBuilder() + .setDownlinkMsg(downlinkMsg) + .build()); + } + + ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId(); + + success = latch.await(10, TimeUnit.SECONDS); + if (!success) { + log.warn("Failed to deliver the batch: {}", downlinkMsgsPack); } } - if (isConnected() && pageData.hasNext()) { - pageLink = pageData.getNextPageLink(); + if (isConnected() && (!success || pageData.hasNext())) { try { Thread.sleep(ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches()); } catch (InterruptedException e) { log.error("Error during sleep between batches", e); } + if (success) { + pageLink = pageData.getNextPageLink(); + } } - } while (isConnected() && pageData.hasNext()); + } while (isConnected() && (!success || pageData.hasNext())); if (ifOffset != null) { Long newStartTs = UUIDs.unixTimestamp(ifOffset); @@ -277,6 +322,42 @@ public final class EdgeGrpcSession implements Closeable { } } + private List convertToDownlinkMsgsPack(List edgeEvents) { + List result = new ArrayList<>(); + for (EdgeEvent edgeEvent : edgeEvents) { + log.trace("Processing edge event [{}]", edgeEvent); + try { + DownlinkMsg downlinkMsg = null; + ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getEdgeEventAction()); + switch (edgeEventAction) { + case UPDATED: + case ADDED: + case ASSIGNED_TO_EDGE: + case DELETED: + case UNASSIGNED_FROM_EDGE: + case ALARM_ACK: + case ALARM_CLEAR: + case CREDENTIALS_UPDATED: + case RELATION_ADD_OR_UPDATE: + case RELATION_DELETED: + downlinkMsg = processEntityMessage(edgeEvent, edgeEventAction); + break; + case ATTRIBUTES_UPDATED: + case ATTRIBUTES_DELETED: + case TIMESERIES_UPDATED: + downlinkMsg = processTelemetryMessage(edgeEvent); + break; + } + if (downlinkMsg != null) { + result.add(downlinkMsg); + } + } catch (Exception e) { + log.error("Exception during processing records from queue", e); + } + } + return result; + } + private ListenableFuture getQueueStartTs() { ListenableFuture> future = ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, QUEUE_START_TS_ATTR_KEY); @@ -296,7 +377,7 @@ public final class EdgeGrpcSession implements Closeable { ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); } - private void processTelemetryMessage(EdgeEvent edgeEvent) throws IOException { + private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) throws IOException { log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent); EntityId entityId = null; switch (edgeEvent.getEdgeEventType()) { @@ -319,74 +400,61 @@ public final class EdgeGrpcSession implements Closeable { entityId = new CustomerId(edgeEvent.getEntityId()); break; } + DownlinkMsg downlinkMsg = null; if (entityId != null) { log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody()); - DownlinkMsg downlinkMsg; try { ActionType actionType = ActionType.valueOf(edgeEvent.getEdgeEventAction()); downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(mapper.writeValueAsString(edgeEvent.getEntityBody()))); - outputStream.onNext(ResponseMsg.newBuilder() - .setDownlinkMsg(downlinkMsg) - .build()); } catch (Exception e) { log.warn("Can't send telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody(), e); } - } + return downlinkMsg; } - private void processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) { + private DownlinkMsg processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) { UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction())); log.trace("Executing processEntityMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType); switch (edgeEvent.getEdgeEventType()) { case EDGE: // TODO: voba - add edge update logic - break; + return null; case DEVICE: - processDevice(edgeEvent, msgType, edgeEventAction); - break; + return processDevice(edgeEvent, msgType, edgeEventAction); case ASSET: - processAsset(edgeEvent, msgType, edgeEventAction); - break; + return processAsset(edgeEvent, msgType, edgeEventAction); case ENTITY_VIEW: - processEntityView(edgeEvent, msgType, edgeEventAction); - break; + return processEntityView(edgeEvent, msgType, edgeEventAction); case DASHBOARD: - processDashboard(edgeEvent, msgType, edgeEventAction); - break; + return processDashboard(edgeEvent, msgType, edgeEventAction); case CUSTOMER: - processCustomer(edgeEvent, msgType, edgeEventAction); - break; + return processCustomer(edgeEvent, msgType, edgeEventAction); case RULE_CHAIN: - processRuleChain(edgeEvent, msgType, edgeEventAction); - break; + return processRuleChain(edgeEvent, msgType, edgeEventAction); case RULE_CHAIN_METADATA: - processRuleChainMetadata(edgeEvent, msgType); - break; + return processRuleChainMetadata(edgeEvent, msgType); case ALARM: - processAlarm(edgeEvent, msgType); - break; + return processAlarm(edgeEvent, msgType); case USER: - processUser(edgeEvent, msgType, edgeEventAction); - break; + return processUser(edgeEvent, msgType, edgeEventAction); case RELATION: - processRelation(edgeEvent, msgType); - break; + return processRelation(edgeEvent, msgType); case WIDGETS_BUNDLE: - processWidgetsBundle(edgeEvent, msgType, edgeEventAction); - break; + return processWidgetsBundle(edgeEvent, msgType, edgeEventAction); case WIDGET_TYPE: - processWidgetType(edgeEvent, msgType, edgeEventAction); - break; + return processWidgetType(edgeEvent, msgType, edgeEventAction); case ADMIN_SETTINGS: - processAdminSettings(edgeEvent); - break; + return processAdminSettings(edgeEvent); + default: + log.warn("Unsupported edge event type [{}]", edgeEvent); + return null; } } - private void processDevice(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { + private DownlinkMsg processDevice(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeActionType) { case ADDED: case UPDATED: @@ -395,8 +463,8 @@ public final class EdgeGrpcSession implements Closeable { if (device != null) { DeviceUpdateMsg deviceUpdateMsg = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(deviceUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) .build(); } break; @@ -404,8 +472,8 @@ public final class EdgeGrpcSession implements Closeable { case UNASSIGNED_FROM_EDGE: DeviceUpdateMsg deviceUpdateMsg = ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(deviceUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) .build(); break; case CREDENTIALS_UPDATED: @@ -413,22 +481,18 @@ public final class EdgeGrpcSession implements Closeable { if (deviceCredentials != null) { DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = ctx.getDeviceUpdateMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceCredentialsUpdateMsg(deviceCredentialsUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllDeviceCredentialsUpdateMsg(Collections.singletonList(deviceCredentialsUpdateMsg)) .build(); } break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { AssetId assetId = new AssetId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeEventAction) { case ADDED: case UPDATED: @@ -437,8 +501,8 @@ public final class EdgeGrpcSession implements Closeable { if (asset != null) { AssetUpdateMsg assetUpdateMsg = ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAssetUpdateMsg(assetUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) .build(); } break; @@ -446,21 +510,17 @@ public final class EdgeGrpcSession implements Closeable { case UNASSIGNED_FROM_EDGE: AssetUpdateMsg assetUpdateMsg = ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAssetUpdateMsg(assetUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeEventAction) { case ADDED: case UPDATED: @@ -469,8 +529,8 @@ public final class EdgeGrpcSession implements Closeable { if (entityView != null) { EntityViewUpdateMsg entityViewUpdateMsg = ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setEntityViewUpdateMsg(entityViewUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) .build(); } break; @@ -478,21 +538,17 @@ public final class EdgeGrpcSession implements Closeable { case UNASSIGNED_FROM_EDGE: EntityViewUpdateMsg entityViewUpdateMsg = ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setEntityViewUpdateMsg(entityViewUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeEventAction) { case ADDED: case UPDATED: @@ -501,8 +557,8 @@ public final class EdgeGrpcSession implements Closeable { if (dashboard != null) { DashboardUpdateMsg dashboardUpdateMsg = ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDashboardUpdateMsg(dashboardUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) .build(); } break; @@ -510,21 +566,17 @@ public final class EdgeGrpcSession implements Closeable { case UNASSIGNED_FROM_EDGE: DashboardUpdateMsg dashboardUpdateMsg = ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDashboardUpdateMsg(dashboardUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processCustomer(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processCustomer(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { CustomerId customerId = new CustomerId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeEventAction) { case ADDED: case UPDATED: @@ -532,29 +584,25 @@ public final class EdgeGrpcSession implements Closeable { if (customer != null) { CustomerUpdateMsg customerUpdateMsg = ctx.getCustomerUpdateMsgConstructor().constructCustomerUpdatedMsg(msgType, customer); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setCustomerUpdateMsg(customerUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllCustomerUpdateMsg(Collections.singletonList(customerUpdateMsg)) .build(); } break; case DELETED: CustomerUpdateMsg customerUpdateMsg = ctx.getCustomerUpdateMsgConstructor().constructCustomerDeleteMsg(customerId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setCustomerUpdateMsg(customerUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllCustomerUpdateMsg(Collections.singletonList(customerUpdateMsg)) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeEventAction) { case ADDED: case UPDATED: @@ -563,46 +611,41 @@ public final class EdgeGrpcSession implements Closeable { if (ruleChain != null) { RuleChainUpdateMsg ruleChainUpdateMsg = ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainUpdateMsg(ruleChainUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllRuleChainUpdateMsg(Collections.singletonList(ruleChainUpdateMsg)) .build(); } break; case DELETED: case UNASSIGNED_FROM_EDGE: - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainUpdateMsg(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainDeleteMsg(ruleChainId)) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllRuleChainUpdateMsg(Collections.singletonList(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainDeleteMsg(ruleChainId))) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processRuleChainMetadata(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private DownlinkMsg processRuleChainMetadata(EdgeEvent edgeEvent, UpdateMsgType msgType) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); + DownlinkMsg downlinkMsg = null; if (ruleChain != null) { RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId); RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = ctx.getRuleChainUpdateMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData); if (ruleChainMetadataUpdateMsg != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllRuleChainMetadataUpdateMsg(Collections.singletonList(ruleChainMetadataUpdateMsg)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } } + return downlinkMsg; } - private void processUser(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { + private DownlinkMsg processUser(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { UserId userId = new UserId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeActionType) { case ADDED: case UPDATED: @@ -612,15 +655,15 @@ public final class EdgeGrpcSession implements Closeable { boolean fullAccess = Authority.TENANT_ADMIN.equals(user.getAuthority()); setFullAccess(user, fullAccess); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user)) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user))) .build(); } break; case DELETED: case UNASSIGNED_FROM_EDGE: - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId)) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId))) .build(); break; case CREDENTIALS_UPDATED: @@ -628,16 +671,12 @@ public final class EdgeGrpcSession implements Closeable { if (userCredentialsByUserId != null && userCredentialsByUserId.isEnabled()) { UserCredentialsUpdateMsg userCredentialsUpdateMsg = ctx.getUserUpdateMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setUserCredentialsUpdateMsg(userCredentialsUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllUserCredentialsUpdateMsg(Collections.singletonList(userCredentialsUpdateMsg)) .build(); } } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } private void setFullAccess(User user, boolean isFullAccess) { @@ -649,36 +688,33 @@ public final class EdgeGrpcSession implements Closeable { user.setAdditionalInfo(additionalInfo); } - private void processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private DownlinkMsg processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setRelationUpdateMsg(ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation)) + RelationUpdateMsg r = ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation); + return DownlinkMsg.newBuilder() + .addAllRelationUpdateMsg(Collections.singletonList(r)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } - private void processAlarm(EdgeEvent edgeEvent, UpdateMsgType msgType) { + private DownlinkMsg processAlarm(EdgeEvent edgeEvent, UpdateMsgType msgType) { + DownlinkMsg downlinkMsg = null; try { AlarmId alarmId = new AlarmId(edgeEvent.getEntityId()); Alarm alarm = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); if (alarm != null) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAlarmUpdateMsg(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm)) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllAlarmUpdateMsg(Collections.singletonList(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm))) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } } catch (Exception e) { log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e); } + return downlinkMsg; } - private void processWidgetsBundle(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { + private DownlinkMsg processWidgetsBundle(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { WidgetsBundleId widgetsBundleId = new WidgetsBundleId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeActionType) { case ADDED: case UPDATED: @@ -686,29 +722,25 @@ public final class EdgeGrpcSession implements Closeable { if (widgetsBundle != null) { WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = ctx.getWidgetsBundleUpdateMsgConstructor().constructWidgetsBundleUpdateMsg(msgType, widgetsBundle); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setWidgetsBundleUpdateMsg(widgetsBundleUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllWidgetsBundleUpdateMsg(Collections.singletonList(widgetsBundleUpdateMsg)) .build(); } break; case DELETED: WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = ctx.getWidgetsBundleUpdateMsgConstructor().constructWidgetsBundleDeleteMsg(widgetsBundleId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setWidgetsBundleUpdateMsg(widgetsBundleUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllWidgetsBundleUpdateMsg(Collections.singletonList(widgetsBundleUpdateMsg)) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processWidgetType(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { + private DownlinkMsg processWidgetType(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) { WidgetTypeId widgetTypeId = new WidgetTypeId(edgeEvent.getEntityId()); - EntityUpdateMsg entityUpdateMsg = null; + DownlinkMsg downlinkMsg = null; switch (edgeActionType) { case ADDED: case UPDATED: @@ -716,34 +748,28 @@ public final class EdgeGrpcSession implements Closeable { if (widgetType != null) { WidgetTypeUpdateMsg widgetTypeUpdateMsg = ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeUpdateMsg(msgType, widgetType); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setWidgetTypeUpdateMsg(widgetTypeUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) .build(); } break; case DELETED: WidgetTypeUpdateMsg widgetTypeUpdateMsg = ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeDeleteMsg(widgetTypeId); - entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setWidgetTypeUpdateMsg(widgetTypeUpdateMsg) + downlinkMsg = DownlinkMsg.newBuilder() + .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) .build(); break; } - if (entityUpdateMsg != null) { - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); - } + return downlinkMsg; } - private void processAdminSettings(EdgeEvent edgeEvent) { + private DownlinkMsg processAdminSettings(EdgeEvent edgeEvent) { AdminSettings adminSettings = mapper.convertValue(edgeEvent.getEntityBody(), AdminSettings.class); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setAdminSettingsUpdateMsg(ctx.getAdminSettingsUpdateMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings)) + AdminSettingsUpdateMsg t = ctx.getAdminSettingsUpdateMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings); + return DownlinkMsg.newBuilder() + .addAllAdminSettingsUpdateMsg(Collections.singletonList(t)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) - .build()); } private UpdateMsgType getResponseMsgType(ActionType actionType) { @@ -775,112 +801,101 @@ public final class EdgeGrpcSession implements Closeable { return builder.build(); } - private UplinkResponseMsg processUplinkMsg(UplinkMsg uplinkMsg) { + private ListenableFuture> processUplinkMsg(UplinkMsg uplinkMsg) { + List> result = new ArrayList<>(); try { if (uplinkMsg.getEntityDataList() != null && !uplinkMsg.getEntityDataList().isEmpty()) { for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) { EntityId entityId = constructEntityId(entityData); if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg()) && entityId != null) { - ListenableFuture metaDataFuture = constructBaseMsgMetadata(entityId); - Futures.transform(metaDataFuture, metaData -> { - if (metaData != null) { - metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE); - if (entityData.hasPostAttributesMsg()) { - processPostAttributes(entityId, entityData.getPostAttributesMsg(), metaData); - } - if (entityData.hasPostTelemetryMsg()) { - processPostTelemetry(entityId, entityData.getPostTelemetryMsg(), metaData); - } - } - return null; - }, ctx.getDbCallbackExecutor()); + TbMsgMetaData metaData = constructBaseMsgMetadata(entityId); + metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE); + if (entityData.hasPostAttributesMsg()) { + metaData.putValue("scope", entityData.getPostAttributeScope()); + result.add(processPostAttributes(entityId, entityData.getPostAttributesMsg(), metaData)); + } + if (entityData.hasPostTelemetryMsg()) { + result.add(processPostTelemetry(entityId, entityData.getPostTelemetryMsg(), metaData)); + } } } } if (uplinkMsg.getDeviceUpdateMsgList() != null && !uplinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { - onDeviceUpdate(deviceUpdateMsg); + result.add(onDeviceUpdate(deviceUpdateMsg)); } } if (uplinkMsg.getDeviceCredentialsUpdateMsgList() != null && !uplinkMsg.getDeviceCredentialsUpdateMsgList().isEmpty()) { for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { - onDeviceCredentialsUpdate(deviceCredentialsUpdateMsg); + result.add(onDeviceCredentialsUpdate(deviceCredentialsUpdateMsg)); } } if (uplinkMsg.getAlarmUpdateMsgList() != null && !uplinkMsg.getAlarmUpdateMsgList().isEmpty()) { for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { - onAlarmUpdate(alarmUpdateMsg); + result.add(onAlarmUpdate(alarmUpdateMsg)); } } if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { - ctx.getSyncEdgeService().processRuleChainMetadataRequestMsg(edge, ruleChainMetadataRequestMsg); + result.add(ctx.getSyncEdgeService().processRuleChainMetadataRequestMsg(edge, ruleChainMetadataRequestMsg)); } } if (uplinkMsg.getAttributesRequestMsgList() != null && !uplinkMsg.getAttributesRequestMsgList().isEmpty()) { for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { - ctx.getSyncEdgeService().processAttributesRequestMsg(edge, attributesRequestMsg); + result.add(ctx.getSyncEdgeService().processAttributesRequestMsg(edge, attributesRequestMsg)); } } if (uplinkMsg.getRelationRequestMsgList() != null && !uplinkMsg.getRelationRequestMsgList().isEmpty()) { for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { - ctx.getSyncEdgeService().processRelationRequestMsg(edge, relationRequestMsg); + result.add(ctx.getSyncEdgeService().processRelationRequestMsg(edge, relationRequestMsg)); } } if (uplinkMsg.getUserCredentialsRequestMsgList() != null && !uplinkMsg.getUserCredentialsRequestMsgList().isEmpty()) { for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { - ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge, userCredentialsRequestMsg); + result.add(ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge, userCredentialsRequestMsg)); } } if (uplinkMsg.getDeviceCredentialsRequestMsgList() != null && !uplinkMsg.getDeviceCredentialsRequestMsgList().isEmpty()) { for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { - ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg); + result.add(ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg)); } } } catch (Exception e) { - return UplinkResponseMsg.newBuilder().setSuccess(false).setErrorMsg(e.getMessage()).build(); + log.error("Can't process uplink msg [{}]", uplinkMsg, e); } - - return UplinkResponseMsg.newBuilder().setSuccess(true).build(); + return Futures.allAsList(result); } - private ListenableFuture constructBaseMsgMetadata(EntityId entityId) { + private TbMsgMetaData constructBaseMsgMetadata(EntityId entityId) { + TbMsgMetaData metaData = new TbMsgMetaData(); switch (entityId.getEntityType()) { case DEVICE: - ListenableFuture deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edge.getTenantId(), new DeviceId(entityId.getId())); - return Futures.transform(deviceFuture, device -> { - TbMsgMetaData metaData = new TbMsgMetaData(); - if (device != null) { - metaData.putValue("deviceName", device.getName()); - metaData.putValue("deviceType", device.getType()); - } - return metaData; - }, ctx.getDbCallbackExecutor()); + Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), new DeviceId(entityId.getId())); + if (device != null) { + metaData.putValue("deviceName", device.getName()); + metaData.putValue("deviceType", device.getType()); + } + break; case ASSET: - ListenableFuture assetFuture = ctx.getAssetService().findAssetByIdAsync(edge.getTenantId(), new AssetId(entityId.getId())); - return Futures.transform(assetFuture, asset -> { - TbMsgMetaData metaData = new TbMsgMetaData(); - if (asset != null) { - metaData.putValue("assetName", asset.getName()); - metaData.putValue("assetType", asset.getType()); - } - return metaData; - }, ctx.getDbCallbackExecutor()); + Asset asset = ctx.getAssetService().findAssetById(edge.getTenantId(), new AssetId(entityId.getId())); + if (asset != null) { + metaData.putValue("assetName", asset.getName()); + metaData.putValue("assetType", asset.getType()); + } + break; case ENTITY_VIEW: - ListenableFuture entityViewFuture = ctx.getEntityViewService().findEntityViewByIdAsync(edge.getTenantId(), new EntityViewId(entityId.getId())); - return Futures.transform(entityViewFuture, entityView -> { - TbMsgMetaData metaData = new TbMsgMetaData(); - if (entityView != null) { - metaData.putValue("entityViewName", entityView.getName()); - metaData.putValue("entityViewType", entityView.getType()); - } - return metaData; - }, ctx.getDbCallbackExecutor()); + EntityView entityView = ctx.getEntityViewService().findEntityViewById(edge.getTenantId(), new EntityViewId(entityId.getId())); + if (entityView != null) { + metaData.putValue("entityViewName", entityView.getName()); + metaData.putValue("entityViewType", entityView.getType()); + } + break; default: - log.debug("Constructing empty metadata for entityId [{}]", entityId); - return Futures.immediateFuture(new TbMsgMetaData()); + log.debug("Using empty metadata for entityId [{}]", entityId); + break; } + return metaData; } private EntityId constructEntityId(EntityDataProto entityData) { @@ -904,7 +919,7 @@ public final class EdgeGrpcSession implements Closeable { } } - private void processPostTelemetry(EntityId entityId, TransportProtos.PostTelemetryMsg msg, TbMsgMetaData metaData) { + private ListenableFuture processPostTelemetry(EntityId entityId, TransportProtos.PostTelemetryMsg msg, TbMsgMetaData metaData) { for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); metaData.putValue("ts", tsKv.getTs() + ""); @@ -912,17 +927,18 @@ public final class EdgeGrpcSession implements Closeable { // TODO: voba - verify that null callback is OK ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, null); } + return Futures.immediateFuture(null); } - private void processPostAttributes(EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { + private ListenableFuture processPostAttributes(EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); // TODO: voba - verify that null callback is OK ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, null); + return Futures.immediateFuture(null); } - private void onDeviceUpdate(DeviceUpdateMsg deviceUpdateMsg) { - log.info("onDeviceUpdate {}", deviceUpdateMsg); + private ListenableFuture onDeviceUpdate(DeviceUpdateMsg deviceUpdateMsg) { DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); switch (deviceUpdateMsg.getMsgType()) { case ENTITY_CREATED_RPC_MESSAGE: @@ -931,11 +947,12 @@ public final class EdgeGrpcSession implements Closeable { if (device != null) { // device with this name already exists on the cloud - update ID on the edge if (!device.getId().equals(edgeDeviceId)) { - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device)) + DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device); + DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() + .addAllDeviceUpdateMsg(Collections.singletonList(d)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) + sendResponseMsg(ResponseMsg.newBuilder() + .setDownlinkMsg(downlinkMsg) .build()); } } else { @@ -943,11 +960,12 @@ public final class EdgeGrpcSession implements Closeable { if (deviceById != null) { // this ID already used by other device - create new device and update ID on the edge device = createDevice(deviceUpdateMsg); - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device)) + DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device); + DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() + .addAllDeviceUpdateMsg(Collections.singletonList(d)) .build(); - outputStream.onNext(ResponseMsg.newBuilder() - .setEntityUpdateMsg(entityUpdateMsg) + sendResponseMsg(ResponseMsg.newBuilder() + .setDownlinkMsg(downlinkMsg) .build()); } else { device = createDevice(deviceUpdateMsg); @@ -966,8 +984,10 @@ public final class EdgeGrpcSession implements Closeable { } break; case UNRECOGNIZED: - log.error("Unsupported msg type"); + log.error("Unsupported msg type {}", deviceUpdateMsg.getMsgType()); + return Futures.immediateFailedFuture(new RuntimeException("Unsupported msg type " + deviceUpdateMsg.getMsgType())); } + return Futures.immediateFuture(null); } private void updateDevice(DeviceUpdateMsg deviceUpdateMsg) { @@ -981,33 +1001,26 @@ public final class EdgeGrpcSession implements Closeable { requestDeviceCredentialsFromEdge(device); } - private void onDeviceCredentialsUpdate(DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { + private ListenableFuture onDeviceCredentialsUpdate(DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); ListenableFuture deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edge.getTenantId(), deviceId); - - Futures.addCallback(deviceFuture, new FutureCallback() { - @Override - public void onSuccess(@Nullable Device device) { - if (device != null) { - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", - device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); - try { - DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId()); - deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType())); - deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId()); - deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue()); - ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials); - } catch (Exception e) { - log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); - } + return Futures.transform(deviceFuture, device -> { + if (device != null) { + log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", + device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); + try { + DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId()); + deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType())); + deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId()); + deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue()); + ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials); + } catch (Exception e) { + log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); + throw new RuntimeException(e); } } - - @Override - public void onFailure(Throwable t) { - log.error("Can't update device credentials for deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg, t); - } + return null; }, ctx.getDbCallbackExecutor()); } @@ -1015,7 +1028,7 @@ public final class EdgeGrpcSession implements Closeable { log.debug("Executing requestDeviceCredentialsFromEdge device [{}]", device); DownlinkMsg downlinkMsg = constructDeviceCredentialsRequestMsg(device.getId()); - outputStream.onNext(ResponseMsg.newBuilder() + sendResponseMsg(ResponseMsg.newBuilder() .setDownlinkMsg(downlinkMsg) .build()); } @@ -1118,49 +1131,52 @@ public final class EdgeGrpcSession implements Closeable { } } - private void onAlarmUpdate(AlarmUpdateMsg alarmUpdateMsg) { + private ListenableFuture onAlarmUpdate(AlarmUpdateMsg alarmUpdateMsg) { EntityId originatorId = getAlarmOriginator(alarmUpdateMsg.getOriginatorName(), org.thingsboard.server.common.data.EntityType.valueOf(alarmUpdateMsg.getOriginatorType())); - if (originatorId != null) { - try { - Alarm existentAlarm = ctx.getAlarmService().findLatestByOriginatorAndType(edge.getTenantId(), originatorId, alarmUpdateMsg.getType()).get(); - switch (alarmUpdateMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - if (existentAlarm == null || existentAlarm.getStatus().isCleared()) { - existentAlarm = new Alarm(); - existentAlarm.setTenantId(edge.getTenantId()); - existentAlarm.setType(alarmUpdateMsg.getName()); - existentAlarm.setOriginator(originatorId); - existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity())); - existentAlarm.setStartTs(alarmUpdateMsg.getStartTs()); - existentAlarm.setClearTs(alarmUpdateMsg.getClearTs()); - existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); - } - existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus())); - existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); - existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); - existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails())); - ctx.getAlarmService().createOrUpdateAlarm(existentAlarm); - break; - case ALARM_ACK_RPC_MESSAGE: - if (existentAlarm != null) { - ctx.getAlarmService().ackAlarm(edge.getTenantId(), existentAlarm.getId(), alarmUpdateMsg.getAckTs()); - } - break; - case ALARM_CLEAR_RPC_MESSAGE: - if (existentAlarm != null) { - ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), mapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); - } - break; - case ENTITY_DELETED_RPC_MESSAGE: - if (existentAlarm != null) { - ctx.getAlarmService().deleteAlarm(edge.getTenantId(), existentAlarm.getId()); - } - break; - } - } catch (Exception e) { - log.error("Error during finding existent alarm", e); + if (originatorId == null) { + return Futures.immediateFuture(null); + } + try { + Alarm existentAlarm = ctx.getAlarmService().findLatestByOriginatorAndType(edge.getTenantId(), originatorId, alarmUpdateMsg.getType()).get(); + switch (alarmUpdateMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + if (existentAlarm == null || existentAlarm.getStatus().isCleared()) { + existentAlarm = new Alarm(); + existentAlarm.setTenantId(edge.getTenantId()); + existentAlarm.setType(alarmUpdateMsg.getName()); + existentAlarm.setOriginator(originatorId); + existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity())); + existentAlarm.setStartTs(alarmUpdateMsg.getStartTs()); + existentAlarm.setClearTs(alarmUpdateMsg.getClearTs()); + existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); + } + existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus())); + existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); + existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); + existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails())); + ctx.getAlarmService().createOrUpdateAlarm(existentAlarm); + break; + case ALARM_ACK_RPC_MESSAGE: + if (existentAlarm != null) { + ctx.getAlarmService().ackAlarm(edge.getTenantId(), existentAlarm.getId(), alarmUpdateMsg.getAckTs()); + } + break; + case ALARM_CLEAR_RPC_MESSAGE: + if (existentAlarm != null) { + ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), mapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); + } + break; + case ENTITY_DELETED_RPC_MESSAGE: + if (existentAlarm != null) { + ctx.getAlarmService().deleteAlarm(edge.getTenantId(), existentAlarm.getId()); + } + break; } + return Futures.immediateFuture(null); + } catch (Exception e) { + log.error("Error during finding existent alarm", e); + return Futures.immediateFailedFuture(new RuntimeException("Error during finding existent alarm", e)); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 9ee5879996..4d688f6999 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -316,64 +316,62 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } @Override - public void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) { + public ListenableFuture processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) { if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null); + ListenableFuture future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null); + return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService); } + return Futures.immediateFuture(null); } @Override - public void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg) { + public ListenableFuture processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg) { EntityId entityId = EntityIdFactory.getByTypeAndUuid( EntityType.valueOf(attributesRequestMsg.getEntityType()), new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB())); final EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(entityId.getEntityType()); if (edgeEventType != null) { ListenableFuture> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); - Futures.addCallback(ssAttrFuture, new FutureCallback>() { - @Override - public void onSuccess(@Nullable List ssAttributes) { - if (ssAttributes != null && !ssAttributes.isEmpty()) { - try { - Map entityData = new HashMap<>(); - ObjectNode attributes = mapper.createObjectNode(); - for (AttributeKvEntry attr : ssAttributes) { - if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { - attributes.put(attr.getKey(), attr.getBooleanValue().get()); - } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { - attributes.put(attr.getKey(), attr.getDoubleValue().get()); - } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { - attributes.put(attr.getKey(), attr.getLongValue().get()); - } else { - attributes.put(attr.getKey(), attr.getValueAsString()); - } + return Futures.transform(ssAttrFuture, ssAttributes -> { + if (ssAttributes != null && !ssAttributes.isEmpty()) { + try { + Map entityData = new HashMap<>(); + ObjectNode attributes = mapper.createObjectNode(); + for (AttributeKvEntry attr : ssAttributes) { + if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { + attributes.put(attr.getKey(), attr.getBooleanValue().get()); + } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { + attributes.put(attr.getKey(), attr.getDoubleValue().get()); + } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { + attributes.put(attr.getKey(), attr.getLongValue().get()); + } else { + attributes.put(attr.getKey(), attr.getValueAsString()); } - entityData.put("kv", attributes); - entityData.put("scope", DataConstants.SERVER_SCOPE); - JsonNode entityBody = mapper.valueToTree(entityData); - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody); - saveEdgeEvent(edge.getTenantId(), - edge.getId(), - edgeEventType, - ActionType.ATTRIBUTES_UPDATED, - entityId, - entityBody); - } catch (Exception e) { - log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); } + entityData.put("kv", attributes); + entityData.put("scope", DataConstants.SERVER_SCOPE); + JsonNode entityBody = mapper.valueToTree(entityData); + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody); + saveEdgeEvent(edge.getTenantId(), + edge.getId(), + edgeEventType, + ActionType.ATTRIBUTES_UPDATED, + entityId, + entityBody); + } catch (Exception e) { + log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); + throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); } } - - @Override - public void onFailure(Throwable t) { - - } + return null; }, dbCallbackExecutorService); // TODO: voba - push shared attributes to edge? - ListenableFuture> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); - ListenableFuture> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); + // ListenableFuture> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); + // ListenableFuture> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); + } else { + return Futures.immediateFuture(null); } } @@ -391,7 +389,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } @Override - public void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg) { + public ListenableFuture processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg) { EntityId entityId = EntityIdFactory.getByTypeAndUuid( EntityType.valueOf(relationRequestMsg.getEntityType()), new UUID(relationRequestMsg.getEntityIdMSB(), relationRequestMsg.getEntityIdLSB())); @@ -400,39 +398,33 @@ public class DefaultSyncEdgeService implements SyncEdgeService { futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.FROM)); futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.TO)); ListenableFuture>> relationsListFuture = Futures.allAsList(futures); - Futures.addCallback(relationsListFuture, new FutureCallback>>() { - @Override - public void onSuccess(@Nullable List> relationsList) { - try { - if (!relationsList.isEmpty()) { - for (List entityRelations : relationsList) { - log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size()); - for (EntityRelation relation : entityRelations) { - try { - if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && - !relation.getTo().getEntityType().equals(EntityType.EDGE)) { - saveEdgeEvent(edge.getTenantId(), - edge.getId(), - EdgeEventType.RELATION, - ActionType.ADDED, - null, - mapper.valueToTree(relation)); - } - } catch (Exception e) { - log.error("Exception during loading relation [{}] to edge on sync!", relation, e); + return Futures.transform(relationsListFuture, relationsList -> { + try { + if (relationsList != null && !relationsList.isEmpty()) { + for (List entityRelations : relationsList) { + log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size()); + for (EntityRelation relation : entityRelations) { + try { + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && + !relation.getTo().getEntityType().equals(EntityType.EDGE)) { + saveEdgeEvent(edge.getTenantId(), + edge.getId(), + EdgeEventType.RELATION, + ActionType.ADDED, + null, + mapper.valueToTree(relation)); } + } catch (Exception e) { + log.error("Exception during loading relation [{}] to edge on sync!", relation, e); } } } - } catch (Exception e) { - log.error("Exception during loading relation(s) to edge on sync!", e); } + } catch (Exception e) { + log.error("Exception during loading relation(s) to edge on sync!", e); + throw new RuntimeException("Exception during loading relation(s) to edge on sync!", e); } - - @Override - public void onFailure(Throwable t) { - log.error("Exception during loading relation(s) to edge on sync!", t); - } + return null; }, dbCallbackExecutorService); } @@ -443,22 +435,26 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } @Override - public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { + public ListenableFuture processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) { DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null); + ListenableFuture future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null); + return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService); } + return Futures.immediateFuture(null); } @Override - public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { + public ListenableFuture processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) { UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null); + ListenableFuture future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null); + return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService); } + return Futures.immediateFuture(null); } - private void saveEdgeEvent(TenantId tenantId, + private ListenableFuture saveEdgeEvent(TenantId tenantId, EdgeId edgeId, EdgeEventType edgeEventType, ActionType edgeEventAction, @@ -476,6 +472,6 @@ public class DefaultSyncEdgeService implements SyncEdgeService { edgeEvent.setEntityId(entityId.getId()); } edgeEvent.setEntityBody(entityBody); - edgeEventService.saveAsync(edgeEvent); + return edgeEventService.saveAsync(edgeEvent); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java index 051af4f6d2..a4df4e227c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.edge.rpc.init; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; @@ -26,13 +27,13 @@ public interface SyncEdgeService { void sync(Edge edge); - void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg); + ListenableFuture processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg); - void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg); + ListenableFuture processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg); - void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg); + ListenableFuture processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg); - void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg); + ListenableFuture processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg); - void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg); + ListenableFuture processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg); } diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 917cc3fa02..45201d3229 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -28,9 +28,9 @@ import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectResponseCode; import org.thingsboard.server.gen.edge.ConnectResponseMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; +import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc; -import org.thingsboard.server.gen.edge.EntityUpdateMsg; import org.thingsboard.server.gen.edge.RequestMsg; import org.thingsboard.server.gen.edge.RequestMsgType; import org.thingsboard.server.gen.edge.ResponseMsg; @@ -41,6 +41,7 @@ import javax.net.ssl.SSLException; import java.io.File; import java.net.URISyntaxException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @Service @@ -62,12 +63,13 @@ public class EdgeGrpcClient implements EdgeRpcClient { private StreamObserver inputStream; + private static final ReentrantLock uplinkMsgLock = new ReentrantLock(); + @Override public void connect(String edgeKey, String edgeSecret, Consumer onUplinkResponse, Consumer onEdgeUpdate, - Consumer onEntityUpdate, Consumer onDownlink, Consumer onError) { NettyChannelBuilder builder = NettyChannelBuilder.forAddress(rpcHost, rpcPort).usePlaintext(); @@ -83,7 +85,7 @@ public class EdgeGrpcClient implements EdgeRpcClient { channel = builder.build(); EdgeRpcServiceGrpc.EdgeRpcServiceStub stub = EdgeRpcServiceGrpc.newStub(channel); log.info("[{}] Sending a connect request to the TB!", edgeKey); - this.inputStream = stub.handleMsgs(initOutputStream(edgeKey, onUplinkResponse, onEdgeUpdate, onEntityUpdate, onDownlink, onError)); + this.inputStream = stub.handleMsgs(initOutputStream(edgeKey, onUplinkResponse, onEdgeUpdate, onDownlink, onError)); this.inputStream.onNext(RequestMsg.newBuilder() .setMsgType(RequestMsgType.CONNECT_RPC_MESSAGE) .setConnectRequestMsg(ConnectRequestMsg.newBuilder().setEdgeRoutingKey(edgeKey).setEdgeSecret(edgeSecret).build()) @@ -110,16 +112,33 @@ public class EdgeGrpcClient implements EdgeRpcClient { @Override public void sendUplinkMsg(UplinkMsg msg) { - this.inputStream.onNext(RequestMsg.newBuilder() - .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) - .setUplinkMsg(msg) - .build()); + try { + uplinkMsgLock.lock(); + this.inputStream.onNext(RequestMsg.newBuilder() + .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) + .setUplinkMsg(msg) + .build()); + } finally { + uplinkMsgLock.unlock(); + } + } + + @Override + public void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg) { + try { + uplinkMsgLock.lock(); + this.inputStream.onNext(RequestMsg.newBuilder() + .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) + .setDownlinkResponseMsg(downlinkResponseMsg) + .build()); + } finally { + uplinkMsgLock.unlock(); + } } private StreamObserver initOutputStream(String edgeKey, Consumer onUplinkResponse, Consumer onEdgeUpdate, - Consumer onEntityUpdate, Consumer onDownlink, Consumer onError) { return new StreamObserver() { @@ -137,9 +156,6 @@ public class EdgeGrpcClient implements EdgeRpcClient { } else if (responseMsg.hasUplinkResponseMsg()) { log.debug("[{}] Uplink response message received {}", edgeKey, responseMsg.getUplinkResponseMsg()); onUplinkResponse.accept(responseMsg.getUplinkResponseMsg()); - } else if (responseMsg.hasEntityUpdateMsg()) { - log.debug("[{}] Entity update message received {}", edgeKey, responseMsg.getEntityUpdateMsg()); - onEntityUpdate.accept(responseMsg.getEntityUpdateMsg()); } else if (responseMsg.hasDownlinkMsg()) { log.debug("[{}] Downlink message received {}", edgeKey, responseMsg.getDownlinkMsg()); onDownlink.accept(responseMsg.getDownlinkMsg()); diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java index d2ab91dfaf..c268b2a9e9 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java @@ -16,8 +16,8 @@ package org.thingsboard.edge.rpc; import org.thingsboard.server.gen.edge.DownlinkMsg; +import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; -import org.thingsboard.server.gen.edge.EntityUpdateMsg; import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; @@ -29,11 +29,12 @@ public interface EdgeRpcClient { String integrationSecret, Consumer onUplinkResponse, Consumer onEdgeUpdate, - Consumer onEntityUpdate, Consumer onDownlink, Consumer onError); void disconnect() throws InterruptedException; - void sendUplinkMsg(UplinkMsg uplinkMsg) throws InterruptedException; + void sendUplinkMsg(UplinkMsg uplinkMsg); + + void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 8be4be9956..9f5754ba31 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -37,31 +37,13 @@ message RequestMsg { RequestMsgType msgType = 1; ConnectRequestMsg connectRequestMsg = 2; UplinkMsg uplinkMsg = 3; + DownlinkResponseMsg downlinkResponseMsg = 4; } message ResponseMsg { ConnectResponseMsg connectResponseMsg = 1; UplinkResponseMsg uplinkResponseMsg = 2; - EntityUpdateMsg entityUpdateMsg = 3; - DownlinkMsg downlinkMsg = 4; -} - -message EntityUpdateMsg { - DeviceUpdateMsg deviceUpdateMsg = 1; - DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 2; - RuleChainUpdateMsg ruleChainUpdateMsg = 3; - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 4; - DashboardUpdateMsg dashboardUpdateMsg = 5; - AssetUpdateMsg assetUpdateMsg = 6; - EntityViewUpdateMsg entityViewUpdateMsg = 7; - AlarmUpdateMsg alarmUpdateMsg = 8; - UserUpdateMsg userUpdateMsg = 9; - UserCredentialsUpdateMsg userCredentialsUpdateMsg = 10; - CustomerUpdateMsg customerUpdateMsg = 11; - RelationUpdateMsg relationUpdateMsg = 12; - WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 13; - WidgetTypeUpdateMsg widgetTypeUpdateMsg = 14; - AdminSettingsUpdateMsg adminSettingsUpdateMsg = 15; + DownlinkMsg downlinkMsg = 3; } enum RequestMsgType { @@ -360,9 +342,30 @@ message UplinkResponseMsg { string errorMsg = 2; } +message DownlinkResponseMsg { + bool success = 1; + string errorMsg = 2; +} + message DownlinkMsg { int32 downlinkMsgId = 1; repeated EntityDataProto entityData = 2; repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 3; + repeated DeviceUpdateMsg deviceUpdateMsg = 4; + repeated DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 5; + repeated RuleChainUpdateMsg ruleChainUpdateMsg = 6; + repeated RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 7; + repeated DashboardUpdateMsg dashboardUpdateMsg = 8; + repeated AssetUpdateMsg assetUpdateMsg = 9; + repeated EntityViewUpdateMsg entityViewUpdateMsg = 10; + repeated AlarmUpdateMsg alarmUpdateMsg = 11; + repeated UserUpdateMsg userUpdateMsg = 12; + repeated UserCredentialsUpdateMsg userCredentialsUpdateMsg = 13; + repeated CustomerUpdateMsg customerUpdateMsg = 14; + repeated RelationUpdateMsg relationUpdateMsg = 15; + repeated WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 16; + repeated WidgetTypeUpdateMsg widgetTypeUpdateMsg = 17; + repeated AdminSettingsUpdateMsg adminSettingsUpdateMsg = 18; + } From 30d686f7528ae90ed57da4bf2d8233618211d1a1 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 19 Aug 2020 13:52:03 +0300 Subject: [PATCH 083/156] Send response only if connected --- .../server/service/edge/rpc/EdgeGrpcSession.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index ba77616f77..121772a01b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -253,11 +253,13 @@ public final class EdgeGrpcSession implements Closeable { } private void sendResponseMsg(ResponseMsg responseMsg) { - try { - responseMsgLock.lock(); - outputStream.onNext(responseMsg); - } finally { - responseMsgLock.unlock(); + if (isConnected()) { + try { + responseMsgLock.lock(); + outputStream.onNext(responseMsg); + } finally { + responseMsgLock.unlock(); + } } } From 8d60c67fafcd4648a96bc5466ce5defd5c39dc46 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 20 Aug 2020 14:45:32 +0300 Subject: [PATCH 084/156] load mail templates from files --- .../AdminSettingsUpdateMsgConstructor.java | 7 +- .../edge/rpc/init/DefaultSyncEdgeService.java | 72 ++++++++++++++++++- common/edge-api/src/main/proto/edge.proto | 7 +- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java index 1b0d188198..31d6683d89 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java @@ -18,7 +18,6 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.AdminSettings; -import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; @@ -30,10 +29,8 @@ public class AdminSettingsUpdateMsgConstructor { AdminSettingsUpdateMsg.Builder builder = AdminSettingsUpdateMsg.newBuilder() .setKey(adminSettings.getKey()) .setJsonValue(JacksonUtil.toString(adminSettings.getJsonValue())); - AdminSettingsId adminSettingsId = adminSettings.getId(); - if (adminSettingsId != null) { - builder.setIdMSB(adminSettingsId.getId().getMostSignificantBits()); - builder.setIdLSB(adminSettingsId.getId().getLeastSignificantBits()); + if (adminSettings.getId() != null) { + builder.setIsSystem(true); } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 4d688f6999..cfe8f86fd6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.edge.rpc.init; +import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -22,8 +23,12 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.text.WordUtils; import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.DefaultResourceLoader; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.DashboardInfo; @@ -37,6 +42,7 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; @@ -76,11 +82,15 @@ import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.service.executors.DbCallbackExecutorService; +import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Service @Slf4j @@ -299,13 +309,71 @@ public class DefaultSyncEdgeService implements SyncEdgeService { private void syncAdminSettings(Edge edge) { try { - AdminSettings mailSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"); - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(mailSettings)); + AdminSettings systemMailSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(systemMailSettings)); + AdminSettings tenantMailSettings = convertToTenantAdminSettings(systemMailSettings.getKey(), (ObjectNode) systemMailSettings.getJsonValue()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(tenantMailSettings)); + AdminSettings systemMailTemplates = loadMailTemplates(); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(systemMailTemplates)); + AdminSettings tenantMailTemplates = convertToTenantAdminSettings(systemMailTemplates.getKey(), (ObjectNode) systemMailTemplates.getJsonValue()); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(tenantMailTemplates)); } catch (Exception e) { log.error("Can't load admin settings", e); } } + private AdminSettings loadMailTemplates() throws Exception { + Map mailTemplates = new HashMap<>(); + Pattern startPattern = Pattern.compile("
"); + Pattern endPattern = Pattern.compile("
"); + File[] files = new DefaultResourceLoader().getResource("classpath:/templates/").getFile().listFiles(); + for (File file: files) { + Map mailTemplate = new HashMap<>(); + String name = validateName(file.getName()); + String stringTemplate = FileUtils.readFileToString(file, StandardCharsets.UTF_8); + Matcher start = startPattern.matcher(stringTemplate); + Matcher end = endPattern.matcher(stringTemplate); + if (start.find() && end.find()) { + String body = StringUtils.substringBetween(stringTemplate, start.group(), end.group()).replaceAll("\t", ""); + String subject = StringUtils.substringBetween(body, "

", "

"); + mailTemplate.put("subject", subject); + mailTemplate.put("body", body); + mailTemplates.put(name, mailTemplate); + } else { + log.error("Can't load mail template from file {}", file.getName()); + } + } + AdminSettings adminSettings = new AdminSettings(); + adminSettings.setId(new AdminSettingsId(UUIDs.timeBased())); + adminSettings.setKey("mailTemplates"); + adminSettings.setJsonValue(mapper.convertValue(mailTemplates, JsonNode.class)); + return adminSettings; + } + + private String validateName(String name) throws Exception { + StringBuilder nameBuilder = new StringBuilder(); + name = name.replace(".vm", ""); + String[] nameParts = name.split("\\."); + if (nameParts.length >= 1) { + nameBuilder.append(nameParts[0]); + for (int i = 1; i < nameParts.length; i++) { + String word = WordUtils.capitalize(nameParts[i]); + nameBuilder.append(word); + } + return nameBuilder.toString(); + } else { + throw new Exception("Error during filename validation"); + } + } + + private AdminSettings convertToTenantAdminSettings(String key, ObjectNode jsonValue) { + AdminSettings tenantMailSettings = new AdminSettings(); + jsonValue.put("useSystemMailSettings", true); + tenantMailSettings.setJsonValue(jsonValue); + tenantMailSettings.setKey(key); + return tenantMailSettings; + } + private void pushUsersToEdge(TextPageData pageData, Edge edge) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 7827d26538..3d91595a2f 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -275,10 +275,9 @@ message WidgetTypeUpdateMsg { } message AdminSettingsUpdateMsg { - int64 idMSB = 1; - int64 idLSB = 2; - string key = 3; - string jsonValue = 4; + bool isSystem = 1; + string key = 2; + string jsonValue = 3; } message UserCredentialsUpdateMsg { From 581f23b0b067bdfb06c9a9955eb4dd0331db4187 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 21 Aug 2020 18:50:11 +0300 Subject: [PATCH 085/156] fixes + processing attributes delete msg from edge --- .../edge/DefaultEdgeNotificationService.java | 50 ++--------------- .../service/edge/rpc/EdgeGrpcSession.java | 31 ++++++++++- .../constructor/EntityDataMsgConstructor.java | 6 +- .../server/dao/edge/EdgeService.java | 6 +- .../server/dao/edge/EdgeServiceImpl.java | 55 ++++++++++++++++++- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 9 +-- 6 files changed, 95 insertions(+), 62 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 279ec96064..27489c98cc 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -242,7 +242,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } } } else { - ListenableFuture> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); + ListenableFuture> edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, dbCallbackExecutorService); Futures.transform(edgeIdsFuture, edgeIds -> { if (edgeIds != null && !edgeIds.isEmpty()) { for (EdgeId edgeId : edgeIds) { @@ -321,7 +321,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { if (alarm != null) { EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType()); if (edgeEventType != null) { - ListenableFuture> relatedEdgeIdsByEntityIdFuture = findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator()); + ListenableFuture> relatedEdgeIdsByEntityIdFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), dbCallbackExecutorService); Futures.transform(relatedEdgeIdsByEntityIdFuture, relatedEdgeIdsByEntityId -> { if (relatedEdgeIdsByEntityId != null) { for (EdgeId edgeId : relatedEdgeIdsByEntityId) { @@ -346,8 +346,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && !relation.getTo().getEntityType().equals(EntityType.EDGE)) { List>> futures = new ArrayList<>(); - futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getTo())); - futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom())); + futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getTo(), dbCallbackExecutorService)); + futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom(), dbCallbackExecutorService)); ListenableFuture>> combinedFuture = Futures.allAsList(futures); Futures.transform(combinedFuture, listOfListsEdgeIds -> { Set uniqueEdgeIds = new HashSet<>(); @@ -373,48 +373,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } } - private ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { - switch (entityId.getEntityType()) { - case DEVICE: - case ASSET: - case ENTITY_VIEW: - ListenableFuture> originatorEdgeRelationsFuture = - relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); - return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { - if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { - return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); - } else { - return Collections.emptyList(); - } - }, dbCallbackExecutorService); - case DASHBOARD: - return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); - case RULE_CHAIN: - return convertToEdgeIds(edgeService.findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); - case USER: - User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); - TextPageData edges; - if (userById.getCustomerId() == null || userById.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { - edges = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); - } else { - edges = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); - } - return convertToEdgeIds(Futures.immediateFuture(edges.getData())); - default: - return Futures.immediateFuture(Collections.emptyList()); - } - } - - private ListenableFuture> convertToEdgeIds(ListenableFuture> future) { - return Futures.transform(future, edges -> { - if (edges != null && !edges.isEmpty()) { - return edges.stream().map(IdBased::getId).collect(Collectors.toList()); - } else { - return Collections.emptyList(); - } - }, dbCallbackExecutorService); - } - private EdgeEventType getEdgeQueueTypeByEntityType(EntityType entityType) { switch (entityType) { case DEVICE: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 121772a01b..86c45c78ba 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -33,6 +33,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; +import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; @@ -64,6 +65,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetsBundleId; +import org.thingsboard.server.common.data.kv.AttributeKey; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; @@ -88,6 +90,7 @@ import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectResponseCode; @@ -125,11 +128,12 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.service.edge.EdgeContextComponent; import java.io.Closeable; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; @@ -382,7 +386,7 @@ public final class EdgeGrpcSession implements Closeable { ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); } - private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) throws IOException { + private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) { log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent); EntityId entityId = null; switch (edgeEvent.getEdgeEventType()) { @@ -823,6 +827,9 @@ public final class EdgeGrpcSession implements Closeable { result.add(processPostTelemetry(entityId, entityData.getPostTelemetryMsg(), metaData)); } } + if (entityData.hasAttributeDeleteMsg()) { + result.add(processAttributeDeleteMsg(entityId, entityData.getAttributeDeleteMsg(), entityData.getEntityType())); + } } } @@ -948,6 +955,26 @@ public final class EdgeGrpcSession implements Closeable { return Futures.immediateFuture(null); } + private ListenableFuture processAttributeDeleteMsg(EntityId entityId, AttributeDeleteMsg attributeDeleteMsg, String entityType) { + try { + String scope = attributeDeleteMsg.getScope(); + List attributeNames = attributeDeleteMsg.getAttributeNamesList(); + ctx.getAttributesService().removeAll(edge.getTenantId(), entityId, scope, attributeNames); + if (EntityType.DEVICE.name().equals(entityType)) { + Set attributeKeys = new HashSet<>(); + for (String attributeName : attributeNames) { + attributeKeys.add(new AttributeKey(scope, attributeName)); + } + ctx.getTbClusterService().pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( + edge.getTenantId(), (DeviceId) entityId, attributeKeys), null); + } + } catch (Exception e) { + log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, e); + return Futures.immediateFailedFuture(new RuntimeException("Can't process attribute delete msg " + attributeDeleteMsg, e)); + } + return Futures.immediateFuture(null); + } + private ListenableFuture onDeviceUpdate(DeviceUpdateMsg deviceUpdateMsg) { DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); switch (deviceUpdateMsg.getMsgType()) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index c1d211af58..0f7fb0523d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -43,9 +43,11 @@ public class EntityDataMsgConstructor { case TIMESERIES_UPDATED: try { JsonObject data = entityData.getAsJsonObject(); - long ts = System.currentTimeMillis(); + long ts; if (data.get("ts") != null && !data.get("ts").isJsonNull()) { - ts = data.getAsJsonObject("ts").getAsLong(); + ts = data.getAsJsonPrimitive("ts").getAsLong(); + } else { + ts = System.currentTimeMillis(); } builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data.getAsJsonObject("data"), ts)); } catch (Exception e) { diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index 5c6e5d7559..71c56068d1 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -22,15 +22,15 @@ import org.thingsboard.server.common.data.edge.EdgeSearchQuery; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.common.data.page.TimePageData; -import org.thingsboard.server.common.data.page.TimePageLink; import java.util.List; import java.util.Optional; +import java.util.concurrent.Executor; public interface EdgeService { @@ -75,6 +75,8 @@ public interface EdgeService { ListenableFuture> findEdgesByTenantIdAndRuleChainId(TenantId tenantId, RuleChainId ruleChainId); ListenableFuture> findEdgesByTenantIdAndDashboardId(TenantId tenantId, DashboardId dashboardId); + + ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, Executor executorService); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 01f82faa17..4ce86beea5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -31,31 +31,35 @@ import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeSearchQuery; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.IdBased; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.common.data.page.TimePageData; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.customer.CustomerDao; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; +import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.tenant.TenantDao; +import org.thingsboard.server.dao.user.UserService; import javax.annotation.Nullable; import java.util.ArrayList; @@ -63,6 +67,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.concurrent.Executor; import java.util.stream.Collectors; import static org.thingsboard.server.common.data.CacheConstants.EDGE_CACHE; @@ -91,6 +96,9 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @Autowired private CustomerDao customerDao; + @Autowired + private UserService userService; + @Autowired private CacheManager cacheManager; @@ -420,4 +428,47 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic } }; + @Override + public ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, Executor executorService) { + switch (entityId.getEntityType()) { + case DEVICE: + case ASSET: + case ENTITY_VIEW: + ListenableFuture> originatorEdgeRelationsFuture = + relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); + return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { + if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { + return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); + } else { + return Collections.emptyList(); + } + }, executorService); + case DASHBOARD: + return convertToEdgeIds(findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId())), executorService); + case RULE_CHAIN: + return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId())), executorService); + case USER: + User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); + TextPageData edges; + if (userById.getCustomerId() == null || userById.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { + edges = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + } else { + edges = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); + } + return convertToEdgeIds(Futures.immediateFuture(edges.getData()), executorService); + default: + return Futures.immediateFuture(Collections.emptyList()); + } + } + + private ListenableFuture> convertToEdgeIds(ListenableFuture> future, Executor executorService) { + return Futures.transform(future, edges -> { + if (edges != null && !edges.isEmpty()) { + return edges.stream().map(IdBased::getId).collect(Collectors.toList()); + } else { + return Collections.emptyList(); + } + }, executorService); + } + } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index be265ebc19..b531af7ed3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -232,14 +232,7 @@ public class TbMsgPushToEdgeNode implements TbNode { TextPageData edgesByTenantId = ctx.getEdgeService().findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); } else { - ListenableFuture> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); - return Futures.transform(future, relations -> { - List result = new ArrayList<>(); - if (relations != null && relations.size() > 0) { - result.add(new EdgeId(relations.get(0).getFrom().getId())); - } - return result; - }, ctx.getDbCallbackExecutor()); + return ctx.getEdgeService().findRelatedEdgeIdsByEntityId(tenantId, originatorId, ctx.getDbCallbackExecutor()); } } From 1d5f5c5d8037c5cc7dfa6ee70cb15ca554d0c327 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 25 Aug 2020 14:04:47 +0300 Subject: [PATCH 086/156] code fixes --- .../edge/DefaultEdgeNotificationService.java | 8 ++-- .../service/edge/rpc/EdgeGrpcSession.java | 48 +++++++++++++++---- .../server/dao/edge/EdgeService.java | 3 +- .../server/dao/edge/EdgeServiceImpl.java | 15 +++--- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 2 +- 5 files changed, 53 insertions(+), 23 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 27489c98cc..fbc5bcf376 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -242,7 +242,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } } } else { - ListenableFuture> edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, dbCallbackExecutorService); + ListenableFuture> edgeIdsFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId); Futures.transform(edgeIdsFuture, edgeIds -> { if (edgeIds != null && !edgeIds.isEmpty()) { for (EdgeId edgeId : edgeIds) { @@ -321,7 +321,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { if (alarm != null) { EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType()); if (edgeEventType != null) { - ListenableFuture> relatedEdgeIdsByEntityIdFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), dbCallbackExecutorService); + ListenableFuture> relatedEdgeIdsByEntityIdFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator()); Futures.transform(relatedEdgeIdsByEntityIdFuture, relatedEdgeIdsByEntityId -> { if (relatedEdgeIdsByEntityId != null) { for (EdgeId edgeId : relatedEdgeIdsByEntityId) { @@ -346,8 +346,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && !relation.getTo().getEntityType().equals(EntityType.EDGE)) { List>> futures = new ArrayList<>(); - futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getTo(), dbCallbackExecutorService)); - futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom(), dbCallbackExecutorService)); + futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getTo())); + futures.add(edgeService.findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom())); ListenableFuture>> combinedFuture = Futures.allAsList(futures); Futures.transform(combinedFuture, listOfListsEdgeIds -> { Set uniqueEdgeIds = new HashSet<>(); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 86c45c78ba..99ffe79d9e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -25,6 +25,7 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.SettableFuture; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -937,25 +938,46 @@ public final class EdgeGrpcSession implements Closeable { } private ListenableFuture processPostTelemetry(EntityId entityId, TransportProtos.PostTelemetryMsg msg, TbMsgMetaData metaData) { + SettableFuture futureToSet = SettableFuture.create(); for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); metaData.putValue("ts", tsKv.getTs() + ""); TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_TELEMETRY_REQUEST.name(), entityId, metaData, gson.toJson(json)); - // TODO: voba - verify that null callback is OK - ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, null); + ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + futureToSet.setException(t); + } + }); } - return Futures.immediateFuture(null); + return futureToSet; } private ListenableFuture processPostAttributes(EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { + SettableFuture futureToSet = SettableFuture.create(); JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); - // TODO: voba - verify that null callback is OK - ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, null); - return Futures.immediateFuture(null); + ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + futureToSet.setException(t); + } + }); + return futureToSet; } private ListenableFuture processAttributeDeleteMsg(EntityId entityId, AttributeDeleteMsg attributeDeleteMsg, String entityType) { + SettableFuture futureToSet = SettableFuture.create(); try { String scope = attributeDeleteMsg.getScope(); List attributeNames = attributeDeleteMsg.getAttributeNamesList(); @@ -966,13 +988,23 @@ public final class EdgeGrpcSession implements Closeable { attributeKeys.add(new AttributeKey(scope, attributeName)); } ctx.getTbClusterService().pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( - edge.getTenantId(), (DeviceId) entityId, attributeKeys), null); + edge.getTenantId(), (DeviceId) entityId, attributeKeys), new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + futureToSet.setException(t); + } + }); } } catch (Exception e) { log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, e); return Futures.immediateFailedFuture(new RuntimeException("Can't process attribute delete msg " + attributeDeleteMsg, e)); } - return Futures.immediateFuture(null); + return futureToSet; } private ListenableFuture onDeviceUpdate(DeviceUpdateMsg deviceUpdateMsg) { diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index 71c56068d1..13702a13ef 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -30,7 +30,6 @@ import org.thingsboard.server.common.data.page.TextPageLink; import java.util.List; import java.util.Optional; -import java.util.concurrent.Executor; public interface EdgeService { @@ -76,7 +75,7 @@ public interface EdgeService { ListenableFuture> findEdgesByTenantIdAndDashboardId(TenantId tenantId, DashboardId dashboardId); - ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, Executor executorService); + ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 4ce86beea5..6d3aa3e901 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -67,7 +67,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; -import java.util.concurrent.Executor; import java.util.stream.Collectors; import static org.thingsboard.server.common.data.CacheConstants.EDGE_CACHE; @@ -429,7 +428,7 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic }; @Override - public ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, Executor executorService) { + public ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { switch (entityId.getEntityType()) { case DEVICE: case ASSET: @@ -442,11 +441,11 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic } else { return Collections.emptyList(); } - }, executorService); + }, MoreExecutors.directExecutor()); case DASHBOARD: - return convertToEdgeIds(findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId())), executorService); + return convertToEdgeIds(findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); case RULE_CHAIN: - return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId())), executorService); + return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); case USER: User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); TextPageData edges; @@ -455,20 +454,20 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic } else { edges = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); } - return convertToEdgeIds(Futures.immediateFuture(edges.getData()), executorService); + return convertToEdgeIds(Futures.immediateFuture(edges.getData())); default: return Futures.immediateFuture(Collections.emptyList()); } } - private ListenableFuture> convertToEdgeIds(ListenableFuture> future, Executor executorService) { + private ListenableFuture> convertToEdgeIds(ListenableFuture> future) { return Futures.transform(future, edges -> { if (edges != null && !edges.isEmpty()) { return edges.stream().map(IdBased::getId).collect(Collectors.toList()); } else { return Collections.emptyList(); } - }, executorService); + }, MoreExecutors.directExecutor()); } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index b531af7ed3..1c0e44050d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -232,7 +232,7 @@ public class TbMsgPushToEdgeNode implements TbNode { TextPageData edgesByTenantId = ctx.getEdgeService().findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); } else { - return ctx.getEdgeService().findRelatedEdgeIdsByEntityId(tenantId, originatorId, ctx.getDbCallbackExecutor()); + return ctx.getEdgeService().findRelatedEdgeIdsByEntityId(tenantId, originatorId); } } From 67fc2f5a197bbe53bf9bd3eb578193961a23e8a5 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 25 Aug 2020 14:22:58 +0300 Subject: [PATCH 087/156] added logs --- .../service/edge/rpc/EdgeGrpcSession.java | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 99ffe79d9e..670c595e72 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -951,6 +951,7 @@ public final class EdgeGrpcSession implements Closeable { @Override public void onFailure(Throwable t) { + log.error("Can't process post telemetry [{}]", msg, t); futureToSet.setException(t); } }); @@ -970,6 +971,7 @@ public final class EdgeGrpcSession implements Closeable { @Override public void onFailure(Throwable t) { + log.error("Can't process post attributes [{}]", msg, t); futureToSet.setException(t); } }); @@ -978,31 +980,27 @@ public final class EdgeGrpcSession implements Closeable { private ListenableFuture processAttributeDeleteMsg(EntityId entityId, AttributeDeleteMsg attributeDeleteMsg, String entityType) { SettableFuture futureToSet = SettableFuture.create(); - try { - String scope = attributeDeleteMsg.getScope(); - List attributeNames = attributeDeleteMsg.getAttributeNamesList(); - ctx.getAttributesService().removeAll(edge.getTenantId(), entityId, scope, attributeNames); - if (EntityType.DEVICE.name().equals(entityType)) { - Set attributeKeys = new HashSet<>(); - for (String attributeName : attributeNames) { - attributeKeys.add(new AttributeKey(scope, attributeName)); + String scope = attributeDeleteMsg.getScope(); + List attributeNames = attributeDeleteMsg.getAttributeNamesList(); + ctx.getAttributesService().removeAll(edge.getTenantId(), entityId, scope, attributeNames); + if (EntityType.DEVICE.name().equals(entityType)) { + Set attributeKeys = new HashSet<>(); + for (String attributeName : attributeNames) { + attributeKeys.add(new AttributeKey(scope, attributeName)); + } + ctx.getTbClusterService().pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( + edge.getTenantId(), (DeviceId) entityId, attributeKeys), new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); } - ctx.getTbClusterService().pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( - edge.getTenantId(), (DeviceId) entityId, attributeKeys), new TbQueueCallback() { - @Override - public void onSuccess(TbQueueMsgMetadata metadata) { - futureToSet.set(null); - } - @Override - public void onFailure(Throwable t) { - futureToSet.setException(t); - } - }); - } - } catch (Exception e) { - log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, e); - return Futures.immediateFailedFuture(new RuntimeException("Can't process attribute delete msg " + attributeDeleteMsg, e)); + @Override + public void onFailure(Throwable t) { + log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, t); + futureToSet.setException(t); + } + }); } return futureToSet; } From 883f8fff4c0db557ea7ef10743164c28026750fd Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 25 Aug 2020 19:23:49 +0300 Subject: [PATCH 088/156] fixed bug with connection to first node --- .../edge/rpc/constructor/RuleChainUpdateMsgConstructor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java index 52e487d973..1d81763a1f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java @@ -68,6 +68,8 @@ public class RuleChainUpdateMsgConstructor { .addAllRuleChainConnections(constructRuleChainConnections(ruleChainMetaData.getRuleChainConnections())); if (ruleChainMetaData.getFirstNodeIndex() != null) { builder.setFirstNodeIndex(ruleChainMetaData.getFirstNodeIndex()); + } else { + builder.setFirstNodeIndex(-1); } builder.setMsgType(msgType); return builder.build(); From 4ac8c0675b61256926f4e2cad49378a6e52467ea Mon Sep 17 00:00:00 2001 From: deaflynx Date: Thu, 27 Aug 2020 08:46:32 +0300 Subject: [PATCH 089/156] Fixed fetch edge rule chains --- ui/src/app/edge/edge.controller.js | 2 +- ui/src/app/edge/set-root-rule-chain-to-edges.controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/app/edge/edge.controller.js b/ui/src/app/edge/edge.controller.js index 7e57fce6a6..94f076c1af 100644 --- a/ui/src/app/edge/edge.controller.js +++ b/ui/src/app/edge/edge.controller.js @@ -552,7 +552,7 @@ export function EdgeController($rootScope, userService, edgeService, customerSer $event.stopPropagation(); } var pageSize = 10; - ruleChainService.getRuleChains({limit: pageSize, textSearch: ''}).then( + ruleChainService.getEdgesRuleChains({limit: pageSize, textSearch: ''}).then( function success(_ruleChains) { var ruleChains = { pageSize: pageSize, diff --git a/ui/src/app/edge/set-root-rule-chain-to-edges.controller.js b/ui/src/app/edge/set-root-rule-chain-to-edges.controller.js index a474fde6a7..a8d134b20e 100644 --- a/ui/src/app/edge/set-root-rule-chain-to-edges.controller.js +++ b/ui/src/app/edge/set-root-rule-chain-to-edges.controller.js @@ -53,7 +53,7 @@ export default function SetRootRuleChainToEdgesController(ruleChainService, edge fetchMoreItems_: function () { if (vm.ruleChains.hasNext && !vm.ruleChains.pending) { vm.ruleChains.pending = true; - ruleChainService.getRuleChains(vm.ruleChains.nextPageLink).then( + ruleChainService.getEdgesRuleChains(vm.ruleChains.nextPageLink).then( function success(ruleChains) { vm.ruleChains.data = vm.ruleChains.data.concat(ruleChains.data); vm.ruleChains.nextPageLink = ruleChains.nextPageLink; From aeaf2ed6c6f167ae37b5eca22d3a41cdd08663d6 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Thu, 27 Aug 2020 11:05:13 +0300 Subject: [PATCH 090/156] Added manage customer edges --- .../app/customer/customer-fieldset.tpl.html | 1 + ui/src/app/customer/customer.controller.js | 22 ++++++++++++++++++ ui/src/app/customer/customer.directive.js | 1 + ui/src/app/customer/customers.tpl.html | 1 + ui/src/app/edge/edge.routes.js | 23 +++++++++++++++++++ ui/src/app/locale/locale.constant-en_US.json | 3 +++ 6 files changed, 51 insertions(+) diff --git a/ui/src/app/customer/customer-fieldset.tpl.html b/ui/src/app/customer/customer-fieldset.tpl.html index 11b2d58fb8..a23959ef96 100644 --- a/ui/src/app/customer/customer-fieldset.tpl.html +++ b/ui/src/app/customer/customer-fieldset.tpl.html @@ -19,6 +19,7 @@ {{ 'customer.manage-assets' | translate }} {{ 'customer.manage-devices' | translate }} {{ 'customer.manage-dashboards' | translate }} +{{ 'customer.manage-edges' | translate }} {{ 'customer.delete' | translate }}
diff --git a/ui/src/app/customer/customer.controller.js b/ui/src/app/customer/customer.controller.js index 42a3801efa..c61962f9f3 100644 --- a/ui/src/app/customer/customer.controller.js +++ b/ui/src/app/customer/customer.controller.js @@ -77,6 +77,20 @@ export default function CustomerController(customerService, $state, $stateParams }, icon: "dashboard" }, + { + onAction: function ($event, item) { + openCustomerEdges($event, item); + }, + name: function() { return $translate.instant('edge.edges') }, + details: function(customer) { + if (customer && customer.additionalInfo && customer.additionalInfo.isPublic) { + return $translate.instant('customer.manage-public-edges') + } else { + return $translate.instant('customer.manage-customer-edges') + } + }, + icon: "router" + }, { onAction: function ($event, item) { vm.grid.deleteItem($event, item); @@ -147,6 +161,7 @@ export default function CustomerController(customerService, $state, $stateParams vm.openCustomerAssets = openCustomerAssets; vm.openCustomerDevices = openCustomerDevices; vm.openCustomerDashboards = openCustomerDashboards; + vm.openCustomerEdges = openCustomerEdges; function deleteCustomerTitle(customer) { return $translate.instant('customer.delete-customer-title', {customerTitle: customer.title}); @@ -216,4 +231,11 @@ export default function CustomerController(customerService, $state, $stateParams $state.go('home.customers.dashboards', {customerId: customer.id.id}); } + function openCustomerEdges($event, customer) { + if ($event) { + $event.stopPropagation(); + } + $state.go('home.customers.edges', {customerId: customer.id.id}); + } + } diff --git a/ui/src/app/customer/customer.directive.js b/ui/src/app/customer/customer.directive.js index ff1befaf9e..33245654bb 100644 --- a/ui/src/app/customer/customer.directive.js +++ b/ui/src/app/customer/customer.directive.js @@ -55,6 +55,7 @@ export default function CustomerDirective($compile, $templateCache, $translate, onManageAssets: '&', onManageDevices: '&', onManageDashboards: '&', + onManageEdges: '&', onDeleteCustomer: '&' } }; diff --git a/ui/src/app/customer/customers.tpl.html b/ui/src/app/customer/customers.tpl.html index 396fc6734b..755425a2ff 100644 --- a/ui/src/app/customer/customers.tpl.html +++ b/ui/src/app/customer/customers.tpl.html @@ -29,6 +29,7 @@ on-manage-assets="vm.openCustomerAssets(event, vm.grid.detailsConfig.currentItem)" on-manage-devices="vm.openCustomerDevices(event, vm.grid.detailsConfig.currentItem)" on-manage-dashboards="vm.openCustomerDashboards(event, vm.grid.detailsConfig.currentItem)" + on-manage-edges="vm.openCustomerEdges(event, vm.grid.detailsConfig.currentItem)" on-delete-customer="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"> diff --git a/ui/src/app/edge/edge.routes.js b/ui/src/app/edge/edge.routes.js index 1afd319609..e3443d1211 100644 --- a/ui/src/app/edge/edge.routes.js +++ b/ui/src/app/edge/edge.routes.js @@ -161,5 +161,28 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "dashboard", "label": "{{ vm.dashboard.title }}", "translate": "false"}' } + }) + .state('home.customers.edges', { + url: '/:customerId/edges', + params: {'topIndex': 0}, + module: 'private', + auth: ['TENANT_ADMIN'], + views: { + "content@home": { + templateUrl: edgesTemplate, + controllerAs: 'vm', + controller: 'EdgeController' + } + }, + data: { + edgesType: 'customer', + searchEnabled: true, + searchByEntitySubtype: true, + searchEntityType: types.entityType.edge, + pageTitle: 'customer.edges' + }, + ncyBreadcrumb: { + label: '{"icon": "router", "label": "{{ vm.customerEdgesTitle }}", "translate": "false"}' + } }); } diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index f8d1c8568a..a86d4b2ffd 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -441,6 +441,7 @@ "manage-assets": "Manage assets", "manage-devices": "Manage devices", "manage-dashboards": "Manage dashboards", + "manage-edges": "Manage edges", "title": "Title", "title-required": "Title is required.", "description": "Description", @@ -812,6 +813,8 @@ "assign-edges-text": "Assign { count, plural, 1 {1 edge} other {# edges} } to customer", "unassign-edge-title": "Are you sure you want to unassign the edge '{{edgeName}}'?", "unassign-edge-text": "After the confirmation the edge will be unassigned and won't be accessible by the customer.", + "unassign-edges-title": "Are you sure you want to unassign { count, plural, 1 {1 edge} other {# edges} }?", + "unassign-edges-text": "After the confirmation all selected edges will be unassigned and won't be accessible by the customer.", "make-public": "Make edge public", "make-public-edge-title": "Are you sure you want to make the edge '{{edgeName}}' public?", "make-public-edge-text": "After the confirmation the edge and all its data will be made public and accessible by others.", From 9c8ceaa37e72ffe1f21532752a777c46f6ca6459 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 28 Aug 2020 14:14:07 +0300 Subject: [PATCH 091/156] Properly handle entities assign/unassign to/from customer --- .../server/controller/AssetController.java | 13 +- .../server/controller/BaseController.java | 11 ++ .../server/controller/CustomerController.java | 5 + .../controller/DashboardController.java | 14 +- .../server/controller/DeviceController.java | 11 +- .../server/controller/EdgeController.java | 8 +- .../controller/EntityViewController.java | 13 +- .../controller/RuleChainController.java | 5 +- .../edge/DefaultEdgeNotificationService.java | 141 ++++++++++++++---- .../service/edge/rpc/EdgeGrpcSession.java | 90 +++++++---- .../AssetUpdateMsgConstructor.java | 9 +- .../DashboardUpdateMsgConstructor.java | 8 +- .../DeviceUpdateMsgConstructor.java | 8 +- .../EntityViewUpdateMsgConstructor.java | 8 +- .../constructor/UserUpdateMsgConstructor.java | 12 +- .../edge/rpc/init/DefaultSyncEdgeService.java | 6 +- .../thingsboard/edge/rpc/EdgeGrpcClient.java | 10 +- common/edge-api/src/main/proto/edge.proto | 34 +++-- .../server/dao/asset/BaseAssetService.java | 8 +- .../server/dao/device/DeviceServiceImpl.java | 10 +- .../server/dao/edge/EdgeServiceImpl.java | 14 +- .../dao/entity/AbstractEntityService.java | 26 ++++ .../dao/entityview/EntityViewServiceImpl.java | 12 ++ 23 files changed, 366 insertions(+), 110 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 0877937afa..2f5b848b29 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -84,7 +84,7 @@ public class AssetController extends BaseController { try { asset.setTenantId(getCurrentUser().getTenantId()); - checkEntity(asset.getId(), asset, Resource.ASSET); + checkEntity(asset.getId(), asset, Resource.ASSET); Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); @@ -92,8 +92,9 @@ public class AssetController extends BaseController { savedAsset.getCustomerId(), asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(), - asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + if (asset.getId() != null) { + sendNotificationMsgToEdgeService(savedAsset.getTenantId(), savedAsset.getId(), ActionType.UPDATED); + } return savedAsset; } catch (Exception e) { @@ -147,6 +148,9 @@ public class AssetController extends BaseController { savedAsset.getCustomerId(), ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, strCustomerId, customer.getName()); + sendNotificationMsgToEdgeService(savedAsset.getTenantId(), savedAsset.getId(), + customerId, ActionType.ASSIGNED_TO_CUSTOMER); + return savedAsset; } catch (Exception e) { @@ -178,6 +182,9 @@ public class AssetController extends BaseController { asset.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strAssetId, customer.getId().toString(), customer.getName()); + sendNotificationMsgToEdgeService(savedAsset.getTenantId(), savedAsset.getId(), + customer.getId(), ActionType.UNASSIGNED_FROM_CUSTOMER); + return savedAsset; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 390b2187fa..79fa90cbdf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -726,6 +726,17 @@ public abstract class BaseController { } } + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, CustomerId customerId, ActionType edgeEventAction) { + EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); + try { + if (edgeEventType != null) { + sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), edgeEventType, edgeEventAction); + } + } catch (Exception e) { + log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); + } + } + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) { try { if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index 75dee42ff8..6e7ca50418 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -108,6 +108,10 @@ public class CustomerController extends BaseController { savedCustomer.getId(), customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); + if (customer.getId() != null) { + sendNotificationMsgToEdgeService(savedCustomer.getTenantId(), savedCustomer.getId(),ActionType.UPDATED); + } + return savedCustomer; } catch (Exception e) { @@ -132,6 +136,7 @@ public class CustomerController extends BaseController { customer.getId(), ActionType.DELETED, null, strCustomerId); + sendNotificationMsgToEdgeService(getTenantId(), customerId, ActionType.DELETED); } catch (Exception e) { logEntityAction(emptyId(EntityType.CUSTOMER), diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index 0ae455d8f4..31c7a7d0b7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -117,8 +117,9 @@ public class DashboardController extends BaseController { null, dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), - dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + if (dashboard.getId() != null) { + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), ActionType.UPDATED); + } return savedDashboard; } catch (Exception e) { @@ -175,6 +176,7 @@ public class DashboardController extends BaseController { customerId, ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, strCustomerId, customer.getName()); + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), customerId, ActionType.ASSIGNED_TO_CUSTOMER); return savedDashboard; } catch (Exception e) { @@ -206,6 +208,8 @@ public class DashboardController extends BaseController { customerId, ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customer.getId().toString(), customer.getName()); + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), customerId, ActionType.UNASSIGNED_FROM_CUSTOMER); + return savedDashboard; } catch (Exception e) { @@ -261,6 +265,7 @@ public class DashboardController extends BaseController { logEntityAction(dashboardId, savedDashboard, customerId, ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle()); + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), customerId, ActionType.ASSIGNED_TO_CUSTOMER); } for (CustomerId customerId : removedCustomerIds) { ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId); @@ -268,7 +273,7 @@ public class DashboardController extends BaseController { logEntityAction(dashboardId, dashboard, customerId, ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle()); - + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), customerId, ActionType.UNASSIGNED_FROM_CUSTOMER); } return savedDashboard; } @@ -312,6 +317,7 @@ public class DashboardController extends BaseController { logEntityAction(dashboardId, savedDashboard, customerId, ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle()); + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), customerId, ActionType.ASSIGNED_TO_CUSTOMER); } return savedDashboard; } @@ -355,7 +361,7 @@ public class DashboardController extends BaseController { logEntityAction(dashboardId, dashboard, customerId, ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle()); - + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(), customerId, ActionType.UNASSIGNED_FROM_CUSTOMER); } return savedDashboard; } diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index b65d6387c2..da9e352dc9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -108,8 +108,9 @@ public class DeviceController extends BaseController { tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(), savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null); - sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(), - device.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + if (device.getId() != null) { + sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(),ActionType.UPDATED); + } logEntityAction(savedDevice.getId(), savedDevice, savedDevice.getCustomerId(), @@ -174,6 +175,9 @@ public class DeviceController extends BaseController { savedDevice.getCustomerId(), ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, strCustomerId, customer.getName()); + sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(), + customerId, ActionType.ASSIGNED_TO_CUSTOMER); + return savedDevice; } catch (Exception e) { logEntityAction(emptyId(EntityType.DEVICE), null, @@ -202,6 +206,9 @@ public class DeviceController extends BaseController { device.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDeviceId, customer.getId().toString(), customer.getName()); + sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(), + customer.getId(), ActionType.UNASSIGNED_FROM_CUSTOMER); + return savedDevice; } catch (Exception e) { logEntityAction(emptyId(EntityType.DEVICE), null, diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 19b82b3b85..44be68b4c2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -174,6 +174,9 @@ public class EdgeController extends BaseController { Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(getCurrentUser().getTenantId(), edgeId, customerId)); + tbClusterService.onEntityStateChange(getTenantId(), edgeId, + ComponentLifecycleEvent.UPDATED); + logEntityAction(edgeId, savedEdge, savedEdge.getCustomerId(), ActionType.ASSIGNED_TO_CUSTOMER, null, strEdgeId, strCustomerId, customer.getName()); @@ -205,12 +208,15 @@ public class EdgeController extends BaseController { Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(getCurrentUser().getTenantId(), edgeId)); + tbClusterService.onEntityStateChange(getTenantId(), edgeId, + ComponentLifecycleEvent.UPDATED); + logEntityAction(edgeId, edge, edge.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEdgeId, customer.getId().toString(), customer.getName()); sendNotificationMsgToEdgeService(savedEdge.getTenantId(), savedEdge.getId(), - edge.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER); + customer.getId(), ActionType.UNASSIGNED_FROM_CUSTOMER); return savedEdge; } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index 821dbcbd70..b4762accab 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -118,8 +118,10 @@ public class EntityViewController extends BaseController { logEntityAction(savedEntityView.getId(), savedEntityView, null, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), - entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED); + if (entityView.getId() != null) { + sendNotificationMsgToEdgeService(savedEntityView.getTenantId(), savedEntityView.getId(), ActionType.UPDATED); + } + return savedEntityView; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, @@ -231,6 +233,10 @@ public class EntityViewController extends BaseController { logEntityAction(entityViewId, savedEntityView, savedEntityView.getCustomerId(), ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, strCustomerId, customer.getName()); + + sendNotificationMsgToEdgeService(savedEntityView.getTenantId(), savedEntityView.getId(), + customerId, ActionType.ASSIGNED_TO_CUSTOMER); + return savedEntityView; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, @@ -257,6 +263,9 @@ public class EntityViewController extends BaseController { entityView.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName()); + sendNotificationMsgToEdgeService(savedEntityView.getTenantId(), savedEntityView.getId(), + customer.getId(), ActionType.UNASSIGNED_FROM_CUSTOMER); + return savedEntityView; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 4d2e78bc67..3b483782d9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -145,8 +145,9 @@ public class RuleChainController extends BaseController { created ? ActionType.ADDED : ActionType.UPDATED, null); if (RuleChainType.EDGE.equals(savedRuleChain.getType())) { - sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(), savedRuleChain.getId(), - created ? ActionType.ADDED : ActionType.UPDATED); + if (!created) { + sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(), savedRuleChain.getId(), ActionType.UPDATED); + } } return savedRuleChain; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 279ec96064..0a85dcacf5 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -54,7 +54,6 @@ import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; -import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.user.UserService; @@ -166,9 +165,14 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case ENTITY_VIEW: case DASHBOARD: case RULE_CHAIN: + processEntity(tenantId, edgeNotificationMsg); + break; + case CUSTOMER: + processCustomer(tenantId, edgeNotificationMsg); + break; case WIDGETS_BUNDLE: case WIDGET_TYPE: - processEntity(tenantId, edgeNotificationMsg); + processWidgetBundleOrWidgetType(tenantId, edgeNotificationMsg); break; case ALARM: processAlarm(tenantId, edgeNotificationMsg); @@ -188,26 +192,24 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } private void processEdge(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { - // TODO: voba - handle edge updates try { ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); + ListenableFuture edgeFuture; switch (edgeEventActionType) { case ASSIGNED_TO_CUSTOMER: - case UNASSIGNED_FROM_CUSTOMER: CustomerId customerId = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); - ListenableFuture edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); + edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); Futures.addCallback(edgeFuture, new FutureCallback() { @Override public void onSuccess(@Nullable Edge edge) { - if (edge != null && customerId != null && !EntityId.NULL_UUID.equals(customerId.getId())) { - ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER.equals(edgeEventActionType) ? ActionType.ADDED : ActionType.DELETED; - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, actionType, customerId, null); + if (edge != null && !customerId.isNullUid()) { + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, ActionType.ADDED, customerId, null); TextPageData pageData = userService.findCustomerUsers(tenantId, customerId, new TextPageLink(Integer.MAX_VALUE)); if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - log.trace("[{}] [{}] user(s) are going to be {} to edge.", edge.getId(), pageData.getData().size(), actionType.name()); + log.trace("[{}] [{}] user(s) are going to be added to edge.", edge.getId(), pageData.getData().size()); for (User user : pageData.getData()) { - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, actionType, user.getId(), null); + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.ADDED, user.getId(), null); } } } @@ -219,44 +221,129 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } }, dbCallbackExecutorService); break; + case UNASSIGNED_FROM_CUSTOMER: + CustomerId customerIdToDelete = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); + edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); + Futures.addCallback(edgeFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable Edge edge) { + if (edge != null && !customerIdToDelete.isNullUid()) { + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, ActionType.DELETED, customerIdToDelete, null); + } + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't find edge by id [{}]", edgeNotificationMsg, t); + } + }, dbCallbackExecutorService); + break; } } catch (Exception e) { log.error("Exception during processing edge event", e); } } - private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { + private void processWidgetBundleOrWidgetType(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); switch (edgeEventActionType) { - // TODO: voba - ADDED is not required for CE version ? case ADDED: case UPDATED: - case CREDENTIALS_UPDATED: - if (edgeEventType.equals(EdgeEventType.WIDGETS_BUNDLE) || edgeEventType.equals(EdgeEventType.WIDGET_TYPE)) { - TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); - if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { - for (Edge edge : edgesByTenantId.getData()) { + case DELETED: + TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { + for (Edge edge : edgesByTenantId.getData()) { + saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); + } + } + break; + } + } + + private void processCustomer(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { + ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); + EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); + EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); + TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { + for (Edge edge : edgesByTenantId.getData()) { + switch (edgeEventActionType) { + case UPDATED: + if (!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(entityId)) { saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); } + break; + case DELETED: + saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); + break; + } + } + } + } + + private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { + ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); + EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); + EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); + ListenableFuture> edgeIdsFuture; + switch (edgeEventActionType) { + case ADDED: // used only for USER entity + case UPDATED: + case CREDENTIALS_UPDATED: + edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); + Futures.addCallback(edgeIdsFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List edgeIds) { + if (edgeIds != null && !edgeIds.isEmpty()) { + for (EdgeId edgeId : edgeIds) { + saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + } + } } - } else { - ListenableFuture> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); - Futures.transform(edgeIdsFuture, edgeIds -> { + @Override + public void onFailure(Throwable throwable) { + log.error("Failed to find related edge ids [{}]", edgeNotificationMsg, throwable); + } + }, dbCallbackExecutorService); + break; + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: + edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); + Futures.addCallback(edgeIdsFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List edgeIds) { if (edgeIds != null && !edgeIds.isEmpty()) { for (EdgeId edgeId : edgeIds) { try { - saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + CustomerId customerId = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); + ListenableFuture future = edgeService.findEdgeByIdAsync(tenantId, edgeId); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable Edge edge) { + if (edge != null && edge.getCustomerId() != null && + !edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(customerId)) { + saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + } + } + @Override + public void onFailure(Throwable throwable) { + log.error("Failed to find edge by id [{}]", edgeNotificationMsg, throwable); + } + }, dbCallbackExecutorService); } catch (Exception e) { - log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]", - tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e); + log.error("Can't parse customer id from entity body [{}]", edgeNotificationMsg, e); } } } - return null; - }, dbCallbackExecutorService); - } + } + + @Override + public void onFailure(Throwable throwable) { + log.error("Failed to find related edge ids [{}]", edgeNotificationMsg, throwable); + } + }, dbCallbackExecutorService); break; case DELETED: TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); @@ -394,7 +481,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { case USER: User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); TextPageData edges; - if (userById.getCustomerId() == null || userById.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { + if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { edges = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); } else { edges = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 121772a01b..e036349ab1 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -17,14 +17,13 @@ package org.thingsboard.server.service.edge.rpc; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.SettableFuture; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -40,6 +39,7 @@ import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; @@ -73,7 +73,6 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; -import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.UserCredentials; @@ -138,8 +137,6 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.function.Consumer; -import static org.thingsboard.server.gen.edge.UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE; - @Slf4j @Data public final class EdgeGrpcSession implements Closeable { @@ -185,13 +182,14 @@ public final class EdgeGrpcSession implements Closeable { public void onNext(RequestMsg requestMsg) { if (!connected && requestMsg.getMsgType().equals(RequestMsgType.CONNECT_RPC_MESSAGE)) { ConnectResponseMsg responseMsg = processConnect(requestMsg.getConnectRequestMsg()); - sendResponseMsg(ResponseMsg.newBuilder() + outputStream.onNext(ResponseMsg.newBuilder() .setConnectResponseMsg(responseMsg) .build()); if (ConnectResponseCode.ACCEPTED != responseMsg.getResponseCode()) { outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); } if (ConnectResponseCode.ACCEPTED == responseMsg.getResponseCode()) { + connected = true; ctx.getSyncEdgeService().sync(edge); } } @@ -212,6 +210,7 @@ public final class EdgeGrpcSession implements Closeable { @Override public void onCompleted() { + connected = false; sessionCloseListener.accept(edge.getId()); outputStream.onCompleted(); } @@ -257,6 +256,10 @@ public final class EdgeGrpcSession implements Closeable { try { responseMsgLock.lock(); outputStream.onNext(responseMsg); + } catch (Exception e) { + log.error("Failed to send response message [{}]", responseMsg, e); + connected = false; + sessionCloseListener.accept(edge.getId()); } finally { responseMsgLock.unlock(); } @@ -337,14 +340,16 @@ public final class EdgeGrpcSession implements Closeable { switch (edgeEventAction) { case UPDATED: case ADDED: - case ASSIGNED_TO_EDGE: case DELETED: + case ASSIGNED_TO_EDGE: case UNASSIGNED_FROM_EDGE: case ALARM_ACK: case ALARM_CLEAR: case CREDENTIALS_UPDATED: case RELATION_ADD_OR_UPDATE: case RELATION_DELETED: + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: downlinkMsg = processEntityMessage(edgeEvent, edgeEventAction); break; case ATTRIBUTES_UPDATED: @@ -464,10 +469,13 @@ public final class EdgeGrpcSession implements Closeable { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: Device device = ctx.getDeviceService().findDeviceById(edgeEvent.getTenantId(), deviceId); if (device != null) { + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); DeviceUpdateMsg deviceUpdateMsg = - ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device); + ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) .build(); @@ -502,10 +510,13 @@ public final class EdgeGrpcSession implements Closeable { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: Asset asset = ctx.getAssetService().findAssetById(edgeEvent.getTenantId(), assetId); if (asset != null) { + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(asset); AssetUpdateMsg assetUpdateMsg = - ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset); + ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) .build(); @@ -530,10 +541,13 @@ public final class EdgeGrpcSession implements Closeable { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: EntityView entityView = ctx.getEntityViewService().findEntityViewById(edgeEvent.getTenantId(), entityViewId); if (entityView != null) { + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(entityView); EntityViewUpdateMsg entityViewUpdateMsg = - ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView); + ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) .build(); @@ -558,10 +572,16 @@ public final class EdgeGrpcSession implements Closeable { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: Dashboard dashboard = ctx.getDashboardService().findDashboardById(edgeEvent.getTenantId(), dashboardId); if (dashboard != null) { + CustomerId customerId = null; + if (!edge.getCustomerId().isNullUid() && dashboard.isAssignedToCustomer(edge.getCustomerId())) { + customerId = edge.getCustomerId(); + } DashboardUpdateMsg dashboardUpdateMsg = - ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard); + ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) .build(); @@ -654,19 +674,15 @@ public final class EdgeGrpcSession implements Closeable { switch (edgeActionType) { case ADDED: case UPDATED: - case ASSIGNED_TO_EDGE: User user = ctx.getUserService().findUserById(edgeEvent.getTenantId(), userId); if (user != null) { - boolean fullAccess = Authority.TENANT_ADMIN.equals(user.getAuthority()); - setFullAccess(user, fullAccess); - + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(user); downlinkMsg = DownlinkMsg.newBuilder() - .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user))) + .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user, customerId))) .build(); } break; case DELETED: - case UNASSIGNED_FROM_EDGE: downlinkMsg = DownlinkMsg.newBuilder() .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId))) .build(); @@ -684,13 +700,12 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private void setFullAccess(User user, boolean isFullAccess) { - JsonNode additionalInfo = user.getAdditionalInfo(); - if (additionalInfo == null || additionalInfo instanceof NullNode) { - additionalInfo = mapper.createObjectNode(); + private CustomerId getCustomerIdIfEdgeAssignedToCustomer(HasCustomerId hasCustomerIdEntity) { + if (!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(hasCustomerIdEntity.getCustomerId())) { + return edge.getCustomerId(); + } else { + return null; } - ((ObjectNode) additionalInfo).put("isFullAccess", isFullAccess); - user.setAdditionalInfo(additionalInfo); } private DownlinkMsg processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { @@ -781,11 +796,13 @@ public final class EdgeGrpcSession implements Closeable { switch (actionType) { case UPDATED: case CREDENTIALS_UPDATED: + case ASSIGNED_TO_CUSTOMER: + case UNASSIGNED_FROM_CUSTOMER: return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; case ADDED: case ASSIGNED_TO_EDGE: case RELATION_ADD_OR_UPDATE: - return ENTITY_CREATED_RPC_MESSAGE; + return UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE; case DELETED: case UNASSIGNED_FROM_EDGE: case RELATION_DELETED: @@ -923,6 +940,8 @@ public final class EdgeGrpcSession implements Closeable { return new TenantId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); case CUSTOMER: return new CustomerId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case USER: + return new UserId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); default: log.warn("Unsupported entity type [{}] during construct of entity id. EntityDataProto [{}]", entityData.getEntityType(), entityData); return null; @@ -930,14 +949,24 @@ public final class EdgeGrpcSession implements Closeable { } private ListenableFuture processPostTelemetry(EntityId entityId, TransportProtos.PostTelemetryMsg msg, TbMsgMetaData metaData) { + SettableFuture futureToSet = SettableFuture.create(); for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); metaData.putValue("ts", tsKv.getTs() + ""); TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_TELEMETRY_REQUEST.name(), entityId, metaData, gson.toJson(json)); - // TODO: voba - verify that null callback is OK - ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, null); + ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + futureToSet.setException(t); + } + }); } - return Futures.immediateFuture(null); + return futureToSet; } private ListenableFuture processPostAttributes(EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { @@ -957,7 +986,8 @@ public final class EdgeGrpcSession implements Closeable { if (device != null) { // device with this name already exists on the cloud - update ID on the edge if (!device.getId().equals(edgeDeviceId)) { - DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device); + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); + DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() .addAllDeviceUpdateMsg(Collections.singletonList(d)) .build(); @@ -970,7 +1000,8 @@ public final class EdgeGrpcSession implements Closeable { if (deviceById != null) { // this ID already used by other device - create new device and update ID on the edge device = createDevice(deviceUpdateMsg); - DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device); + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); + DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() .addAllDeviceUpdateMsg(Collections.singletonList(d)) .build(); @@ -1250,7 +1281,6 @@ public final class EdgeGrpcSession implements Closeable { edge = optional.get(); try { if (edge.getSecret().equals(request.getEdgeSecret())) { - connected = true; sessionOpenListener.accept(edge.getId(), this); return ConnectResponseMsg.newBuilder() .setResponseCode(ConnectResponseCode.ACCEPTED) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java index c404fe5c41..ddcb531583 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java @@ -17,8 +17,11 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -26,7 +29,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Slf4j public class AssetUpdateMsgConstructor { - public AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset) { + public AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset, CustomerId customerId) { AssetUpdateMsg.Builder builder = AssetUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(asset.getId().getId().getMostSignificantBits()) @@ -36,6 +39,10 @@ public class AssetUpdateMsgConstructor { if (asset.getLabel() != null) { builder.setLabel(asset.getLabel()); } + if (customerId != null) { + builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); + builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java index 6c52464326..69b9d8dbd2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java @@ -18,7 +18,9 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -27,13 +29,17 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Slf4j public class DashboardUpdateMsgConstructor { - public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) { + public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard, CustomerId customerId) { DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(dashboard.getId().getId().getMostSignificantBits()) .setIdLSB(dashboard.getId().getId().getLeastSignificantBits()) .setTitle(dashboard.getTitle()) .setConfiguration(JacksonUtil.toString(dashboard.getConfiguration())); + if (customerId != null) { + builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); + builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java index dcef0a57c6..885511b3db 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java @@ -18,7 +18,9 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; @@ -28,7 +30,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Slf4j public class DeviceUpdateMsgConstructor { - public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) { + public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId) { DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(device.getId().getId().getMostSignificantBits()) @@ -38,6 +40,10 @@ public class DeviceUpdateMsgConstructor { if (device.getLabel() != null) { builder.setLabel(device.getLabel()); } + if (customerId != null) { + builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); + builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java index 2ca0b4fcbe..af61e9e4ad 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java @@ -18,6 +18,8 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.gen.edge.EdgeEntityType; import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; @@ -27,7 +29,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Slf4j public class EntityViewUpdateMsgConstructor { - public EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView) { + public EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView, CustomerId customerId) { EdgeEntityType entityType; switch (entityView.getEntityId().getEntityType()) { case DEVICE: @@ -48,6 +50,10 @@ public class EntityViewUpdateMsgConstructor { .setEntityIdMSB(entityView.getEntityId().getId().getMostSignificantBits()) .setEntityIdLSB(entityView.getEntityId().getId().getLeastSignificantBits()) .setEntityType(entityType); + if (customerId != null) { + builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); + builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java index b50e0c2b5e..4240d21292 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java @@ -18,6 +18,8 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.util.mapping.JacksonUtil; @@ -25,20 +27,22 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.UserUpdateMsg; +import java.util.UUID; + @Component @Slf4j public class UserUpdateMsgConstructor { - public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user) { + public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user, CustomerId customerId) { UserUpdateMsg.Builder builder = UserUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(user.getId().getId().getMostSignificantBits()) .setIdLSB(user.getId().getId().getLeastSignificantBits()) .setEmail(user.getEmail()) .setAuthority(user.getAuthority().name()); - if (user.getCustomerId() != null) { - builder.setCustomerIdMSB(user.getCustomerId().getId().getMostSignificantBits()); - builder.setCustomerIdLSB(user.getCustomerId().getId().getLeastSignificantBits()); + if (customerId != null) { + builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); + builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); } if (user.getFirstName() != null) { builder.setFirstName(user.getFirstName()); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index cfe8f86fd6..27ea1379f5 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -140,14 +140,14 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Override public void sync(Edge edge) { try { - syncUsers(edge); + syncWidgetsBundleAndWidgetTypes(edge); + syncAdminSettings(edge); syncRuleChains(edge); + syncUsers(edge); syncDevices(edge); syncAssets(edge); syncEntityViews(edge); syncDashboards(edge); - syncWidgetsBundleAndWidgetTypes(edge); - syncAdminSettings(edge); } catch (Exception e) { log.error("Exception during sync process", e); } diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 45201d3229..57c1cf272e 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -104,7 +104,10 @@ public class EdgeGrpcClient implements EdgeRpcClient { @Override public void disconnect() throws InterruptedException { - inputStream.onCompleted(); + try { + inputStream.onCompleted(); + } catch (Exception e) { + } if (channel != null) { channel.shutdown().awaitTermination(timeoutSecs, TimeUnit.SECONDS); } @@ -151,6 +154,11 @@ public class EdgeGrpcClient implements EdgeRpcClient { onEdgeUpdate.accept(connectResponseMsg.getConfiguration()); } else { log.error("[{}] Failed to establish the connection! Code: {}. Error message: {}.", edgeKey, connectResponseMsg.getResponseCode(), connectResponseMsg.getErrorMsg()); + try { + EdgeGrpcClient.this.disconnect(); + } catch (InterruptedException e) { + log.error("[{}] Got interruption during disconnect!", edgeKey, e); + } onError.accept(new EdgeConnectionException("Failed to establish the connection! Response code: " + connectResponseMsg.getResponseCode().name())); } } else if (responseMsg.hasUplinkResponseMsg()) { diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 3d91595a2f..35be11839f 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -154,17 +154,21 @@ message DashboardUpdateMsg { UpdateMsgType msgType = 1; int64 idMSB = 2; int64 idLSB = 3; - string title = 4; - string configuration = 5; + int64 customerIdMSB = 4; + int64 customerIdLSB = 5; + string title = 6; + string configuration = 7; } message DeviceUpdateMsg { UpdateMsgType msgType = 1; int64 idMSB = 2; int64 idLSB = 3; - string name = 4; - string type = 5; - string label = 6; + int64 customerIdMSB = 4; + int64 customerIdLSB = 5; + string name = 6; + string type = 7; + string label = 8; } message DeviceCredentialsUpdateMsg { @@ -179,20 +183,24 @@ message AssetUpdateMsg { UpdateMsgType msgType = 1; int64 idMSB = 2; int64 idLSB = 3; - string name = 4; - string type = 5; - string label = 6; + int64 customerIdMSB = 4; + int64 customerIdLSB = 5; + string name = 6; + string type = 7; + string label = 8; } message EntityViewUpdateMsg { UpdateMsgType msgType = 1; int64 idMSB = 2; int64 idLSB = 3; - string name = 4; - string type = 5; - int64 entityIdMSB = 6; - int64 entityIdLSB = 7; - EdgeEntityType entityType = 8; + int64 customerIdMSB = 4; + int64 customerIdLSB = 5; + string name = 6; + string type = 7; + int64 entityIdMSB = 8; + int64 entityIdLSB = 9; + EdgeEntityType entityType = 10; } message AlarmUpdateMsg { diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index 62f68e962c..d23f840938 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -30,7 +30,6 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Customer; -import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; @@ -53,7 +52,6 @@ import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.customer.CustomerDao; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; -import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; @@ -92,9 +90,6 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ @Autowired private CustomerDao customerDao; - @Autowired - private EntityViewService entityViewService; - @Autowired private EdgeService edgeService; @@ -317,6 +312,9 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ if (edge == null) { throw new DataValidationException("Can't unassign asset from non-existent edge!"); } + + checkAssignedEntityViewsToEdge(tenantId, assetId, edgeId); + try { deleteRelation(tenantId, new EntityRelation(edgeId, assetId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE)); } catch (ExecutionException | InterruptedException e) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index c8f24262a1..31d3f1a7ab 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; @@ -50,17 +49,14 @@ import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.dao.customer.CustomerDao; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; -import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; -import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.tenant.TenantDao; import javax.annotation.Nullable; @@ -102,9 +98,6 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe @Autowired private DeviceCredentialsService deviceCredentialsService; - @Autowired - private EntityViewService entityViewService; - @Autowired private EdgeService edgeService; @@ -357,6 +350,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe if (edge == null) { throw new DataValidationException("Can't unassign device from non-existent edge!"); } + + checkAssignedEntityViewsToEdge(tenantId, deviceId, edgeId); + try { deleteRelation(tenantId, new EntityRelation(edgeId, deviceId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE)); } catch (ExecutionException | InterruptedException e) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 01f82faa17..0cc5c056d8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -41,14 +41,15 @@ import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.common.data.page.TimePageData; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.customer.CustomerDao; import org.thingsboard.server.dao.dashboard.DashboardService; +import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.entity.AbstractEntityService; +import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; @@ -94,6 +95,15 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @Autowired private CacheManager cacheManager; + @Autowired + private AssetService assetService; + + @Autowired + private DeviceService deviceService; + + @Autowired + private EntityViewService entityViewService; + @Autowired private DashboardService dashboardService; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java index 523df59db5..deb2f75c6e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java @@ -19,12 +19,18 @@ import lombok.extern.slf4j.Slf4j; import org.hibernate.exception.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.dao.entityview.EntityViewService; +import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.relation.RelationService; import javax.annotation.PostConstruct; +import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; @@ -37,6 +43,9 @@ public abstract class AbstractEntityService { @Autowired protected RelationService relationService; + @Autowired + protected EntityViewService entityViewService; + @Value("${database.entities.type:sql}") private String databaseType; @@ -72,4 +81,21 @@ public abstract class AbstractEntityService { } } + protected void checkAssignedEntityViewsToEdge(TenantId tenantId, EntityId entityId, EdgeId edgeId) { + try { + List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId).get(); + if (entityViews != null && !entityViews.isEmpty()) { + EntityView entityView = entityViews.get(0); + Boolean relationExists = relationService.checkRelation(tenantId,edgeId, entityView.getId(), + EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE).get(); + if (relationExists) { + throw new DataValidationException("Can't unassign device/asset from edge that is related to entity view and entity view is assigned to edge!"); + } + } + } catch (ExecutionException | InterruptedException e) { + log.error("Exception while finding entity views for entityId [{}]", entityId, e); + throw new RuntimeException("Exception while finding entity views for entityId [" + entityId + "]", e); + } + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 907072e549..8729085ded 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -305,6 +305,18 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti if (!edge.getTenantId().getId().equals(entityView.getTenantId().getId())) { throw new DataValidationException("Can't assign entityView to edge from different tenant!"); } + + try { + Boolean relationExists = relationService.checkRelation(tenantId, edgeId, entityView.getEntityId(), + EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE).get(); + if (!relationExists) { + throw new DataValidationException("Can't assign entity view to edge because related device/asset doesn't assigned to edge!"); + } + } catch (ExecutionException | InterruptedException e) { + log.error("Exception during relation check", e); + throw new RuntimeException("Exception during relation check", e); + } + try { createRelation(tenantId, new EntityRelation(edgeId, entityViewId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE)); } catch (ExecutionException | InterruptedException e) { From 1de29d7b51f02f8afd0286a40beafb3a257f9823 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 28 Aug 2020 15:27:43 +0300 Subject: [PATCH 092/156] Remove unused code --- .../dao/dashboard/DashboardService.java | 2 -- .../server/dao/rule/RuleChainService.java | 2 -- .../dao/dashboard/DashboardServiceImpl.java | 36 ------------------- .../server/dao/edge/EdgeServiceImpl.java | 16 --------- .../server/dao/rule/BaseRuleChainService.java | 35 ------------------ 5 files changed, 91 deletions(-) diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java index f16d551eae..22ebff199c 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java @@ -59,7 +59,5 @@ public interface DashboardService { Dashboard unassignDashboardFromEdge(TenantId tenantId, DashboardId dashboardId, EdgeId edgeId); - void unassignEdgeDashboards(TenantId tenantId, EdgeId edgeId); - ListenableFuture> findDashboardsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java index d0e28a4a57..6fd168c915 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java @@ -71,8 +71,6 @@ public interface RuleChainService { RuleChain unassignRuleChainFromEdge(TenantId tenantId, RuleChainId ruleChainId, EdgeId edgeId, boolean remove); - void unassignEdgeRuleChains(TenantId tenantId, EdgeId edgeId); - ListenableFuture> findRuleChainsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); RuleChain getDefaultRootEdgeRuleChain(TenantId tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java index 06bf99f5c3..8b228c1984 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java @@ -260,17 +260,6 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb return dashboard; } - @Override - public void unassignEdgeDashboards(TenantId tenantId, EdgeId edgeId) { - log.trace("Executing unassignEdgeDashboards, edgeId [{}]", edgeId); - Validator.validateId(edgeId, "Incorrect edgeId " + edgeId); - Edge edge = edgeDao.findById(tenantId, edgeId.getId()); - if (edge == null) { - throw new DataValidationException("Can't unassign dashboards from non-existent edge!"); - } - new EdgeDashboardsUnassigner(edge).removeEntities(tenantId, edge); - } - @Override public ListenableFuture> findDashboardsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) { log.trace("Executing findDashboardsByTenantIdAndEdgeId, tenantId [{}], edgeId [{}], pageLink [{}]", tenantId, edgeId, pageLink); @@ -369,29 +358,4 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb } } - - private class EdgeDashboardsUnassigner extends TimePaginatedRemover { - - private Edge edge; - - EdgeDashboardsUnassigner(Edge edge) { - this.edge = edge; - } - - @Override - protected List findEntities(TenantId tenantId, Edge edge, TimePageLink pageLink) { - try { - return dashboardInfoDao.findDashboardsByTenantIdAndEdgeId(edge.getTenantId().getId(), edge.getId().getId(), pageLink).get(); - } catch (InterruptedException | ExecutionException e) { - log.warn("Failed to get dashboards by tenantId [{}] and edgeId [{}].", edge.getTenantId().getId(), edge.getId().getId()); - throw new RuntimeException(e); - } - } - - @Override - protected void removeEntity(TenantId tenantId, DashboardInfo entity) { - unassignDashboardFromEdge(edge.getTenantId(), new DashboardId(entity.getUuidId()), this.edge.getId()); - } - - } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 023c65fd37..a484821890 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -104,18 +104,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @Autowired private CacheManager cacheManager; - @Autowired - private AssetService assetService; - - @Autowired - private DeviceService deviceService; - - @Autowired - private EntityViewService entityViewService; - - @Autowired - private DashboardService dashboardService; - @Autowired private RuleChainService ruleChainService; @@ -181,10 +169,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic Edge edge = edgeDao.findById(tenantId, edgeId.getId()); - dashboardService.unassignEdgeDashboards(tenantId, edgeId); - // TODO: validate that rule chains are removed by deleteEntityRelations(tenantId, edgeId); call - ruleChainService.unassignEdgeRuleChains(tenantId, edgeId); - List list = new ArrayList<>(); list.add(edge.getTenantId()); list.add(edge.getName()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index 73272c3328..c2ee2fcb7d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -445,17 +445,6 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC return ruleChain; } - @Override - public void unassignEdgeRuleChains(TenantId tenantId, EdgeId edgeId) { - log.trace("Executing unassignEdgeRuleChains, edgeId [{}]", edgeId); - Validator.validateId(edgeId, "Incorrect edgeId " + edgeId); - Edge edge = edgeService.findEdgeById(tenantId, edgeId); - if (edge == null) { - throw new DataValidationException("Can't unassign ruleChains from non-existent edge!"); - } - new EdgeRuleChainsUnassigner(edge).removeEntities(tenantId, edge); - } - @Override public ListenableFuture> findRuleChainsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) { log.trace("Executing findRuleChainsByTenantIdAndEdgeId, tenantId [{}], edgeId [{}], pageLink [{}]", tenantId, edgeId, pageLink); @@ -603,28 +592,4 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC checkRuleNodesAndDelete(tenantId, entity.getId()); } }; - - private class EdgeRuleChainsUnassigner extends TimePaginatedRemover { - - private Edge edge; - - EdgeRuleChainsUnassigner(Edge edge) { - this.edge = edge; - } - - @Override - protected List findEntities(TenantId tenantId, Edge edge, TimePageLink pageLink) { - try { - return ruleChainDao.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId().getId(), edge.getId().getId(), pageLink).get(); - } catch (InterruptedException | ExecutionException e) { - log.warn("Failed to get ruleChains by tenantId [{}] and edgeId [{}].", edge.getTenantId().getId(), edge.getId().getId()); - throw new RuntimeException(e); - } - } - - @Override - protected void removeEntity(TenantId tenantId, RuleChain entity) { - unassignRuleChainFromEdge(edge.getTenantId(), new RuleChainId(entity.getUuidId()), this.edge.getId(), true); - } - } } From dcf6bd5e635ea6c47357232479e1501f12be7817 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 1 Sep 2020 14:59:08 +0300 Subject: [PATCH 093/156] deleted invalid case, deleted unused imports --- .../server/controller/EntityRelationController.java | 4 ---- .../service/edge/DefaultEdgeNotificationService.java | 9 --------- 2 files changed, 13 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java index 38060c7731..03e9ace3fa 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java @@ -24,9 +24,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.EntityId; @@ -132,8 +130,6 @@ public class EntityRelationController extends BaseController { try { relationService.deleteEntityRelations(getTenantId(), entityId); logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, null); - - sendNotificationMsgToEdgeService(getTenantId(), entityId, ActionType.RELATIONS_DELETED); } catch (Exception e) { logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, e); throw handleException(e); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 9ce455c758..58b07f122e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -34,20 +34,16 @@ import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; -import org.thingsboard.server.common.data.id.IdBased; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; -import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.msg.queue.TbCallback; @@ -65,14 +61,12 @@ import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.stream.Collectors; @Service @TbCoreComponent @@ -361,9 +355,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId); } break; - case RELATIONS_DELETED: - // TODO: voba - add support for relations deleted - break; } } From febfc6443e1f652c04e79bd791a303d313de054d Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 3 Sep 2020 16:27:49 +0300 Subject: [PATCH 094/156] Misc fixes --- .../server/controller/AuthController.java | 2 ++ .../server/service/edge/rpc/EdgeGrpcSession.java | 14 +++++++++----- .../thingsboard/server/common/data/EdgeUtils.java | 2 ++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index e00ee733b1..4d586c06ad 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -235,6 +235,8 @@ public class AuthController extends BaseController { } } + sendNotificationMsgToEdgeService(user.getTenantId(), user.getId(), ActionType.CREDENTIALS_UPDATED); + JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 7a088fd836..2232c43286 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -867,7 +867,7 @@ public final class EdgeGrpcSession implements Closeable { } if (uplinkMsg.getRelationUpdateMsgList() != null && !uplinkMsg.getRelationUpdateMsgList().isEmpty()) { for (RelationUpdateMsg relationUpdateMsg: uplinkMsg.getRelationUpdateMsgList()) { - onRelationUpdate(relationUpdateMsg); + result.add(onRelationUpdate(relationUpdateMsg)); } } if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { @@ -1170,11 +1170,13 @@ public final class EdgeGrpcSession implements Closeable { @Override public void onSuccess(TbQueueMsgMetadata metadata) { // TODO: voba - handle success + log.debug("Successfully send ENTITY_CREATED EVENT to rule engine [{}]", device); } @Override public void onFailure(Throwable t) { // TODO: voba - handle failure + log.debug("Failed to send ENTITY_CREATED EVENT to rule engine [{}]", device, t); } }); } catch (JsonProcessingException | IllegalArgumentException e) { @@ -1262,12 +1264,12 @@ public final class EdgeGrpcSession implements Closeable { } return Futures.immediateFuture(null); } catch (Exception e) { - log.error("Error during finding existent alarm", e); - return Futures.immediateFailedFuture(new RuntimeException("Error during finding existent alarm", e)); + log.error("Failed to process alarm update msg [{}]", alarmUpdateMsg, e); + return Futures.immediateFailedFuture(new RuntimeException("Failed to process alarm update msg", e)); } } - private void onRelationUpdate(RelationUpdateMsg relationUpdateMsg) { + private ListenableFuture onRelationUpdate(RelationUpdateMsg relationUpdateMsg) { log.info("onRelationUpdate {}", relationUpdateMsg); try { EntityRelation entityRelation = new EntityRelation(); @@ -1297,8 +1299,10 @@ public final class EdgeGrpcSession implements Closeable { case UNRECOGNIZED: log.error("Unsupported msg type"); } + return Futures.immediateFuture(null); } catch (Exception e) { - log.error("Error during relation update msg", e); + log.error("Failed to process relation update msg [{}]", relationUpdateMsg, e); + return Futures.immediateFailedFuture(new RuntimeException("Failed to process relation update msg", e)); } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java index 2394ea0047..465e1fcd72 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java @@ -24,6 +24,8 @@ public final class EdgeUtils { public static EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType) { switch (entityType) { + case EDGE: + return EdgeEventType.EDGE; case DEVICE: return EdgeEventType.DEVICE; case ASSET: From 450026d53bc6c8f69f51a2660c8890f127ac3d78 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 4 Sep 2020 16:44:31 +0300 Subject: [PATCH 095/156] Added processor. Renaming constructors --- .../service/edge/EdgeContextComponent.java | 73 ++- .../service/edge/rpc/EdgeGrpcSession.java | 585 +++--------------- ....java => AdminSettingsMsgConstructor.java} | 2 +- ...structor.java => AlarmMsgConstructor.java} | 2 +- ...structor.java => AssetMsgConstructor.java} | 2 +- ...uctor.java => CustomerMsgConstructor.java} | 2 +- ...ctor.java => DashboardMsgConstructor.java} | 2 +- ...tructor.java => DeviceMsgConstructor.java} | 2 +- ...tor.java => EntityViewMsgConstructor.java} | 2 +- ...uctor.java => RelationMsgConstructor.java} | 2 +- ...ctor.java => RuleChainMsgConstructor.java} | 2 +- ...nstructor.java => UserMsgConstructor.java} | 2 +- ...tor.java => WidgetTypeMsgConstructor.java} | 2 +- ....java => WidgetsBundleMsgConstructor.java} | 2 +- .../edge/rpc/processor/AlarmProcessor.java | 96 +++ .../edge/rpc/processor/BaseProcessor.java | 112 ++++ .../edge/rpc/processor/DeviceProcessor.java | 216 +++++++ .../edge/rpc/processor/RelationProcessor.java | 102 +++ .../rpc/processor/TelemetryProcessor.java | 202 ++++++ .../server/common/data/audit/ActionType.java | 3 +- 20 files changed, 856 insertions(+), 557 deletions(-) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{AdminSettingsUpdateMsgConstructor.java => AdminSettingsMsgConstructor.java} (96%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{AlarmUpdateMsgConstructor.java => AlarmMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{AssetUpdateMsgConstructor.java => AssetMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{CustomerUpdateMsgConstructor.java => CustomerMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{DashboardUpdateMsgConstructor.java => DashboardMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{DeviceUpdateMsgConstructor.java => DeviceMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{EntityViewUpdateMsgConstructor.java => EntityViewMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{RelationUpdateMsgConstructor.java => RelationMsgConstructor.java} (97%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{RuleChainUpdateMsgConstructor.java => RuleChainMsgConstructor.java} (99%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{UserUpdateMsgConstructor.java => UserMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{WidgetTypeUpdateMsgConstructor.java => WidgetTypeMsgConstructor.java} (98%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/{WidgetsBundleUpdateMsgConstructor.java => WidgetsBundleMsgConstructor.java} (97%) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index f5a97e2326..c90cc99965 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -36,23 +36,26 @@ import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.queue.discovery.PartitionService; -import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; -import org.thingsboard.server.service.edge.rpc.constructor.AdminSettingsUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.CustomerUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.AdminSettingsMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.AlarmMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.AssetMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.CustomerMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.DashboardMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.DeviceMsgConstructor; import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.WidgetTypeUpdateMsgConstructor; -import org.thingsboard.server.service.edge.rpc.constructor.WidgetsBundleUpdateMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.EntityViewMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.RelationMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.RuleChainMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.UserMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.WidgetTypeMsgConstructor; +import org.thingsboard.server.service.edge.rpc.constructor.WidgetsBundleMsgConstructor; import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; +import org.thingsboard.server.service.edge.rpc.processor.AlarmProcessor; +import org.thingsboard.server.service.edge.rpc.processor.DeviceProcessor; +import org.thingsboard.server.service.edge.rpc.processor.RelationProcessor; +import org.thingsboard.server.service.edge.rpc.processor.TelemetryProcessor; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.state.DeviceStateService; @@ -69,10 +72,6 @@ public class EdgeContextComponent { @Autowired private PartitionService partitionService; - @Autowired - @Lazy - private TbQueueProducerProvider producerProvider; - @Lazy @Autowired private EdgeNotificationService edgeNotificationService; @@ -147,56 +146,72 @@ public class EdgeContextComponent { @Lazy @Autowired - private RuleChainUpdateMsgConstructor ruleChainUpdateMsgConstructor; + private RuleChainMsgConstructor ruleChainMsgConstructor; @Lazy @Autowired - private AlarmUpdateMsgConstructor alarmUpdateMsgConstructor; + private AlarmMsgConstructor alarmMsgConstructor; @Lazy @Autowired - private DeviceUpdateMsgConstructor deviceUpdateMsgConstructor; + private DeviceMsgConstructor deviceMsgConstructor; @Lazy @Autowired - private AssetUpdateMsgConstructor assetUpdateMsgConstructor; + private AssetMsgConstructor assetMsgConstructor; @Lazy @Autowired - private EntityViewUpdateMsgConstructor entityViewUpdateMsgConstructor; + private EntityViewMsgConstructor entityViewMsgConstructor; @Lazy @Autowired - private DashboardUpdateMsgConstructor dashboardUpdateMsgConstructor; + private DashboardMsgConstructor dashboardMsgConstructor; @Lazy @Autowired - private CustomerUpdateMsgConstructor customerUpdateMsgConstructor; + private CustomerMsgConstructor customerMsgConstructor; @Lazy @Autowired - private UserUpdateMsgConstructor userUpdateMsgConstructor; + private UserMsgConstructor userMsgConstructor; @Lazy @Autowired - private RelationUpdateMsgConstructor relationUpdateMsgConstructor; + private RelationMsgConstructor relationMsgConstructor; @Lazy @Autowired - private WidgetsBundleUpdateMsgConstructor widgetsBundleUpdateMsgConstructor; + private WidgetsBundleMsgConstructor widgetsBundleMsgConstructor; @Lazy @Autowired - private WidgetTypeUpdateMsgConstructor widgetTypeUpdateMsgConstructor; + private WidgetTypeMsgConstructor widgetTypeMsgConstructor; @Lazy @Autowired - private AdminSettingsUpdateMsgConstructor adminSettingsUpdateMsgConstructor; + private AdminSettingsMsgConstructor adminSettingsMsgConstructor; @Lazy @Autowired private EntityDataMsgConstructor entityDataMsgConstructor; + @Lazy + @Autowired + private AlarmProcessor alarmProcessor; + + @Lazy + @Autowired + private DeviceProcessor deviceProcessor; + + @Lazy + @Autowired + private RelationProcessor relationProcessor; + + @Lazy + @Autowired + private TelemetryProcessor telemetryProcessor; + @Lazy @Autowired private EdgeEventStorageSettings edgeEventStorageSettings; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 2232c43286..078978435d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -18,39 +18,29 @@ package org.thingsboard.server.service.edge.rpc; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.SettableFuture; -import com.google.gson.Gson; import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import io.grpc.stub.StreamObserver; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.RandomStringUtils; import org.checkerframework.checker.nullness.qual.Nullable; -import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmSeverity; -import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; -import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; @@ -58,38 +48,28 @@ import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetsBundleId; -import org.thingsboard.server.common.data.kv.AttributeKey; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; -import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetsBundle; -import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.common.msg.TbMsgMetaData; -import org.thingsboard.server.common.msg.queue.ServiceType; -import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; -import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; -import org.thingsboard.server.gen.edge.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.AttributesRequestMsg; import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectResponseCode; @@ -119,20 +99,13 @@ import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; -import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.queue.TbQueueCallback; -import org.thingsboard.server.queue.TbQueueMsgMetadata; -import org.thingsboard.server.queue.TbQueueProducer; -import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.service.edge.EdgeContextComponent; import java.io.Closeable; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; @@ -145,12 +118,8 @@ import java.util.function.Consumer; @Data public final class EdgeGrpcSession implements Closeable { - private static final ReentrantLock deviceCreationLock = new ReentrantLock(); - private static final ReentrantLock responseMsgLock = new ReentrantLock(); - private final Gson gson = new Gson(); - private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs"; private final UUID sessionId; @@ -166,8 +135,6 @@ public final class EdgeGrpcSession implements Closeable { private CountDownLatch latch; - private TbQueueProducer> ruleEngineMsgProducer; - EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener, Consumer sessionCloseListener, ObjectMapper mapper) { this.sessionId = UUID.randomUUID(); @@ -176,7 +143,6 @@ public final class EdgeGrpcSession implements Closeable { this.sessionOpenListener = sessionOpenListener; this.sessionCloseListener = sessionCloseListener; this.mapper = mapper; - this.ruleEngineMsgProducer = ctx.getProducerProvider().getRuleEngineMsgProducer(); initInputStream(); } @@ -361,6 +327,12 @@ public final class EdgeGrpcSession implements Closeable { case TIMESERIES_UPDATED: downlinkMsg = processTelemetryMessage(edgeEvent); break; + case CREDENTIALS_REQUEST: + downlinkMsg = processCredentialsRequestMessage(edgeEvent); + break; + case ENTITY_EXISTS_REQUEST: + downlinkMsg = processEntityExistsRequestMessage(edgeEvent); + break; } if (downlinkMsg != null) { result.add(downlinkMsg); @@ -372,6 +344,36 @@ public final class EdgeGrpcSession implements Closeable { return result; } + private DownlinkMsg processEntityExistsRequestMessage(EdgeEvent edgeEvent) { + DownlinkMsg downlinkMsg = null; + if (EdgeEventType.DEVICE.equals(edgeEvent.getEdgeEventType())) { + DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); + Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); + CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); + DeviceUpdateMsg d = ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); + downlinkMsg = DownlinkMsg.newBuilder() + .addAllDeviceUpdateMsg(Collections.singletonList(d)) + .build(); + } + return downlinkMsg; + } + + private DownlinkMsg processCredentialsRequestMessage(EdgeEvent edgeEvent) { + DownlinkMsg downlinkMsg = null; + if (EdgeEventType.DEVICE.equals(edgeEvent.getEdgeEventType())) { + DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); + DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() + .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) + .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) + .build(); + DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() + .addAllDeviceCredentialsRequestMsg(Collections.singletonList(deviceCredentialsRequestMsg)); + downlinkMsg = builder.build(); + } + return downlinkMsg; + } + + private ListenableFuture getQueueStartTs() { ListenableFuture> future = ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, QUEUE_START_TS_ATTR_KEY); @@ -479,7 +481,7 @@ public final class EdgeGrpcSession implements Closeable { if (device != null) { CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); DeviceUpdateMsg deviceUpdateMsg = - ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId); + ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) .build(); @@ -488,7 +490,7 @@ public final class EdgeGrpcSession implements Closeable { case DELETED: case UNASSIGNED_FROM_EDGE: DeviceUpdateMsg deviceUpdateMsg = - ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId); + ctx.getDeviceMsgConstructor().constructDeviceDeleteMsg(deviceId); downlinkMsg = DownlinkMsg.newBuilder() .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) .build(); @@ -497,7 +499,7 @@ public final class EdgeGrpcSession implements Closeable { DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId); if (deviceCredentials != null) { DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = - ctx.getDeviceUpdateMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials); + ctx.getDeviceMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials); downlinkMsg = DownlinkMsg.newBuilder() .addAllDeviceCredentialsUpdateMsg(Collections.singletonList(deviceCredentialsUpdateMsg)) .build(); @@ -520,7 +522,7 @@ public final class EdgeGrpcSession implements Closeable { if (asset != null) { CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(asset); AssetUpdateMsg assetUpdateMsg = - ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset, customerId); + ctx.getAssetMsgConstructor().constructAssetUpdatedMsg(msgType, asset, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) .build(); @@ -529,7 +531,7 @@ public final class EdgeGrpcSession implements Closeable { case DELETED: case UNASSIGNED_FROM_EDGE: AssetUpdateMsg assetUpdateMsg = - ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId); + ctx.getAssetMsgConstructor().constructAssetDeleteMsg(assetId); downlinkMsg = DownlinkMsg.newBuilder() .addAllAssetUpdateMsg(Collections.singletonList(assetUpdateMsg)) .build(); @@ -551,7 +553,7 @@ public final class EdgeGrpcSession implements Closeable { if (entityView != null) { CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(entityView); EntityViewUpdateMsg entityViewUpdateMsg = - ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView, customerId); + ctx.getEntityViewMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) .build(); @@ -560,7 +562,7 @@ public final class EdgeGrpcSession implements Closeable { case DELETED: case UNASSIGNED_FROM_EDGE: EntityViewUpdateMsg entityViewUpdateMsg = - ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId); + ctx.getEntityViewMsgConstructor().constructEntityViewDeleteMsg(entityViewId); downlinkMsg = DownlinkMsg.newBuilder() .addAllEntityViewUpdateMsg(Collections.singletonList(entityViewUpdateMsg)) .build(); @@ -585,7 +587,7 @@ public final class EdgeGrpcSession implements Closeable { customerId = edge.getCustomerId(); } DashboardUpdateMsg dashboardUpdateMsg = - ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard, customerId); + ctx.getDashboardMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard, customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) .build(); @@ -594,7 +596,7 @@ public final class EdgeGrpcSession implements Closeable { case DELETED: case UNASSIGNED_FROM_EDGE: DashboardUpdateMsg dashboardUpdateMsg = - ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId); + ctx.getDashboardMsgConstructor().constructDashboardDeleteMsg(dashboardId); downlinkMsg = DownlinkMsg.newBuilder() .addAllDashboardUpdateMsg(Collections.singletonList(dashboardUpdateMsg)) .build(); @@ -612,7 +614,7 @@ public final class EdgeGrpcSession implements Closeable { Customer customer = ctx.getCustomerService().findCustomerById(edgeEvent.getTenantId(), customerId); if (customer != null) { CustomerUpdateMsg customerUpdateMsg = - ctx.getCustomerUpdateMsgConstructor().constructCustomerUpdatedMsg(msgType, customer); + ctx.getCustomerMsgConstructor().constructCustomerUpdatedMsg(msgType, customer); downlinkMsg = DownlinkMsg.newBuilder() .addAllCustomerUpdateMsg(Collections.singletonList(customerUpdateMsg)) .build(); @@ -620,7 +622,7 @@ public final class EdgeGrpcSession implements Closeable { break; case DELETED: CustomerUpdateMsg customerUpdateMsg = - ctx.getCustomerUpdateMsgConstructor().constructCustomerDeleteMsg(customerId); + ctx.getCustomerMsgConstructor().constructCustomerDeleteMsg(customerId); downlinkMsg = DownlinkMsg.newBuilder() .addAllCustomerUpdateMsg(Collections.singletonList(customerUpdateMsg)) .build(); @@ -639,7 +641,7 @@ public final class EdgeGrpcSession implements Closeable { RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId); if (ruleChain != null) { RuleChainUpdateMsg ruleChainUpdateMsg = - ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); + ctx.getRuleChainMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); downlinkMsg = DownlinkMsg.newBuilder() .addAllRuleChainUpdateMsg(Collections.singletonList(ruleChainUpdateMsg)) .build(); @@ -648,7 +650,7 @@ public final class EdgeGrpcSession implements Closeable { case DELETED: case UNASSIGNED_FROM_EDGE: downlinkMsg = DownlinkMsg.newBuilder() - .addAllRuleChainUpdateMsg(Collections.singletonList(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainDeleteMsg(ruleChainId))) + .addAllRuleChainUpdateMsg(Collections.singletonList(ctx.getRuleChainMsgConstructor().constructRuleChainDeleteMsg(ruleChainId))) .build(); break; } @@ -662,7 +664,7 @@ public final class EdgeGrpcSession implements Closeable { if (ruleChain != null) { RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId); RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = - ctx.getRuleChainUpdateMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData); + ctx.getRuleChainMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData); if (ruleChainMetadataUpdateMsg != null) { downlinkMsg = DownlinkMsg.newBuilder() .addAllRuleChainMetadataUpdateMsg(Collections.singletonList(ruleChainMetadataUpdateMsg)) @@ -682,20 +684,20 @@ public final class EdgeGrpcSession implements Closeable { if (user != null) { CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(user); downlinkMsg = DownlinkMsg.newBuilder() - .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user, customerId))) + .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserMsgConstructor().constructUserUpdatedMsg(msgType, user, customerId))) .build(); } break; case DELETED: downlinkMsg = DownlinkMsg.newBuilder() - .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId))) + .addAllUserUpdateMsg(Collections.singletonList(ctx.getUserMsgConstructor().constructUserDeleteMsg(userId))) .build(); break; case CREDENTIALS_UPDATED: UserCredentials userCredentialsByUserId = ctx.getUserService().findUserCredentialsByUserId(edge.getTenantId(), userId); if (userCredentialsByUserId != null && userCredentialsByUserId.isEnabled()) { UserCredentialsUpdateMsg userCredentialsUpdateMsg = - ctx.getUserUpdateMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); + ctx.getUserMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId); downlinkMsg = DownlinkMsg.newBuilder() .addAllUserCredentialsUpdateMsg(Collections.singletonList(userCredentialsUpdateMsg)) .build(); @@ -714,7 +716,7 @@ public final class EdgeGrpcSession implements Closeable { private DownlinkMsg processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); - RelationUpdateMsg r = ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation); + RelationUpdateMsg r = ctx.getRelationMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation); return DownlinkMsg.newBuilder() .addAllRelationUpdateMsg(Collections.singletonList(r)) .build(); @@ -727,7 +729,7 @@ public final class EdgeGrpcSession implements Closeable { Alarm alarm = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get(); if (alarm != null) { downlinkMsg = DownlinkMsg.newBuilder() - .addAllAlarmUpdateMsg(Collections.singletonList(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm))) + .addAllAlarmUpdateMsg(Collections.singletonList(ctx.getAlarmMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm))) .build(); } } catch (Exception e) { @@ -745,7 +747,7 @@ public final class EdgeGrpcSession implements Closeable { WidgetsBundle widgetsBundle = ctx.getWidgetsBundleService().findWidgetsBundleById(edgeEvent.getTenantId(), widgetsBundleId); if (widgetsBundle != null) { WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = - ctx.getWidgetsBundleUpdateMsgConstructor().constructWidgetsBundleUpdateMsg(msgType, widgetsBundle); + ctx.getWidgetsBundleMsgConstructor().constructWidgetsBundleUpdateMsg(msgType, widgetsBundle); downlinkMsg = DownlinkMsg.newBuilder() .addAllWidgetsBundleUpdateMsg(Collections.singletonList(widgetsBundleUpdateMsg)) .build(); @@ -753,7 +755,7 @@ public final class EdgeGrpcSession implements Closeable { break; case DELETED: WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = - ctx.getWidgetsBundleUpdateMsgConstructor().constructWidgetsBundleDeleteMsg(widgetsBundleId); + ctx.getWidgetsBundleMsgConstructor().constructWidgetsBundleDeleteMsg(widgetsBundleId); downlinkMsg = DownlinkMsg.newBuilder() .addAllWidgetsBundleUpdateMsg(Collections.singletonList(widgetsBundleUpdateMsg)) .build(); @@ -771,7 +773,7 @@ public final class EdgeGrpcSession implements Closeable { WidgetType widgetType = ctx.getWidgetTypeService().findWidgetTypeById(edgeEvent.getTenantId(), widgetTypeId); if (widgetType != null) { WidgetTypeUpdateMsg widgetTypeUpdateMsg = - ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeUpdateMsg(msgType, widgetType); + ctx.getWidgetTypeMsgConstructor().constructWidgetTypeUpdateMsg(msgType, widgetType); downlinkMsg = DownlinkMsg.newBuilder() .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) .build(); @@ -779,10 +781,10 @@ public final class EdgeGrpcSession implements Closeable { break; case DELETED: WidgetTypeUpdateMsg widgetTypeUpdateMsg = - ctx.getWidgetTypeUpdateMsgConstructor().constructWidgetTypeDeleteMsg(widgetTypeId); - downlinkMsg = DownlinkMsg.newBuilder() - .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) - .build(); + ctx.getWidgetTypeMsgConstructor().constructWidgetTypeDeleteMsg(widgetTypeId); + downlinkMsg = DownlinkMsg.newBuilder() + .addAllWidgetTypeUpdateMsg(Collections.singletonList(widgetTypeUpdateMsg)) + .build(); break; } return downlinkMsg; @@ -790,7 +792,7 @@ public final class EdgeGrpcSession implements Closeable { private DownlinkMsg processAdminSettings(EdgeEvent edgeEvent) { AdminSettings adminSettings = mapper.convertValue(edgeEvent.getEntityBody(), AdminSettings.class); - AdminSettingsUpdateMsg t = ctx.getAdminSettingsUpdateMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings); + AdminSettingsUpdateMsg t = ctx.getAdminSettingsMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings); return DownlinkMsg.newBuilder() .addAllAdminSettingsUpdateMsg(Collections.singletonList(t)) .build(); @@ -832,42 +834,28 @@ public final class EdgeGrpcSession implements Closeable { try { if (uplinkMsg.getEntityDataList() != null && !uplinkMsg.getEntityDataList().isEmpty()) { for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) { - EntityId entityId = constructEntityId(entityData); - if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg()) && entityId != null) { - TbMsgMetaData metaData = constructBaseMsgMetadata(entityId); - metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE); - if (entityData.hasPostAttributesMsg()) { - metaData.putValue("scope", entityData.getPostAttributeScope()); - result.add(processPostAttributes(entityId, entityData.getPostAttributesMsg(), metaData)); - } - if (entityData.hasPostTelemetryMsg()) { - result.add(processPostTelemetry(entityId, entityData.getPostTelemetryMsg(), metaData)); - } - } - if (entityData.hasAttributeDeleteMsg()) { - result.add(processAttributeDeleteMsg(entityId, entityData.getAttributeDeleteMsg(), entityData.getEntityType())); - } + result.addAll(ctx.getTelemetryProcessor().onTelemetryUpdate(edge.getTenantId(), entityData)); } } if (uplinkMsg.getDeviceUpdateMsgList() != null && !uplinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { - result.add(onDeviceUpdate(deviceUpdateMsg)); + result.add(ctx.getDeviceProcessor().onDeviceUpdate(edge.getTenantId(), edge, deviceUpdateMsg)); } } if (uplinkMsg.getDeviceCredentialsUpdateMsgList() != null && !uplinkMsg.getDeviceCredentialsUpdateMsgList().isEmpty()) { for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { - result.add(onDeviceCredentialsUpdate(deviceCredentialsUpdateMsg)); + result.add(ctx.getDeviceProcessor().onDeviceCredentialsUpdate(edge.getTenantId(), deviceCredentialsUpdateMsg)); } } if (uplinkMsg.getAlarmUpdateMsgList() != null && !uplinkMsg.getAlarmUpdateMsgList().isEmpty()) { for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { - result.add(onAlarmUpdate(alarmUpdateMsg)); + result.add(ctx.getAlarmProcessor().onAlarmUpdate(edge.getTenantId(), alarmUpdateMsg)); } } if (uplinkMsg.getRelationUpdateMsgList() != null && !uplinkMsg.getRelationUpdateMsgList().isEmpty()) { - for (RelationUpdateMsg relationUpdateMsg: uplinkMsg.getRelationUpdateMsgList()) { - result.add(onRelationUpdate(relationUpdateMsg)); + for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) { + result.add(ctx.getRelationProcessor().onRelationUpdate(edge.getTenantId(), relationUpdateMsg)); } } if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { @@ -901,430 +889,6 @@ public final class EdgeGrpcSession implements Closeable { return Futures.allAsList(result); } - private TbMsgMetaData constructBaseMsgMetadata(EntityId entityId) { - TbMsgMetaData metaData = new TbMsgMetaData(); - switch (entityId.getEntityType()) { - case DEVICE: - Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), new DeviceId(entityId.getId())); - if (device != null) { - metaData.putValue("deviceName", device.getName()); - metaData.putValue("deviceType", device.getType()); - } - break; - case ASSET: - Asset asset = ctx.getAssetService().findAssetById(edge.getTenantId(), new AssetId(entityId.getId())); - if (asset != null) { - metaData.putValue("assetName", asset.getName()); - metaData.putValue("assetType", asset.getType()); - } - break; - case ENTITY_VIEW: - EntityView entityView = ctx.getEntityViewService().findEntityViewById(edge.getTenantId(), new EntityViewId(entityId.getId())); - if (entityView != null) { - metaData.putValue("entityViewName", entityView.getName()); - metaData.putValue("entityViewType", entityView.getType()); - } - break; - default: - log.debug("Using empty metadata for entityId [{}]", entityId); - break; - } - return metaData; - } - - private EntityId constructEntityId(EntityDataProto entityData) { - EntityType entityType = EntityType.valueOf(entityData.getEntityType()); - switch (entityType) { - case DEVICE: - return new DeviceId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - case ASSET: - return new AssetId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - case ENTITY_VIEW: - return new EntityViewId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - case DASHBOARD: - return new DashboardId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - case TENANT: - return new TenantId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - case CUSTOMER: - return new CustomerId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - case USER: - return new UserId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); - default: - log.warn("Unsupported entity type [{}] during construct of entity id. EntityDataProto [{}]", entityData.getEntityType(), entityData); - return null; - } - } - - private ListenableFuture processPostTelemetry(EntityId entityId, TransportProtos.PostTelemetryMsg msg, TbMsgMetaData metaData) { - SettableFuture futureToSet = SettableFuture.create(); - for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { - JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); - metaData.putValue("ts", tsKv.getTs() + ""); - TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_TELEMETRY_REQUEST.name(), entityId, metaData, gson.toJson(json)); - ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { - @Override - public void onSuccess(TbQueueMsgMetadata metadata) { - futureToSet.set(null); - } - - @Override - public void onFailure(Throwable t) { - log.error("Can't process post telemetry [{}]", msg, t); - futureToSet.setException(t); - } - }); - } - return futureToSet; - } - - private ListenableFuture processPostAttributes(EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { - SettableFuture futureToSet = SettableFuture.create(); - JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); - TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); - ctx.getTbClusterService().pushMsgToRuleEngine(edge.getTenantId(), tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { - @Override - public void onSuccess(TbQueueMsgMetadata metadata) { - futureToSet.set(null); - } - - @Override - public void onFailure(Throwable t) { - log.error("Can't process post attributes [{}]", msg, t); - futureToSet.setException(t); - } - }); - return futureToSet; - } - - private ListenableFuture processAttributeDeleteMsg(EntityId entityId, AttributeDeleteMsg attributeDeleteMsg, String entityType) { - SettableFuture futureToSet = SettableFuture.create(); - String scope = attributeDeleteMsg.getScope(); - List attributeNames = attributeDeleteMsg.getAttributeNamesList(); - ctx.getAttributesService().removeAll(edge.getTenantId(), entityId, scope, attributeNames); - if (EntityType.DEVICE.name().equals(entityType)) { - Set attributeKeys = new HashSet<>(); - for (String attributeName : attributeNames) { - attributeKeys.add(new AttributeKey(scope, attributeName)); - } - ctx.getTbClusterService().pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( - edge.getTenantId(), (DeviceId) entityId, attributeKeys), new TbQueueCallback() { - @Override - public void onSuccess(TbQueueMsgMetadata metadata) { - futureToSet.set(null); - } - - @Override - public void onFailure(Throwable t) { - log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, t); - futureToSet.setException(t); - } - }); - } - return futureToSet; - } - - private ListenableFuture onDeviceUpdate(DeviceUpdateMsg deviceUpdateMsg) { - DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); - switch (deviceUpdateMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - String deviceName = deviceUpdateMsg.getName(); - Device device = ctx.getDeviceService().findDeviceByTenantIdAndName(edge.getTenantId(), deviceName); - if (device != null) { - // device with this name already exists on the cloud - update ID on the edge - if (!device.getId().equals(edgeDeviceId)) { - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); - DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); - DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() - .addAllDeviceUpdateMsg(Collections.singletonList(d)) - .build(); - sendResponseMsg(ResponseMsg.newBuilder() - .setDownlinkMsg(downlinkMsg) - .build()); - } - } else { - Device deviceById = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId); - if (deviceById != null) { - // this ID already used by other device - create new device and update ID on the edge - device = createDevice(deviceUpdateMsg); - CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); - DeviceUpdateMsg d = ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); - DownlinkMsg downlinkMsg = DownlinkMsg.newBuilder() - .addAllDeviceUpdateMsg(Collections.singletonList(d)) - .build(); - sendResponseMsg(ResponseMsg.newBuilder() - .setDownlinkMsg(downlinkMsg) - .build()); - } else { - device = createDevice(deviceUpdateMsg); - } - } - // TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment - ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId()); - break; - case ENTITY_UPDATED_RPC_MESSAGE: - updateDevice(deviceUpdateMsg); - break; - case ENTITY_DELETED_RPC_MESSAGE: - Device deviceToDelete = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId); - if (deviceToDelete != null) { - ctx.getDeviceService().unassignDeviceFromEdge(edge.getTenantId(), edgeDeviceId, edge.getId()); - } - break; - case UNRECOGNIZED: - log.error("Unsupported msg type {}", deviceUpdateMsg.getMsgType()); - return Futures.immediateFailedFuture(new RuntimeException("Unsupported msg type " + deviceUpdateMsg.getMsgType())); - } - return Futures.immediateFuture(null); - } - - private void updateDevice(DeviceUpdateMsg deviceUpdateMsg) { - DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); - Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); - device.setName(deviceUpdateMsg.getName()); - device.setType(deviceUpdateMsg.getType()); - device.setLabel(deviceUpdateMsg.getLabel()); - device = ctx.getDeviceService().saveDevice(device); - - requestDeviceCredentialsFromEdge(device); - } - - private ListenableFuture onDeviceCredentialsUpdate(DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { - log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); - DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); - ListenableFuture deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edge.getTenantId(), deviceId); - return Futures.transform(deviceFuture, device -> { - if (device != null) { - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", - device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); - try { - DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId()); - deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType())); - deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId()); - deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue()); - ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials); - } catch (Exception e) { - log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); - throw new RuntimeException(e); - } - } - return null; - }, ctx.getDbCallbackExecutor()); - } - - private void requestDeviceCredentialsFromEdge(Device device) { - log.debug("Executing requestDeviceCredentialsFromEdge device [{}]", device); - - DownlinkMsg downlinkMsg = constructDeviceCredentialsRequestMsg(device.getId()); - sendResponseMsg(ResponseMsg.newBuilder() - .setDownlinkMsg(downlinkMsg) - .build()); - } - - private DownlinkMsg constructDeviceCredentialsRequestMsg(DeviceId deviceId) { - DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() - .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) - .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) - .build(); - DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() - .addAllDeviceCredentialsRequestMsg(Collections.singletonList(deviceCredentialsRequestMsg)); - return builder.build(); - } - - private Device createDevice(DeviceUpdateMsg deviceUpdateMsg) { - Device device; - try { - deviceCreationLock.lock(); - DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); - device = new Device(); - device.setTenantId(edge.getTenantId()); - device.setCustomerId(edge.getCustomerId()); - device.setId(deviceId); - device.setName(deviceUpdateMsg.getName()); - device.setType(deviceUpdateMsg.getType()); - device.setLabel(deviceUpdateMsg.getLabel()); - device = ctx.getDeviceService().saveDevice(device); - createDeviceCredentials(device); - createRelationFromEdge(device.getId()); - ctx.getDeviceStateService().onDeviceAdded(device); - pushDeviceCreatedEventToRuleEngine(device); - requestDeviceCredentialsFromEdge(device); - } finally { - deviceCreationLock.unlock(); - } - return device; - } - - private void createDeviceCredentials(Device device) { - DeviceCredentials deviceCredentials = new DeviceCredentials(); - deviceCredentials.setDeviceId(device.getId()); - deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); - deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20)); - ctx.getDeviceCredentialsService().createDeviceCredentials(device.getTenantId(), deviceCredentials); - } - - private void pushDeviceCreatedEventToRuleEngine(Device device) { - try { - ObjectNode entityNode = mapper.valueToTree(device); - TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, device.getId(), getActionTbMsgMetaData(device.getCustomerId()), mapper.writeValueAsString(entityNode)); - sendToRuleEngine(edge.getTenantId(), tbMsg, new TbQueueCallback() { - @Override - public void onSuccess(TbQueueMsgMetadata metadata) { - // TODO: voba - handle success - log.debug("Successfully send ENTITY_CREATED EVENT to rule engine [{}]", device); - } - - @Override - public void onFailure(Throwable t) { - // TODO: voba - handle failure - log.debug("Failed to send ENTITY_CREATED EVENT to rule engine [{}]", device, t); - } - }); - } catch (JsonProcessingException | IllegalArgumentException e) { - log.warn("[{}] Failed to push device action to rule engine: {}", device.getId(), DataConstants.ENTITY_CREATED, e); - } - } - - protected void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) { - TopicPartitionInfo tpi = ctx.getPartitionService().resolve(ServiceType.TB_RULE_ENGINE, tenantId, tbMsg.getOriginator()); - TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder().setTbMsg(TbMsg.toByteString(tbMsg)) - .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) - .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()).build(); - ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), callback); - } - - private TbMsgMetaData getActionTbMsgMetaData(CustomerId customerId) { - TbMsgMetaData metaData = getTbMsgMetaData(edge); - if (customerId != null && !customerId.isNullUid()) { - metaData.putValue("customerId", customerId.toString()); - } - return metaData; - } - - private TbMsgMetaData getTbMsgMetaData(Edge edge) { - TbMsgMetaData metaData = new TbMsgMetaData(); - metaData.putValue("edgeId", edge.getId().toString()); - metaData.putValue("edgeName", edge.getName()); - return metaData; - } - - private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) { - switch (entityType) { - case DEVICE: - return ctx.getDeviceService().findDeviceByTenantIdAndName(edge.getTenantId(), entityName).getId(); - case ASSET: - return ctx.getAssetService().findAssetByTenantIdAndName(edge.getTenantId(), entityName).getId(); - case ENTITY_VIEW: - return ctx.getEntityViewService().findEntityViewByTenantIdAndName(edge.getTenantId(), entityName).getId(); - default: - return null; - } - } - - private ListenableFuture onAlarmUpdate(AlarmUpdateMsg alarmUpdateMsg) { - EntityId originatorId = getAlarmOriginator(alarmUpdateMsg.getOriginatorName(), org.thingsboard.server.common.data.EntityType.valueOf(alarmUpdateMsg.getOriginatorType())); - if (originatorId == null) { - return Futures.immediateFuture(null); - } - try { - Alarm existentAlarm = ctx.getAlarmService().findLatestByOriginatorAndType(edge.getTenantId(), originatorId, alarmUpdateMsg.getType()).get(); - switch (alarmUpdateMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - if (existentAlarm == null || existentAlarm.getStatus().isCleared()) { - existentAlarm = new Alarm(); - existentAlarm.setTenantId(edge.getTenantId()); - existentAlarm.setType(alarmUpdateMsg.getName()); - existentAlarm.setOriginator(originatorId); - existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity())); - existentAlarm.setStartTs(alarmUpdateMsg.getStartTs()); - existentAlarm.setClearTs(alarmUpdateMsg.getClearTs()); - existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); - } - existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus())); - existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); - existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); - existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails())); - ctx.getAlarmService().createOrUpdateAlarm(existentAlarm); - break; - case ALARM_ACK_RPC_MESSAGE: - if (existentAlarm != null) { - ctx.getAlarmService().ackAlarm(edge.getTenantId(), existentAlarm.getId(), alarmUpdateMsg.getAckTs()); - } - break; - case ALARM_CLEAR_RPC_MESSAGE: - if (existentAlarm != null) { - ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), mapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); - } - break; - case ENTITY_DELETED_RPC_MESSAGE: - if (existentAlarm != null) { - ctx.getAlarmService().deleteAlarm(edge.getTenantId(), existentAlarm.getId()); - } - break; - } - return Futures.immediateFuture(null); - } catch (Exception e) { - log.error("Failed to process alarm update msg [{}]", alarmUpdateMsg, e); - return Futures.immediateFailedFuture(new RuntimeException("Failed to process alarm update msg", e)); - } - } - - private ListenableFuture onRelationUpdate(RelationUpdateMsg relationUpdateMsg) { - log.info("onRelationUpdate {}", relationUpdateMsg); - try { - EntityRelation entityRelation = new EntityRelation(); - - UUID fromUUID = new UUID(relationUpdateMsg.getFromIdMSB(), relationUpdateMsg.getFromIdLSB()); - EntityId fromId = EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(relationUpdateMsg.getFromEntityType()), fromUUID); - entityRelation.setFrom(fromId); - - UUID toUUID = new UUID(relationUpdateMsg.getToIdMSB(), relationUpdateMsg.getToIdLSB()); - EntityId toId = EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(relationUpdateMsg.getToEntityType()), toUUID); - entityRelation.setTo(toId); - - entityRelation.setType(relationUpdateMsg.getType()); - entityRelation.setTypeGroup(RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup())); - entityRelation.setAdditionalInfo(mapper.readTree(relationUpdateMsg.getAdditionalInfo())); - switch (relationUpdateMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - if (isEntityExists(edge.getTenantId(), entityRelation.getTo()) - && isEntityExists(edge.getTenantId(), entityRelation.getFrom())) { - ctx.getRelationService().saveRelationAsync(edge.getTenantId(), entityRelation); - } - break; - case ENTITY_DELETED_RPC_MESSAGE: - ctx.getRelationService().deleteRelation(edge.getTenantId(), entityRelation); - break; - case UNRECOGNIZED: - log.error("Unsupported msg type"); - } - return Futures.immediateFuture(null); - } catch (Exception e) { - log.error("Failed to process relation update msg [{}]", relationUpdateMsg, e); - return Futures.immediateFailedFuture(new RuntimeException("Failed to process relation update msg", e)); - } - } - - private boolean isEntityExists(TenantId tenantId, EntityId entityId) throws ThingsboardException { - switch (entityId.getEntityType()) { - case DEVICE: - return ctx.getDeviceService().findDeviceById(tenantId, new DeviceId(entityId.getId())) != null; - case ASSET: - return ctx.getAssetService().findAssetById(tenantId, new AssetId(entityId.getId())) != null; - case ENTITY_VIEW: - return ctx.getEntityViewService().findEntityViewById(tenantId, new EntityViewId(entityId.getId())) != null; - case CUSTOMER: - return ctx.getCustomerService().findCustomerById(tenantId, new CustomerId(entityId.getId())) != null; - case USER: - return ctx.getUserService().findUserById(tenantId, new UserId(entityId.getId())) != null; - case DASHBOARD: - return ctx.getDashboardService().findDashboardById(tenantId, new DashboardId(entityId.getId())) != null; - default: - throw new ThingsboardException("Unsupported entity type " + entityId.getEntityType(), ThingsboardErrorCode.INVALID_ARGUMENTS); - } - } - private ConnectResponseMsg processConnect(ConnectRequestMsg request) { Optional optional = ctx.getEdgeService().findEdgeByRoutingKey(TenantId.SYS_TENANT_ID, request.getEdgeRoutingKey()); if (optional.isPresent()) { @@ -1355,15 +919,6 @@ public final class EdgeGrpcSession implements Closeable { .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); } - private void createRelationFromEdge(EntityId entityId) { - EntityRelation relation = new EntityRelation(); - relation.setFrom(edge.getId()); - relation.setTo(entityId); - relation.setTypeGroup(RelationTypeGroup.COMMON); - relation.setType(EntityRelation.EDGE_TYPE); - ctx.getRelationService().saveRelation(edge.getTenantId(), relation); - } - private EdgeConfiguration constructEdgeConfigProto(Edge edge) throws JsonProcessingException { return EdgeConfiguration.newBuilder() .setEdgeIdMSB(edge.getId().getId().getMostSignificantBits()) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsMsgConstructor.java similarity index 96% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsMsgConstructor.java index 31d6683d89..6a6b67e2e6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsMsgConstructor.java @@ -23,7 +23,7 @@ import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg; @Slf4j @Component -public class AdminSettingsUpdateMsgConstructor { +public class AdminSettingsMsgConstructor { public AdminSettingsUpdateMsg constructAdminSettingsUpdateMsg(AdminSettings adminSettings) { AdminSettingsUpdateMsg.Builder builder = AdminSettingsUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java index 91f3570c4e..3414727575 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java @@ -34,7 +34,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class AlarmUpdateMsgConstructor { +public class AlarmMsgConstructor { @Autowired private DeviceService deviceService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java index ddcb531583..694efcd081 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java @@ -27,7 +27,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class AssetUpdateMsgConstructor { +public class AssetMsgConstructor { public AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset, CustomerId customerId) { AssetUpdateMsg.Builder builder = AssetUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerMsgConstructor.java index a5f54fb443..94687b88d4 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerMsgConstructor.java @@ -25,7 +25,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class CustomerUpdateMsgConstructor { +public class CustomerMsgConstructor { public CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer) { CustomerUpdateMsg.Builder builder = CustomerUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardMsgConstructor.java index 69b9d8dbd2..a41b987c1c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardMsgConstructor.java @@ -27,7 +27,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class DashboardUpdateMsgConstructor { +public class DashboardMsgConstructor { public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard, CustomerId customerId) { DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java index 885511b3db..ebc180d0f9 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java @@ -28,7 +28,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class DeviceUpdateMsgConstructor { +public class DeviceMsgConstructor { public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId) { DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java index af61e9e4ad..c19a84cfcb 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java @@ -27,7 +27,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class EntityViewUpdateMsgConstructor { +public class EntityViewMsgConstructor { public EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView, CustomerId customerId) { EdgeEntityType entityType; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationMsgConstructor.java similarity index 97% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationMsgConstructor.java index e09b9f2e8b..5a1f7ce39d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationMsgConstructor.java @@ -24,7 +24,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j -public class RelationUpdateMsgConstructor { +public class RelationMsgConstructor { public RelationUpdateMsg constructRelationUpdatedMsg(UpdateMsgType msgType, EntityRelation entityRelation) { RelationUpdateMsg.Builder builder = RelationUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java similarity index 99% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java index 1d81763a1f..22017c56c2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java @@ -38,7 +38,7 @@ import java.util.List; @Component @Slf4j -public class RuleChainUpdateMsgConstructor { +public class RuleChainMsgConstructor { private static final ObjectMapper objectMapper = new ObjectMapper(); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserMsgConstructor.java index 4240d21292..b5b6b080f7 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserMsgConstructor.java @@ -31,7 +31,7 @@ import java.util.UUID; @Component @Slf4j -public class UserUpdateMsgConstructor { +public class UserMsgConstructor { public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user, CustomerId customerId) { UserUpdateMsg.Builder builder = UserUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java index 784bfd6fdc..e01b2afa66 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java @@ -26,7 +26,7 @@ import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; @Component @Slf4j -public class WidgetTypeUpdateMsgConstructor { +public class WidgetTypeMsgConstructor { public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(UpdateMsgType msgType, WidgetType widgetType) { WidgetTypeUpdateMsg.Builder builder = WidgetTypeUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java similarity index 97% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java index 4d26e0be59..13dd78980c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java @@ -26,7 +26,7 @@ import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; @Component @Slf4j -public class WidgetsBundleUpdateMsgConstructor { +public class WidgetsBundleMsgConstructor { public WidgetsBundleUpdateMsg constructWidgetsBundleUpdateMsg(UpdateMsgType msgType, WidgetsBundle widgetsBundle) { WidgetsBundleUpdateMsg.Builder builder = WidgetsBundleUpdateMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java new file mode 100644 index 0000000000..257bb746c5 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java @@ -0,0 +1,96 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.processor; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.gen.edge.AlarmUpdateMsg; + +@Component +@Slf4j +public class AlarmProcessor extends BaseProcessor { + + public ListenableFuture onAlarmUpdate(TenantId tenantId, AlarmUpdateMsg alarmUpdateMsg) { + EntityId originatorId = getAlarmOriginator(tenantId, alarmUpdateMsg.getOriginatorName(), + EntityType.valueOf(alarmUpdateMsg.getOriginatorType())); + if (originatorId == null) { + return Futures.immediateFuture(null); + } + try { + Alarm existentAlarm = alarmService.findLatestByOriginatorAndType(tenantId, originatorId, alarmUpdateMsg.getType()).get(); + switch (alarmUpdateMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + if (existentAlarm == null || existentAlarm.getStatus().isCleared()) { + existentAlarm = new Alarm(); + existentAlarm.setTenantId(tenantId); + existentAlarm.setType(alarmUpdateMsg.getName()); + existentAlarm.setOriginator(originatorId); + existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity())); + existentAlarm.setStartTs(alarmUpdateMsg.getStartTs()); + existentAlarm.setClearTs(alarmUpdateMsg.getClearTs()); + existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); + } + existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus())); + existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); + existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); + existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails())); + alarmService.createOrUpdateAlarm(existentAlarm); + break; + case ALARM_ACK_RPC_MESSAGE: + if (existentAlarm != null) { + alarmService.ackAlarm(tenantId, existentAlarm.getId(), alarmUpdateMsg.getAckTs()); + } + break; + case ALARM_CLEAR_RPC_MESSAGE: + if (existentAlarm != null) { + alarmService.clearAlarm(tenantId, existentAlarm.getId(), mapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); + } + break; + case ENTITY_DELETED_RPC_MESSAGE: + if (existentAlarm != null) { + alarmService.deleteAlarm(tenantId, existentAlarm.getId()); + } + break; + } + return Futures.immediateFuture(null); + } catch (Exception e) { + log.error("Failed to process alarm update msg [{}]", alarmUpdateMsg, e); + return Futures.immediateFailedFuture(new RuntimeException("Failed to process alarm update msg", e)); + } + } + + private EntityId getAlarmOriginator(TenantId tenantId, String entityName, EntityType entityType) { + switch (entityType) { + case DEVICE: + return deviceService.findDeviceByTenantIdAndName(tenantId, entityName).getId(); + case ASSET: + return assetService.findAssetByTenantIdAndName(tenantId, entityName).getId(); + case ENTITY_VIEW: + return entityViewService.findEntityViewByTenantIdAndName(tenantId, entityName).getId(); + default: + return null; + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java new file mode 100644 index 0000000000..ee5c545999 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java @@ -0,0 +1,112 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.processor; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.alarm.AlarmService; +import org.thingsboard.server.dao.asset.AssetService; +import org.thingsboard.server.dao.attributes.AttributesService; +import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.dao.dashboard.DashboardService; +import org.thingsboard.server.dao.device.DeviceCredentialsService; +import org.thingsboard.server.dao.device.DeviceService; +import org.thingsboard.server.dao.edge.EdgeEventService; +import org.thingsboard.server.dao.entityview.EntityViewService; +import org.thingsboard.server.dao.relation.RelationService; +import org.thingsboard.server.dao.user.UserService; +import org.thingsboard.server.service.executors.DbCallbackExecutorService; +import org.thingsboard.server.service.queue.TbClusterService; +import org.thingsboard.server.service.state.DeviceStateService; + +@Slf4j +public abstract class BaseProcessor { + + protected static final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + protected AlarmService alarmService; + + @Autowired + protected DeviceService deviceService; + + @Autowired + protected DashboardService dashboardService; + + @Autowired + protected AssetService assetService; + + @Autowired + protected EntityViewService entityViewService; + + @Autowired + protected CustomerService customerService; + + @Autowired + protected UserService userService; + + @Autowired + protected RelationService relationService; + + @Autowired + protected DeviceCredentialsService deviceCredentialsService; + + @Autowired + protected AttributesService attributesService; + + @Autowired + protected TbClusterService tbClusterService; + + @Autowired + protected DeviceStateService deviceStateService; + + @Autowired + protected EdgeEventService edgeEventService; + + @Autowired + protected DbCallbackExecutorService dbCallbackExecutorService; + + protected ListenableFuture saveEdgeEvent(TenantId tenantId, + EdgeId edgeId, + EdgeEventType edgeEventType, + ActionType edgeEventAction, + EntityId entityId, + JsonNode entityBody) { + log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], edgeEventType[{}], " + + "edgeEventAction [{}], entityId [{}], entityBody [{}]", + tenantId, edgeId, edgeEventType, edgeEventAction, entityId, entityBody); + + EdgeEvent edgeEvent = new EdgeEvent(); + edgeEvent.setTenantId(tenantId); + edgeEvent.setEdgeId(edgeId); + edgeEvent.setEdgeEventType(edgeEventType); + edgeEvent.setEdgeEventAction(edgeEventAction.name()); + if (entityId != null) { + edgeEvent.setEntityId(entityId.getId()); + } + edgeEvent.setEntityBody(entityBody); + return edgeEventService.saveAsync(edgeEvent); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java new file mode 100644 index 0000000000..db122e31f9 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java @@ -0,0 +1,216 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.processor; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.RandomStringUtils; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.data.security.DeviceCredentialsType; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgDataType; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceUpdateMsg; +import org.thingsboard.server.queue.TbQueueCallback; +import org.thingsboard.server.queue.TbQueueMsgMetadata; + +import java.util.UUID; +import java.util.concurrent.locks.ReentrantLock; + +@Component +@Slf4j +public class DeviceProcessor extends BaseProcessor { + + private static final ReentrantLock deviceCreationLock = new ReentrantLock(); + + public ListenableFuture onDeviceUpdate(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { + DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); + switch (deviceUpdateMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + String deviceName = deviceUpdateMsg.getName(); + Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); + if (device != null) { + // device with this name already exists on the cloud - update ID on the edge + if (!device.getId().equals(edgeDeviceId)) { + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, ActionType.ENTITY_EXISTS_REQUEST, device.getId(), null); + } + } else { + Device deviceById = deviceService.findDeviceById(edge.getTenantId(), edgeDeviceId); + if (deviceById != null) { + // this ID already used by other device - create new device and update ID on the edge + device = createDevice(tenantId, edge, deviceUpdateMsg); + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, ActionType.ENTITY_EXISTS_REQUEST, device.getId(), null); + } else { + device = createDevice(tenantId, edge, deviceUpdateMsg); + } + } + // TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment + deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId()); + break; + case ENTITY_UPDATED_RPC_MESSAGE: + updateDevice(tenantId, edge, deviceUpdateMsg); + break; + case ENTITY_DELETED_RPC_MESSAGE: + Device deviceToDelete = deviceService.findDeviceById(tenantId, edgeDeviceId); + if (deviceToDelete != null) { + deviceService.unassignDeviceFromEdge(tenantId, edgeDeviceId, edge.getId()); + } + break; + case UNRECOGNIZED: + log.error("Unsupported msg type {}", deviceUpdateMsg.getMsgType()); + return Futures.immediateFailedFuture(new RuntimeException("Unsupported msg type " + deviceUpdateMsg.getMsgType())); + } + return Futures.immediateFuture(null); + } + + + public ListenableFuture onDeviceCredentialsUpdate(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { + log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); + DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); + ListenableFuture deviceFuture = deviceService.findDeviceByIdAsync(tenantId, deviceId); + return Futures.transform(deviceFuture, device -> { + if (device != null) { + log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]", + device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue()); + try { + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, device.getId()); + deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType())); + deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId()); + deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue()); + deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials); + } catch (Exception e) { + log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e); + throw new RuntimeException(e); + } + } + return null; + }, dbCallbackExecutorService); + } + + + private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { + DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); + Device device = deviceService.findDeviceById(tenantId, deviceId); + device.setName(deviceUpdateMsg.getName()); + device.setType(deviceUpdateMsg.getType()); + device.setLabel(deviceUpdateMsg.getLabel()); + deviceService.saveDevice(device); + + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_REQUEST, deviceId, null); + } + + private Device createDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { + Device device; + try { + deviceCreationLock.lock(); + DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); + device = new Device(); + device.setTenantId(edge.getTenantId()); + device.setCustomerId(edge.getCustomerId()); + device.setId(deviceId); + device.setName(deviceUpdateMsg.getName()); + device.setType(deviceUpdateMsg.getType()); + device.setLabel(deviceUpdateMsg.getLabel()); + device = deviceService.saveDevice(device); + createDeviceCredentials(device); + createRelationFromEdge(tenantId, edge.getId(), device.getId()); + deviceStateService.onDeviceAdded(device); + pushDeviceCreatedEventToRuleEngine(tenantId, edge, device); + + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_REQUEST, deviceId, null); + } finally { + deviceCreationLock.unlock(); + } + return device; + } + + private void createRelationFromEdge(TenantId tenantId, EdgeId edgeId, EntityId entityId) { + EntityRelation relation = new EntityRelation(); + relation.setFrom(edgeId); + relation.setTo(entityId); + relation.setTypeGroup(RelationTypeGroup.COMMON); + relation.setType(EntityRelation.EDGE_TYPE); + relationService.saveRelation(tenantId, relation); + } + + private void createDeviceCredentials(Device device) { + DeviceCredentials deviceCredentials = new DeviceCredentials(); + deviceCredentials.setDeviceId(device.getId()); + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); + deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20)); + deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials); + } + + private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) { + try { + DeviceId deviceId = device.getId(); + ObjectNode entityNode = mapper.valueToTree(device); + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, + getActionTbMsgMetaData(edge, device.getCustomerId()), TbMsgDataType.JSON, mapper.writeValueAsString(entityNode)); + tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + // TODO: voba - handle success + log.debug("Successfully send ENTITY_CREATED EVENT to rule engine [{}]", device); + } + + @Override + public void onFailure(Throwable t) { + // TODO: voba - handle failure + log.debug("Failed to send ENTITY_CREATED EVENT to rule engine [{}]", device, t); + } + + ; + }); + } catch (JsonProcessingException | IllegalArgumentException e) { + log.warn("[{}] Failed to push device action to rule engine: {}", device.getId(), DataConstants.ENTITY_CREATED, e); + } + } + + + private TbMsgMetaData getActionTbMsgMetaData(Edge edge, CustomerId customerId) { + TbMsgMetaData metaData = getTbMsgMetaData(edge); + if (customerId != null && !customerId.isNullUid()) { + metaData.putValue("customerId", customerId.toString()); + } + return metaData; + } + + + private TbMsgMetaData getTbMsgMetaData(Edge edge) { + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("edgeId", edge.getId().toString()); + metaData.putValue("edgeName", edge.getName()); + return metaData; + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java new file mode 100644 index 0000000000..1ef4044d75 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java @@ -0,0 +1,102 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.processor; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.id.EntityViewId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.gen.edge.RelationUpdateMsg; + +import java.util.UUID; + +@Component +@Slf4j +public class RelationProcessor extends BaseProcessor { + + public ListenableFuture onRelationUpdate(TenantId tenantId, RelationUpdateMsg relationUpdateMsg) { + log.info("onRelationUpdate {}", relationUpdateMsg); + try { + EntityRelation entityRelation = new EntityRelation(); + + UUID fromUUID = new UUID(relationUpdateMsg.getFromIdMSB(), relationUpdateMsg.getFromIdLSB()); + EntityId fromId = EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(relationUpdateMsg.getFromEntityType()), fromUUID); + entityRelation.setFrom(fromId); + + UUID toUUID = new UUID(relationUpdateMsg.getToIdMSB(), relationUpdateMsg.getToIdLSB()); + EntityId toId = EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(relationUpdateMsg.getToEntityType()), toUUID); + entityRelation.setTo(toId); + + entityRelation.setType(relationUpdateMsg.getType()); + entityRelation.setTypeGroup(RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup())); + entityRelation.setAdditionalInfo(mapper.readTree(relationUpdateMsg.getAdditionalInfo())); + switch (relationUpdateMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + if (isEntityExists(tenantId, entityRelation.getTo()) + && isEntityExists(tenantId, entityRelation.getFrom())) { + relationService.saveRelationAsync(tenantId, entityRelation); + } + break; + case ENTITY_DELETED_RPC_MESSAGE: + relationService.deleteRelation(tenantId, entityRelation); + break; + case UNRECOGNIZED: + log.error("Unsupported msg type"); + } + return Futures.immediateFuture(null); + } catch (Exception e) { + log.error("Failed to process relation update msg [{}]", relationUpdateMsg, e); + return Futures.immediateFailedFuture(new RuntimeException("Failed to process relation update msg", e)); + } + } + + + private boolean isEntityExists(TenantId tenantId, EntityId entityId) throws ThingsboardException { + switch (entityId.getEntityType()) { + case DEVICE: + return deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId())) != null; + case ASSET: + return assetService.findAssetById(tenantId, new AssetId(entityId.getId())) != null; + case ENTITY_VIEW: + return entityViewService.findEntityViewById(tenantId, new EntityViewId(entityId.getId())) != null; + case CUSTOMER: + return customerService.findCustomerById(tenantId, new CustomerId(entityId.getId())) != null; + case USER: + return userService.findUserById(tenantId, new UserId(entityId.getId())) != null; + case DASHBOARD: + return dashboardService.findDashboardById(tenantId, new DashboardId(entityId.getId())) != null; + default: + throw new ThingsboardException("Unsupported entity type " + entityId.getEntityType(), ThingsboardErrorCode.INVALID_ARGUMENTS); + } + } + + +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java new file mode 100644 index 0000000000..506d9f6ba7 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java @@ -0,0 +1,202 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.edge.rpc.processor; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityViewId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.kv.AttributeKey; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.session.SessionMsgType; +import org.thingsboard.server.common.transport.util.JsonUtils; +import org.thingsboard.server.gen.edge.AttributeDeleteMsg; +import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.TbQueueCallback; +import org.thingsboard.server.queue.TbQueueMsgMetadata; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +@Component +@Slf4j +public class TelemetryProcessor extends BaseProcessor { + + private final Gson gson = new Gson(); + + public List> onTelemetryUpdate(TenantId tenantId, EntityDataProto entityData) { + List> result = new ArrayList<>(); + EntityId entityId = constructEntityId(entityData); + if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg()) && entityId != null) { + TbMsgMetaData metaData = constructBaseMsgMetadata(tenantId, entityId); + metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE); + if (entityData.hasPostAttributesMsg()) { + metaData.putValue("scope", entityData.getPostAttributeScope()); + result.add(processPostAttributes(tenantId, entityId, entityData.getPostAttributesMsg(), metaData)); + } + if (entityData.hasPostTelemetryMsg()) { + result.add(processPostTelemetry(tenantId, entityId, entityData.getPostTelemetryMsg(), metaData)); + } + } + if (entityData.hasAttributeDeleteMsg()) { + result.add(processAttributeDeleteMsg(tenantId, entityId, entityData.getAttributeDeleteMsg(), entityData.getEntityType())); + } + return result; + } + + private TbMsgMetaData constructBaseMsgMetadata(TenantId tenantId, EntityId entityId) { + TbMsgMetaData metaData = new TbMsgMetaData(); + switch (entityId.getEntityType()) { + case DEVICE: + Device device = deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId())); + if (device != null) { + metaData.putValue("deviceName", device.getName()); + metaData.putValue("deviceType", device.getType()); + } + break; + case ASSET: + Asset asset = assetService.findAssetById(tenantId, new AssetId(entityId.getId())); + if (asset != null) { + metaData.putValue("assetName", asset.getName()); + metaData.putValue("assetType", asset.getType()); + } + break; + case ENTITY_VIEW: + EntityView entityView = entityViewService.findEntityViewById(tenantId, new EntityViewId(entityId.getId())); + if (entityView != null) { + metaData.putValue("entityViewName", entityView.getName()); + metaData.putValue("entityViewType", entityView.getType()); + } + break; + default: + log.debug("Using empty metadata for entityId [{}]", entityId); + break; + } + return metaData; + } + + private ListenableFuture processPostTelemetry(TenantId tenantId, EntityId entityId, TransportProtos.PostTelemetryMsg msg, TbMsgMetaData metaData) { + SettableFuture futureToSet = SettableFuture.create(); + for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { + JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); + metaData.putValue("ts", tsKv.getTs() + ""); + TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_TELEMETRY_REQUEST.name(), entityId, metaData, gson.toJson(json)); + tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't process post telemetry [{}]", msg, t); + futureToSet.setException(t); + } + }); + } + return futureToSet; + } + + private ListenableFuture processPostAttributes(TenantId tenantId, EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { + SettableFuture futureToSet = SettableFuture.create(); + JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); + TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); + tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't process post attributes [{}]", msg, t); + futureToSet.setException(t); + } + }); + return futureToSet; + } + + private ListenableFuture processAttributeDeleteMsg(TenantId tenantId, EntityId entityId, AttributeDeleteMsg attributeDeleteMsg, String entityType) { + SettableFuture futureToSet = SettableFuture.create(); + String scope = attributeDeleteMsg.getScope(); + List attributeNames = attributeDeleteMsg.getAttributeNamesList(); + attributesService.removeAll(tenantId, entityId, scope, attributeNames); + if (EntityType.DEVICE.name().equals(entityType)) { + Set attributeKeys = new HashSet<>(); + for (String attributeName : attributeNames) { + attributeKeys.add(new AttributeKey(scope, attributeName)); + } + tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete( + tenantId, (DeviceId) entityId, attributeKeys), new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't process attribute delete msg [{}]", attributeDeleteMsg, t); + futureToSet.setException(t); + } + }); + } + return futureToSet; + } + + private EntityId constructEntityId(EntityDataProto entityData) { + EntityType entityType = EntityType.valueOf(entityData.getEntityType()); + switch (entityType) { + case DEVICE: + return new DeviceId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case ASSET: + return new AssetId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case ENTITY_VIEW: + return new EntityViewId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case DASHBOARD: + return new DashboardId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case TENANT: + return new TenantId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case CUSTOMER: + return new CustomerId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + case USER: + return new UserId(new UUID(entityData.getEntityIdMSB(), entityData.getEntityIdLSB())); + default: + log.warn("Unsupported entity type [{}] during construct of entity id. EntityDataProto [{}]", entityData.getEntityType(), entityData); + return null; + } + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java b/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java index 84273148c5..158bf62e4c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java @@ -44,7 +44,8 @@ public enum ActionType { LOCKOUT(false), ASSIGNED_TO_EDGE(false), // log edge name UNASSIGNED_FROM_EDGE(false), // log edge name - CREDENTIALS_REQUEST(false); // request credentials from edge + CREDENTIALS_REQUEST(false), // request credentials from edge + ENTITY_EXISTS_REQUEST(false); // request to recreate entity on edge private final boolean isRead; From 4686b2323a18cce31a05bae0190b7b884734573d Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 4 Sep 2020 18:16:42 +0300 Subject: [PATCH 096/156] Null pointer fix --- .../server/service/edge/DefaultEdgeNotificationService.java | 3 ++- .../org/thingsboard/server/dao/edge/EdgeServiceImpl.java | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 58b07f122e..3154f71ab5 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -280,7 +280,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); - EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); + EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, + new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); ListenableFuture> edgeIdsFuture; switch (edgeEventActionType) { case ADDED: // used only for USER entity diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index a484821890..b7562aea84 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -432,7 +432,8 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic ListenableFuture> originatorEdgeRelationsFuture = relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { - if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { + if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0 && + originatorEdgeRelations.get(0).getFrom() != null) { return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); } else { return Collections.emptyList(); @@ -444,6 +445,9 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); case USER: User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); + if (userById == null) { + return Futures.immediateFuture(Collections.emptyList()); + } TextPageData edges; if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { edges = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); From 85fcfef8a5e45b88f359fe3242dbfc2b242123ec Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 15 Sep 2020 13:12:53 +0300 Subject: [PATCH 097/156] Added support for RPC call for edge devices --- .../server/actors/ActorSystemContext.java | 3 + .../service/edge/rpc/EdgeGrpcSession.java | 18 +++ .../rpc/constructor/DeviceMsgConstructor.java | 25 ++++- .../edge/rpc/processor/BaseProcessor.java | 4 + .../edge/rpc/processor/DeviceProcessor.java | 17 +++ .../rpc/DefaultTbRuleEngineRpcService.java | 3 +- .../rpc/TbRuleEngineDeviceRpcService.java | 3 + .../src/main/resources/thingsboard.yml | 2 +- common/edge-api/src/main/proto/edge.proto | 25 ++++- .../server/dao/edge/EdgeServiceImpl.java | 63 ++++++----- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 105 ++++++++---------- .../rule/engine/rpc/TbSendRPCRequestNode.java | 72 ++++++++++-- 12 files changed, 237 insertions(+), 103 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 3f4dcb3c0b..b95e1d92f8 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -255,12 +255,15 @@ public class ActorSystemContext { @Getter private TbCoreDeviceRpcService tbCoreDeviceRpcService; + @Lazy @Autowired(required = false) @Getter private EdgeService edgeService; + @Lazy @Autowired(required = false) @Getter private EdgeEventService edgeEventService; + @Lazy @Autowired(required = false) @Getter private EdgeRpcService edgeRpcService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 078978435d..5332810ee2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -78,6 +78,7 @@ import org.thingsboard.server.gen.edge.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.DownlinkResponseMsg; @@ -333,6 +334,9 @@ public final class EdgeGrpcSession implements Closeable { case ENTITY_EXISTS_REQUEST: downlinkMsg = processEntityExistsRequestMessage(edgeEvent); break; + case RPC_CALL: + downlinkMsg = processRpcCallMsg(edgeEvent); + break; } if (downlinkMsg != null) { result.add(downlinkMsg); @@ -358,6 +362,15 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } + private DownlinkMsg processRpcCallMsg(EdgeEvent edgeEvent) { + log.trace("Executing processRpcCall, edgeEvent [{}]", edgeEvent); + DeviceRpcCallMsg deviceRpcCallMsg = + ctx.getDeviceMsgConstructor().constructDeviceRpcCallMsg(edgeEvent.getEntityBody()); + return DownlinkMsg.newBuilder() + .addAllDeviceRpcCallMsg(Collections.singletonList(deviceRpcCallMsg)) + .build(); + } + private DownlinkMsg processCredentialsRequestMessage(EdgeEvent edgeEvent) { DownlinkMsg downlinkMsg = null; if (EdgeEventType.DEVICE.equals(edgeEvent.getEdgeEventType())) { @@ -883,6 +896,11 @@ public final class EdgeGrpcSession implements Closeable { result.add(ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg)); } } + if (uplinkMsg.getDeviceRpcCallMsgList() != null && !uplinkMsg.getDeviceRpcCallMsgList().isEmpty()) { + for (DeviceRpcCallMsg deviceRpcCallMsg: uplinkMsg.getDeviceRpcCallMsgList()) { + result.add(ctx.getDeviceProcessor().processDeviceRpcCallResponseMsg(edge.getTenantId(), deviceRpcCallMsg)); + } + } } catch (Exception e) { log.error("Can't process uplink msg [{}]", uplinkMsg, e); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java index ebc180d0f9..38905d7529 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java @@ -15,21 +15,27 @@ */ package org.thingsboard.server.service.edge.rpc.constructor; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; +import org.thingsboard.server.gen.edge.RpcRequestMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @Component @Slf4j public class DeviceMsgConstructor { + protected static final ObjectMapper mapper = new ObjectMapper(); + public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId) { DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() .setMsgType(msgType) @@ -67,4 +73,21 @@ public class DeviceMsgConstructor { .setIdMSB(deviceId.getId().getMostSignificantBits()) .setIdLSB(deviceId.getId().getLeastSignificantBits()).build(); } + + public DeviceRpcCallMsg constructDeviceRpcCallMsg(JsonNode body) { + RuleEngineDeviceRpcRequest request = mapper.convertValue(body, RuleEngineDeviceRpcRequest.class); + RpcRequestMsg.Builder requestBuilder = RpcRequestMsg.newBuilder(); + requestBuilder.setMethod(request.getMethod()); + requestBuilder.setParams(request.getBody()); + DeviceRpcCallMsg.Builder builder = DeviceRpcCallMsg.newBuilder() + .setDeviceIdMSB(request.getDeviceId().getId().getMostSignificantBits()) + .setDeviceIdLSB(request.getDeviceId().getId().getLeastSignificantBits()) + .setRequestIdMSB(request.getRequestUUID().getMostSignificantBits()) + .setRequestIdLSB(request.getRequestUUID().getLeastSignificantBits()) + .setExpirationTime(request.getExpirationTime()) + .setOriginServiceId(request.getOriginServiceId()) + .setOneway(request.isOneway()) + .setRequestMsg(requestBuilder.build()); + return builder.build(); + } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java index ee5c545999..08597b1743 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java @@ -39,6 +39,7 @@ import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.queue.TbClusterService; +import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; import org.thingsboard.server.service.state.DeviceStateService; @Slf4j @@ -46,6 +47,9 @@ public abstract class BaseProcessor { protected static final ObjectMapper mapper = new ObjectMapper(); + @Autowired + protected TbRuleEngineDeviceRpcService tbDeviceRpcService; + @Autowired protected AlarmService alarmService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java index db122e31f9..b1f588c6f4 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java @@ -21,7 +21,9 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; +import org.thingsboard.rule.engine.api.RpcError; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.audit.ActionType; @@ -40,9 +42,11 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; +import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; import java.util.UUID; import java.util.concurrent.locks.ReentrantLock; @@ -213,4 +217,17 @@ public class DeviceProcessor extends BaseProcessor { metaData.putValue("edgeName", edge.getName()); return metaData; } + + public ListenableFuture processDeviceRpcCallResponseMsg(TenantId tenantId, DeviceRpcCallMsg deviceRpcCallMsg) { + UUID uuid = new UUID(deviceRpcCallMsg.getRequestIdMSB(), deviceRpcCallMsg.getRequestIdLSB()); + FromDeviceRpcResponse response; + if (!StringUtils.isEmpty(deviceRpcCallMsg.getResponseMsg().getError())) { + response = new FromDeviceRpcResponse(uuid, null, RpcError.valueOf(deviceRpcCallMsg.getResponseMsg().getError())); + } else { + response = new FromDeviceRpcResponse(uuid, deviceRpcCallMsg.getResponseMsg().getResponse(), null); + } + tbDeviceRpcService.sendRpcResponseToTbCore(deviceRpcCallMsg.getOriginServiceId(), response); + return Futures.immediateFuture(null); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java index 80d47a84e8..9ebbed0e44 100644 --- a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java @@ -151,7 +151,8 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi } } - private void sendRpcResponseToTbCore(String originServiceId, FromDeviceRpcResponse response) { + @Override + public void sendRpcResponseToTbCore(String originServiceId, FromDeviceRpcResponse response) { if (serviceId.equals(originServiceId)) { if (tbCoreRpcService.isPresent()) { tbCoreRpcService.get().processRpcResponseFromRuleEngine(response); diff --git a/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java b/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java index 3d4f23a796..4508da381e 100644 --- a/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java @@ -29,4 +29,7 @@ public interface TbRuleEngineDeviceRpcService extends RuleEngineRpcService { */ void processRpcResponseFromDevice(FromDeviceRpcResponse response); + + void sendRpcResponseToTbCore(String originServiceId, FromDeviceRpcResponse response); + } diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 3845517ffb..2a748b7f34 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -588,7 +588,7 @@ transport: # Edges parameters edges: rpc: - enabled: "${EDGES_RPC_ENABLED:true}" + enabled: "${EDGES_RPC_ENABLED:false}" port: "${EDGES_RPC_PORT:7070}" ssl: # Enable/disable SSL support diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 35be11839f..560522e021 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -322,6 +322,28 @@ message DeviceCredentialsRequestMsg { int64 deviceIdLSB = 2; } +message DeviceRpcCallMsg { + int64 deviceIdMSB = 1; + int64 deviceIdLSB = 2; + int64 requestIdMSB = 3; + int64 requestIdLSB = 4; + int64 expirationTime = 5; + bool oneway = 6; + string originServiceId = 7; + RpcRequestMsg requestMsg = 8; + RpcResponseMsg responseMsg = 9; +} + +message RpcRequestMsg { + string method = 1; + string params = 2; +} + +message RpcResponseMsg { + string response = 1; + string error = 2; +} + enum EdgeEntityType { DEVICE = 0; ASSET = 1; @@ -343,6 +365,7 @@ message UplinkMsg { repeated RelationRequestMsg relationRequestMsg = 9; repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 10; repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 11; + repeated DeviceRpcCallMsg deviceRpcCallMsg = 12; } message UplinkResponseMsg { @@ -374,6 +397,6 @@ message DownlinkMsg { repeated WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 16; repeated WidgetTypeUpdateMsg widgetTypeUpdateMsg = 17; repeated AdminSettingsUpdateMsg adminSettingsUpdateMsg = 18; - + repeated DeviceRpcCallMsg deviceRpcCallMsg = 19; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index b7562aea84..2a362e6483 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -425,38 +425,43 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @Override public ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { - switch (entityId.getEntityType()) { - case DEVICE: - case ASSET: - case ENTITY_VIEW: - ListenableFuture> originatorEdgeRelationsFuture = - relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); - return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { - if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0 && - originatorEdgeRelations.get(0).getFrom() != null) { - return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); + if (EntityType.TENANT.equals(entityId.getEntityType())) { + TextPageData edgesByTenantId = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); + return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); + } else { + switch (entityId.getEntityType()) { + case DEVICE: + case ASSET: + case ENTITY_VIEW: + ListenableFuture> originatorEdgeRelationsFuture = + relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); + return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { + if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0 && + originatorEdgeRelations.get(0).getFrom() != null) { + return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); + } else { + return Collections.emptyList(); + } + }, MoreExecutors.directExecutor()); + case DASHBOARD: + return convertToEdgeIds(findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); + case RULE_CHAIN: + return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); + case USER: + User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); + if (userById == null) { + return Futures.immediateFuture(Collections.emptyList()); + } + TextPageData edges; + if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { + edges = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); } else { - return Collections.emptyList(); + edges = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); } - }, MoreExecutors.directExecutor()); - case DASHBOARD: - return convertToEdgeIds(findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); - case RULE_CHAIN: - return convertToEdgeIds(findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); - case USER: - User userById = userService.findUserById(tenantId, new UserId(entityId.getId())); - if (userById == null) { + return convertToEdgeIds(Futures.immediateFuture(edges.getData())); + default: return Futures.immediateFuture(Collections.emptyList()); - } - TextPageData edges; - if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { - edges = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); - } else { - edges = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); - } - return convertToEdgeIds(Futures.immediateFuture(edges.getData())); - default: - return Futures.immediateFuture(Collections.emptyList()); + } } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 1c0e44050d..b7cea6de20 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -33,29 +33,20 @@ import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.IdBased; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.page.TextPageData; -import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.relation.EntityRelation; -import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import javax.annotation.Nullable; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.stream.Collectors; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -86,51 +77,12 @@ public class TbMsgPushToEdgeNode implements TbNode { public void onMsg(TbContext ctx, TbMsg msg) { if (DataConstants.EDGE_MSG_SOURCE.equalsIgnoreCase(msg.getMetaData().getValue(DataConstants.MSG_SOURCE_KEY))) { log.debug("Ignoring msg from the cloud, msg [{}]", msg); + ctx.ack(msg); return; } if (isSupportedOriginator(msg.getOriginator().getEntityType())) { if (isSupportedMsgType(msg.getType())) { - ListenableFuture> getEdgeIdsFuture = getEdgeIdsByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator()); - Futures.addCallback(getEdgeIdsFuture, new FutureCallback>() { - @Override - public void onSuccess(@Nullable List edgeIds) { - if (edgeIds != null && !edgeIds.isEmpty()) { - for (EdgeId edgeId : edgeIds) { - try { - EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx); - if (edgeEvent == null) { - log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); - ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); - } else { - edgeEvent.setEdgeId(edgeId); - ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); - Futures.addCallback(saveFuture, new FutureCallback() { - @Override - public void onSuccess(@Nullable EdgeEvent event) { - ctx.tellNext(msg, SUCCESS); - } - - @Override - public void onFailure(Throwable th) { - log.error("Could not save edge event", th); - ctx.tellFailure(msg, th); - } - }, ctx.getDbCallbackExecutor()); - } - } catch (JsonProcessingException e) { - log.error("Failed to build edge event", e); - ctx.tellFailure(msg, e); - } - } - } - } - - @Override - public void onFailure(Throwable t) { - ctx.tellFailure(msg, t); - } - - }, ctx.getDbCallbackExecutor()); + processMsg(ctx, msg); } else { log.debug("Unsupported msg type {}", msg.getType()); ctx.tellFailure(msg, new RuntimeException("Unsupported msg type '" + msg.getType() + "'")); @@ -141,6 +93,50 @@ public class TbMsgPushToEdgeNode implements TbNode { } } + private void processMsg(TbContext ctx, TbMsg msg) { + ListenableFuture> getEdgeIdsFuture = ctx.getEdgeService().findRelatedEdgeIdsByEntityId(ctx.getTenantId(), msg.getOriginator()); + Futures.addCallback(getEdgeIdsFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List edgeIds) { + if (edgeIds != null && !edgeIds.isEmpty()) { + for (EdgeId edgeId : edgeIds) { + try { + EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx); + if (edgeEvent == null) { + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType()); + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'")); + } else { + edgeEvent.setEdgeId(edgeId); + ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); + Futures.addCallback(saveFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent event) { + ctx.tellNext(msg, SUCCESS); + } + + @Override + public void onFailure(Throwable th) { + log.error("Could not save edge event", th); + ctx.tellFailure(msg, th); + } + }, ctx.getDbCallbackExecutor()); + } + } catch (JsonProcessingException e) { + log.error("Failed to build edge event", e); + ctx.tellFailure(msg, e); + } + } + } + } + + @Override + public void onFailure(Throwable t) { + ctx.tellFailure(msg, t); + } + + }, ctx.getDbCallbackExecutor()); + } + private EdgeEvent buildEdgeEvent(TbMsg msg, TbContext ctx) throws JsonProcessingException { if (DataConstants.ALARM.equals(msg.getType())) { return buildEdgeEvent(ctx.getTenantId(), ActionType.ADDED, getUUIDFromMsgData(msg), EdgeEventType.ALARM, null); @@ -227,15 +223,6 @@ public class TbMsgPushToEdgeNode implements TbNode { || DataConstants.ALARM.equals(msgType); } - private ListenableFuture> getEdgeIdsByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) { - if (EntityType.TENANT.equals(originatorId.getEntityType())) { - TextPageData edgesByTenantId = ctx.getEdgeService().findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); - return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); - } else { - return ctx.getEdgeService().findRelatedEdgeIdsByEntityId(tenantId, originatorId); - } - } - @Override public void destroy() { } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java index 301c7cd36c..fe3326c4bc 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java @@ -16,13 +16,16 @@ package org.thingsboard.rule.engine.rpc; import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; @@ -30,13 +33,21 @@ import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.TbRelationTypes; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.msg.TbMsg; +import javax.annotation.Nullable; +import java.util.List; import java.util.Random; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -55,6 +66,7 @@ import java.util.concurrent.TimeUnit; ) public class TbSendRPCRequestNode implements TbNode { + private static final ObjectMapper json = new ObjectMapper(); private Random random = new Random(); private Gson gson = new Gson(); private JsonParser jsonParser = new JsonParser(); @@ -111,19 +123,57 @@ public class TbSendRPCRequestNode implements TbNode { .restApiCall(restApiCall) .build(); - ctx.getRpcService().sendRpcRequestToDevice(request, ruleEngineDeviceRpcResponse -> { - if (!ruleEngineDeviceRpcResponse.getError().isPresent()) { - TbMsg next = ctx.newMsg(msg.getQueueName(), msg.getType(), msg.getOriginator(), msg.getMetaData(), ruleEngineDeviceRpcResponse.getResponse().orElse("{}")); - ctx.enqueueForTellNext(next, TbRelationTypes.SUCCESS); - } else { - TbMsg next = ctx.newMsg(msg.getQueueName(), msg.getType(), msg.getOriginator(), msg.getMetaData(), wrap("error", ruleEngineDeviceRpcResponse.getError().get().name())); - ctx.tellFailure(next, new RuntimeException(ruleEngineDeviceRpcResponse.getError().get().name())); - } - }); + EdgeId edgeId = findRelatedEdgeId(ctx, msg); + if (edgeId != null) { + sendRpcRequestToEdgeDevice(ctx, msg, edgeId, request); + } else { + ctx.getRpcService().sendRpcRequestToDevice(request, ruleEngineDeviceRpcResponse -> { + if (!ruleEngineDeviceRpcResponse.getError().isPresent()) { + TbMsg next = ctx.newMsg(msg.getQueueName(), msg.getType(), msg.getOriginator(), msg.getMetaData(), ruleEngineDeviceRpcResponse.getResponse().orElse("{}")); + ctx.enqueueForTellNext(next, TbRelationTypes.SUCCESS); + } else { + TbMsg next = ctx.newMsg(msg.getQueueName(), msg.getType(), msg.getOriginator(), msg.getMetaData(), wrap("error", ruleEngineDeviceRpcResponse.getError().get().name())); + ctx.tellFailure(next, new RuntimeException(ruleEngineDeviceRpcResponse.getError().get().name())); + } + }); + } ctx.ack(msg); } } + private EdgeId findRelatedEdgeId(TbContext ctx, TbMsg msg) { + List result = + ctx.getRelationService().findByToAndType(ctx.getTenantId(), msg.getOriginator(), EntityRelation.EDGE_TYPE, RelationTypeGroup.COMMON); + if (result != null && result.size() > 0) { + return new EdgeId(result.get(0).getFrom().getId()); + } else { + return null; + } + } + + private void sendRpcRequestToEdgeDevice(TbContext ctx, TbMsg msg, EdgeId edgeId, RuleEngineDeviceRpcRequest request) { + EdgeEvent edgeEvent = new EdgeEvent(); + edgeEvent.setTenantId(ctx.getTenantId()); + edgeEvent.setEdgeEventAction(ActionType.RPC_CALL.name()); + edgeEvent.setEntityId(request.getDeviceId().getId()); + edgeEvent.setEdgeEventType(EdgeEventType.DEVICE); + edgeEvent.setEntityBody(json.valueToTree(request)); + edgeEvent.setEdgeId(edgeId); + ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); + Futures.addCallback(saveFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent event) { + ctx.tellSuccess(msg); + } + + @Override + public void onFailure(Throwable th) { + log.error("Could not save edge event", th); + ctx.tellFailure(msg, th); + } + }, ctx.getDbCallbackExecutor()); + } + @Override public void destroy() { } From 4bb56df51a747b78015a83dd1b21b9ee6ddef933 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 17 Sep 2020 12:53:38 +0300 Subject: [PATCH 098/156] Added cassandra edge dao. Tests fixed --- .../demo/rule_chains/root_rule_chain.json | 1 + .../main/data/upgrade/2.6.0/schema_update.cql | 34 ++++- .../main/data/upgrade/2.6.0/schema_update.sql | 16 ++- .../server/controller/BaseController.java | 15 +++ .../controller/DashboardController.java | 2 - .../edge/DefaultEdgeNotificationService.java | 9 +- .../service/edge/rpc/EdgeGrpcSession.java | 26 ++-- .../edge/rpc/init/DefaultSyncEdgeService.java | 6 +- .../edge/rpc/processor/BaseProcessor.java | 6 +- .../rpc/TbRuleEngineDeviceRpcService.java | 6 + application/src/main/resources/logback.xml | 1 - .../src/main/resources/thingsboard.yml | 1 + .../controller/AbstractControllerTest.java | 14 ++ .../controller/BaseAssetControllerTest.java | 28 ++++ .../BaseDashboardControllerTest.java | 56 ++++++-- .../controller/BaseDeviceControllerTest.java | 29 ++++ .../controller/BaseEdgeControllerTest.java | 13 -- .../BaseEdgeEventControllerTest.java | 25 ++-- .../BaseEntityViewControllerTest.java | 30 ++++- .../controller/ControllerNoSqlTestSuite.java | 3 +- .../server/mqtt/MqttNoSqlTestSuite.java | 3 +- .../server/system/SystemNoSqlTestSuite.java | 3 +- .../server/dao/edge/EdgeService.java | 11 -- .../server/common/data/DashboardInfo.java | 7 +- .../server/common/data/ShortEdgeInfo.java | 50 ------- .../server/common/data/edge/Edge.java | 8 -- .../server/common/data/edge/EdgeEvent.java | 7 +- .../server/common/data/rule/RuleChain.java | 7 - .../server/dao/edge/BaseEdgeEventService.java | 2 +- .../server/dao/edge/CassandraEdgeDao.java | 125 ++++++++++++++++-- .../dao/edge/CassandraEdgeEventDao.java | 74 ++++++++++- .../server/dao/model/ModelConstants.java | 11 +- .../server/dao/model/nosql/EdgeEntity.java | 10 +- .../dao/model/nosql/EdgeEventEntity.java | 64 ++++----- .../server/dao/model/sql/EdgeEventEntity.java | 23 ++-- .../dao/nosql/CassandraAbstractDao.java | 4 + .../server/dao/rule/BaseRuleChainService.java | 6 - .../resources/cassandra/schema-entities.cql | 33 ++++- .../resources/sql/schema-entities-hsql.sql | 5 +- .../main/resources/sql/schema-entities.sql | 4 +- .../server/dao/NoSqlDaoServiceTestSuite.java | 3 +- .../dao/service/BaseEdgeEventServiceTest.java | 14 +- .../resources/application-test.properties | 2 + .../engine/action/TbAssignToCustomerNode.java | 11 +- .../rule/engine/action/TbClearAlarmNode.java | 4 +- .../TbCopyAttributesToEntityViewNode.java | 6 +- .../rule/engine/action/TbCreateAlarmNode.java | 4 +- .../engine/action/TbCreateRelationNode.java | 4 +- .../engine/action/TbDeleteRelationNode.java | 4 +- .../rule/engine/action/TbLogNode.java | 12 +- .../rule/engine/action/TbMsgCountNode.java | 12 +- .../TbSaveToCustomCassandraTableNode.java | 4 + .../rule/engine/aws/sns/TbSnsNode.java | 7 +- .../rule/engine/aws/sqs/TbSqsNode.java | 8 +- .../rule/engine/debug/TbMsgGeneratorNode.java | 8 +- .../rule/engine/delay/TbMsgDelayNode.java | 2 - .../rule/engine/edge/TbMsgPushToEdgeNode.java | 6 +- .../engine/filter/TbCheckMessageNode.java | 4 +- .../engine/filter/TbCheckRelationNode.java | 4 +- .../rule/engine/filter/TbJsFilterNode.java | 12 +- .../rule/engine/filter/TbJsSwitchNode.java | 11 +- .../engine/filter/TbMsgTypeFilterNode.java | 10 +- .../engine/filter/TbMsgTypeSwitchNode.java | 4 +- .../filter/TbOriginatorTypeFilterNode.java | 10 +- .../filter/TbOriginatorTypeSwitchNode.java | 11 +- .../rule/engine/gcp/pubsub/TbPubSubNode.java | 9 +- .../engine/geo/TbGpsGeofencingActionNode.java | 1 - .../engine/geo/TbGpsGeofencingFilterNode.java | 22 +-- .../rule/engine/kafka/TbKafkaNode.java | 1 - .../rule/engine/mail/TbMsgToEmailNode.java | 7 +- .../rule/engine/mail/TbSendEmailNode.java | 1 - .../engine/metadata/TbGetAttributesNode.java | 6 +- .../metadata/TbGetCustomerAttributeNode.java | 4 +- .../metadata/TbGetCustomerDetailsNode.java | 4 +- .../engine/metadata/TbGetDeviceAttrNode.java | 7 +- .../metadata/TbGetOriginatorFieldsNode.java | 5 +- .../metadata/TbGetRelatedAttributeNode.java | 10 +- .../engine/metadata/TbGetTelemetryNode.java | 5 +- .../metadata/TbGetTenantAttributeNode.java | 4 +- .../metadata/TbGetTenantDetailsNode.java | 4 +- .../rule/engine/mqtt/TbMqttNode.java | 9 +- .../rule/engine/rabbitmq/TbRabbitMqNode.java | 14 +- .../rule/engine/rest/TbRestApiCallNode.java | 1 - .../rule/engine/rpc/TbSendRPCReplyNode.java | 4 +- .../rule/engine/rpc/TbSendRPCRequestNode.java | 14 +- .../engine/telemetry/TbMsgAttributesNode.java | 13 +- .../engine/telemetry/TbMsgTimeseriesNode.java | 3 +- .../TbSynchronizationBeginNode.java | 7 +- .../transaction/TbSynchronizationEndNode.java | 6 - .../transform/TbChangeOriginatorNode.java | 3 +- .../engine/transform/TbTransformMsgNode.java | 13 +- 91 files changed, 705 insertions(+), 427 deletions(-) delete mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/ShortEdgeInfo.java diff --git a/application/src/main/data/json/demo/rule_chains/root_rule_chain.json b/application/src/main/data/json/demo/rule_chains/root_rule_chain.json index 9805c6f996..f51b89ab24 100644 --- a/application/src/main/data/json/demo/rule_chains/root_rule_chain.json +++ b/application/src/main/data/json/demo/rule_chains/root_rule_chain.json @@ -2,6 +2,7 @@ "ruleChain": { "additionalInfo": null, "name": "Root Rule Chain", + "type": "CORE", "firstRuleNodeId": null, "root": true, "debugMode": false, diff --git a/application/src/main/data/upgrade/2.6.0/schema_update.cql b/application/src/main/data/upgrade/2.6.0/schema_update.cql index 7e1a99f8db..f85b309836 100644 --- a/application/src/main/data/upgrade/2.6.0/schema_update.cql +++ b/application/src/main/data/upgrade/2.6.0/schema_update.cql @@ -18,11 +18,16 @@ CREATE TABLE IF NOT EXISTS thingsboard.edge ( id timeuuid, tenant_id timeuuid, customer_id timeuuid, + root_rule_chain_id timeuuid, + type text, name text, + label text, search_text text, + routing_key text, + secret text, configuration text, additional_info text, - PRIMARY KEY (id, tenant_id) + PRIMARY KEY (id, tenant_id, customer_id, type) ); CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS @@ -32,6 +37,13 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS PRIMARY KEY ( tenant_id, name, id, customer_id, type) WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_routing_key AS + SELECT * + from thingsboard.edge + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND routing_key IS NOT NULL AND id IS NOT NULL + PRIMARY KEY ( tenant_id, routing_key, id, customer_id, type) + WITH CLUSTERING ORDER BY ( routing_key ASC, id DESC, customer_id DESC); + CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS SELECT * from thingsboard.edge @@ -60,4 +72,22 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_customer_by_type_and_ PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); --- VOBA ADD changes for the MATERIALIZED view for DEVICE ASSET ENTITY_VIEW RULE_CHAIN \ No newline at end of file +CREATE TABLE IF NOT EXISTS thingsboard.edge_event ( + id timeuuid, + tenant_id timeuuid, + edge_id timeuuid, + edge_event_type text, + edge_event_action text, + edge_event_uid text, + entity_id timeuuid, + body text, + PRIMARY KEY ((tenant_id, edge_id), edge_event_type, edge_event_uid) +); + +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_event_by_id AS + SELECT * + FROM thingsboard.edge_event + WHERE tenant_id IS NOT NULL AND edge_id IS NOT NULL AND edge_event_type IS NOT NULL + AND id IS NOT NULL AND edge_event_uid IS NOT NULL + PRIMARY KEY ((tenant_id, edge_id), id, edge_event_type, edge_event_uid) + WITH CLUSTERING ORDER BY (id ASC); \ No newline at end of file diff --git a/application/src/main/data/upgrade/2.6.0/schema_update.sql b/application/src/main/data/upgrade/2.6.0/schema_update.sql index 5d2c368d1d..90660d4026 100644 --- a/application/src/main/data/upgrade/2.6.0/schema_update.sql +++ b/application/src/main/data/upgrade/2.6.0/schema_update.sql @@ -26,5 +26,19 @@ CREATE TABLE IF NOT EXISTS edge ( routing_key varchar(255), secret varchar(255), search_text varchar(255), - tenant_id varchar(31) + tenant_id varchar(31), + CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name), + CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key) +); + +CREATE TABLE IF NOT EXISTS edge_event ( + id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY, + edge_id varchar(31), + edge_event_type varchar(255), + edge_event_uid varchar(255), + entity_id varchar(31), + edge_event_action varchar(255), + body varchar(10000000), + tenant_id varchar(31), + ts bigint NOT NULL ); diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 479d3208ff..6b43b83549 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -212,6 +212,9 @@ public abstract class BaseController { @Getter private boolean logControllerErrorStackTrace; + @Value("${edges.rpc.enabled}") + @Getter + private boolean edgesSupportEnabled; @ExceptionHandler(ThingsboardException.class) public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { @@ -745,6 +748,9 @@ public abstract class BaseController { } protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, CustomerId customerId, ActionType edgeEventAction) { + if (!edgesSupportEnabled) { + return; + } try { sendNotificationMsgToEdgeService(tenantId, edgeId, null, json.writeValueAsString(customerId), EdgeEventType.EDGE, edgeEventAction); } catch (Exception e) { @@ -753,6 +759,9 @@ public abstract class BaseController { } protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, CustomerId customerId, ActionType edgeEventAction) { + if (!edgesSupportEnabled) { + return; + } EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); try { if (edgeEventType != null) { @@ -764,6 +773,9 @@ public abstract class BaseController { } protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) { + if (!edgesSupportEnabled) { + return; + } try { if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && !relation.getTo().getEntityType().equals(EntityType.EDGE)) { @@ -779,6 +791,9 @@ public abstract class BaseController { } protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, ActionType edgeEventAction) { + if (!edgesSupportEnabled) { + return; + } EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); if (edgeEventType != null) { sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, edgeEventType, edgeEventAction); diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index 31c7a7d0b7..95230dc4f5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -31,10 +31,8 @@ import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.ShortCustomerInfo; -import org.thingsboard.server.common.data.ShortEdgeInfo; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 3154f71ab5..a014ec3d30 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -87,9 +87,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @Autowired private RuleChainService ruleChainService; - @Autowired - private RelationService relationService; - @Autowired private EdgeEventService edgeEventService; @@ -135,12 +132,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setEdgeId(edgeId); edgeEvent.setTenantId(tenantId); - edgeEvent.setEdgeEventType(edgeEventType); - edgeEvent.setEdgeEventAction(edgeEventAction.name()); + edgeEvent.setType(edgeEventType); + edgeEvent.setAction(edgeEventAction.name()); if (entityId != null) { edgeEvent.setEntityId(entityId.getId()); } - edgeEvent.setEntityBody(entityBody); + edgeEvent.setBody(entityBody); edgeEventService.saveAsync(edgeEvent); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 5332810ee2..375db62e80 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -307,7 +307,7 @@ public final class EdgeGrpcSession implements Closeable { log.trace("Processing edge event [{}]", edgeEvent); try { DownlinkMsg downlinkMsg = null; - ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getEdgeEventAction()); + ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getAction()); switch (edgeEventAction) { case UPDATED: case ADDED: @@ -350,7 +350,7 @@ public final class EdgeGrpcSession implements Closeable { private DownlinkMsg processEntityExistsRequestMessage(EdgeEvent edgeEvent) { DownlinkMsg downlinkMsg = null; - if (EdgeEventType.DEVICE.equals(edgeEvent.getEdgeEventType())) { + if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); @@ -365,7 +365,7 @@ public final class EdgeGrpcSession implements Closeable { private DownlinkMsg processRpcCallMsg(EdgeEvent edgeEvent) { log.trace("Executing processRpcCall, edgeEvent [{}]", edgeEvent); DeviceRpcCallMsg deviceRpcCallMsg = - ctx.getDeviceMsgConstructor().constructDeviceRpcCallMsg(edgeEvent.getEntityBody()); + ctx.getDeviceMsgConstructor().constructDeviceRpcCallMsg(edgeEvent.getBody()); return DownlinkMsg.newBuilder() .addAllDeviceRpcCallMsg(Collections.singletonList(deviceRpcCallMsg)) .build(); @@ -373,7 +373,7 @@ public final class EdgeGrpcSession implements Closeable { private DownlinkMsg processCredentialsRequestMessage(EdgeEvent edgeEvent) { DownlinkMsg downlinkMsg = null; - if (EdgeEventType.DEVICE.equals(edgeEvent.getEdgeEventType())) { + if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) @@ -409,7 +409,7 @@ public final class EdgeGrpcSession implements Closeable { private DownlinkMsg processTelemetryMessage(EdgeEvent edgeEvent) { log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent); EntityId entityId = null; - switch (edgeEvent.getEdgeEventType()) { + switch (edgeEvent.getType()) { case DEVICE: entityId = new DeviceId(edgeEvent.getEntityId()); break; @@ -431,21 +431,21 @@ public final class EdgeGrpcSession implements Closeable { } DownlinkMsg downlinkMsg = null; if (entityId != null) { - log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody()); + log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getBody()); try { - ActionType actionType = ActionType.valueOf(edgeEvent.getEdgeEventAction()); - downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(mapper.writeValueAsString(edgeEvent.getEntityBody()))); + ActionType actionType = ActionType.valueOf(edgeEvent.getAction()); + downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(mapper.writeValueAsString(edgeEvent.getBody()))); } catch (Exception e) { - log.warn("Can't send telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody(), e); + log.warn("Can't send telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getBody(), e); } } return downlinkMsg; } private DownlinkMsg processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) { - UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction())); + UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getAction())); log.trace("Executing processEntityMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType); - switch (edgeEvent.getEdgeEventType()) { + switch (edgeEvent.getType()) { case EDGE: // TODO: voba - add edge update logic return null; @@ -728,7 +728,7 @@ public final class EdgeGrpcSession implements Closeable { } private DownlinkMsg processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) { - EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); + EntityRelation entityRelation = mapper.convertValue(edgeEvent.getBody(), EntityRelation.class); RelationUpdateMsg r = ctx.getRelationMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation); return DownlinkMsg.newBuilder() .addAllRelationUpdateMsg(Collections.singletonList(r)) @@ -804,7 +804,7 @@ public final class EdgeGrpcSession implements Closeable { } private DownlinkMsg processAdminSettings(EdgeEvent edgeEvent) { - AdminSettings adminSettings = mapper.convertValue(edgeEvent.getEntityBody(), AdminSettings.class); + AdminSettings adminSettings = mapper.convertValue(edgeEvent.getBody(), AdminSettings.class); AdminSettingsUpdateMsg t = ctx.getAdminSettingsMsgConstructor().constructAdminSettingsUpdateMsg(adminSettings); return DownlinkMsg.newBuilder() .addAllAdminSettingsUpdateMsg(Collections.singletonList(t)) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 27ea1379f5..b241a17eb1 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -534,12 +534,12 @@ public class DefaultSyncEdgeService implements SyncEdgeService { EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setTenantId(tenantId); edgeEvent.setEdgeId(edgeId); - edgeEvent.setEdgeEventType(edgeEventType); - edgeEvent.setEdgeEventAction(edgeEventAction.name()); + edgeEvent.setType(edgeEventType); + edgeEvent.setAction(edgeEventAction.name()); if (entityId != null) { edgeEvent.setEntityId(entityId.getId()); } - edgeEvent.setEntityBody(entityBody); + edgeEvent.setBody(entityBody); return edgeEventService.saveAsync(edgeEvent); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java index 08597b1743..7cdc6b08c5 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java @@ -105,12 +105,12 @@ public abstract class BaseProcessor { EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setTenantId(tenantId); edgeEvent.setEdgeId(edgeId); - edgeEvent.setEdgeEventType(edgeEventType); - edgeEvent.setEdgeEventAction(edgeEventAction.name()); + edgeEvent.setType(edgeEventType); + edgeEvent.setAction(edgeEventAction.name()); if (entityId != null) { edgeEvent.setEntityId(entityId.getId()); } - edgeEvent.setEntityBody(entityBody); + edgeEvent.setBody(entityBody); return edgeEventService.saveAsync(edgeEvent); } } diff --git a/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java b/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java index 4508da381e..4739338c6c 100644 --- a/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/rpc/TbRuleEngineDeviceRpcService.java @@ -30,6 +30,12 @@ public interface TbRuleEngineDeviceRpcService extends RuleEngineRpcService { void processRpcResponseFromDevice(FromDeviceRpcResponse response); + /** + * Sends Rpc response from the Device to TB Core. + * + * @param originServiceId Service ID of the origin component + * @param response the RPC response + */ void sendRpcResponseToTbCore(String originServiceId, FromDeviceRpcResponse response); } diff --git a/application/src/main/resources/logback.xml b/application/src/main/resources/logback.xml index 83d29a3755..81eb788e35 100644 --- a/application/src/main/resources/logback.xml +++ b/application/src/main/resources/logback.xml @@ -26,7 +26,6 @@ - diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 2a748b7f34..bcf3425f53 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -599,6 +599,7 @@ edges: max_read_records_count: "${EDGES_RPC_STORAGE_MAX_READ_RECORDS_COUNT:50}" no_read_records_sleep: "${EDGES_RPC_NO_READ_RECORDS_SLEEP:1000}" sleep_between_batches: "${EDGES_RPC_SLEEP_BETWEEN_BATCHES:1000}" + edge_events_ttl: "${EDGES_EDGE_EVENTS_TTL:0}" state: persistToTelemetry: "${EDGES_PERSIST_STATE_TO_TELEMETRY:false}" diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java index ca1991ed12..0b3a86a22e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java @@ -23,6 +23,7 @@ import io.jsonwebtoken.Header; import io.jsonwebtoken.Jwt; import io.jsonwebtoken.Jwts; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.hamcrest.Matcher; import org.junit.After; @@ -62,6 +63,7 @@ import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.page.TextPageLink; @@ -498,4 +500,16 @@ public abstract class AbstractControllerTest { return jsonPath("$.message", matcher); } + protected Edge constructEdge(String name, String type) { + return constructEdge(tenantId, name, type); + } + protected Edge constructEdge(TenantId tenantId, String name, String type) { + Edge edge = new Edge(); + edge.setTenantId(tenantId); + edge.setName(name); + edge.setType(type); + edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); + edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); + return edge; + } } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java index 24dbcca2db..6896106292 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java @@ -27,9 +27,11 @@ import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.service.stats.DefaultRuleEngineStatisticsService; @@ -690,4 +692,30 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { Assert.assertEquals(0, pageData.getData().size()); } + @Test + public void testAssignAssetToEdge() throws Exception { + Edge edge = constructEdge("My edge", "default"); + Edge savedEdge = doPost("/api/edge", edge, Edge.class); + + Asset asset = new Asset(); + asset.setName("My asset"); + asset.setType("default"); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + + doPost("/api/edge/" + savedEdge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + + TimePageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(1, pageData.getData().size()); + + doDelete("/api/edge/" + savedEdge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + + pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(0, pageData.getData().size()); + } } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java index e8fbfe4aa1..109a4695a9 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java @@ -15,28 +15,32 @@ */ package org.thingsboard.server.controller; -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.lang3.RandomStringUtils; -import org.thingsboard.server.common.data.*; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.common.data.DashboardInfo; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.security.Authority; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import com.fasterxml.jackson.core.type.TypeReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public abstract class BaseDashboardControllerTest extends AbstractControllerTest { @@ -349,4 +353,30 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest Assert.assertEquals(dashboards, loadedDashboards); } + @Test + public void testAssignDashboardToEdge() throws Exception { + Edge edge = constructEdge("My edge", "default"); + Edge savedEdge = doPost("/api/edge", edge, Edge.class); + + Dashboard dashboard = new Dashboard(); + dashboard.setTitle("My dashboard"); + Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class); + + doPost("/api/edge/" + savedEdge.getId().getId().toString() + + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); + + TimePageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/dashboards?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(1, pageData.getData().size()); + + doDelete("/api/edge/" + savedEdge.getId().getId().toString() + + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); + + pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/dashboards?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(0, pageData.getData().size()); + } + } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java index 99de423086..5e45b535d5 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java @@ -27,11 +27,13 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceCredentialsId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.security.Authority; @@ -849,4 +851,31 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { doDelete("/api/tenant/" + savedDifferentTenant.getId().getId().toString()) .andExpect(status().isOk()); } + + @Test + public void testAssignDeviceToEdge() throws Exception { + Edge edge = constructEdge("My edge", "default"); + Edge savedEdge = doPost("/api/edge", edge, Edge.class); + + Device device = new Device(); + device.setName("My device"); + device.setType("default"); + Device savedDevice = doPost("/api/device", device, Device.class); + + doPost("/api/edge/" + savedEdge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + + TimePageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(1, pageData.getData().size()); + + doDelete("/api/edge/" + savedEdge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + + pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(0, pageData.getData().size()); + } } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index 2b33776eee..1f655a2c3c 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -638,17 +638,4 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { Assert.assertEquals(0, pageData.getData().size()); } - private Edge constructEdge(String name, String type) { - return constructEdge(tenantId, name, type); - } - - private Edge constructEdge(TenantId tenantId, String name, String type) { - Edge edge = new Edge(); - edge.setTenantId(tenantId); - edge.setName(name); - edge.setType(type); - edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); - edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); - return edge; - } } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java index b3bc16b3d5..2d838d3ae4 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java @@ -83,38 +83,29 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { Device savedDevice = doPost("/api/device", device, Device.class); doPost("/api/edge/" + edge.getId().toString() + "/device/" + savedDevice.getId().toString(), Device.class); + Thread.sleep(1000); Asset asset = constructAsset("TestAsset", "default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); doPost("/api/edge/" + edge.getId().toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); + Thread.sleep(1000); EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE); doPost("/api/relation", relation); - - Thread.sleep(2000); + Thread.sleep(1000); List edgeEvents = doGetTypedWithTimePageLink("/api/edge/" + edge.getId().toString() + "/events?", new TypeReference>() { - }, new TimePageLink(5)).getData(); + }, new TimePageLink(4)).getData(); Assert.assertFalse(edgeEvents.isEmpty()); Assert.assertEquals(4, edgeEvents.size()); - Assert.assertEquals(edgeEvents.get(0).getEdgeEventType(), EdgeEventType.RELATION); - Assert.assertEquals(edgeEvents.get(1).getEdgeEventType(), EdgeEventType.ASSET); - Assert.assertEquals(edgeEvents.get(2).getEdgeEventType(), EdgeEventType.DEVICE); - Assert.assertEquals(edgeEvents.get(3).getEdgeEventType(), EdgeEventType.RULE_CHAIN); - } - - private Edge constructEdge(String name, String type) { - Edge edge = new Edge(); - edge.setTenantId(tenantId); - edge.setName(name); - edge.setType(type); - edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); - edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); - return edge; + Assert.assertEquals(EdgeEventType.RELATION, edgeEvents.get(0).getType()); + Assert.assertEquals(EdgeEventType.ASSET, edgeEvents.get(1).getType()); + Assert.assertEquals(EdgeEventType.DEVICE, edgeEvents.get(2).getType()); + Assert.assertEquals(EdgeEventType.RULE_CHAIN, edgeEvents.get(3).getType()); } private Device constructDevice(String name, String type) { diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java index bec1b55a79..9db11b7eb1 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java @@ -31,11 +31,13 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.objects.AttributesEntityView; import org.thingsboard.server.common.data.objects.TelemetryEntityView; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.model.ModelConstants; @@ -52,7 +54,6 @@ import java.util.concurrent.TimeUnit; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; @@ -552,4 +553,31 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes return loadedItems; } + + @Test + public void testAssignEntityViewToEdge() throws Exception { + Edge edge = constructEdge("My edge", "default"); + Edge savedEdge = doPost("/api/edge", edge, Edge.class); + + EntityView savedEntityView = getNewSavedEntityView("My entityView"); + + doPost("/api/edge/" + savedEdge.getId().getId().toString() + + "/device/" + testDevice.getId().getId().toString(), Device.class); + + doPost("/api/edge/" + savedEdge.getId().getId().toString() + + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); + + TimePageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/entityViews?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(1, pageData.getData().size()); + + doDelete("/api/edge/" + savedEdge.getId().getId().toString() + + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); + + pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/entityViews?", + new TypeReference>() {}, new TextPageLink(100)); + + Assert.assertEquals(0, pageData.getData().size()); + } } diff --git a/application/src/test/java/org/thingsboard/server/controller/ControllerNoSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/controller/ControllerNoSqlTestSuite.java index 86960f4450..781c483fc5 100644 --- a/application/src/test/java/org/thingsboard/server/controller/ControllerNoSqlTestSuite.java +++ b/application/src/test/java/org/thingsboard/server/controller/ControllerNoSqlTestSuite.java @@ -27,8 +27,7 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClasspathSuite.ClassnameFilters({ - // TODO: voba - fix before final test on cassandra - "org.thingsboard.server.controller.nosql.*VOBA_FIX_BEFORE_FINAL_TESTTest"}) + "org.thingsboard.server.controller.nosql.*Test"}) public class ControllerNoSqlTestSuite { @ClassRule diff --git a/application/src/test/java/org/thingsboard/server/mqtt/MqttNoSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/mqtt/MqttNoSqlTestSuite.java index 5874f45f25..7360c5c506 100644 --- a/application/src/test/java/org/thingsboard/server/mqtt/MqttNoSqlTestSuite.java +++ b/application/src/test/java/org/thingsboard/server/mqtt/MqttNoSqlTestSuite.java @@ -27,8 +27,7 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClasspathSuite.ClassnameFilters({ - // TODO: voba - fix before final test on cassandra - "org.thingsboard.server.mqtt.*.nosql.*VOBA_FIX_BEFORE_FINAL_TESTTest"}) + "org.thingsboard.server.mqtt.*.nosql.*Test"}) public class MqttNoSqlTestSuite { @ClassRule diff --git a/application/src/test/java/org/thingsboard/server/system/SystemNoSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/system/SystemNoSqlTestSuite.java index 2eb8608c8f..27ab059ced 100644 --- a/application/src/test/java/org/thingsboard/server/system/SystemNoSqlTestSuite.java +++ b/application/src/test/java/org/thingsboard/server/system/SystemNoSqlTestSuite.java @@ -30,8 +30,7 @@ import java.util.Arrays; */ @RunWith(ClasspathSuite.class) @ClasspathSuite.ClassnameFilters({ - // TODO: voba - fix before final test on cassandra - "org.thingsboard.server.system.*VOBA_FIX_BEFORE_FINAL_TESTNoSqlTest"}) + "org.thingsboard.server.system.*NoSqlTest"}) public class SystemNoSqlTestSuite { @ClassRule diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index 13702a13ef..f09db3e9e1 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -77,14 +77,3 @@ public interface EdgeService { ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId); } - - - - - - - - - - - \ No newline at end of file diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java index 97889a488e..73b893d099 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java @@ -16,15 +16,12 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.Setter; -import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; -import java.util.*; +import java.util.HashSet; +import java.util.Set; public class DashboardInfo extends SearchTextBased implements HasName, HasTenantId { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ShortEdgeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/ShortEdgeInfo.java deleted file mode 100644 index bdfc1dbb22..0000000000 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ShortEdgeInfo.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.data; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.RuleChainId; - -@AllArgsConstructor -public class ShortEdgeInfo { - - @Getter @Setter - private EdgeId edgeId; - - @Getter @Setter - private String title; - - @Getter @Setter - private RuleChainId rootRuleChainId; - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ShortEdgeInfo that = (ShortEdgeInfo) o; - - return edgeId.equals(that.edgeId); - } - - @Override - public int hashCode() { - return edgeId.hashCode(); - } -} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java index 2c9656a364..56990cff44 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.common.data.edge; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -25,8 +24,6 @@ import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; -import org.thingsboard.server.common.data.ShortCustomerInfo; -import org.thingsboard.server.common.data.ShortEdgeInfo; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.RuleChainId; @@ -70,11 +67,6 @@ public class Edge extends SearchTextBasedWithAdditionalInfo implements H this.configuration = edge.getConfiguration(); } - @JsonIgnore - public ShortEdgeInfo toShortEdgeInfo() { - return new ShortEdgeInfo(id, name, rootRuleChainId); - } - @Override public String getSearchText() { return getName(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java index f108db0056..c76a03fa43 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java @@ -29,10 +29,11 @@ public class EdgeEvent extends BaseData { private TenantId tenantId; private EdgeId edgeId; - private String edgeEventAction; + private String action; private UUID entityId; - private EdgeEventType edgeEventType; - private transient JsonNode entityBody; + private String uid; + private EdgeEventType type; + private transient JsonNode body; public EdgeEvent() { super(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java index cedc458edb..50cd23ac3f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java @@ -20,20 +20,13 @@ import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; -import org.thingsboard.server.common.data.ShortEdgeInfo; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.TenantId; -import java.util.HashSet; -import java.util.Set; - @Data @EqualsAndHashCode(callSuper = true) @Slf4j diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java index 08e5d2570f..8e9ec44238 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java @@ -56,7 +56,7 @@ public class BaseEdgeEventService implements EdgeEventService { if (edgeEvent.getEdgeId() == null) { throw new DataValidationException("Edge id should be specified!"); } - if (StringUtils.isEmpty(edgeEvent.getEdgeEventAction())) { + if (StringUtils.isEmpty(edgeEvent.getAction())) { throw new DataValidationException("Edge Event action should be specified!"); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java index ec99c673a6..3d77b5fa78 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java @@ -15,13 +15,21 @@ */ package org.thingsboard.server.dao.edge; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.ResultSetFuture; +import com.datastax.driver.core.Statement; +import com.datastax.driver.core.querybuilder.Select; +import com.datastax.driver.mapping.Result; +import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.RuleChainId; @@ -29,17 +37,40 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.model.EntitySubtypeEntity; import org.thingsboard.server.dao.model.nosql.EdgeEntity; import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; import org.thingsboard.server.dao.relation.RelationDao; import org.thingsboard.server.dao.util.NoSqlDao; +import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.UUID; +import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; +import static com.datastax.driver.core.querybuilder.QueryBuilder.in; +import static com.datastax.driver.core.querybuilder.QueryBuilder.select; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_NAME_VIEW_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_ROUTING_KEY_VIEW_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TYPE_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_SUBTYPE_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_SUBTYPE_TENANT_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; @Component @Slf4j @@ -59,50 +90,124 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao findEdgesByTenantId(UUID tenantId, TextPageLink pageLink) { - return null; + log.debug("Try to find edge by tenantId [{}] and pageLink [{}]", tenantId, pageLink); + List edgeEntities = findPageWithTextSearch(new TenantId(tenantId), EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, + Collections.singletonList(eq(EDGE_TENANT_ID_PROPERTY, tenantId)), pageLink); + + log.trace("Found edges [{}] by tenantId [{}] and pageLink [{}]", edgeEntities, tenantId, pageLink); + return DaoUtil.convertDataList(edgeEntities); } @Override public List findEdgesByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) { - return null; + log.debug("Try to find edges by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink); + List edgeEntities = findPageWithTextSearch(new TenantId(tenantId), EDGE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, + Arrays.asList(eq(EDGE_TYPE_PROPERTY, type), + eq(EDGE_TENANT_ID_PROPERTY, tenantId)), pageLink); + log.trace("Found edges [{}] by tenantId [{}], type [{}] and pageLink [{}]", edgeEntities, tenantId, type, pageLink); + return DaoUtil.convertDataList(edgeEntities); } @Override public ListenableFuture> findEdgesByTenantIdAndIdsAsync(UUID tenantId, List edgeIds) { - return null; + log.debug("Try to find edges by tenantId [{}] and edge Ids [{}]", tenantId, edgeIds); + Select select = select().from(getColumnFamilyName()); + Select.Where query = select.where(); + query.and(eq(EDGE_TENANT_ID_PROPERTY, tenantId)); + query.and(in(ID_PROPERTY, edgeIds)); + return findListByStatementAsync(new TenantId(tenantId), query); } @Override public List findEdgesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) { - return null; + log.debug("Try to find edges by tenantId [{}], customerId[{}] and pageLink [{}]", tenantId, customerId, pageLink); + List edgeEntities = findPageWithTextSearch(new TenantId(tenantId), EDGE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, + Arrays.asList(eq(EDGE_CUSTOMER_ID_PROPERTY, customerId), + eq(EDGE_TENANT_ID_PROPERTY, tenantId)), + pageLink); + + log.trace("Found edges [{}] by tenantId [{}], customerId [{}] and pageLink [{}]", edgeEntities, tenantId, customerId, pageLink); + return DaoUtil.convertDataList(edgeEntities); } @Override public List findEdgesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) { - return null; + log.debug("Try to find edges by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink); + List edgeEntities = findPageWithTextSearch(new TenantId(tenantId), EDGE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, + Arrays.asList(eq(EDGE_TYPE_PROPERTY, type), + eq(EDGE_CUSTOMER_ID_PROPERTY, customerId), + eq(EDGE_TENANT_ID_PROPERTY, tenantId)), + pageLink); + + log.trace("Found edges [{}] by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", edgeEntities, tenantId, customerId, type, pageLink); + return DaoUtil.convertDataList(edgeEntities); } @Override public ListenableFuture> findEdgesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List edgeIds) { - return null; + log.debug("Try to find edges by tenantId [{}], customerId [{}] and edges Ids [{}]", tenantId, customerId, edgeIds); + Select select = select().from(getColumnFamilyName()); + Select.Where query = select.where(); + query.and(eq(EDGE_TENANT_ID_PROPERTY, tenantId)); + query.and(eq(EDGE_CUSTOMER_ID_PROPERTY, customerId)); + query.and(in(ID_PROPERTY, edgeIds)); + return findListByStatementAsync(new TenantId(tenantId), query); } @Override - public Optional findEdgeByTenantIdAndName(UUID tenantId, String name) { - return Optional.empty(); + public Optional findEdgeByTenantIdAndName(UUID tenantId, String edgeName) { + Select select = select().from(EDGE_BY_TENANT_AND_NAME_VIEW_NAME); + Select.Where query = select.where(); + query.and(eq(EDGE_TENANT_ID_PROPERTY, tenantId)); + query.and(eq(EDGE_NAME_PROPERTY, edgeName)); + return Optional.ofNullable(DaoUtil.getData(findOneByStatement(new TenantId(tenantId), query))); } @Override public ListenableFuture> findTenantEdgeTypesAsync(UUID tenantId) { - return null; + Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME); + Select.Where query = select.where(); + query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId)); + query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.EDGE)); + query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); + ResultSetFuture resultSetFuture = executeAsyncRead(new TenantId(tenantId), query); + return Futures.transform(resultSetFuture, new Function>() { + @Nullable + @Override + public List apply(@Nullable ResultSet resultSet) { + Result result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet); + if (result != null) { + List entitySubtypes = new ArrayList<>(); + result.all().forEach((entitySubtypeEntity) -> + entitySubtypes.add(entitySubtypeEntity.toEntitySubtype()) + ); + return entitySubtypes; + } else { + return Collections.emptyList(); + } + } + }, MoreExecutors.directExecutor()); } @Override public Optional findByRoutingKey(UUID tenantId, String routingKey) { - return Optional.empty(); + Select select = select().from(EDGE_BY_TENANT_AND_ROUTING_KEY_VIEW_NAME); + Select.Where query = select.where(); + query.and(eq(EDGE_TENANT_ID_PROPERTY, tenantId)); + query.and(eq(EDGE_ROUTING_KEY_PROPERTY, routingKey)); + return Optional.ofNullable(DaoUtil.getData(findOneByStatement(new TenantId(tenantId), query))); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java index e127abad39..defe51036c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeEventDao.java @@ -15,19 +15,38 @@ */ package org.thingsboard.server.dao.edge; +import com.datastax.driver.core.ResultSetFuture; +import com.datastax.driver.core.querybuilder.Insert; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.utils.UUIDs; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeEventId; import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.nosql.EdgeEventEntity; import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTimeDao; import org.thingsboard.server.dao.util.NoSqlDao; +import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; +import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; +import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_BY_ID_VIEW_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME; @Component @@ -35,6 +54,8 @@ import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_ @NoSqlDao public class CassandraEdgeEventDao extends CassandraAbstractSearchTimeDao implements EdgeEventDao { + @Value("${edges.edge_events_ttl:0}") + private int edgeEventsTtl; @Override protected Class getColumnFamilyClass() { @@ -46,14 +67,61 @@ public class CassandraEdgeEventDao extends CassandraAbstractSearchTimeDao saveAsync(EdgeEvent edgeEvent) { - return null; + log.debug("Save edge event [{}] ", edgeEvent); + if (edgeEvent.getId() == null) { + edgeEvent.setId(new EdgeEventId(UUIDs.timeBased())); + } + if (StringUtils.isEmpty(edgeEvent.getUid())) { + edgeEvent.setUid(edgeEvent.getId().toString()); + } + ListenableFuture> optionalSave = saveAsync(edgeEvent.getTenantId(), new EdgeEventEntity(edgeEvent), edgeEventsTtl); + return Futures.transform(optionalSave, opt -> opt.orElse(null), MoreExecutors.directExecutor()); + } + + private ListenableFuture> saveAsync(TenantId tenantId, EdgeEventEntity entity, int ttl) { + if (entity.getUuid() == null) { + entity.setUuid(UUIDs.timeBased()); + } + Insert insert = QueryBuilder.insertInto(getColumnFamilyName()) + .value(ModelConstants.ID_PROPERTY, entity.getUuid()) + .value(ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY, entity.getTenantId()) + .value(ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY, entity.getEdgeId()) + .value(ModelConstants.EDGE_EVENT_TYPE_PROPERTY, entity.getEdgeEventType()) + .value(ModelConstants.EDGE_EVENT_UID_PROPERTY, entity.getEdgeEventUid()) + .value(ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY, entity.getEntityId()) + .value(ModelConstants.EDGE_EVENT_ACTION_PROPERTY, entity.getEdgeEventAction()) + .value(ModelConstants.EDGE_EVENT_BODY_PROPERTY, entity.getBody()); + + if (ttl > 0) { + insert.using(ttl(ttl)); + } + ResultSetFuture resultSetFuture = executeAsyncWrite(tenantId, insert); + return Futures.transform(resultSetFuture, rs -> { + if (rs.wasApplied()) { + return Optional.of(DaoUtil.getData(entity)); + } else { + return Optional.empty(); + } + }, MoreExecutors.directExecutor()); } @Override public List findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink, boolean withTsUpdate) { - return null; + log.trace("Try to find edge events by tenant [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); + List entities = findPageWithTimeSearch(new TenantId(tenantId), EDGE_EVENT_BY_ID_VIEW_NAME, + Arrays.asList(eq(ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY, tenantId), + eq(ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY, edgeId.getId())), + pageLink); + log.trace("Found events by tenant [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); + List edgeEvents = DaoUtil.convertDataList(entities); + if (!withTsUpdate) { + return edgeEvents.stream() + .filter(edgeEvent -> !edgeEvent.getAction().equals(ActionType.TIMESERIES_UPDATED.name())) + .collect(Collectors.toList()); + } else { + return edgeEvents; + } } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 5a7b5ce45f..98e7177d33 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -368,6 +368,12 @@ public class ModelConstants { public static final String EDGE_TYPE_PROPERTY = "type"; public static final String EDGE_CONFIGURATION_PROPERTY = "configuration"; public static final String EDGE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; + public static final String EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_tenant_and_search_text"; + public static final String EDGE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_tenant_by_type_and_search_text"; + public static final String EDGE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_customer_and_search_text"; + public static final String EDGE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_customer_by_type_and_search_text"; + public static final String EDGE_BY_TENANT_AND_NAME_VIEW_NAME = "edge_by_tenant_and_name"; + public static final String EDGE_BY_TENANT_AND_ROUTING_KEY_VIEW_NAME = "edge_by_tenant_and_routing_key"; public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key"; public static final String EDGE_SECRET_PROPERTY = "secret"; @@ -380,8 +386,11 @@ public class ModelConstants { public static final String EDGE_EVENT_EDGE_ID_PROPERTY = "edge_id"; public static final String EDGE_EVENT_TYPE_PROPERTY = "edge_event_type"; public static final String EDGE_EVENT_ACTION_PROPERTY = "edge_event_action"; + public static final String EDGE_EVENT_UID_PROPERTY = "edge_event_uid"; public static final String EDGE_EVENT_ENTITY_ID_PROPERTY = "entity_id"; - public static final String EDGE_EVENT_ENTITY_BODY_PROPERTY = "entity_body"; + public static final String EDGE_EVENT_BODY_PROPERTY = "body"; + + public static final String EDGE_EVENT_BY_ID_VIEW_NAME = "edge_event_by_id"; /** * Cassandra attributes and timeseries constants. diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java index 91c87ade2f..37e2d821ba 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java @@ -32,6 +32,9 @@ import org.thingsboard.server.dao.model.type.JsonCodec; import java.util.UUID; +import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_CUSTOMER_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TENANT_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TYPE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ADDITIONAL_INFO_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CONFIGURATION_PROPERTY; @@ -50,21 +53,22 @@ import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPER @Table(name = EDGE_COLUMN_FAMILY_NAME) public class EdgeEntity implements SearchTextEntity { - @PartitionKey + @PartitionKey(value = 0) @Column(name = ID_PROPERTY) private UUID id; - @ClusteringColumn + @PartitionKey(value = 1) @Column(name = EDGE_TENANT_ID_PROPERTY) private UUID tenantId; - @ClusteringColumn + @PartitionKey(value = 2) @Column(name = EDGE_CUSTOMER_ID_PROPERTY) private UUID customerId; @Column(name = EDGE_ROOT_RULE_CHAIN_ID_PROPERTY) private UUID rootRuleChainId; + @PartitionKey(value = 3) @Column(name = EDGE_TYPE_PROPERTY) private String type; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEventEntity.java index 8a3ed1b437..780d463cac 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEventEntity.java @@ -23,18 +23,13 @@ import com.datastax.driver.mapping.annotations.Table; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.NoArgsConstructor; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeEventId; import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.EntityIdFactory; -import org.thingsboard.server.common.data.id.EventId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.type.EdgeEventTypeCodec; -import org.thingsboard.server.dao.model.type.EntityTypeCodec; import org.thingsboard.server.dao.model.type.JsonCodec; import java.util.UUID; @@ -42,17 +37,11 @@ import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_BODY_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_BODY_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_BODY_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_COLUMN_FAMILY_NAME; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_TYPE_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_TENANT_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_TYPE_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EVENT_UID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_UID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; @Data @@ -71,25 +60,23 @@ public class EdgeEventEntity implements BaseEntity { @Column(name = EDGE_EVENT_EDGE_ID_PROPERTY) private UUID edgeId; - @PartitionKey(value = 2) + @ClusteringColumn() @Column(name = EDGE_EVENT_TYPE_PROPERTY, codec = EdgeEventTypeCodec.class) private EdgeEventType edgeEventType; - @PartitionKey(value = 3) - @Column(name = EDGE_EVENT_ENTITY_ID_PROPERTY) - private UUID entityId; - - @ClusteringColumn() + @ClusteringColumn(value = 1) @Column(name = EDGE_EVENT_ACTION_PROPERTY) private String edgeEventAction; - // TODO - @ClusteringColumn(value = 1) - @Column(name = EVENT_UID_PROPERTY) - private String eventUid; + @ClusteringColumn(value = 2) + @Column(name = EDGE_EVENT_UID_PROPERTY) + private String edgeEventUid; + + @Column(name = EDGE_EVENT_ENTITY_ID_PROPERTY) + private UUID entityId; - @Column(name = EDGE_EVENT_ENTITY_BODY_PROPERTY, codec = JsonCodec.class) - private JsonNode entityBody; + @Column(name = EDGE_EVENT_BODY_PROPERTY, codec = JsonCodec.class) + private JsonNode body; public EdgeEventEntity(EdgeEvent edgeEvent) { if (edgeEvent.getId() != null) { @@ -101,13 +88,11 @@ public class EdgeEventEntity implements BaseEntity { if (edgeEvent.getEdgeId() != null) { this.edgeId = edgeEvent.getEdgeId().getId(); } -// if (event.getEntityId() != null) { -// this.entityType = event.getEntityId().getEntityType(); -// this.entityId = event.getEntityId().getId(); -// } -// this.edgeEventType = edgeEvent.getEdgeEventType(); -// this.edgeEventAction = edgeEvent.getEdgeEventAction(); -// this.entityBody = edgeEvent.getEntityBody(); + this.entityId = edgeEvent.getEntityId(); + this.edgeEventType = edgeEvent.getType(); + this.edgeEventAction = edgeEvent.getAction(); + this.edgeEventUid = edgeEvent.getUid(); + this.body = edgeEvent.getBody(); } @Override @@ -123,13 +108,14 @@ public class EdgeEventEntity implements BaseEntity { @Override public EdgeEvent toData() { EdgeEvent edgeEvent = new EdgeEvent(new EdgeEventId(id)); -// edgeEvent.setCreatedTime(UUIDs.unixTimestamp(id)); -// edgeEvent.setTenantId(new TenantId(tenantId)); -// edgeEvent.setEdgeId(new EdgeId(edgeId)); -// edgeEvent.setEntityId(entityId); -// event.setBody(body); -// event.setType(eventType); -// event.setUid(eventUid); + edgeEvent.setCreatedTime(UUIDs.unixTimestamp(id)); + edgeEvent.setTenantId(new TenantId(tenantId)); + edgeEvent.setEdgeId(new EdgeId(edgeId)); + edgeEvent.setEntityId(entityId); + edgeEvent.setType(edgeEventType); + edgeEvent.setAction(edgeEventAction); + edgeEvent.setBody(body); + edgeEvent.setUid(edgeEventUid); return edgeEvent; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java index 9c6dca59ef..7ad71e4a85 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java @@ -41,11 +41,13 @@ import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_BODY_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_BODY_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_UID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EPOCH_DIFF; +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_UID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.TS_COLUMN; @Data @@ -73,9 +75,12 @@ public class EdgeEventEntity extends BaseSqlEntity implements BaseEnt private String edgeEventAction; @Type(type = "json") - @Column(name = EDGE_EVENT_ENTITY_BODY_PROPERTY) + @Column(name = EDGE_EVENT_BODY_PROPERTY) private JsonNode entityBody; + @Column(name = EDGE_EVENT_UID_PROPERTY) + private String edgeEventUid; + @Column(name = TS_COLUMN) private long ts; @@ -95,9 +100,10 @@ public class EdgeEventEntity extends BaseSqlEntity implements BaseEnt if (edgeEvent.getEntityId() != null) { this.entityId = toString(edgeEvent.getEntityId()); } - this.edgeEventType = edgeEvent.getEdgeEventType(); - this.edgeEventAction = edgeEvent.getEdgeEventAction(); - this.entityBody = edgeEvent.getEntityBody(); + this.edgeEventType = edgeEvent.getType(); + this.edgeEventAction = edgeEvent.getAction(); + this.entityBody = edgeEvent.getBody(); + this.edgeEventUid = edgeEvent.getUid(); } @Override @@ -109,9 +115,10 @@ public class EdgeEventEntity extends BaseSqlEntity implements BaseEnt if (entityId != null) { edgeEvent.setEntityId(toUUID(entityId)); } - edgeEvent.setEdgeEventType(edgeEventType); - edgeEvent.setEdgeEventAction(edgeEventAction); - edgeEvent.setEntityBody(entityBody); + edgeEvent.setType(edgeEventType); + edgeEvent.setAction(edgeEventAction); + edgeEvent.setBody(entityBody); + edgeEvent.setUid(edgeEventUid); return edgeEvent; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java index 2f6f8626fd..fef07b319e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java @@ -35,8 +35,10 @@ import org.thingsboard.server.dao.model.type.ComponentLifecycleStateCodec; import org.thingsboard.server.dao.model.type.ComponentScopeCodec; import org.thingsboard.server.dao.model.type.ComponentTypeCodec; import org.thingsboard.server.dao.model.type.DeviceCredentialsTypeCodec; +import org.thingsboard.server.dao.model.type.EdgeEventTypeCodec; import org.thingsboard.server.dao.model.type.EntityTypeCodec; import org.thingsboard.server.dao.model.type.JsonCodec; +import org.thingsboard.server.dao.model.type.RuleChainTypeCodec; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -71,6 +73,8 @@ public abstract class CassandraAbstractDao { registerCodecIfNotFound(registry, new ComponentTypeCodec()); registerCodecIfNotFound(registry, new ComponentScopeCodec()); registerCodecIfNotFound(registry, new EntityTypeCodec()); + registerCodecIfNotFound(registry, new EdgeEventTypeCodec()); + registerCodecIfNotFound(registry, new RuleChainTypeCodec()); } return session; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index c2ee2fcb7d..bd0e30d401 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -19,14 +19,12 @@ import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import jnr.ffi.annotations.In; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.ShortEdgeInfo; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.EdgeId; @@ -46,14 +44,11 @@ import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleNode; -import org.thingsboard.server.dao.edge.EdgeDao; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; -import org.thingsboard.server.dao.relation.RelationDao; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; -import org.thingsboard.server.dao.service.TimePaginatedRemover; import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.tenant.TenantDao; @@ -65,7 +60,6 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateString; /** * Created by igor on 3/12/18. diff --git a/dao/src/main/resources/cassandra/schema-entities.cql b/dao/src/main/resources/cassandra/schema-entities.cql index 8155ad1ff3..7375f7e9e7 100644 --- a/dao/src/main/resources/cassandra/schema-entities.cql +++ b/dao/src/main/resources/cassandra/schema-entities.cql @@ -730,9 +730,13 @@ CREATE TABLE IF NOT EXISTS thingsboard.edge ( id timeuuid, tenant_id timeuuid, customer_id timeuuid, - name text, + root_rule_chain_id timeuuid, type text, + name text, + label text, search_text text, + routing_key text, + secret text, configuration text, additional_info text, PRIMARY KEY (id, tenant_id, customer_id, type) @@ -745,6 +749,13 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS PRIMARY KEY ( tenant_id, name, id, customer_id, type) WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_routing_key AS + SELECT * + from thingsboard.edge + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND routing_key IS NOT NULL AND id IS NOT NULL + PRIMARY KEY ( tenant_id, routing_key, id, customer_id, type) + WITH CLUSTERING ORDER BY ( routing_key ASC, id DESC, customer_id DESC); + CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS SELECT * from thingsboard.edge @@ -772,3 +783,23 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_customer_by_type_and_ WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); + +CREATE TABLE IF NOT EXISTS thingsboard.edge_event ( + id timeuuid, + tenant_id timeuuid, + edge_id timeuuid, + edge_event_type text, + edge_event_action text, + edge_event_uid text, + entity_id timeuuid, + body text, + PRIMARY KEY ((tenant_id, edge_id), edge_event_type, edge_event_uid) +); + +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_event_by_id AS + SELECT * + FROM thingsboard.edge_event + WHERE tenant_id IS NOT NULL AND edge_id IS NOT NULL AND edge_event_type IS NOT NULL + AND id IS NOT NULL AND edge_event_uid IS NOT NULL + PRIMARY KEY ((tenant_id, edge_id), id, edge_event_type, edge_event_uid) + WITH CLUSTERING ORDER BY (id ASC); diff --git a/dao/src/main/resources/sql/schema-entities-hsql.sql b/dao/src/main/resources/sql/schema-entities-hsql.sql index 53042215cd..32855d2df3 100644 --- a/dao/src/main/resources/sql/schema-entities-hsql.sql +++ b/dao/src/main/resources/sql/schema-entities-hsql.sql @@ -275,9 +275,10 @@ CREATE TABLE IF NOT EXISTS edge_event ( id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY, edge_id varchar(31), edge_event_type varchar(255), + edge_event_uid varchar(255), entity_id varchar(31), edge_event_action varchar(255), - entity_body varchar(10000000), + body varchar(10000000), tenant_id varchar(31), ts bigint NOT NULL -); \ No newline at end of file +); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 04346b4ed3..d1d33ff71f 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -275,14 +275,16 @@ CREATE TABLE IF NOT EXISTS edge_event ( id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY, edge_id varchar(31), edge_event_type varchar(255), + edge_event_uid varchar(255), entity_id varchar(31), edge_event_action varchar(255), - entity_body varchar(10000000), + body varchar(10000000), tenant_id varchar(31), ts bigint NOT NULL ); + CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) LANGUAGE plpgsql AS $$ diff --git a/dao/src/test/java/org/thingsboard/server/dao/NoSqlDaoServiceTestSuite.java b/dao/src/test/java/org/thingsboard/server/dao/NoSqlDaoServiceTestSuite.java index 8d5c2afec1..1f9acd81b0 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/NoSqlDaoServiceTestSuite.java +++ b/dao/src/test/java/org/thingsboard/server/dao/NoSqlDaoServiceTestSuite.java @@ -25,8 +25,7 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClassnameFilters({ - // TODO: voba - fix before final test on cassandra - "org.thingsboard.server.dao.service.*VOBA_FIX_BEFORE_FINAL_TESTServiceNoSqlTest" + "org.thingsboard.server.dao.service.nosql.*ServiceNoSqlTest" }) public class NoSqlDaoServiceTestSuite { diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java index 5da642d254..7890fcd80d 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java @@ -46,9 +46,9 @@ public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest { Assert.assertEquals(saved.getTenantId(), edgeEvent.getTenantId()); Assert.assertEquals(saved.getEdgeId(), edgeEvent.getEdgeId()); Assert.assertEquals(saved.getEntityId(), edgeEvent.getEntityId()); - Assert.assertEquals(saved.getEdgeEventType(), edgeEvent.getEdgeEventType()); - Assert.assertEquals(saved.getEdgeEventAction(), edgeEvent.getEdgeEventAction()); - Assert.assertEquals(saved.getEntityBody(), edgeEvent.getEntityBody()); + Assert.assertEquals(saved.getType(), edgeEvent.getType()); + Assert.assertEquals(saved.getAction(), edgeEvent.getAction()); + Assert.assertEquals(saved.getBody(), edgeEvent.getBody()); } protected EdgeEvent generateEdgeEvent(TenantId tenantId, EdgeId edgeId, EntityId entityId, String edgeEventAction) throws IOException { @@ -59,9 +59,9 @@ public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest { edgeEvent.setTenantId(tenantId); edgeEvent.setEdgeId(edgeId); edgeEvent.setEntityId(entityId.getId()); - edgeEvent.setEdgeEventType(EdgeEventType.DEVICE); - edgeEvent.setEdgeEventAction(edgeEventAction); - edgeEvent.setEntityBody(readFromResource("TestJsonData.json")); + edgeEvent.setType(EdgeEventType.DEVICE); + edgeEvent.setAction(edgeEventAction); + edgeEvent.setBody(readFromResource("TestJsonData.json")); return edgeEvent; } @@ -109,7 +109,7 @@ public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest { TimePageLink pageLink = new TimePageLink(1); EdgeEvent edgeEventWithTsUpdate = generateEdgeEvent(tenantId, edgeId, deviceId, ActionType.TIMESERIES_UPDATED.name()); - edgeEventService.saveAsync(edgeEventWithTsUpdate); + edgeEventService.saveAsync(edgeEventWithTsUpdate).get(); TimePageData allEdgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, true); TimePageData edgeEventsWithoutTsUpdate = edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, false); diff --git a/dao/src/test/resources/application-test.properties b/dao/src/test/resources/application-test.properties index b19fa66e9b..0ea0be2518 100644 --- a/dao/src/test/resources/application-test.properties +++ b/dao/src/test/resources/application-test.properties @@ -45,3 +45,5 @@ security.claim.duration=60000 database.ts_max_intervals=700 sql.remove_null_chars=true + +edges.rpc.enabled=true diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java index 5e68409362..2ae79c81e5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java @@ -22,9 +22,13 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.*; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -37,7 +41,8 @@ import org.thingsboard.server.common.msg.TbMsg; "Will create new Customer if it doesn't exists and 'Create new Customer if not exists' is set to true.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeAssignToCustomerConfig", - icon = "add_circle") + icon = "add_circle" +) public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java index df91c3d73c..30bf2d4d6e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java @@ -29,7 +29,6 @@ import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -46,7 +45,8 @@ import org.thingsboard.server.common.msg.TbMsg; "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeClearAlarmConfig", - icon = "notifications_off") + icon = "notifications_off" +) public class TbClearAlarmNode extends TbAbstractAlarmNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java index c8cd6b7b53..6c569a1713 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java @@ -21,19 +21,18 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.adaptor.JsonConverter; @@ -57,7 +56,8 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "Changes message originator to related entity view and produces new messages according to count of updated entity views", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig", - icon = "content_copy") + icon = "content_copy" +) public class TbCopyAttributesToEntityViewNode implements TbNode { EmptyNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java index 8754686752..f5cc8bee33 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.io.IOException; @@ -51,7 +50,8 @@ import java.util.List; "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCreateAlarmConfig", - icon = "notifications_active") + icon = "notifications_active" +) public class TbCreateAlarmNode extends TbAbstractAlarmNode { private static ObjectMapper mapper = new ObjectMapper(); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java index 7a3364d55a..f87c49ba7f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java @@ -34,7 +34,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.ArrayList; @@ -54,7 +53,8 @@ import java.util.List; nodeDetails = "If the relation already exists or successfully created - Message send via Success chain, otherwise Failure chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCreateRelationConfig", - icon = "add_circle") + icon = "add_circle" +) public class TbCreateRelationNode extends TbAbstractRelationActionNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java index d5bc429cd7..b27dde1140 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java @@ -27,7 +27,6 @@ import org.thingsboard.rule.engine.util.EntityContainer; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.ArrayList; @@ -44,7 +43,8 @@ import java.util.List; nodeDetails = "If the relation(s) successfully deleted - Message send via Success chain, otherwise Failure chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeDeleteRelationConfig", - icon = "remove_circle") + icon = "remove_circle" +) public class TbDeleteRelationNode extends TbAbstractRelationActionNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java index 05391b0a7a..3dbdb2a57c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java @@ -17,14 +17,17 @@ package org.thingsboard.rule.engine.action; import lombok.extern.slf4j.Slf4j; import org.thingsboard.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.ScriptEngine; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import static org.thingsboard.common.util.DonAsynchron.withCallback; -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @Slf4j @RuleNode( @@ -37,7 +40,8 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeLogConfig", - icon = "menu") + icon = "menu" +) public class TbLogNode implements TbNode { private TbLogNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java index 01ed0c9499..81b8e0b542 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java @@ -15,16 +15,17 @@ */ package org.thingsboard.rule.engine.action; -import com.datastax.driver.core.utils.UUIDs; import com.google.gson.Gson; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.rule.engine.api.*; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.ServiceQueue; import org.thingsboard.server.common.msg.session.SessionMsgType; @@ -44,7 +45,8 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDetails = "Count incoming messages for specified interval and produces POST_TELEMETRY_REQUEST msg with messages count", icon = "functions", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbActionNodeMsgCountConfig") + configDirective = "tbActionNodeMsgCountConfig" +) public class TbMsgCountNode implements TbNode { private static final String TB_MSG_COUNT_NODE_MSG = "TbMsgCountNodeMsg"; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java index c1e9d7152f..b623f8d628 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java @@ -48,8 +48,10 @@ import org.thingsboard.server.dao.model.type.ComponentLifecycleStateCodec; import org.thingsboard.server.dao.model.type.ComponentScopeCodec; import org.thingsboard.server.dao.model.type.ComponentTypeCodec; import org.thingsboard.server.dao.model.type.DeviceCredentialsTypeCodec; +import org.thingsboard.server.dao.model.type.EdgeEventTypeCodec; import org.thingsboard.server.dao.model.type.EntityTypeCodec; import org.thingsboard.server.dao.model.type.JsonCodec; +import org.thingsboard.server.dao.model.type.RuleChainTypeCodec; import org.thingsboard.server.dao.nosql.CassandraStatementTask; import javax.annotation.Nullable; @@ -144,6 +146,8 @@ public class TbSaveToCustomCassandraTableNode implements TbNode { registerCodecIfNotFound(registry, new ComponentTypeCodec()); registerCodecIfNotFound(registry, new ComponentScopeCodec()); registerCodecIfNotFound(registry, new EntityTypeCodec()); + registerCodecIfNotFound(registry, new EdgeEventTypeCodec()); + registerCodecIfNotFound(registry, new RuleChainTypeCodec()); } return session; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java index 9b013740a8..2c0bf17575 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java @@ -24,10 +24,13 @@ import com.amazonaws.services.sns.model.PublishRequest; import com.amazonaws.services.sns.model.PublishResult; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java index 9a53a1307a..0fd09ca351 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java @@ -26,16 +26,18 @@ import com.amazonaws.services.sqs.model.SendMessageResult; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ExecutionException; import static org.thingsboard.common.util.DonAsynchron.withCallback; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java index cd4e912a10..8a2b1e2887 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java @@ -18,12 +18,16 @@ package org.thingsboard.rule.engine.debug; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.ScriptEngine; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java index e6a79eb5f6..6f14e20300 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java @@ -24,7 +24,6 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.ServiceQueue; @@ -34,7 +33,6 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; -import static org.thingsboard.rule.engine.api.TbRelationTypes.FAILURE; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @Slf4j diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index b7cea6de20..8d00507a7d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -154,10 +154,10 @@ public class TbMsgPushToEdgeNode implements TbNode { private EdgeEvent buildEdgeEvent(TenantId tenantId, ActionType edgeEventAction, UUID entityId, EdgeEventType edgeEventType, JsonNode entityBody) { EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setTenantId(tenantId); - edgeEvent.setEdgeEventAction(edgeEventAction.name()); + edgeEvent.setAction(edgeEventAction.name()); edgeEvent.setEntityId(entityId); - edgeEvent.setEdgeEventType(edgeEventType); - edgeEvent.setEntityBody(entityBody); + edgeEvent.setType(edgeEventType); + edgeEvent.setBody(entityBody); return edgeEvent; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java index 23025f836f..52fb7e8a77 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java @@ -24,7 +24,6 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.List; @@ -40,8 +39,7 @@ import java.util.Map; nodeDetails = "If selected checkbox 'Check that all selected keys are present'\" and all keys in message data and metadata are exist - send Message via True chain, otherwise False chain is used.\n" + "Else if the checkbox is not selected, and at least one of the keys from data or metadata of the message exists - send Message via True chain, otherwise, False chain is used. ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeCheckMessageConfig" -) + configDirective = "tbFilterNodeCheckMessageConfig") public class TbCheckMessageNode implements TbNode { private static final Gson gson = new Gson(); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java index 21f4222689..89cd986b7e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.List; @@ -52,8 +51,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; " any relation to the originator of the message by type and direction.", nodeDetails = "If at least one relation exists - send Message via True chain, otherwise False chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeCheckRelationConfig" -) + configDirective = "tbFilterNodeCheckRelationConfig") public class TbCheckRelationNode implements TbNode { private TbCheckRelationNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java index 7656cb6ead..5e6f2129f4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java @@ -16,11 +16,14 @@ package org.thingsboard.rule.engine.filter; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.ScriptEngine; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -37,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
" + "Message type can be accessed via msgType property.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeScriptConfig" -) + configDirective = "tbFilterNodeScriptConfig") public class TbJsFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java index 8f4f466d85..a717185e5a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java @@ -17,10 +17,14 @@ package org.thingsboard.rule.engine.filter; import lombok.extern.slf4j.Slf4j; import org.thingsboard.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.ScriptEngine; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.Set; @@ -40,8 +44,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
" + "Message type can be accessed via msgType property.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeSwitchConfig" -) + configDirective = "tbFilterNodeSwitchConfig") public class TbJsSwitchNode implements TbNode { private TbJsSwitchNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java index 1e77943c49..7dd2dec9fb 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java @@ -16,10 +16,13 @@ package org.thingsboard.rule.engine.filter; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; /** @@ -34,8 +37,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Filter incoming messages by Message Type", nodeDetails = "If incoming MessageType is expected - send Message via True chain, otherwise False chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbFilterNodeMessageTypeConfig" -) + configDirective = "tbFilterNodeMessageTypeConfig") public class TbMsgTypeFilterNode implements TbNode { TbMsgTypeFilterNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java index fddfecccd3..c5739e24ff 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java @@ -25,7 +25,6 @@ import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; @@ -40,8 +39,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; nodeDescription = "Route incoming messages by Message Type", nodeDetails = "Sends messages with message types \"Post attributes\", \"Post telemetry\", \"RPC Request\" etc. via corresponding chain, otherwise Other chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbNodeEmptyConfig" -) + configDirective = "tbNodeEmptyConfig") public class TbMsgTypeSwitchNode implements TbNode { EmptyNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java index dd01f67383..e0972c89f5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java @@ -16,11 +16,14 @@ package org.thingsboard.rule.engine.filter; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -32,8 +35,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Filter incoming messages by message Originator Type", nodeDetails = "If Originator Type of incoming message is expected - send Message via True chain, otherwise False chain is used.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbFilterNodeOriginatorTypeConfig" -) + configDirective = "tbFilterNodeOriginatorTypeConfig") public class TbOriginatorTypeFilterNode implements TbNode { TbOriginatorTypeFilterNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java index 6f01e02c5c..89209449d4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java @@ -16,11 +16,15 @@ package org.thingsboard.rule.engine.filter; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -32,8 +36,7 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Route incoming messages by Message Originator Type", nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbNodeEmptyConfig" -) + configDirective = "tbNodeEmptyConfig") public class TbOriginatorTypeSwitchNode implements TbNode { EmptyNodeConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java index 9b10cad9d8..925ca98ced 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java @@ -26,10 +26,13 @@ import com.google.protobuf.ByteString; import com.google.pubsub.v1.ProjectTopicName; import com.google.pubsub.v1.PubsubMessage; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.rule.engine.api.*; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -37,8 +40,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.concurrent.TimeUnit; -import static org.thingsboard.common.util.DonAsynchron.withCallback; - @Slf4j @RuleNode( type = ComponentType.EXTERNAL, diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java index ca9f890032..832a86b5cb 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java @@ -28,7 +28,6 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.Collections; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java index 61a08736f8..fe5f1448c5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java @@ -15,32 +15,13 @@ */ package org.thingsboard.rule.engine.geo; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; -import org.locationtech.spatial4j.context.jts.JtsSpatialContext; -import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory; -import org.locationtech.spatial4j.shape.Point; -import org.locationtech.spatial4j.shape.Shape; -import org.locationtech.spatial4j.shape.ShapeFactory; -import org.locationtech.spatial4j.shape.SpatialRelation; -import org.springframework.util.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; -import org.thingsboard.rule.engine.api.TbNode; -import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.filter.TbMsgTypeFilterNodeConfiguration; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; -import java.util.Collections; -import java.util.List; - /** * Created by ashvayka on 19.01.18. */ @@ -53,8 +34,7 @@ import java.util.List; nodeDescription = "Filter incoming messages by GPS based geofencing", nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbFilterNodeGpsGeofencingConfig" -) + configDirective = "tbFilterNodeGpsGeofencingConfig") public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java index 12807bbf19..967d8e4a50 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java @@ -33,7 +33,6 @@ import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.TbRelationTypes; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java index 758d818fe5..b57394ca4e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java @@ -19,10 +19,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java index 23d2485bc4..3ca2d5dbab 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java @@ -27,7 +27,6 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import javax.mail.internet.MimeMessage; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java index 2d9a2b4be0..e56f38ce19 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java @@ -18,14 +18,13 @@ package org.thingsboard.rule.engine.metadata; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; /** @@ -41,8 +40,7 @@ import org.thingsboard.server.common.msg.TbMsg; "To access those attributes in other nodes this template can be used " + "metadata.cs_temperature or metadata.shared_limit ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeOriginatorAttributesConfig" -) + configDirective = "tbEnrichmentNodeOriginatorAttributesConfig") public class TbGetAttributesNode extends TbAbstractGetAttributesNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java index bb8b642f83..7fb51bc00d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java @@ -22,7 +22,6 @@ import org.thingsboard.rule.engine.util.EntitiesCustomerIdAsyncLoader; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; @RuleNode( type = ComponentType.ENRICHMENT, @@ -34,8 +33,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; "To access those attributes in other nodes this template can be used " + "metadata.temperature.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbEnrichmentNodeCustomerAttributesConfig" -) + configDirective = "tbEnrichmentNodeCustomerAttributesConfig") public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java index a486ae5007..7659facf63 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -43,8 +42,7 @@ import org.thingsboard.server.common.msg.TbMsg; "Note: only Device, Asset, and Entity View type are allowed.

" + "If the originator of the message is not assigned to Customer, or originator type is not supported - Message will be forwarded to Failure chain, otherwise, Success chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeEntityDetailsConfig" -) + configDirective = "tbEnrichmentNodeEntityDetailsConfig") public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode { private static final String CUSTOMER_PREFIX = "customer_"; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java index 97b4918db9..b3c1bbbae3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java @@ -17,16 +17,14 @@ package org.thingsboard.rule.engine.metadata; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.util.EntitiesRelatedDeviceIdAsyncLoader; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -39,8 +37,7 @@ import org.thingsboard.server.common.msg.TbMsg; "To access those attributes in other nodes this template can be used " + "metadata.cs_temperature or metadata.shared_limit ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeDeviceAttributesConfig" -) + configDirective = "tbEnrichmentNodeDeviceAttributesConfig") public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java index ec6d57f5c5..fc2c574d5d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java @@ -28,11 +28,9 @@ import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.util.EntitiesFieldsAsyncLoader; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import static org.thingsboard.common.util.DonAsynchron.withCallback; -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; /** * Created by ashvayka on 19.01.18. @@ -44,8 +42,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; nodeDescription = "Add Message Originator fields values into Message Metadata", nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeOriginatorFieldsConfig" -) + configDirective = "tbEnrichmentNodeOriginatorFieldsConfig") public class TbGetOriginatorFieldsNode implements TbNode { private TbGetOriginatorFieldsConfiguration config; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java index fadf8b9366..fddbe3e32b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java @@ -16,13 +16,14 @@ package org.thingsboard.rule.engine.metadata; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.rule.engine.util.EntitiesRelatedEntityIdAsyncLoader; - import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; @RuleNode( type = ComponentType.ENRICHMENT, @@ -36,8 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; "To access those attributes in other nodes this template can be used " + "metadata.temperature.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbEnrichmentNodeRelatedAttributesConfig" -) + configDirective = "tbEnrichmentNodeRelatedAttributesConfig") public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index e106052f80..245728b0ca 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -38,7 +38,6 @@ import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.io.IOException; @@ -47,7 +46,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.FETCH_MODE_ALL; import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.FETCH_MODE_FIRST; import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.MAX_FETCH_SIZE; @@ -67,8 +65,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE; "Also, the rule node allows you to select telemetry sampling order: ASC or DESC.
" + "Note: The maximum size of the fetched array is 1000 records.\n ", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase" -) + configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase") public class TbGetTelemetryNode implements TbNode { private static final String DESC_ORDER = "DESC"; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java index e9ba41acd7..3b69f0eb04 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java @@ -23,7 +23,6 @@ import org.thingsboard.rule.engine.util.EntitiesTenantIdAsyncLoader; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; @Slf4j @RuleNode( @@ -36,8 +35,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; "To access those attributes in other nodes this template can be used " + "metadata.temperature.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbEnrichmentNodeTenantAttributesConfig" -) + configDirective = "tbEnrichmentNodeTenantAttributesConfig") public class TbGetTenantAttributeNode extends TbEntityGetAttrNode { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java index 2098dc4fc0..f7ba2a8597 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java @@ -26,7 +26,6 @@ import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.ContactBased; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -38,8 +37,7 @@ import org.thingsboard.server.common.msg.TbMsg; "Note: only Device, Asset, and Entity View type are allowed.

" + "If the originator of the message is not assigned to Tenant, or originator type is not supported - Message will be forwarded to Failure chain, otherwise, Success chain will be used.", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbEnrichmentNodeEntityDetailsConfig" -) + configDirective = "tbEnrichmentNodeEntityDetailsConfig") public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode { private static final String TENANT_PREFIX = "tenant_"; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java index 751fe3a24a..260a946aa7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java @@ -21,14 +21,17 @@ import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.util.concurrent.Future; import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; import org.thingsboard.mqtt.MqttClient; import org.thingsboard.mqtt.MqttClientConfig; import org.thingsboard.mqtt.MqttConnectResult; -import org.springframework.util.StringUtils; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java index b260fa8cef..141a70022c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java @@ -16,18 +16,24 @@ package org.thingsboard.rule.engine.rabbitmq; import com.google.common.util.concurrent.ListenableFuture; -import com.rabbitmq.client.*; +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.MessageProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import java.nio.charset.Charset; -import java.util.concurrent.ExecutionException; import static org.thingsboard.common.util.DonAsynchron.withCallback; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index 0db4989b07..51363866bf 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -23,7 +23,6 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; @Slf4j diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java index 9c824a104c..fea7356b32 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java @@ -17,16 +17,14 @@ package org.thingsboard.rule.engine.rpc; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.UUID; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java index fe3326c4bc..ad1154005b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java @@ -145,19 +145,21 @@ public class TbSendRPCRequestNode implements TbNode { List result = ctx.getRelationService().findByToAndType(ctx.getTenantId(), msg.getOriginator(), EntityRelation.EDGE_TYPE, RelationTypeGroup.COMMON); if (result != null && result.size() > 0) { - return new EdgeId(result.get(0).getFrom().getId()); - } else { - return null; + EntityRelation relationToEdge = result.get(0); + if (relationToEdge.getFrom() != null && relationToEdge.getFrom().getId() != null) { + return new EdgeId(relationToEdge.getFrom().getId()); + } } + return null; } private void sendRpcRequestToEdgeDevice(TbContext ctx, TbMsg msg, EdgeId edgeId, RuleEngineDeviceRpcRequest request) { EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setTenantId(ctx.getTenantId()); - edgeEvent.setEdgeEventAction(ActionType.RPC_CALL.name()); + edgeEvent.setAction(ActionType.RPC_CALL.name()); edgeEvent.setEntityId(request.getDeviceId().getId()); - edgeEvent.setEdgeEventType(EdgeEventType.DEVICE); - edgeEvent.setEntityBody(json.valueToTree(request)); + edgeEvent.setType(EdgeEventType.DEVICE); + edgeEvent.setBody(json.valueToTree(request)); edgeEvent.setEdgeId(edgeId); ListenableFuture saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent); Futures.addCallback(saveFuture, new FutureCallback() { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index 17c66dd36f..f0f5d2418f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -24,12 +24,8 @@ import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.server.common.data.DataConstants; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.adaptor.JsonConverter; @@ -67,12 +63,11 @@ public class TbMsgAttributesNode implements TbNode { } String src = msg.getData(); Set attributes = JsonConverter.convertToAttributes(new JsonParser().parse(src)); - String scope = msg.getMetaData().getValue(SCOPE); - if (StringUtils.isEmpty(scope)) { - scope = config.getScope(); - msg.getMetaData().putValue("scope", scope); + if (StringUtils.isEmpty(msg.getMetaData().getValue(SCOPE))) { + msg.getMetaData().putValue(SCOPE, config.getScope()); } - ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), scope, new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); + ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), config.getScope(), + new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); } @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java index 3b25e4d9f2..8bc14800f5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java @@ -18,17 +18,16 @@ package org.thingsboard.rule.engine.telemetry; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.adaptor.JsonConverter; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java index 8b376ae977..c05008167c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java @@ -22,13 +22,9 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; - @Slf4j @RuleNode( type = ComponentType.ACTION, @@ -39,8 +35,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "Subsequent messages will not be processed until the previous message processing is completed or timeout event occurs.\n" + "Size of the queue per originator and timeout values are configurable on a system level", uiResources = {"static/rulenode/rulenode-core-config.js"}, - configDirective = "tbNodeEmptyConfig" -) + configDirective = "tbNodeEmptyConfig") @Deprecated public class TbSynchronizationBeginNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java index 068aefe862..fd7a6b6c60 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java @@ -22,15 +22,9 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; -import java.util.concurrent.ExecutionException; - -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; - @Slf4j @RuleNode( type = ComponentType.ACTION, diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java index 8b65c9ca0c..7fc6dc72ad 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java @@ -20,18 +20,17 @@ import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.util.EntitiesAlarmOriginatorIdAsyncLoader; import org.thingsboard.rule.engine.util.EntitiesCustomerIdAsyncLoader; import org.thingsboard.rule.engine.util.EntitiesRelatedEntityIdAsyncLoader; import org.thingsboard.rule.engine.util.EntitiesTenantIdAsyncLoader; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; import java.util.HashSet; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java index 15937d6cd5..0de29a0274 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java @@ -16,15 +16,15 @@ package org.thingsboard.rule.engine.transform; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.ScriptEngine; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; -import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.msg.TbMsg; -import static org.thingsboard.rule.engine.api.TbRelationTypes.FAILURE; -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; - @RuleNode( type = ComponentType.TRANSFORMATION, name = "script", @@ -38,8 +38,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; "{ msg: new payload,
   metadata: new metadata,
   msgType: new msgType }

" + "All fields in resulting object are optional and will be taken from original message if not specified.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, - configDirective = "tbTransformationNodeScriptConfig" -) + configDirective = "tbTransformationNodeScriptConfig") public class TbTransformMsgNode extends TbAbstractTransformNode { private TbTransformMsgNodeConfiguration config; From fc8b138cfdf3241ca69776b12fbd7eb7e1f58ae0 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 17 Sep 2020 18:42:42 +0300 Subject: [PATCH 099/156] Added correct future callbacks --- .../edge/rpc/init/DefaultSyncEdgeService.java | 124 ++++++++++++------ .../edge/rpc/processor/AlarmProcessor.java | 2 + .../edge/rpc/processor/BaseProcessor.java | 3 - .../edge/rpc/processor/DeviceProcessor.java | 20 ++- .../edge/rpc/processor/RelationProcessor.java | 2 + .../rpc/processor/TelemetryProcessor.java | 2 + 6 files changed, 110 insertions(+), 43 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index b241a17eb1..2195d15236 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; @@ -385,12 +386,25 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Override public ListenableFuture processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) { + SettableFuture futureToSet = SettableFuture.create(); if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { - RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); + RuleChainId ruleChainId = + new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); ListenableFuture future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null); - return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent result) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't save edge event [{}]", ruleChainMetadataRequestMsg, t); + futureToSet.setException(t); + } + }, dbCallbackExecutorService); } - return Futures.immediateFuture(null); + return futureToSet; } @Override @@ -400,41 +414,51 @@ public class DefaultSyncEdgeService implements SyncEdgeService { new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB())); final EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(entityId.getEntityType()); if (edgeEventType != null) { + SettableFuture futureToSet = SettableFuture.create(); ListenableFuture> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); - return Futures.transform(ssAttrFuture, ssAttributes -> { - if (ssAttributes != null && !ssAttributes.isEmpty()) { - try { - Map entityData = new HashMap<>(); - ObjectNode attributes = mapper.createObjectNode(); - for (AttributeKvEntry attr : ssAttributes) { - if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { - attributes.put(attr.getKey(), attr.getBooleanValue().get()); - } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { - attributes.put(attr.getKey(), attr.getDoubleValue().get()); - } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { - attributes.put(attr.getKey(), attr.getLongValue().get()); - } else { - attributes.put(attr.getKey(), attr.getValueAsString()); + Futures.addCallback(ssAttrFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List ssAttributes) { + if (ssAttributes != null && !ssAttributes.isEmpty()) { + try { + Map entityData = new HashMap<>(); + ObjectNode attributes = mapper.createObjectNode(); + for (AttributeKvEntry attr : ssAttributes) { + if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { + attributes.put(attr.getKey(), attr.getBooleanValue().get()); + } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) { + attributes.put(attr.getKey(), attr.getDoubleValue().get()); + } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) { + attributes.put(attr.getKey(), attr.getLongValue().get()); + } else { + attributes.put(attr.getKey(), attr.getValueAsString()); + } + } + entityData.put("kv", attributes); + entityData.put("scope", DataConstants.SERVER_SCOPE); + JsonNode entityBody = mapper.valueToTree(entityData); + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody); + saveEdgeEvent(edge.getTenantId(), + edge.getId(), + edgeEventType, + ActionType.ATTRIBUTES_UPDATED, + entityId, + entityBody); + } catch (Exception e) { + log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); + throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); + } } + futureToSet.set(null); } - entityData.put("kv", attributes); - entityData.put("scope", DataConstants.SERVER_SCOPE); - JsonNode entityBody = mapper.valueToTree(entityData); - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody); - saveEdgeEvent(edge.getTenantId(), - edge.getId(), - edgeEventType, - ActionType.ATTRIBUTES_UPDATED, - entityId, - entityBody); - } catch (Exception e) { - log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); - throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); - } - } - return null; - }, dbCallbackExecutorService); + @Override + public void onFailure(Throwable t) { + log.error("Can't save attributes [{}]", attributesRequestMsg, t); + futureToSet.setException(t); + } + }, dbCallbackExecutorService); + return futureToSet; // TODO: voba - push shared attributes to edge? // ListenableFuture> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); // ListenableFuture> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); @@ -504,22 +528,46 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @Override public ListenableFuture processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { + SettableFuture futureToSet = SettableFuture.create(); if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) { DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB())); ListenableFuture future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null); - return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent result) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't save edge event [{}]", deviceCredentialsRequestMsg, t); + futureToSet.setException(t); + } + }, dbCallbackExecutorService); } - return Futures.immediateFuture(null); + return futureToSet; } @Override public ListenableFuture processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { + SettableFuture futureToSet = SettableFuture.create(); if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) { UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB())); ListenableFuture future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null); - return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable EdgeEvent result) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't save edge event [{}]", userCredentialsRequestMsg, t); + futureToSet.setException(t); + } + }, dbCallbackExecutorService); } - return Futures.immediateFuture(null); + return futureToSet; } private ListenableFuture saveEdgeEvent(TenantId tenantId, diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java index 257bb746c5..c24b127e73 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/AlarmProcessor.java @@ -26,9 +26,11 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.queue.util.TbCoreComponent; @Component @Slf4j +@TbCoreComponent public class AlarmProcessor extends BaseProcessor { public ListenableFuture onAlarmUpdate(TenantId tenantId, AlarmUpdateMsg alarmUpdateMsg) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java index 7cdc6b08c5..6809501a0e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java @@ -47,9 +47,6 @@ public abstract class BaseProcessor { protected static final ObjectMapper mapper = new ObjectMapper(); - @Autowired - protected TbRuleEngineDeviceRpcService tbDeviceRpcService; - @Autowired protected AlarmService alarmService; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java index b1f588c6f4..85ffab4799 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; @@ -46,6 +47,7 @@ import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; +import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; import java.util.UUID; @@ -53,6 +55,7 @@ import java.util.concurrent.locks.ReentrantLock; @Component @Slf4j +@TbCoreComponent public class DeviceProcessor extends BaseProcessor { private static final ReentrantLock deviceCreationLock = new ReentrantLock(); @@ -219,6 +222,7 @@ public class DeviceProcessor extends BaseProcessor { } public ListenableFuture processDeviceRpcCallResponseMsg(TenantId tenantId, DeviceRpcCallMsg deviceRpcCallMsg) { + SettableFuture futureToSet = SettableFuture.create(); UUID uuid = new UUID(deviceRpcCallMsg.getRequestIdMSB(), deviceRpcCallMsg.getRequestIdLSB()); FromDeviceRpcResponse response; if (!StringUtils.isEmpty(deviceRpcCallMsg.getResponseMsg().getError())) { @@ -226,8 +230,20 @@ public class DeviceProcessor extends BaseProcessor { } else { response = new FromDeviceRpcResponse(uuid, deviceRpcCallMsg.getResponseMsg().getResponse(), null); } - tbDeviceRpcService.sendRpcResponseToTbCore(deviceRpcCallMsg.getOriginServiceId(), response); - return Futures.immediateFuture(null); + TbQueueCallback callback = new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't process push notification to core [{}]", deviceRpcCallMsg, t); + futureToSet.setException(t); + } + }; + tbClusterService.pushNotificationToCore(deviceRpcCallMsg.getOriginServiceId(), response, callback); + return futureToSet; } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java index 1ef4044d75..21849e74cd 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RelationProcessor.java @@ -34,11 +34,13 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.queue.util.TbCoreComponent; import java.util.UUID; @Component @Slf4j +@TbCoreComponent public class RelationProcessor extends BaseProcessor { public ListenableFuture onRelationUpdate(TenantId tenantId, RelationUpdateMsg relationUpdateMsg) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java index 506d9f6ba7..d5b31cb18c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java @@ -45,6 +45,7 @@ import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; +import org.thingsboard.server.queue.util.TbCoreComponent; import java.util.ArrayList; import java.util.HashSet; @@ -54,6 +55,7 @@ import java.util.UUID; @Component @Slf4j +@TbCoreComponent public class TelemetryProcessor extends BaseProcessor { private final Gson gson = new Gson(); From 6d7c28c88f04ab8bd51bcda561b23ac1c0caeb01 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Thu, 17 Sep 2020 18:52:12 +0300 Subject: [PATCH 100/156] Added TbCore annotation --- .../java/org/thingsboard/server/controller/EdgeController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 44be68b4c2..057e4a90bf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.controller; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -45,6 +44,7 @@ import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; @@ -54,6 +54,7 @@ import java.util.List; import java.util.stream.Collectors; @RestController +@TbCoreComponent @RequestMapping("/api") public class EdgeController extends BaseController { From 87601a4c63e06c955d99a495bd85a0254a3e32f5 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 12:09:21 +0300 Subject: [PATCH 101/156] Micro code refactoring in component-descriptor.service.js --- ui/src/app/api/component-descriptor.service.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/src/app/api/component-descriptor.service.js b/ui/src/app/api/component-descriptor.service.js index b4cacf4991..1069eef33d 100644 --- a/ui/src/app/api/component-descriptor.service.js +++ b/ui/src/app/api/component-descriptor.service.js @@ -28,31 +28,31 @@ function ComponentDescriptorService($http, $q) { return service; - function getComponentDescriptorsByTypes(componentTypes, ruleChainType) { + function getComponentDescriptorsByTypes(componentTypes, type) { var deferred = $q.defer(); var result = []; - if (!componentsByType[ruleChainType]) { - componentsByType[ruleChainType] = {}; + if (!componentsByType[type]) { + componentsByType[type] = {}; } for (var i=componentTypes.length-1;i>=0;i--) { var componentType = componentTypes[i]; - if (componentsByType[ruleChainType][componentType]) { - result = result.concat(componentsByType[ruleChainType][componentType]); + if (componentsByType[type][componentType]) { + result = result.concat(componentsByType[type][componentType]); componentTypes.splice(i, 1); } } if (!componentTypes.length) { deferred.resolve(result); } else { - var url = '/api/components?componentTypes=' + componentTypes.join(',') + '&ruleChainType=' + ruleChainType; + var url = '/api/components?componentTypes=' + componentTypes.join(',') + '&ruleChainType=' + type; $http.get(url, null).then(function success(response) { var components = response.data; for (var i = 0; i < components.length; i++) { var component = components[i]; - var componentsList = componentsByType[ruleChainType][component.type]; + var componentsList = componentsByType[type][component.type]; if (!componentsList) { componentsList = []; - componentsByType[ruleChainType][component.type] = componentsList; + componentsByType[type][component.type] = componentsList; } componentsList.push(component); componentsByClazz[component.clazz] = component; From 73ef6e07983492345b1ce93dc146f6b00ad4cb06 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 12:21:33 +0300 Subject: [PATCH 102/156] Rule chains EDGE & CORE types refactored --- ui/src/app/api/rule-chain.service.js | 2 +- ui/src/app/common/types.constant.js | 6 ++++-- ui/src/app/rulechain/rulechain.controller.js | 6 +++--- ui/src/app/rulechain/rulechain.routes.js | 6 +++--- ui/src/app/rulechain/rulechains.controller.js | 16 ++++++++-------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/ui/src/app/api/rule-chain.service.js b/ui/src/app/api/rule-chain.service.js index 78c891ba06..af9cfe436a 100644 --- a/ui/src/app/api/rule-chain.service.js +++ b/ui/src/app/api/rule-chain.service.js @@ -311,7 +311,7 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co } function getEdgesRuleChains(pageLink, config) { - return getRuleChains(pageLink, config, types.edgeRuleChainType); + return getRuleChains(pageLink, config, types.ruleChainType.edge); } function getEdgeRuleChains(edgeId, pageLink, config) { diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 969042bbd4..21056cce8d 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -786,8 +786,10 @@ export default angular.module('thingsboard.types', []) clientSide: false } }, - coreRuleChainType: "CORE", - edgeRuleChainType: "EDGE", + ruleChainType: { + core: "CORE", + edge: "EDGE" + }, ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], ruleChainNodeComponent: { type: 'RULE_CHAIN', diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js index ba7c76cc55..51f82108c2 100644 --- a/ui/src/app/rulechain/rulechain.controller.js +++ b/ui/src/app/rulechain/rulechain.controller.js @@ -1180,7 +1180,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time var saveRuleChainPromise; if (vm.isImport) { if (angular.isUndefined(vm.ruleChain.type)) { - vm.ruleChain.type = types.coreRuleChainType; + vm.ruleChain.type = types.ruleChainType.core; } saveRuleChainPromise = ruleChainService.saveRuleChain(vm.ruleChain); } else { @@ -1269,7 +1269,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time vm.isDirty = false; vm.isImport = false; $mdUtil.nextTick(() => { - if (vm.ruleChain.type === vm.types.coreRuleChainType) { + if (vm.ruleChain.type === vm.types.ruleChainType.core) { $state.go('home.ruleChains.core.ruleChain', {ruleChainId: vm.ruleChain.id.id}); } else { $state.go('home.ruleChains.edge.ruleChain', {ruleChainId: vm.ruleChain.id.id}); @@ -1293,7 +1293,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time ruleNode.configuration = angular.copy(ruleNode.component.configurationDescriptor.nodeDefinition.defaultConfiguration); var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null; - var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.coreRuleChainType; + var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.ruleChainType.core; vm.enableHotKeys = false; diff --git a/ui/src/app/rulechain/rulechain.routes.js b/ui/src/app/rulechain/rulechain.routes.js index a3f533eb57..7489091665 100644 --- a/ui/src/app/rulechain/rulechain.routes.js +++ b/ui/src/app/rulechain/rulechain.routes.js @@ -82,7 +82,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider ruleNodeComponents: /*@ngInject*/ function($stateParams, ruleChainService) { - return ruleChainService.getRuleNodeComponents(types.coreRuleChainType); + return ruleChainService.getRuleNodeComponents(types.ruleChainType.core); } }, data: { @@ -180,7 +180,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider ruleNodeComponents: /*@ngInject*/ function($stateParams, ruleChainService) { - return ruleChainService.getRuleNodeComponents(types.edgeRuleChainType); + return ruleChainService.getRuleNodeComponents(types.ruleChainType.edge); } }, data: { @@ -237,7 +237,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider ruleNodeComponents: /*@ngInject*/ function($stateParams, ruleChainService) { - return ruleChainService.getRuleNodeComponents(types.edgeRuleChainType); + return ruleChainService.getRuleNodeComponents(types.ruleChainType.edge); } }, data: { diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index 5a032a2f84..300e7cbc80 100644 --- a/ui/src/app/rulechain/rulechains.controller.js +++ b/ui/src/app/rulechain/rulechains.controller.js @@ -114,7 +114,7 @@ export default function RuleChainsController(ruleChainService, userService, edge if (vm.ruleChainsScope === 'tenant') { fetchRuleChainsFunction = function (pageLink) { - return fetchRuleChains(pageLink, types.coreRuleChainType); + return fetchRuleChains(pageLink, types.ruleChainType.core); }; deleteRuleChainFunction = function (ruleChainId) { return deleteRuleChain(ruleChainId); @@ -162,9 +162,9 @@ export default function RuleChainsController(ruleChainService, userService, edge }); vm.ruleChainGridConfig.addItemActions.push({ onAction: function ($event) { - importExport.importRuleChain($event, types.coreRuleChainType).then( + importExport.importRuleChain($event, types.ruleChainType.core).then( function(ruleChainImport) { - $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.coreRuleChainType}); + $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.ruleChainType.core}); } ); }, @@ -175,7 +175,7 @@ export default function RuleChainsController(ruleChainService, userService, edge } else if (vm.ruleChainsScope === 'edges') { fetchRuleChainsFunction = function (pageLink) { - return fetchRuleChains(pageLink, types.edgeRuleChainType); + return fetchRuleChains(pageLink, types.ruleChainType.edge); }; deleteRuleChainFunction = function (ruleChainId) { return deleteRuleChain(ruleChainId); @@ -243,9 +243,9 @@ export default function RuleChainsController(ruleChainService, userService, edge }); vm.ruleChainGridConfig.addItemActions.push({ onAction: function ($event) { - importExport.importRuleChain($event, types.edgeRuleChainType).then( + importExport.importRuleChain($event, types.ruleChainType.edge).then( function(ruleChainImport) { - $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.edgeRuleChainType}); + $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.ruleChainType.edge}); } ); }, @@ -383,9 +383,9 @@ export default function RuleChainsController(ruleChainService, userService, edge function saveRuleChain(ruleChain) { if (angular.isUndefined(ruleChain.type)) { if (vm.ruleChainsScope === 'edges') { - ruleChain.type = types.edgeRuleChainType; + ruleChain.type = types.ruleChainType.edge; } else { - ruleChain.type = types.coreRuleChainType; + ruleChain.type = types.ruleChainType.core; } } return ruleChainService.saveRuleChain(ruleChain); From 113c2ba848536148d1ed9a660d773ba682108a93 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 12:28:15 +0300 Subject: [PATCH 103/156] Added types in edgeEventType --- ui/src/app/common/types.constant.js | 2124 ++++++++++++++------------- 1 file changed, 1066 insertions(+), 1058 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 21056cce8d..680d295687 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -1,1058 +1,1066 @@ -/* - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export default angular.module('thingsboard.types', []) - .constant('types', - { - serverErrorCode: { - general: 2, - authentication: 10, - jwtTokenExpired: 11, - credentialsExpired: 15, - permissionDenied: 20, - invalidArguments: 30, - badRequestParams: 31, - itemNotFound: 32, - tooManyRequests: 33, - tooManyUpdates: 34 - }, - entryPoints: { - login: "/api/auth/login", - tokenRefresh: "/api/auth/token", - nonTokenBased: "/api/noauth" - }, - id: { - nullUid: "13814000-1dd2-11b2-8080-808080808080", - }, - aggregation: { - min: { - value: "MIN", - name: "aggregation.min" - }, - max: { - value: "MAX", - name: "aggregation.max" - }, - avg: { - value: "AVG", - name: "aggregation.avg" - }, - sum: { - value: "SUM", - name: "aggregation.sum" - }, - count: { - value: "COUNT", - name: "aggregation.count" - }, - none: { - value: "NONE", - name: "aggregation.none" - } - }, - alarmFields: { - createdTime: { - keyName: 'createdTime', - value: "createdTime", - name: "alarm.created-time", - time: true - }, - startTime: { - keyName: 'startTime', - value: "startTs", - name: "alarm.start-time", - time: true - }, - endTime: { - keyName: 'endTime', - value: "endTs", - name: "alarm.end-time", - time: true - }, - ackTime: { - keyName: 'ackTime', - value: "ackTs", - name: "alarm.ack-time", - time: true - }, - clearTime: { - keyName: 'clearTime', - value: "clearTs", - name: "alarm.clear-time", - time: true - }, - originator: { - keyName: 'originator', - value: "originatorName", - name: "alarm.originator" - }, - originatorType: { - keyName: 'originatorType', - value: "originator.entityType", - name: "alarm.originator-type" - }, - type: { - keyName: 'type', - value: "type", - name: "alarm.type" - }, - severity: { - keyName: 'severity', - value: "severity", - name: "alarm.severity" - }, - status: { - keyName: 'status', - value: "status", - name: "alarm.status" - } - }, - alarmStatus: { - activeUnack: "ACTIVE_UNACK", - activeAck: "ACTIVE_ACK", - clearedUnack: "CLEARED_UNACK", - clearedAck: "CLEARED_ACK" - }, - alarmSearchStatus: { - any: "ANY", - active: "ACTIVE", - cleared: "CLEARED", - ack: "ACK", - unack: "UNACK" - }, - alarmSeverity: { - "CRITICAL": { - name: "alarm.severity-critical", - class: "tb-critical", - color: "red" - }, - "MAJOR": { - name: "alarm.severity-major", - class: "tb-major", - color: "orange" - }, - "MINOR": { - name: "alarm.severity-minor", - class: "tb-minor", - color: "#ffca3d" - }, - "WARNING": { - name: "alarm.severity-warning", - class: "tb-warning", - color: "#abab00" - }, - "INDETERMINATE": { - name: "alarm.severity-indeterminate", - class: "tb-indeterminate", - color: "green" - } - }, - auditLogActionType: { - "ADDED": { - name: "audit-log.type-added" - }, - "DELETED": { - name: "audit-log.type-deleted" - }, - "UPDATED": { - name: "audit-log.type-updated" - }, - "ATTRIBUTES_UPDATED": { - name: "audit-log.type-attributes-updated" - }, - "ATTRIBUTES_DELETED": { - name: "audit-log.type-attributes-deleted" - }, - "RPC_CALL": { - name: "audit-log.type-rpc-call" - }, - "CREDENTIALS_UPDATED": { - name: "audit-log.type-credentials-updated" - }, - "ASSIGNED_TO_CUSTOMER": { - name: "audit-log.type-assigned-to-customer" - }, - "UNASSIGNED_FROM_CUSTOMER": { - name: "audit-log.type-unassigned-from-customer" - }, - "ACTIVATED": { - name: "audit-log.type-activated" - }, - "SUSPENDED": { - name: "audit-log.type-suspended" - }, - "CREDENTIALS_READ": { - name: "audit-log.type-credentials-read" - }, - "ATTRIBUTES_READ": { - name: "audit-log.type-attributes-read" - }, - "RELATION_ADD_OR_UPDATE": { - name: "audit-log.type-relation-add-or-update" - }, - "RELATION_DELETED": { - name: "audit-log.type-relation-delete" - }, - "RELATIONS_DELETED": { - name: "audit-log.type-relations-delete" - }, - "ALARM_ACK": { - name: "audit-log.type-alarm-ack" - }, - "ALARM_CLEAR": { - name: "audit-log.type-alarm-clear" - }, - "LOGIN": { - name: "audit-log.type-login" - }, - "LOGOUT": { - name: "audit-log.type-logout" - }, - "LOCKOUT": { - name: "audit-log.type-lockout" - }, - "ASSIGNED_FROM_TENANT": { - name: "audit-log.type-assigned-from-tenant" - }, - "ASSIGNED_TO_TENANT": { - name: "audit-log.type-assigned-to-tenant" - }, - "ASSIGNED_TO_EDGE": { - name: "audit-log.type-assigned-to-edge" - }, - "UNASSIGNED_FROM_EDGE": { - name: "audit-log.type-unassigned-from-edge" - } - }, - auditLogActionStatus: { - "SUCCESS": { - value: "SUCCESS", - name: "audit-log.status-success" - }, - "FAILURE": { - value: "FAILURE", - name: "audit-log.status-failure" - } - }, - auditLogMode: { - tenant: "tenant", - entity: "entity", - user: "user", - customer: "customer" - }, - aliasFilterType: { - singleEntity: { - value: 'singleEntity', - name: 'alias.filter-type-single-entity' - }, - entityList: { - value: 'entityList', - name: 'alias.filter-type-entity-list' - }, - entityName: { - value: 'entityName', - name: 'alias.filter-type-entity-name' - }, - stateEntity: { - value: 'stateEntity', - name: 'alias.filter-type-state-entity' - }, - assetType: { - value: 'assetType', - name: 'alias.filter-type-asset-type' - }, - deviceType: { - value: 'deviceType', - name: 'alias.filter-type-device-type' - }, - entityViewType: { - value: 'entityViewType', - name: 'alias.filter-type-entity-view-type' - }, - edgeType: { - value: 'edgeType', - name: 'alias.filter-type-edge-type' - }, - relationsQuery: { - value: 'relationsQuery', - name: 'alias.filter-type-relations-query' - }, - assetSearchQuery: { - value: 'assetSearchQuery', - name: 'alias.filter-type-asset-search-query' - }, - deviceSearchQuery: { - value: 'deviceSearchQuery', - name: 'alias.filter-type-device-search-query' - }, - entityViewSearchQuery: { - value: 'entityViewSearchQuery', - name: 'alias.filter-type-entity-view-search-query' - }, - edgeSearchQuery: { - value: 'edgeSearchQuery', - name: 'alias.filter-type-edge-search-query' - } - }, - direction: { - column: { - value: "column", - name: "direction.column" - }, - row: { - value: "row", - name: "direction.row" - } - }, - position: { - top: { - value: "top", - name: "position.top" - }, - bottom: { - value: "bottom", - name: "position.bottom" - }, - left: { - value: "left", - name: "position.left" - }, - right: { - value: "right", - name: "position.right" - } - }, - datasourceType: { - function: "function", - entity: "entity" - }, - dataKeyType: { - timeseries: "timeseries", - attribute: "attribute", - function: "function", - alarm: "alarm", - entityField: "entityField" - }, - contentType: { - "JSON": { - value: "JSON", - name: "content-type.json", - code: "json" - }, - "TEXT": { - value: "TEXT", - name: "content-type.text", - code: "text" - }, - "BINARY": { - value: "BINARY", - name: "content-type.binary", - code: "text" - } - }, - componentType: { - enrichment: "ENRICHMENT", - filter: "FILTER", - transformation: "TRANSFORMATION", - action: "ACTION", - external: "EXTERNAL" - }, - entityType: { - device: "DEVICE", - asset: "ASSET", - tenant: "TENANT", - customer: "CUSTOMER", - user: "USER", - dashboard: "DASHBOARD", - alarm: "ALARM", - rulechain: "RULE_CHAIN", - rulenode: "RULE_NODE", - entityView: "ENTITY_VIEW", - edge: "EDGE" - }, - edgeEventType:{ - dashboard: "DASHBOARD", - asset: "ASSET", - device: "DEVICE", - entityView: "ENTITY_VIEW", - alarm: "ALARM", - rulechain: "RULE_CHAIN", - ruleChainMetaData: "RULE_CHAIN_METADATA", - edge: "EDGE", - user: "USER", - customer: "CUSTOMER", - relation: "RELATION" - }, - edgeEventAction: { - updated: "UPDATED", - added: "ADDED", - assignedToEdge: "ASSIGNED_TO_EDGE", - deleted: "DELETED", - unassignedFromEdge: "UNASSIGNED_FROM_EDGE", - alarmAck: "ALARM_ACK", - alarmClear: "ALARM_CLEAR", - credentialsUpdated: "CREDENTIALS_UPDATED", - attributesUpdated: "ATTRIBUTES_UPDATED", - attributesDeleted: "ATTRIBUTES_DELETED", - timeseriesUpdated: "TIMESERIES_UPDATED" - }, - edgeAttributeKeys: { - active: "active", - lastConnectTime: "lastConnectTime", - lastDisconnectTime: "lastDisconnectTime", - queueStartTs: "queueStartTs" - }, - importEntityColumnType: { - name: { - name: 'import.column-type.name', - value: 'name' - }, - type: { - name: 'import.column-type.type', - value: 'type' - }, - label: { - name: 'import.column-type.label', - value: 'label' - }, - clientAttribute: { - name: 'import.column-type.client-attribute', - value: 'CLIENT_ATTRIBUTE' - }, - sharedAttribute: { - name: 'import.column-type.shared-attribute', - value: 'SHARED_ATTRIBUTE' - }, - serverAttribute: { - name: 'import.column-type.server-attribute', - value: 'SERVER_ATTRIBUTE' - }, - timeseries: { - name: 'import.column-type.timeseries', - value: 'TIMESERIES' - }, - entityField: { - name: 'import.column-type.entity-field', - value: 'ENTITY_FIELD' - }, - accessToken: { - name: 'import.column-type.access-token', - value: 'ACCESS_TOKEN' - }, - isGateway: { - name: 'import.column-type.isgateway', - value: 'gateway' - }, - description: { - name: 'import.column-type.description', - value: 'description' - } - }, - aliasEntityType: { - current_customer: "CURRENT_CUSTOMER", - current_tenant: "CURRENT_TENANT" - }, - entityTypeTranslations: { - "DEVICE": { - type: 'entity.type-device', - typePlural: 'entity.type-devices', - list: 'entity.list-of-devices', - nameStartsWith: 'entity.device-name-starts-with' - }, - "ASSET": { - type: 'entity.type-asset', - typePlural: 'entity.type-assets', - list: 'entity.list-of-assets', - nameStartsWith: 'entity.asset-name-starts-with' - }, - "ENTITY_VIEW": { - type: 'entity.type-entity-view', - typePlural: 'entity.type-entity-views', - list: 'entity.list-of-entity-views', - nameStartsWith: 'entity.entity-view-name-starts-with' - }, - "TENANT": { - type: 'entity.type-tenant', - typePlural: 'entity.type-tenants', - list: 'entity.list-of-tenants', - nameStartsWith: 'entity.tenant-name-starts-with' - }, - "CUSTOMER": { - type: 'entity.type-customer', - typePlural: 'entity.type-customers', - list: 'entity.list-of-customers', - nameStartsWith: 'entity.customer-name-starts-with' - }, - "USER": { - type: 'entity.type-user', - typePlural: 'entity.type-users', - list: 'entity.list-of-users', - nameStartsWith: 'entity.user-name-starts-with' - }, - "DASHBOARD": { - type: 'entity.type-dashboard', - typePlural: 'entity.type-dashboards', - list: 'entity.list-of-dashboards', - nameStartsWith: 'entity.dashboard-name-starts-with' - }, - "ALARM": { - type: 'entity.type-alarm', - typePlural: 'entity.type-alarms', - list: 'entity.list-of-alarms', - nameStartsWith: 'entity.alarm-name-starts-with' - }, - "RULE_CHAIN": { - type: 'entity.type-rulechain', - typePlural: 'entity.type-rulechains', - list: 'entity.list-of-rulechains', - nameStartsWith: 'entity.rulechain-name-starts-with' - }, - "RULE_NODE": { - type: 'entity.type-rulenode', - typePlural: 'entity.type-rulenodes', - list: 'entity.list-of-rulenodes', - nameStartsWith: 'entity.rulenode-name-starts-with' - }, - "CURRENT_CUSTOMER": { - type: 'entity.type-current-customer', - list: 'entity.type-current-customer' - }, - "CURRENT_TENANT": { - type: 'entity.type-current-tenant', - list: 'entity.type-current-tenant' - }, - "EDGE": { - type: 'entity.type-edge', - typePlural: 'entity.type-edges', - list: 'entity.list-of-edges', - nameStartsWith: 'entity.edge-name-starts-with' - } - }, - entityField: { - createdTime: { - keyName: 'createdTime', - name: 'entity-field.created-time', - value: 'createdTime', - time: true - }, - name: { - keyName: 'name', - name: 'entity-field.name', - value: 'name' - }, - type: { - keyName: 'type', - name: 'entity-field.type', - value: 'type' - }, - firstName: { - keyName: 'firstName', - name: 'entity-field.first-name', - value: 'firstName' - }, - lastName: { - keyName: 'lastName', - name: 'entity-field.last-name', - value: 'lastName' - }, - email: { - keyName: 'email', - name: 'entity-field.email', - value: 'email' - }, - title: { - keyName: 'title', - name: 'entity-field.title', - value: 'title' - }, - country: { - keyName: 'country', - name: 'entity-field.country', - value: 'country' - }, - state: { - keyName: 'state', - name: 'entity-field.state', - value: 'state' - }, - city: { - keyName: 'city', - name: 'entity-field.city', - value: 'city' - }, - address: { - keyName: 'address', - name: 'entity-field.address', - value: 'address' - }, - address2: { - keyName: 'address2', - name: 'entity-field.address2', - value: 'address2' - }, - zip: { - keyName: 'zip', - name: 'entity-field.zip', - value: 'zip' - }, - phone: { - keyName: 'phone', - name: 'entity-field.phone', - value: 'phone' - }, - label: { - keyName: 'label', - name: 'entity-field.label', - value: 'label' - } - }, - entitySearchDirection: { - from: "FROM", - to: "TO" - }, - entityRelationType: { - contains: "Contains", - manages: "Manages" - }, - eventType: { - error: { - value: "ERROR", - name: "event.type-error" - }, - lcEvent: { - value: "LC_EVENT", - name: "event.type-lc-event" - }, - stats: { - value: "STATS", - name: "event.type-stats" - }, - edgeEvent: { - value: "EDGE_EVENT", - name: "event.type-edge-event" - } - }, - debugEventType: { - debugRuleNode: { - value: "DEBUG_RULE_NODE", - name: "event.type-debug-rule-node" - }, - debugRuleChain: { - value: "DEBUG_RULE_CHAIN", - name: "event.type-debug-rule-chain" - } - }, - extensionType: { - http: "HTTP", - mqtt: "MQTT", - opc: "OPC UA", - modbus: "MODBUS" - }, - gatewayConfigType: { - mqtt: { - value: "mqtt", - name: "MQTT" - }, - modbus: { - value: "modbus", - name: "Modbus" - }, - opcua: { - value: "opcua", - name: "OPC-UA" - }, - ble: { - value: "ble", - name: "BLE" - }, - request: { - value: "request", - name: "Request" - }, - can: { - value: "can", - name: "CAN" - }, - bacnet: { - value: "bacnet", - name: "BACnet" - }, - custom: { - value: "custom", - name: "Custom" - } - }, - gatewayLogLevel: { - none: "NONE", - critical: "CRITICAL", - error: "ERROR", - warning: "WARNING", - info: "INFO", - debug: "DEBUG" - }, - extensionValueType: { - string: 'value.string', - long: 'value.long', - double: 'value.double', - boolean: 'value.boolean' - }, - extensionTransformerType: { - toDouble: 'extension.to-double', - custom: 'extension.custom' - }, - mqttConverterTypes: { - json: 'extension.converter-json', - custom: 'extension.custom' - }, - mqttCredentialTypes: { - anonymous: { - value: "anonymous", - name: "extension.anonymous" - }, - basic: { - value: "basic", - name: "extension.basic" - }, - pem: { - value: "cert.PEM", - name: "extension.pem" - } - }, - extensionOpcSecurityTypes: { - Basic128Rsa15: "Basic128Rsa15", - Basic256: "Basic256", - Basic256Sha256: "Basic256Sha256", - None: "None" - }, - extensionIdentityType: { - anonymous: "extension.anonymous", - username: "extension.username" - }, - extensionKeystoreType: { - PKCS12: "PKCS12", - JKS: "JKS" - }, - extensionModbusFunctionCodes: { - 1: "Read Coils (1)", - 2: "Read Discrete Inputs (2)", - 3: "Read Multiple Holding Registers (3)", - 4: "Read Input Registers (4)" - }, - extensionModbusTransports: { - tcp: "TCP", - udp: "UDP", - rtu: "RTU" - }, - extensionModbusRtuParities: { - none: "none", - even: "even", - odd: "odd" - }, - extensionModbusRtuEncodings: { - ascii: "ascii", - rtu: "rtu" - }, - latestTelemetry: { - value: "LATEST_TELEMETRY", - name: "attribute.scope-latest-telemetry", - clientSide: true - }, - attributesScope: { - client: { - value: "CLIENT_SCOPE", - name: "attribute.scope-client", - clientSide: true - }, - server: { - value: "SERVER_SCOPE", - name: "attribute.scope-server", - clientSide: false - }, - shared: { - value: "SHARED_SCOPE", - name: "attribute.scope-shared", - clientSide: false - } - }, - ruleChainType: { - core: "CORE", - edge: "EDGE" - }, - ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], - ruleChainNodeComponent: { - type: 'RULE_CHAIN', - name: 'rule chain', - clazz: 'tb.internal.RuleChain', - configurationDescriptor: { - nodeDefinition: { - description: "", - details: "Forwards incoming messages to specified Rule Chain", - inEnabled: true, - outEnabled: false, - relationTypes: [], - customRelations: false, - defaultConfiguration: {} - } - } - }, - unknownNodeComponent: { - type: 'UNKNOWN', - name: 'unknown', - clazz: 'tb.internal.Unknown', - configurationDescriptor: { - nodeDefinition: { - description: "", - details: "", - inEnabled: true, - outEnabled: true, - relationTypes: [], - customRelations: false, - defaultConfiguration: {} - } - } - }, - inputNodeComponent: { - type: 'INPUT', - name: 'Input', - clazz: 'tb.internal.Input' - }, - ruleNodeType: { - FILTER: { - value: "FILTER", - name: "rulenode.type-filter", - details: "rulenode.type-filter-details", - nodeClass: "tb-filter-type", - icon: "filter_list" - }, - ENRICHMENT: { - value: "ENRICHMENT", - name: "rulenode.type-enrichment", - details: "rulenode.type-enrichment-details", - nodeClass: "tb-enrichment-type", - icon: "playlist_add" - }, - TRANSFORMATION: { - value: "TRANSFORMATION", - name: "rulenode.type-transformation", - details: "rulenode.type-transformation-details", - nodeClass: "tb-transformation-type", - icon: "transform" - }, - ACTION: { - value: "ACTION", - name: "rulenode.type-action", - details: "rulenode.type-action-details", - nodeClass: "tb-action-type", - icon: "flash_on" - }, - EXTERNAL: { - value: "EXTERNAL", - name: "rulenode.type-external", - details: "rulenode.type-external-details", - nodeClass: "tb-external-type", - icon: "cloud_upload" - }, - RULE_CHAIN: { - value: "RULE_CHAIN", - name: "rulenode.type-rule-chain", - details: "rulenode.type-rule-chain-details", - nodeClass: "tb-rule-chain-type", - icon: "settings_ethernet" - }, - INPUT: { - value: "INPUT", - name: "rulenode.type-input", - details: "rulenode.type-input-details", - nodeClass: "tb-input-type", - icon: "input", - special: true - }, - UNKNOWN: { - value: "UNKNOWN", - name: "rulenode.type-unknown", - details: "rulenode.type-unknown-details", - nodeClass: "tb-unknown-type", - icon: "help_outline" - } - }, - messageType: { - 'POST_ATTRIBUTES_REQUEST': { - name: 'Post attributes', - value: 'POST_ATTRIBUTES_REQUEST' - }, - 'POST_TELEMETRY_REQUEST': { - name: 'Post telemetry', - value: 'POST_TELEMETRY_REQUEST' - }, - 'TO_SERVER_RPC_REQUEST': { - name: 'RPC Request from Device', - value: 'TO_SERVER_RPC_REQUEST' - }, - 'RPC_CALL_FROM_SERVER_TO_DEVICE': { - name: 'RPC Request to Device', - value: 'RPC_CALL_FROM_SERVER_TO_DEVICE' - }, - 'ACTIVITY_EVENT': { - name: 'Activity Event', - value: 'ACTIVITY_EVENT' - }, - 'INACTIVITY_EVENT': { - name: 'Inactivity Event', - value: 'INACTIVITY_EVENT' - }, - 'CONNECT_EVENT': { - name: 'Connect Event', - value: 'CONNECT_EVENT' - }, - 'DISCONNECT_EVENT': { - name: 'Disconnect Event', - value: 'DISCONNECT_EVENT' - }, - 'ENTITY_CREATED': { - name: 'Entity Created', - value: 'ENTITY_CREATED' - }, - 'ENTITY_UPDATED': { - name: 'Entity Updated', - value: 'ENTITY_UPDATED' - }, - 'ENTITY_DELETED': { - name: 'Entity Deleted', - value: 'ENTITY_DELETED' - }, - 'ENTITY_ASSIGNED': { - name: 'Entity Assigned', - value: 'ENTITY_ASSIGNED' - }, - 'ENTITY_UNASSIGNED': { - name: 'Entity Unassigned', - value: 'ENTITY_UNASSIGNED' - }, - 'ATTRIBUTES_UPDATED': { - name: 'Attributes Updated', - value: 'ATTRIBUTES_UPDATED' - }, - 'ATTRIBUTES_DELETED': { - name: 'Attributes Deleted', - value: 'ATTRIBUTES_DELETED' - } - }, - valueType: { - string: { - value: "string", - name: "value.string", - icon: "mdi:format-text" - }, - integer: { - value: "integer", - name: "value.integer", - icon: "mdi:numeric" - }, - double: { - value: "double", - name: "value.double", - icon: "mdi:numeric" - }, - boolean: { - value: "boolean", - name: "value.boolean", - icon: "mdi:checkbox-marked-outline" - }, - json: { - value: "json", - name: "value.json", - icon: "mdi:json" - } - }, - widgetType: { - timeseries: { - value: "timeseries", - name: "widget.timeseries", - template: { - bundleAlias: "charts", - alias: "basic_timeseries" - } - }, - latest: { - value: "latest", - name: "widget.latest-values", - template: { - bundleAlias: "cards", - alias: "attributes_card" - } - }, - rpc: { - value: "rpc", - name: "widget.rpc", - template: { - bundleAlias: "gpio_widgets", - alias: "basic_gpio_control" - } - }, - alarm: { - value: "alarm", - name: "widget.alarm", - template: { - bundleAlias: "alarm_widgets", - alias: "alarms_table" - } - }, - static: { - value: "static", - name: "widget.static", - template: { - bundleAlias: "cards", - alias: "html_card" - } - } - }, - widgetActionSources: { - headerButton: { - name: 'widget-action.header-button', - value: 'headerButton', - multiple: true - } - }, - widgetActionTypes: { - openDashboardState: { - name: 'widget-action.open-dashboard-state', - value: 'openDashboardState' - }, - updateDashboardState: { - name: 'widget-action.update-dashboard-state', - value: 'updateDashboardState' - }, - openDashboard: { - name: 'widget-action.open-dashboard', - value: 'openDashboard' - }, - custom: { - name: 'widget-action.custom', - value: 'custom' - }, - customPretty: { - name: 'widget-action.custom-pretty', - value: 'customPretty' - } - }, - systemBundleAlias: { - charts: "charts", - cards: "cards" - }, - translate: { - customTranslationsPrefix: "custom." - } - } - ).name; +/* + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export default angular.module('thingsboard.types', []) + .constant('types', + { + serverErrorCode: { + general: 2, + authentication: 10, + jwtTokenExpired: 11, + credentialsExpired: 15, + permissionDenied: 20, + invalidArguments: 30, + badRequestParams: 31, + itemNotFound: 32, + tooManyRequests: 33, + tooManyUpdates: 34 + }, + entryPoints: { + login: "/api/auth/login", + tokenRefresh: "/api/auth/token", + nonTokenBased: "/api/noauth" + }, + id: { + nullUid: "13814000-1dd2-11b2-8080-808080808080", + }, + aggregation: { + min: { + value: "MIN", + name: "aggregation.min" + }, + max: { + value: "MAX", + name: "aggregation.max" + }, + avg: { + value: "AVG", + name: "aggregation.avg" + }, + sum: { + value: "SUM", + name: "aggregation.sum" + }, + count: { + value: "COUNT", + name: "aggregation.count" + }, + none: { + value: "NONE", + name: "aggregation.none" + } + }, + alarmFields: { + createdTime: { + keyName: 'createdTime', + value: "createdTime", + name: "alarm.created-time", + time: true + }, + startTime: { + keyName: 'startTime', + value: "startTs", + name: "alarm.start-time", + time: true + }, + endTime: { + keyName: 'endTime', + value: "endTs", + name: "alarm.end-time", + time: true + }, + ackTime: { + keyName: 'ackTime', + value: "ackTs", + name: "alarm.ack-time", + time: true + }, + clearTime: { + keyName: 'clearTime', + value: "clearTs", + name: "alarm.clear-time", + time: true + }, + originator: { + keyName: 'originator', + value: "originatorName", + name: "alarm.originator" + }, + originatorType: { + keyName: 'originatorType', + value: "originator.entityType", + name: "alarm.originator-type" + }, + type: { + keyName: 'type', + value: "type", + name: "alarm.type" + }, + severity: { + keyName: 'severity', + value: "severity", + name: "alarm.severity" + }, + status: { + keyName: 'status', + value: "status", + name: "alarm.status" + } + }, + alarmStatus: { + activeUnack: "ACTIVE_UNACK", + activeAck: "ACTIVE_ACK", + clearedUnack: "CLEARED_UNACK", + clearedAck: "CLEARED_ACK" + }, + alarmSearchStatus: { + any: "ANY", + active: "ACTIVE", + cleared: "CLEARED", + ack: "ACK", + unack: "UNACK" + }, + alarmSeverity: { + "CRITICAL": { + name: "alarm.severity-critical", + class: "tb-critical", + color: "red" + }, + "MAJOR": { + name: "alarm.severity-major", + class: "tb-major", + color: "orange" + }, + "MINOR": { + name: "alarm.severity-minor", + class: "tb-minor", + color: "#ffca3d" + }, + "WARNING": { + name: "alarm.severity-warning", + class: "tb-warning", + color: "#abab00" + }, + "INDETERMINATE": { + name: "alarm.severity-indeterminate", + class: "tb-indeterminate", + color: "green" + } + }, + auditLogActionType: { + "ADDED": { + name: "audit-log.type-added" + }, + "DELETED": { + name: "audit-log.type-deleted" + }, + "UPDATED": { + name: "audit-log.type-updated" + }, + "ATTRIBUTES_UPDATED": { + name: "audit-log.type-attributes-updated" + }, + "ATTRIBUTES_DELETED": { + name: "audit-log.type-attributes-deleted" + }, + "RPC_CALL": { + name: "audit-log.type-rpc-call" + }, + "CREDENTIALS_UPDATED": { + name: "audit-log.type-credentials-updated" + }, + "ASSIGNED_TO_CUSTOMER": { + name: "audit-log.type-assigned-to-customer" + }, + "UNASSIGNED_FROM_CUSTOMER": { + name: "audit-log.type-unassigned-from-customer" + }, + "ACTIVATED": { + name: "audit-log.type-activated" + }, + "SUSPENDED": { + name: "audit-log.type-suspended" + }, + "CREDENTIALS_READ": { + name: "audit-log.type-credentials-read" + }, + "ATTRIBUTES_READ": { + name: "audit-log.type-attributes-read" + }, + "RELATION_ADD_OR_UPDATE": { + name: "audit-log.type-relation-add-or-update" + }, + "RELATION_DELETED": { + name: "audit-log.type-relation-delete" + }, + "RELATIONS_DELETED": { + name: "audit-log.type-relations-delete" + }, + "ALARM_ACK": { + name: "audit-log.type-alarm-ack" + }, + "ALARM_CLEAR": { + name: "audit-log.type-alarm-clear" + }, + "LOGIN": { + name: "audit-log.type-login" + }, + "LOGOUT": { + name: "audit-log.type-logout" + }, + "LOCKOUT": { + name: "audit-log.type-lockout" + }, + "ASSIGNED_FROM_TENANT": { + name: "audit-log.type-assigned-from-tenant" + }, + "ASSIGNED_TO_TENANT": { + name: "audit-log.type-assigned-to-tenant" + }, + "ASSIGNED_TO_EDGE": { + name: "audit-log.type-assigned-to-edge" + }, + "UNASSIGNED_FROM_EDGE": { + name: "audit-log.type-unassigned-from-edge" + } + }, + auditLogActionStatus: { + "SUCCESS": { + value: "SUCCESS", + name: "audit-log.status-success" + }, + "FAILURE": { + value: "FAILURE", + name: "audit-log.status-failure" + } + }, + auditLogMode: { + tenant: "tenant", + entity: "entity", + user: "user", + customer: "customer" + }, + aliasFilterType: { + singleEntity: { + value: 'singleEntity', + name: 'alias.filter-type-single-entity' + }, + entityList: { + value: 'entityList', + name: 'alias.filter-type-entity-list' + }, + entityName: { + value: 'entityName', + name: 'alias.filter-type-entity-name' + }, + stateEntity: { + value: 'stateEntity', + name: 'alias.filter-type-state-entity' + }, + assetType: { + value: 'assetType', + name: 'alias.filter-type-asset-type' + }, + deviceType: { + value: 'deviceType', + name: 'alias.filter-type-device-type' + }, + entityViewType: { + value: 'entityViewType', + name: 'alias.filter-type-entity-view-type' + }, + edgeType: { + value: 'edgeType', + name: 'alias.filter-type-edge-type' + }, + relationsQuery: { + value: 'relationsQuery', + name: 'alias.filter-type-relations-query' + }, + assetSearchQuery: { + value: 'assetSearchQuery', + name: 'alias.filter-type-asset-search-query' + }, + deviceSearchQuery: { + value: 'deviceSearchQuery', + name: 'alias.filter-type-device-search-query' + }, + entityViewSearchQuery: { + value: 'entityViewSearchQuery', + name: 'alias.filter-type-entity-view-search-query' + }, + edgeSearchQuery: { + value: 'edgeSearchQuery', + name: 'alias.filter-type-edge-search-query' + } + }, + direction: { + column: { + value: "column", + name: "direction.column" + }, + row: { + value: "row", + name: "direction.row" + } + }, + position: { + top: { + value: "top", + name: "position.top" + }, + bottom: { + value: "bottom", + name: "position.bottom" + }, + left: { + value: "left", + name: "position.left" + }, + right: { + value: "right", + name: "position.right" + } + }, + datasourceType: { + function: "function", + entity: "entity" + }, + dataKeyType: { + timeseries: "timeseries", + attribute: "attribute", + function: "function", + alarm: "alarm", + entityField: "entityField" + }, + contentType: { + "JSON": { + value: "JSON", + name: "content-type.json", + code: "json" + }, + "TEXT": { + value: "TEXT", + name: "content-type.text", + code: "text" + }, + "BINARY": { + value: "BINARY", + name: "content-type.binary", + code: "text" + } + }, + componentType: { + enrichment: "ENRICHMENT", + filter: "FILTER", + transformation: "TRANSFORMATION", + action: "ACTION", + external: "EXTERNAL" + }, + entityType: { + device: "DEVICE", + asset: "ASSET", + tenant: "TENANT", + customer: "CUSTOMER", + user: "USER", + dashboard: "DASHBOARD", + alarm: "ALARM", + rulechain: "RULE_CHAIN", + rulenode: "RULE_NODE", + entityView: "ENTITY_VIEW", + edge: "EDGE" + }, + edgeEventType:{ + dashboard: "DASHBOARD", + asset: "ASSET", + device: "DEVICE", + entityView: "ENTITY_VIEW", + alarm: "ALARM", + rulechain: "RULE_CHAIN", + ruleChainMetaData: "RULE_CHAIN_METADATA", + edge: "EDGE", + user: "USER", + customer: "CUSTOMER", + relation: "RELATION", + entityGroup: "ENTITY_GROUP", + schedulerEvent: "SCHEDULER_EVENT", + whiteLabeling: "WHITE_LABELING", + loginWhiteLabeling: "LOGIN_WHITE_LABELING", + customTranslation: "CUSTOM_TRANSLATION", + widgetsBundle: "WIDGETS_BUNDLE", + widgetType: "WIDGET_TYPE", + adminSettings: "ADMIN_SETTINGS" + }, + edgeEventAction: { + updated: "UPDATED", + added: "ADDED", + assignedToEdge: "ASSIGNED_TO_EDGE", + deleted: "DELETED", + unassignedFromEdge: "UNASSIGNED_FROM_EDGE", + alarmAck: "ALARM_ACK", + alarmClear: "ALARM_CLEAR", + credentialsUpdated: "CREDENTIALS_UPDATED", + attributesUpdated: "ATTRIBUTES_UPDATED", + attributesDeleted: "ATTRIBUTES_DELETED", + timeseriesUpdated: "TIMESERIES_UPDATED" + }, + edgeAttributeKeys: { + active: "active", + lastConnectTime: "lastConnectTime", + lastDisconnectTime: "lastDisconnectTime", + queueStartTs: "queueStartTs" + }, + importEntityColumnType: { + name: { + name: 'import.column-type.name', + value: 'name' + }, + type: { + name: 'import.column-type.type', + value: 'type' + }, + label: { + name: 'import.column-type.label', + value: 'label' + }, + clientAttribute: { + name: 'import.column-type.client-attribute', + value: 'CLIENT_ATTRIBUTE' + }, + sharedAttribute: { + name: 'import.column-type.shared-attribute', + value: 'SHARED_ATTRIBUTE' + }, + serverAttribute: { + name: 'import.column-type.server-attribute', + value: 'SERVER_ATTRIBUTE' + }, + timeseries: { + name: 'import.column-type.timeseries', + value: 'TIMESERIES' + }, + entityField: { + name: 'import.column-type.entity-field', + value: 'ENTITY_FIELD' + }, + accessToken: { + name: 'import.column-type.access-token', + value: 'ACCESS_TOKEN' + }, + isGateway: { + name: 'import.column-type.isgateway', + value: 'gateway' + }, + description: { + name: 'import.column-type.description', + value: 'description' + } + }, + aliasEntityType: { + current_customer: "CURRENT_CUSTOMER", + current_tenant: "CURRENT_TENANT" + }, + entityTypeTranslations: { + "DEVICE": { + type: 'entity.type-device', + typePlural: 'entity.type-devices', + list: 'entity.list-of-devices', + nameStartsWith: 'entity.device-name-starts-with' + }, + "ASSET": { + type: 'entity.type-asset', + typePlural: 'entity.type-assets', + list: 'entity.list-of-assets', + nameStartsWith: 'entity.asset-name-starts-with' + }, + "ENTITY_VIEW": { + type: 'entity.type-entity-view', + typePlural: 'entity.type-entity-views', + list: 'entity.list-of-entity-views', + nameStartsWith: 'entity.entity-view-name-starts-with' + }, + "TENANT": { + type: 'entity.type-tenant', + typePlural: 'entity.type-tenants', + list: 'entity.list-of-tenants', + nameStartsWith: 'entity.tenant-name-starts-with' + }, + "CUSTOMER": { + type: 'entity.type-customer', + typePlural: 'entity.type-customers', + list: 'entity.list-of-customers', + nameStartsWith: 'entity.customer-name-starts-with' + }, + "USER": { + type: 'entity.type-user', + typePlural: 'entity.type-users', + list: 'entity.list-of-users', + nameStartsWith: 'entity.user-name-starts-with' + }, + "DASHBOARD": { + type: 'entity.type-dashboard', + typePlural: 'entity.type-dashboards', + list: 'entity.list-of-dashboards', + nameStartsWith: 'entity.dashboard-name-starts-with' + }, + "ALARM": { + type: 'entity.type-alarm', + typePlural: 'entity.type-alarms', + list: 'entity.list-of-alarms', + nameStartsWith: 'entity.alarm-name-starts-with' + }, + "RULE_CHAIN": { + type: 'entity.type-rulechain', + typePlural: 'entity.type-rulechains', + list: 'entity.list-of-rulechains', + nameStartsWith: 'entity.rulechain-name-starts-with' + }, + "RULE_NODE": { + type: 'entity.type-rulenode', + typePlural: 'entity.type-rulenodes', + list: 'entity.list-of-rulenodes', + nameStartsWith: 'entity.rulenode-name-starts-with' + }, + "CURRENT_CUSTOMER": { + type: 'entity.type-current-customer', + list: 'entity.type-current-customer' + }, + "CURRENT_TENANT": { + type: 'entity.type-current-tenant', + list: 'entity.type-current-tenant' + }, + "EDGE": { + type: 'entity.type-edge', + typePlural: 'entity.type-edges', + list: 'entity.list-of-edges', + nameStartsWith: 'entity.edge-name-starts-with' + } + }, + entityField: { + createdTime: { + keyName: 'createdTime', + name: 'entity-field.created-time', + value: 'createdTime', + time: true + }, + name: { + keyName: 'name', + name: 'entity-field.name', + value: 'name' + }, + type: { + keyName: 'type', + name: 'entity-field.type', + value: 'type' + }, + firstName: { + keyName: 'firstName', + name: 'entity-field.first-name', + value: 'firstName' + }, + lastName: { + keyName: 'lastName', + name: 'entity-field.last-name', + value: 'lastName' + }, + email: { + keyName: 'email', + name: 'entity-field.email', + value: 'email' + }, + title: { + keyName: 'title', + name: 'entity-field.title', + value: 'title' + }, + country: { + keyName: 'country', + name: 'entity-field.country', + value: 'country' + }, + state: { + keyName: 'state', + name: 'entity-field.state', + value: 'state' + }, + city: { + keyName: 'city', + name: 'entity-field.city', + value: 'city' + }, + address: { + keyName: 'address', + name: 'entity-field.address', + value: 'address' + }, + address2: { + keyName: 'address2', + name: 'entity-field.address2', + value: 'address2' + }, + zip: { + keyName: 'zip', + name: 'entity-field.zip', + value: 'zip' + }, + phone: { + keyName: 'phone', + name: 'entity-field.phone', + value: 'phone' + }, + label: { + keyName: 'label', + name: 'entity-field.label', + value: 'label' + } + }, + entitySearchDirection: { + from: "FROM", + to: "TO" + }, + entityRelationType: { + contains: "Contains", + manages: "Manages" + }, + eventType: { + error: { + value: "ERROR", + name: "event.type-error" + }, + lcEvent: { + value: "LC_EVENT", + name: "event.type-lc-event" + }, + stats: { + value: "STATS", + name: "event.type-stats" + }, + edgeEvent: { + value: "EDGE_EVENT", + name: "event.type-edge-event" + } + }, + debugEventType: { + debugRuleNode: { + value: "DEBUG_RULE_NODE", + name: "event.type-debug-rule-node" + }, + debugRuleChain: { + value: "DEBUG_RULE_CHAIN", + name: "event.type-debug-rule-chain" + } + }, + extensionType: { + http: "HTTP", + mqtt: "MQTT", + opc: "OPC UA", + modbus: "MODBUS" + }, + gatewayConfigType: { + mqtt: { + value: "mqtt", + name: "MQTT" + }, + modbus: { + value: "modbus", + name: "Modbus" + }, + opcua: { + value: "opcua", + name: "OPC-UA" + }, + ble: { + value: "ble", + name: "BLE" + }, + request: { + value: "request", + name: "Request" + }, + can: { + value: "can", + name: "CAN" + }, + bacnet: { + value: "bacnet", + name: "BACnet" + }, + custom: { + value: "custom", + name: "Custom" + } + }, + gatewayLogLevel: { + none: "NONE", + critical: "CRITICAL", + error: "ERROR", + warning: "WARNING", + info: "INFO", + debug: "DEBUG" + }, + extensionValueType: { + string: 'value.string', + long: 'value.long', + double: 'value.double', + boolean: 'value.boolean' + }, + extensionTransformerType: { + toDouble: 'extension.to-double', + custom: 'extension.custom' + }, + mqttConverterTypes: { + json: 'extension.converter-json', + custom: 'extension.custom' + }, + mqttCredentialTypes: { + anonymous: { + value: "anonymous", + name: "extension.anonymous" + }, + basic: { + value: "basic", + name: "extension.basic" + }, + pem: { + value: "cert.PEM", + name: "extension.pem" + } + }, + extensionOpcSecurityTypes: { + Basic128Rsa15: "Basic128Rsa15", + Basic256: "Basic256", + Basic256Sha256: "Basic256Sha256", + None: "None" + }, + extensionIdentityType: { + anonymous: "extension.anonymous", + username: "extension.username" + }, + extensionKeystoreType: { + PKCS12: "PKCS12", + JKS: "JKS" + }, + extensionModbusFunctionCodes: { + 1: "Read Coils (1)", + 2: "Read Discrete Inputs (2)", + 3: "Read Multiple Holding Registers (3)", + 4: "Read Input Registers (4)" + }, + extensionModbusTransports: { + tcp: "TCP", + udp: "UDP", + rtu: "RTU" + }, + extensionModbusRtuParities: { + none: "none", + even: "even", + odd: "odd" + }, + extensionModbusRtuEncodings: { + ascii: "ascii", + rtu: "rtu" + }, + latestTelemetry: { + value: "LATEST_TELEMETRY", + name: "attribute.scope-latest-telemetry", + clientSide: true + }, + attributesScope: { + client: { + value: "CLIENT_SCOPE", + name: "attribute.scope-client", + clientSide: true + }, + server: { + value: "SERVER_SCOPE", + name: "attribute.scope-server", + clientSide: false + }, + shared: { + value: "SHARED_SCOPE", + name: "attribute.scope-shared", + clientSide: false + } + }, + ruleChainType: { + core: "CORE", + edge: "EDGE" + }, + ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], + ruleChainNodeComponent: { + type: 'RULE_CHAIN', + name: 'rule chain', + clazz: 'tb.internal.RuleChain', + configurationDescriptor: { + nodeDefinition: { + description: "", + details: "Forwards incoming messages to specified Rule Chain", + inEnabled: true, + outEnabled: false, + relationTypes: [], + customRelations: false, + defaultConfiguration: {} + } + } + }, + unknownNodeComponent: { + type: 'UNKNOWN', + name: 'unknown', + clazz: 'tb.internal.Unknown', + configurationDescriptor: { + nodeDefinition: { + description: "", + details: "", + inEnabled: true, + outEnabled: true, + relationTypes: [], + customRelations: false, + defaultConfiguration: {} + } + } + }, + inputNodeComponent: { + type: 'INPUT', + name: 'Input', + clazz: 'tb.internal.Input' + }, + ruleNodeType: { + FILTER: { + value: "FILTER", + name: "rulenode.type-filter", + details: "rulenode.type-filter-details", + nodeClass: "tb-filter-type", + icon: "filter_list" + }, + ENRICHMENT: { + value: "ENRICHMENT", + name: "rulenode.type-enrichment", + details: "rulenode.type-enrichment-details", + nodeClass: "tb-enrichment-type", + icon: "playlist_add" + }, + TRANSFORMATION: { + value: "TRANSFORMATION", + name: "rulenode.type-transformation", + details: "rulenode.type-transformation-details", + nodeClass: "tb-transformation-type", + icon: "transform" + }, + ACTION: { + value: "ACTION", + name: "rulenode.type-action", + details: "rulenode.type-action-details", + nodeClass: "tb-action-type", + icon: "flash_on" + }, + EXTERNAL: { + value: "EXTERNAL", + name: "rulenode.type-external", + details: "rulenode.type-external-details", + nodeClass: "tb-external-type", + icon: "cloud_upload" + }, + RULE_CHAIN: { + value: "RULE_CHAIN", + name: "rulenode.type-rule-chain", + details: "rulenode.type-rule-chain-details", + nodeClass: "tb-rule-chain-type", + icon: "settings_ethernet" + }, + INPUT: { + value: "INPUT", + name: "rulenode.type-input", + details: "rulenode.type-input-details", + nodeClass: "tb-input-type", + icon: "input", + special: true + }, + UNKNOWN: { + value: "UNKNOWN", + name: "rulenode.type-unknown", + details: "rulenode.type-unknown-details", + nodeClass: "tb-unknown-type", + icon: "help_outline" + } + }, + messageType: { + 'POST_ATTRIBUTES_REQUEST': { + name: 'Post attributes', + value: 'POST_ATTRIBUTES_REQUEST' + }, + 'POST_TELEMETRY_REQUEST': { + name: 'Post telemetry', + value: 'POST_TELEMETRY_REQUEST' + }, + 'TO_SERVER_RPC_REQUEST': { + name: 'RPC Request from Device', + value: 'TO_SERVER_RPC_REQUEST' + }, + 'RPC_CALL_FROM_SERVER_TO_DEVICE': { + name: 'RPC Request to Device', + value: 'RPC_CALL_FROM_SERVER_TO_DEVICE' + }, + 'ACTIVITY_EVENT': { + name: 'Activity Event', + value: 'ACTIVITY_EVENT' + }, + 'INACTIVITY_EVENT': { + name: 'Inactivity Event', + value: 'INACTIVITY_EVENT' + }, + 'CONNECT_EVENT': { + name: 'Connect Event', + value: 'CONNECT_EVENT' + }, + 'DISCONNECT_EVENT': { + name: 'Disconnect Event', + value: 'DISCONNECT_EVENT' + }, + 'ENTITY_CREATED': { + name: 'Entity Created', + value: 'ENTITY_CREATED' + }, + 'ENTITY_UPDATED': { + name: 'Entity Updated', + value: 'ENTITY_UPDATED' + }, + 'ENTITY_DELETED': { + name: 'Entity Deleted', + value: 'ENTITY_DELETED' + }, + 'ENTITY_ASSIGNED': { + name: 'Entity Assigned', + value: 'ENTITY_ASSIGNED' + }, + 'ENTITY_UNASSIGNED': { + name: 'Entity Unassigned', + value: 'ENTITY_UNASSIGNED' + }, + 'ATTRIBUTES_UPDATED': { + name: 'Attributes Updated', + value: 'ATTRIBUTES_UPDATED' + }, + 'ATTRIBUTES_DELETED': { + name: 'Attributes Deleted', + value: 'ATTRIBUTES_DELETED' + } + }, + valueType: { + string: { + value: "string", + name: "value.string", + icon: "mdi:format-text" + }, + integer: { + value: "integer", + name: "value.integer", + icon: "mdi:numeric" + }, + double: { + value: "double", + name: "value.double", + icon: "mdi:numeric" + }, + boolean: { + value: "boolean", + name: "value.boolean", + icon: "mdi:checkbox-marked-outline" + }, + json: { + value: "json", + name: "value.json", + icon: "mdi:json" + } + }, + widgetType: { + timeseries: { + value: "timeseries", + name: "widget.timeseries", + template: { + bundleAlias: "charts", + alias: "basic_timeseries" + } + }, + latest: { + value: "latest", + name: "widget.latest-values", + template: { + bundleAlias: "cards", + alias: "attributes_card" + } + }, + rpc: { + value: "rpc", + name: "widget.rpc", + template: { + bundleAlias: "gpio_widgets", + alias: "basic_gpio_control" + } + }, + alarm: { + value: "alarm", + name: "widget.alarm", + template: { + bundleAlias: "alarm_widgets", + alias: "alarms_table" + } + }, + static: { + value: "static", + name: "widget.static", + template: { + bundleAlias: "cards", + alias: "html_card" + } + } + }, + widgetActionSources: { + headerButton: { + name: 'widget-action.header-button', + value: 'headerButton', + multiple: true + } + }, + widgetActionTypes: { + openDashboardState: { + name: 'widget-action.open-dashboard-state', + value: 'openDashboardState' + }, + updateDashboardState: { + name: 'widget-action.update-dashboard-state', + value: 'updateDashboardState' + }, + openDashboard: { + name: 'widget-action.open-dashboard', + value: 'openDashboard' + }, + custom: { + name: 'widget-action.custom', + value: 'custom' + }, + customPretty: { + name: 'widget-action.custom-pretty', + value: 'customPretty' + } + }, + systemBundleAlias: { + charts: "charts", + cards: "cards" + }, + translate: { + customTranslationsPrefix: "custom." + } + } + ).name; From ad704fe37880a137b9fcef78be47bd468636b7db Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 15:59:06 +0300 Subject: [PATCH 104/156] Code review and refactoring --- ui/src/app/entity-view/entity-view.routes.js | 1 + .../import-export/import-export.service.js | 3 -- ui/src/app/locale/locale.constant-de_DE.json | 2 +- .../app/rulechain/rulechain-fieldset.tpl.html | 5 ---- ui/src/app/rulechain/rulechain.directive.js | 1 - ui/src/app/rulechain/rulechains.controller.js | 28 +++++++++---------- ui/src/app/rulechain/rulechains.tpl.html | 1 - 7 files changed, 16 insertions(+), 25 deletions(-) diff --git a/ui/src/app/entity-view/entity-view.routes.js b/ui/src/app/entity-view/entity-view.routes.js index 4da8c80500..c55add94fa 100644 --- a/ui/src/app/entity-view/entity-view.routes.js +++ b/ui/src/app/entity-view/entity-view.routes.js @@ -68,4 +68,5 @@ export default function EntityViewRoutes($stateProvider, types) { label: '{"icon": "view_quilt", "label": "{{ vm.customerEntityViewsTitle }}", "translate": "false"}' } }); + } diff --git a/ui/src/app/import-export/import-export.service.js b/ui/src/app/import-export/import-export.service.js index 04aa8805a1..dc0fbf1ea7 100644 --- a/ui/src/app/import-export/import-export.service.js +++ b/ui/src/app/import-export/import-export.service.js @@ -257,9 +257,6 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, ruleChain.firstRuleNodeId = null; } ruleChain.root = false; - delete ruleChain.assignedEdgesText; - delete ruleChain.assignedEdges; - delete ruleChain.assignedEdgesIds; return ruleChain; } diff --git a/ui/src/app/locale/locale.constant-de_DE.json b/ui/src/app/locale/locale.constant-de_DE.json index 62f0bc5156..9e822188ee 100644 --- a/ui/src/app/locale/locale.constant-de_DE.json +++ b/ui/src/app/locale/locale.constant-de_DE.json @@ -67,7 +67,7 @@ "general-settings": "Allgemeine Einstellungen", "outgoing-mail": "E-Mail Versand", "outgoing-mail-settings": "Konfiguration des Postausgangsservers", - "system-settings": "Systeminstellungen", + "system-settings": "Systemeinstellungen", "test-mail-sent": "Test E-Mail wurde erfolgreich versendet!", "base-url": "Basis-URL", "base-url-required": "Basis-URL ist erforderlich.", diff --git a/ui/src/app/rulechain/rulechain-fieldset.tpl.html b/ui/src/app/rulechain/rulechain-fieldset.tpl.html index a85a423358..4afd6ee96e 100644 --- a/ui/src/app/rulechain/rulechain-fieldset.tpl.html +++ b/ui/src/app/rulechain/rulechain-fieldset.tpl.html @@ -36,11 +36,6 @@ - - - -
diff --git a/ui/src/app/rulechain/rulechain.directive.js b/ui/src/app/rulechain/rulechain.directive.js index dd6405c1c9..a4951c2f8b 100644 --- a/ui/src/app/rulechain/rulechain.directive.js +++ b/ui/src/app/rulechain/rulechain.directive.js @@ -22,7 +22,6 @@ import ruleChainFieldsetTemplate from './rulechain-fieldset.tpl.html'; /*@ngInject*/ export default function RuleChainDirective($compile, $templateCache, $mdDialog, $document, $q, $translate, types, toast) { var linker = function (scope, element) { - var template = $templateCache.get(ruleChainFieldsetTemplate); element.html(template); diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index 300e7cbc80..fe19cad5ca 100644 --- a/ui/src/app/rulechain/rulechains.controller.js +++ b/ui/src/app/rulechain/rulechains.controller.js @@ -22,8 +22,8 @@ import addRuleChainsToEdgeTemplate from "./add-rulechains-to-edge.tpl.html"; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function RuleChainsController(ruleChainService, userService, edgeService, importExport, $state, - $stateParams, $filter, $translate, $mdDialog, $document, $q, types) { +export default function RuleChainsController(ruleChainService, userService, importExport, $state, $stateParams, $filter, $translate, $mdDialog, types, + $document, $q, edgeService) { var vm = this; var edgeId = $stateParams.edgeId; @@ -203,21 +203,21 @@ export default function RuleChainsController(ruleChainService, userService, edge ruleChainActionsList.push({ onAction: function ($event, item) { - vm.grid.deleteItem($event, item); + setDefaultRootEdgeRuleChain($event, item); }, - name: function() { return $translate.instant('action.delete') }, - details: function() { return $translate.instant('rulechain.delete') }, - icon: "delete", + name: function() { return $translate.instant('rulechain.set-default-root-edge') }, + details: function() { return $translate.instant('rulechain.set-default-root-edge') }, + icon: "flag", isEnabled: isNonRootRuleChain }); ruleChainActionsList.push({ onAction: function ($event, item) { - setDefaultRootEdgeRuleChain($event, item); + vm.grid.deleteItem($event, item); }, - name: function() { return $translate.instant('rulechain.set-default-root-edge') }, - details: function() { return $translate.instant('rulechain.set-default-root-edge') }, - icon: "flag", + name: function() { return $translate.instant('action.delete') }, + details: function() { return $translate.instant('rulechain.delete') }, + icon: "delete", isEnabled: isNonRootRuleChain }); @@ -395,13 +395,13 @@ export default function RuleChainsController(ruleChainService, userService, edge if ($event) { $event.stopPropagation(); } - + var ruleChainParams = {ruleChainId: ruleChain.id.id}; if (vm.ruleChainsScope === 'edge') { - $state.go('home.edges.ruleChains.ruleChain', {ruleChainId: ruleChain.id.id, edgeId: vm.edge.id.id}); + $state.go('home.edges.ruleChains.ruleChain', {...ruleChainParams, edgeId: vm.edge.id.id}); } else if (vm.ruleChainsScope === 'edges') { - $state.go('home.ruleChains.edge.ruleChain', {ruleChainId: ruleChain.id.id}); + $state.go('home.ruleChains.edge.ruleChain', ruleChainParams); } else { - $state.go('home.ruleChains.core.ruleChain', {ruleChainId: ruleChain.id.id}); + $state.go('home.ruleChains.core.ruleChain', ruleChainParams); } } diff --git a/ui/src/app/rulechain/rulechains.tpl.html b/ui/src/app/rulechain/rulechains.tpl.html index fae3e8d63d..9880ac0213 100644 --- a/ui/src/app/rulechain/rulechains.tpl.html +++ b/ui/src/app/rulechain/rulechains.tpl.html @@ -24,7 +24,6 @@ Date: Fri, 18 Sep 2020 17:11:57 +0300 Subject: [PATCH 105/156] Code review and refactoring 2 --- .../add-dashboards-to-edge.controller.js | 8 +- ui/src/app/dashboard/dashboards.controller.js | 9 +- ui/src/app/edge/edge.routes.js | 113 ++++-- .../app/event/event-row-edge-event.tpl.html | 6 +- ui/src/app/event/event-row.directive.js | 377 +++++++++--------- .../add-rulechains-to-edge.controller.js | 2 +- ui/src/app/rulechain/rulechain.routes.js | 57 --- ui/src/app/rulechain/rulechains.controller.js | 2 +- 8 files changed, 283 insertions(+), 291 deletions(-) diff --git a/ui/src/app/dashboard/add-dashboards-to-edge.controller.js b/ui/src/app/dashboard/add-dashboards-to-edge.controller.js index ff579d492f..e5dcc00b33 100644 --- a/ui/src/app/dashboard/add-dashboards-to-edge.controller.js +++ b/ui/src/app/dashboard/add-dashboards-to-edge.controller.js @@ -53,13 +53,7 @@ export default function AddDashboardsToEdgeController(dashboardService, types, $ fetchMoreItems_: function () { if (vm.dashboards.hasNext && !vm.dashboards.pending) { vm.dashboards.pending = true; - var fetchDashboardsPromise; - if (edgeCustomerId === vm.types.id.nullUid) { - fetchDashboardsPromise = dashboardService.getTenantDashboards(vm.dashboards.nextPageLink); - } else { - fetchDashboardsPromise = dashboardService.getCustomerDashboards(edgeCustomerId, vm.dashboards.nextPageLink); - } - fetchDashboardsPromise.then( + dashboardService.getTenantDashboards(vm.dashboards.nextPageLink).then( function success(dashboards) { vm.dashboards.data = vm.dashboards.data.concat(dashboards.data); vm.dashboards.nextPageLink = dashboards.nextPageLink; diff --git a/ui/src/app/dashboard/dashboards.controller.js b/ui/src/app/dashboard/dashboards.controller.js index 6d61029b84..12a4d1cee0 100644 --- a/ui/src/app/dashboard/dashboards.controller.js +++ b/ui/src/app/dashboard/dashboards.controller.js @@ -708,14 +708,7 @@ export function DashboardsController(userService, dashboardService, customerServ $event.stopPropagation(); } var pageSize = 10; - var fetchDashboardsPromise; - if (vm.edgeCustomerId.id === vm.types.id.nullUid) { - fetchDashboardsPromise = dashboardService.getTenantDashboards({limit: pageSize, textSearch: ''}); - } else { - fetchDashboardsPromise = dashboardService.getCustomerDashboards(vm.edgeCustomerId.id, {limit: pageSize, textSearch: ''}); - } - - fetchDashboardsPromise.then( + dashboardService.getTenantDashboards({limit: pageSize, textSearch: ''}).then( function success(_dashboards) { var dashboards = { pageSize: pageSize, diff --git a/ui/src/app/edge/edge.routes.js b/ui/src/app/edge/edge.routes.js index e3443d1211..bcba2cffe1 100644 --- a/ui/src/app/edge/edge.routes.js +++ b/ui/src/app/edge/edge.routes.js @@ -21,6 +21,8 @@ import devicesTemplate from "../device/devices.tpl.html"; import assetsTemplate from "../asset/assets.tpl.html"; import dashboardsTemplate from "../dashboard/dashboards.tpl.html"; import dashboardTemplate from "../dashboard/dashboard.tpl.html"; +import ruleChainsTemplate from "../rulechain/rulechains.tpl.html"; +import ruleChainTemplate from "../rulechain/rulechain.tpl.html"; /* eslint-enable import/no-unresolved, import/default */ @@ -49,8 +51,7 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "transform", "label": "edge.edges"}' } - }) - .state('home.edges.entityViews', { + }).state('home.edges.entityViews', { url: '/:edgeId/entityViews', params: {'topIndex': 0}, module: 'private', @@ -72,8 +73,7 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "view_quilt", "label": "edge.entity-views"}' } - }) - .state('home.edges.devices', { + }).state('home.edges.devices', { url: '/:edgeId/devices', params: {'topIndex': 0}, module: 'private', @@ -95,8 +95,7 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "devices_other", "label": "edge.devices"}' } - }) - .state('home.edges.assets', { + }).state('home.edges.assets', { url: '/:edgeId/assets', params: {'topIndex': 0}, module: 'private', @@ -118,29 +117,27 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "domain", "label": "edge.assets"}' } - }) - .state('home.edges.dashboards', { - url: '/:edgeId/dashboards', - params: {'topIndex': 0}, - module: 'private', - auth: ['TENANT_ADMIN'], - views: { - "content@home": { - templateUrl: dashboardsTemplate, - controllerAs: 'vm', - controller: 'DashboardsController' + }).state('home.edges.dashboards', { + url: '/:edgeId/dashboards', + params: {'topIndex': 0}, + module: 'private', + auth: ['TENANT_ADMIN'], + views: { + "content@home": { + templateUrl: dashboardsTemplate, + controllerAs: 'vm', + controller: 'DashboardsController' + } + }, + data: { + dashboardsType: 'edge', + searchEnabled: true, + pageTitle: 'edge.dashboards' + }, + ncyBreadcrumb: { + label: '{"icon": "dashboard", "label": "edge.dashboards"}' } - }, - data: { - dashboardsType: 'edge', - searchEnabled: true, - pageTitle: 'edge.dashboards' - }, - ncyBreadcrumb: { - label: '{"icon": "dashboard", "label": "edge.dashboards"}' - } - }) - .state('home.edges.dashboards.dashboard', { + }).state('home.edges.dashboards.dashboard', { url: '/:dashboardId?state', reloadOnSearch: false, module: 'private', @@ -161,8 +158,7 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "dashboard", "label": "{{ vm.dashboard.title }}", "translate": "false"}' } - }) - .state('home.customers.edges', { + }).state('home.customers.edges', { url: '/:customerId/edges', params: {'topIndex': 0}, module: 'private', @@ -184,5 +180,62 @@ export default function EdgeRoutes($stateProvider, types) { ncyBreadcrumb: { label: '{"icon": "router", "label": "{{ vm.customerEdgesTitle }}", "translate": "false"}' } + }).state('home.edges.ruleChains', { + url: '/:edgeId/ruleChains', + params: {'topIndex': 0}, + module: 'private', + auth: ['TENANT_ADMIN'], + views: { + "content@home": { + templateUrl: ruleChainsTemplate, + controllerAs: 'vm', + controller: 'RuleChainsController' + } + }, + data: { + searchEnabled: true, + pageTitle: 'edge.rulechains', + ruleChainsType: 'edge' + }, + ncyBreadcrumb: { + label: '{"icon": "settings_ethernet", "label": "rulechain.edge-rulechains"}' + } + }).state('home.edges.ruleChains.ruleChain', { + url: '/:ruleChainId', + reloadOnSearch: false, + module: 'private', + auth: ['SYS_ADMIN', 'TENANT_ADMIN'], + views: { + "content@home": { + templateUrl: ruleChainTemplate, + controller: 'RuleChainController', + controllerAs: 'vm' + } + }, + resolve: { + ruleChain: + /*@ngInject*/ + function($stateParams, ruleChainService) { + return ruleChainService.getRuleChain($stateParams.ruleChainId); + }, + ruleChainMetaData: + /*@ngInject*/ + function($stateParams, ruleChainService) { + return ruleChainService.getRuleChainMetaData($stateParams.ruleChainId); + }, + ruleNodeComponents: + /*@ngInject*/ + function($stateParams, ruleChainService) { + return ruleChainService.getRuleNodeComponents(types.ruleChainType.edge); + } + }, + data: { + import: false, + searchEnabled: false, + pageTitle: 'edge.rulechain' + }, + ncyBreadcrumb: { + label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name }}", "translate": "false"}' + } }); } diff --git a/ui/src/app/event/event-row-edge-event.tpl.html b/ui/src/app/event/event-row-edge-event.tpl.html index d47ca55b81..6cc06d0cc3 100644 --- a/ui/src/app/event/event-row-edge-event.tpl.html +++ b/ui/src/app/event/event-row-edge-event.tpl.html @@ -16,12 +16,12 @@ -->
{{ event.createdTime | date : 'yyyy-MM-dd HH:mm:ss' }}
-
{{ event.edgeEventType }}
-
{{ event.edgeEventAction }}
+
{{ event.type }}
+
{{ event.action }}
{{ event.entityId }}
{{ updateStatus(event.createdTime) | translate }}
- diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index e1266323ed..c08048379e 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -1,184 +1,193 @@ -/* - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* eslint-disable import/no-unresolved, import/default */ - -import eventErrorDialogTemplate from './event-content-dialog.tpl.html'; - -import eventRowLcEventTemplate from './event-row-lc-event.tpl.html'; -import eventRowStatsTemplate from './event-row-stats.tpl.html'; -import eventRowErrorTemplate from './event-row-error.tpl.html'; -import eventRowDebugRuleNodeTemplate from './event-row-debug-rulenode.tpl.html'; -import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; - -/* eslint-enable import/no-unresolved, import/default */ - -/*@ngInject*/ -export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, - types, utils, toast, entityService, ruleChainService) { - - var linker = function (scope, element, attrs) { - - var getTemplate = function(eventType) { - var template = ''; - switch(eventType) { - case types.eventType.lcEvent.value: - template = eventRowLcEventTemplate; - break; - case types.eventType.stats.value: - template = eventRowStatsTemplate; - break; - case types.eventType.error.value: - template = eventRowErrorTemplate; - break; - case types.debugEventType.debugRuleNode.value: - template = eventRowDebugRuleNodeTemplate; - break; - case types.debugEventType.debugRuleChain.value: - template = eventRowDebugRuleNodeTemplate; - break; - case types.eventType.edgeEvent.value: - template = eventRowEdgeEventTemplate; - break; - } - return $templateCache.get(template); - } - - scope.loadTemplate = function() { - element.html(getTemplate(attrs.eventType)); - $compile(element.contents())(scope); - } - - attrs.$observe('eventType', function() { - scope.loadTemplate(); - }); - - scope.types = types; - - scope.event = attrs.event; - - scope.showContent = function($event, content, title, contentType) { - var onShowingCallback = { - onShowing: function(){} - } - if (!contentType) { - contentType = null; - } - var sortedContent; - try { - sortedContent = angular.toJson(utils.sortObjectKeys(angular.fromJson(content))); - } - catch(err) { - sortedContent = content; - } - $mdDialog.show({ - controller: 'EventContentDialogController', - controllerAs: 'vm', - templateUrl: eventErrorDialogTemplate, - locals: {content: sortedContent, title: title, contentType: contentType, showingCallback: onShowingCallback}, - parent: angular.element($document[0].body), - fullscreen: true, - targetEvent: $event, - multiple: true, - onShowing: function(scope, element) { - onShowingCallback.onShowing(scope, element); - } - }); - } - - scope.showEdgeEntityContent = function($event, title, contentType) { - var onShowingCallback = { - onShowing: function(){} - } - if (!contentType) { - contentType = null; - } - var content = ''; - switch(scope.event.edgeEventType) { - case types.edgeEventType.relation: - content = angular.toJson(scope.event.entityBody); - showDialog(); - break; - case types.edgeEventType.ruleChainMetaData: - content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then( - function success(info) { - showDialog(); - return angular.toJson(info); - }, function fail() { - showError(); - }); - break; - default: - content = entityService.getEntity(scope.event.edgeEventType, scope.event.entityId, {ignoreErrors: true}).then( - function success(info) { - showDialog(); - return angular.toJson(info); - }, function fail() { - showError(); - }); - break; - } - function showDialog() { - $mdDialog.show({ - controller: 'EventContentDialogController', - controllerAs: 'vm', - templateUrl: eventErrorDialogTemplate, - locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, - parent: angular.element($document[0].body), - fullscreen: true, - targetEvent: $event, - multiple: true, - onShowing: function(scope, element) { - onShowingCallback.onShowing(scope, element); - } - }); - } - function showError() { - toast.showError($translate.instant('edge.load-entity-error')); - } - } - - scope.checkTooltip = function($event) { - var el = $event.target; - var $el = angular.element(el); - if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){ - $el.attr('title', $el.text()); - } - } - - $compile(element.contents())(scope); - - scope.updateStatus = function(eventCreatedTime) { - if (scope.queueStartTs) { - var status; - if (eventCreatedTime < scope.queueStartTs) { - status = $translate.instant('edge.success'); - scope.isPending = false; - } else { - status = $translate.instant('edge.failed'); - scope.isPending = true; - } - return status; - } - } - } - - return { - restrict: "A", - replace: false, - link: linker, - scope: false - }; -} +/* + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* eslint-disable import/no-unresolved, import/default */ + +import eventErrorDialogTemplate from './event-content-dialog.tpl.html'; + +import eventRowLcEventTemplate from './event-row-lc-event.tpl.html'; +import eventRowStatsTemplate from './event-row-stats.tpl.html'; +import eventRowErrorTemplate from './event-row-error.tpl.html'; +import eventRowDebugRuleNodeTemplate from './event-row-debug-rulenode.tpl.html'; +import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; + +/* eslint-enable import/no-unresolved, import/default */ + +/*@ngInject*/ +export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, + types, utils, toast, entityService, ruleChainService) { + + var linker = function (scope, element, attrs) { + + var getTemplate = function(eventType) { + var template = ''; + switch(eventType) { + case types.eventType.lcEvent.value: + template = eventRowLcEventTemplate; + break; + case types.eventType.stats.value: + template = eventRowStatsTemplate; + break; + case types.eventType.error.value: + template = eventRowErrorTemplate; + break; + case types.debugEventType.debugRuleNode.value: + template = eventRowDebugRuleNodeTemplate; + break; + case types.debugEventType.debugRuleChain.value: + template = eventRowDebugRuleNodeTemplate; + break; + case types.eventType.edgeEvent.value: + template = eventRowEdgeEventTemplate; + break; + } + return $templateCache.get(template); + } + + scope.loadTemplate = function() { + element.html(getTemplate(attrs.eventType)); + $compile(element.contents())(scope); + } + + attrs.$observe('eventType', function() { + scope.loadTemplate(); + }); + + scope.types = types; + + scope.event = attrs.event; + + scope.showContent = function($event, content, title, contentType) { + var onShowingCallback = { + onShowing: function(){} + } + if (!contentType) { + contentType = null; + } + var sortedContent; + try { + sortedContent = angular.toJson(utils.sortObjectKeys(angular.fromJson(content))); + } + catch(err) { + sortedContent = content; + } + $mdDialog.show({ + controller: 'EventContentDialogController', + controllerAs: 'vm', + templateUrl: eventErrorDialogTemplate, + locals: {content: sortedContent, title: title, contentType: contentType, showingCallback: onShowingCallback}, + parent: angular.element($document[0].body), + fullscreen: true, + targetEvent: $event, + multiple: true, + onShowing: function(scope, element) { + onShowingCallback.onShowing(scope, element); + } + }); + } + + scope.showEdgeEntityContent = function($event, title, contentType) { + var onShowingCallback = { + onShowing: function(){} + } + if (!contentType) { + contentType = null; + } + var content = ''; + switch(scope.event.type) { + case types.edgeEventType.relation: + case types.edgeEventType.whiteLabeling: + case types.edgeEventType.loginWhiteLabeling: + case types.edgeEventType.customTranslation: + content = angular.toJson(scope.event.body); + showDialog(); + break; + case types.edgeEventType.ruleChainMetaData: + content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then( + function success(info) { + showDialog(); + return angular.toJson(info); + }, function fail() { + showError(); + }); + break; + default: + content = entityService.getEntity(scope.event.type, scope.event.entityId, {ignoreErrors: true}).then( + function success(info) { + showDialog(); + return angular.toJson(info); + }, function fail() { + showError(); + }); + break; + } + function showDialog() { + $mdDialog.show({ + controller: 'EventContentDialogController', + controllerAs: 'vm', + templateUrl: eventErrorDialogTemplate, + locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, + parent: angular.element($document[0].body), + fullscreen: true, + targetEvent: $event, + multiple: true, + onShowing: function(scope, element) { + onShowingCallback.onShowing(scope, element); + } + }); + } + function showError() { + toast.showError($translate.instant('edge.load-entity-error')); + } + } + + scope.checkEdgeEventType = function (edgeEventType) { + return !(edgeEventType === types.edgeEventType.widgetType || + edgeEventType === types.edgeEventType.adminSettings || + edgeEventType === types.edgeEventType.widgetsBundle ); + } + + scope.checkTooltip = function($event) { + var el = $event.target; + var $el = angular.element(el); + if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){ + $el.attr('title', $el.text()); + } + } + + $compile(element.contents())(scope); + + scope.updateStatus = function(eventCreatedTime) { + if (scope.queueStartTs) { + var status; + if (eventCreatedTime < scope.queueStartTs) { + status = $translate.instant('edge.success'); + scope.isPending = false; + } else { + status = $translate.instant('edge.failed'); + scope.isPending = true; + } + return status; + } + } + } + + return { + restrict: "A", + replace: false, + link: linker, + scope: false + }; +} diff --git a/ui/src/app/rulechain/add-rulechains-to-edge.controller.js b/ui/src/app/rulechain/add-rulechains-to-edge.controller.js index 236c44b091..df05c47eee 100644 --- a/ui/src/app/rulechain/add-rulechains-to-edge.controller.js +++ b/ui/src/app/rulechain/add-rulechains-to-edge.controller.js @@ -54,7 +54,7 @@ export default function AddRuleChainsToEdgeController(ruleChainService, $mdDialo vm.ruleChains.pending = true; ruleChainService.getEdgesRuleChains(vm.ruleChains.nextPageLink).then( function success(ruleChains) { - vm.ruleChains.data = ruleChains.data; + vm.ruleChains.data = vm.ruleChains.data.concat(ruleChains.data); vm.ruleChains.nextPageLink = ruleChains.nextPageLink; vm.ruleChains.hasNext = ruleChains.hasNext; if (vm.ruleChains.hasNext) { diff --git a/ui/src/app/rulechain/rulechain.routes.js b/ui/src/app/rulechain/rulechain.routes.js index 7489091665..faad077e79 100644 --- a/ui/src/app/rulechain/rulechain.routes.js +++ b/ui/src/app/rulechain/rulechain.routes.js @@ -191,62 +191,5 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider ncyBreadcrumb: { label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name }}", "translate": "false"}' } - }).state('home.edges.ruleChains', { - url: '/:edgeId/ruleChains', - params: {'topIndex': 0}, - module: 'private', - auth: ['TENANT_ADMIN'], - views: { - "content@home": { - templateUrl: ruleChainsTemplate, - controllerAs: 'vm', - controller: 'RuleChainsController' - } - }, - data: { - searchEnabled: true, - pageTitle: 'edge.rulechains', - ruleChainsType: 'edge' - }, - ncyBreadcrumb: { - label: '{"icon": "settings_ethernet", "label": "rulechain.edge-rulechains"}' - } - }).state('home.edges.ruleChains.ruleChain', { - url: '/:ruleChainId', - reloadOnSearch: false, - module: 'private', - auth: ['SYS_ADMIN', 'TENANT_ADMIN'], - views: { - "content@home": { - templateUrl: ruleChainTemplate, - controller: 'RuleChainController', - controllerAs: 'vm' - } - }, - resolve: { - ruleChain: - /*@ngInject*/ - function($stateParams, ruleChainService) { - return ruleChainService.getRuleChain($stateParams.ruleChainId); - }, - ruleChainMetaData: - /*@ngInject*/ - function($stateParams, ruleChainService) { - return ruleChainService.getRuleChainMetaData($stateParams.ruleChainId); - }, - ruleNodeComponents: - /*@ngInject*/ - function($stateParams, ruleChainService) { - return ruleChainService.getRuleNodeComponents(types.ruleChainType.edge); - } - }, - data: { - import: false, - searchEnabled: false, - pageTitle: 'edge.rulechain' - }, - ncyBreadcrumb: { - label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name }}", "translate": "false"}' - } }); } diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index fe19cad5ca..16ee29bd1a 100644 --- a/ui/src/app/rulechain/rulechains.controller.js +++ b/ui/src/app/rulechain/rulechains.controller.js @@ -397,7 +397,7 @@ export default function RuleChainsController(ruleChainService, userService, impo } var ruleChainParams = {ruleChainId: ruleChain.id.id}; if (vm.ruleChainsScope === 'edge') { - $state.go('home.edges.ruleChains.ruleChain', {...ruleChainParams, edgeId: vm.edge.id.id}); + $state.go('home.edges.ruleChains.ruleChain', Object.assign(ruleChainParams, edgeId = vm.edge.id.id)); } else if (vm.ruleChainsScope === 'edges') { $state.go('home.ruleChains.edge.ruleChain', ruleChainParams); } else { From 6aa5655e6fb0d81ccacaa1e6ac1e4ac720be93a0 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 18 Sep 2020 17:18:49 +0300 Subject: [PATCH 106/156] Fixes for upgrade functionality --- .../main/data/upgrade/2.6.0/schema_update.cql | 38 ++++++++- .../install/ThingsboardInstallService.java | 9 ++ .../service/edge/rpc/EdgeGrpcService.java | 3 + .../service/edge/rpc/EdgeGrpcSession.java | 84 ++++++++++--------- .../AbstractSqlTsDatabaseUpgradeService.java | 2 +- .../CassandraDatabaseUpgradeService.java | 36 ++++++-- .../CassandraTsDatabaseUpgradeService.java | 1 + .../service/install/DatabaseHelper.java | 1 + .../service/install/InstallScripts.java | 5 ++ .../install/PsqlTsDatabaseUpgradeService.java | 18 ++-- .../install/SqlDatabaseUpgradeService.java | 2 +- .../TimescaleTsDatabaseUpgradeService.java | 10 ++- .../install/cql/CassandraDbHelper.java | 4 + .../update/DefaultDataUpdateService.java | 26 +++++- .../server/dao/edge/CassandraEdgeDao.java | 6 +- .../server/dao/model/ModelConstants.java | 2 +- .../dao/rule/CassandraRuleChainDao.java | 4 - .../resources/cassandra/schema-entities.cql | 6 +- 18 files changed, 181 insertions(+), 76 deletions(-) diff --git a/application/src/main/data/upgrade/2.6.0/schema_update.cql b/application/src/main/data/upgrade/2.6.0/schema_update.cql index f85b309836..6ac8f404bd 100644 --- a/application/src/main/data/upgrade/2.6.0/schema_update.cql +++ b/application/src/main/data/upgrade/2.6.0/schema_update.cql @@ -14,6 +14,38 @@ -- limitations under the License. -- +DROP MATERIALIZED VIEW IF EXISTS thingsboard.rule_chain_by_tenant_and_search_text; + +DROP TABLE IF EXISTS thingsboard.rule_chain; + +CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( + id uuid, + tenant_id uuid, + name text, + type text, + search_text text, + first_rule_node_id uuid, + root boolean, + debug_mode boolean, + configuration text, + additional_info text, + PRIMARY KEY (id, tenant_id, type) +); + +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.rule_chain_by_tenant_and_search_text AS + SELECT * + from thingsboard.rule_chain + WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL AND type IS NOT NULL + PRIMARY KEY ( tenant_id, search_text, id, type ) + WITH CLUSTERING ORDER BY ( search_text ASC, id DESC ); + +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.rule_chain_by_tenant_by_type_and_search_text AS + SELECT * + from thingsboard.rule_chain + WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL AND type IS NOT NULL + PRIMARY KEY ( tenant_id, type, search_text, id ) + WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC ); + CREATE TABLE IF NOT EXISTS thingsboard.edge ( id timeuuid, tenant_id timeuuid, @@ -37,12 +69,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS PRIMARY KEY ( tenant_id, name, id, customer_id, type) WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_routing_key AS +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_routing_key AS SELECT * from thingsboard.edge WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND routing_key IS NOT NULL AND id IS NOT NULL - PRIMARY KEY ( tenant_id, routing_key, id, customer_id, type) - WITH CLUSTERING ORDER BY ( routing_key ASC, id DESC, customer_id DESC); + PRIMARY KEY ( routing_key, tenant_id, id, customer_id, type) + WITH CLUSTERING ORDER BY ( tenant_id DESC, id DESC, customer_id DESC); CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS SELECT * diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index 01ad8a29e9..c9f6b94922 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -152,6 +152,15 @@ public class ThingsboardInstallService { databaseTsUpgradeService.upgradeDatabase("2.5.4"); } + case "2.5.5": + log.info("Upgrading ThingsBoard from version 2.5.5 to 2.6.0 ..."); + if (databaseTsUpgradeService != null) { + databaseTsUpgradeService.upgradeDatabase("2.5.5"); + } + databaseEntitiesUpgradeService.upgradeDatabase("2.5.5"); + + dataUpdateService.updateData("2.5.5"); + log.info("Updating system data..."); systemDataLoaderService.deleteSystemWidgetBundle("charts"); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index 8e2990c75f..f6359275ea 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -150,6 +150,9 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i } } catch (Exception e) { log.warn("Failed to process messages handling!", e); + try { + Thread.sleep(1000); + } catch (InterruptedException ignore) {} } } }); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 375db62e80..4b76fb9731 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -252,52 +252,54 @@ public final class EdgeGrpcSession implements Closeable { } void processHandleMessages() throws ExecutionException, InterruptedException { - Long queueStartTs = getQueueStartTs().get(); - TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true); - TimePageData pageData; - UUID ifOffset = null; - boolean success = true; - do { - pageData = ctx.getEdgeNotificationService().findEdgeEvents(edge.getTenantId(), edge.getId(), pageLink); - if (isConnected() && !pageData.getData().isEmpty()) { - log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); - List downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData()); - log.trace("[{}] downlink msg(s) are going to be send.", downlinkMsgsPack.size()); - - latch = new CountDownLatch(downlinkMsgsPack.size()); - for (DownlinkMsg downlinkMsg : downlinkMsgsPack) { - sendResponseMsg(ResponseMsg.newBuilder() - .setDownlinkMsg(downlinkMsg) - .build()); - } + if (isConnected()) { + Long queueStartTs = getQueueStartTs().get(); + TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true); + TimePageData pageData; + UUID ifOffset = null; + boolean success = true; + do { + pageData = ctx.getEdgeNotificationService().findEdgeEvents(edge.getTenantId(), edge.getId(), pageLink); + if (isConnected() && !pageData.getData().isEmpty()) { + log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); + List downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData()); + log.trace("[{}] downlink msg(s) are going to be send.", downlinkMsgsPack.size()); + + latch = new CountDownLatch(downlinkMsgsPack.size()); + for (DownlinkMsg downlinkMsg : downlinkMsgsPack) { + sendResponseMsg(ResponseMsg.newBuilder() + .setDownlinkMsg(downlinkMsg) + .build()); + } - ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId(); + ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId(); - success = latch.await(10, TimeUnit.SECONDS); - if (!success) { - log.warn("Failed to deliver the batch: {}", downlinkMsgsPack); - } - } - if (isConnected() && (!success || pageData.hasNext())) { - try { - Thread.sleep(ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches()); - } catch (InterruptedException e) { - log.error("Error during sleep between batches", e); + success = latch.await(10, TimeUnit.SECONDS); + if (!success) { + log.warn("Failed to deliver the batch: {}", downlinkMsgsPack); + } } - if (success) { - pageLink = pageData.getNextPageLink(); + if (isConnected() && (!success || pageData.hasNext())) { + try { + Thread.sleep(ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches()); + } catch (InterruptedException e) { + log.error("Error during sleep between batches", e); + } + if (success) { + pageLink = pageData.getNextPageLink(); + } } - } - } while (isConnected() && (!success || pageData.hasNext())); + } while (isConnected() && (!success || pageData.hasNext())); - if (ifOffset != null) { - Long newStartTs = UUIDs.unixTimestamp(ifOffset); - updateQueueStartTs(newStartTs); - } - try { - Thread.sleep(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()); - } catch (InterruptedException e) { - log.error("Error during sleep", e); + if (ifOffset != null) { + Long newStartTs = UUIDs.unixTimestamp(ifOffset); + updateQueueStartTs(newStartTs); + } + try { + Thread.sleep(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()); + } catch (InterruptedException e) { + log.error("Error during sleep", e); + } } } diff --git a/application/src/main/java/org/thingsboard/server/service/install/AbstractSqlTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/AbstractSqlTsDatabaseUpgradeService.java index 5f084c7a9d..ae650592d2 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/AbstractSqlTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/AbstractSqlTsDatabaseUpgradeService.java @@ -50,7 +50,7 @@ public abstract class AbstractSqlTsDatabaseUpgradeService { @Autowired protected InstallScripts installScripts; - protected abstract void loadSql(Connection conn, String fileName); + protected abstract void loadSql(Connection conn, String version, String fileName); protected void loadFunctions(Path sqlFile, Connection conn) throws Exception { String sql = new String(Files.readAllBytes(sqlFile), StandardCharsets.UTF_8); diff --git a/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java index 29d698d0a4..7cd81d8832 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.util.NoSqlDao; import org.thingsboard.server.service.install.cql.CassandraDbHelper; @@ -44,6 +45,7 @@ import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_VIEWS import static org.thingsboard.server.service.install.DatabaseHelper.ID; import static org.thingsboard.server.service.install.DatabaseHelper.KEYS; import static org.thingsboard.server.service.install.DatabaseHelper.NAME; +import static org.thingsboard.server.service.install.DatabaseHelper.RULE_CHAIN; import static org.thingsboard.server.service.install.DatabaseHelper.SEARCH_TEXT; import static org.thingsboard.server.service.install.DatabaseHelper.START_TS; import static org.thingsboard.server.service.install.DatabaseHelper.TENANT_ID; @@ -306,17 +308,39 @@ public class CassandraDatabaseUpgradeService extends AbstractCassandraDatabaseUp } log.info("Schema updated."); break; - case "2.5.0": + case "2.5.5": + + log.info("Upgrading Cassandra DataBase from version {} to 2.6.0 ...", fromVersion); + + // Dump rule chains + + cluster.getSession(); + + ks = cluster.getCluster().getMetadata().getKeyspace(cluster.getKeyspaceName()); + + log.info("Dumping rule chains ..."); + Path ruleChainsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), RULE_CHAIN, + new String[]{ID, TENANT_ID, NAME, SEARCH_TEXT, "first_rule_node_id", "root", "debug_mode", CONFIGURATION, ADDITIONAL_INFO, TYPE}, + new String[]{"", "", "", "", "", "", "", "", "", RuleChainType.CORE.name()}, + "tb-rule-chains"); + log.info("Rule chains dumped."); + log.info("Updating schema ..."); schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.6.0", SCHEMA_UPDATE_CQL); loadCql(schemaUpdateFile); - - try { - cluster.getSession().execute("alter table rule_chain add type text"); - Thread.sleep(2500); - } catch (InvalidQueryException e) {} log.info("Schema updated."); + + // Restore rule chains + + log.info("Restoring rule chains ..."); + if (ruleChainsDump != null) { + CassandraDbHelper.loadCf(ks, cluster.getSession(), RULE_CHAIN, + new String[]{ID, TENANT_ID, NAME, SEARCH_TEXT, "first_rule_node_id", "root", "debug_mode", CONFIGURATION, ADDITIONAL_INFO, TYPE}, ruleChainsDump); + Files.deleteIfExists(ruleChainsDump); + } + log.info("Rule chains restored."); break; + default: throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion); } diff --git a/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java index 07b8522323..9be454fc9f 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java @@ -50,6 +50,7 @@ public class CassandraTsDatabaseUpgradeService extends AbstractCassandraDatabase break; case "2.5.0": case "2.5.4": + case "2.5.5": break; default: throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion); diff --git a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java index aea04bcf56..5c6b63debb 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java @@ -57,6 +57,7 @@ public class DatabaseHelper { public static final String DASHBOARD = "dashboard"; public static final String ENTITY_VIEWS = "entity_views"; public static final String ENTITY_VIEW = "entity_view"; + public static final String RULE_CHAIN = "rule_chain"; public static final String ID = "id"; public static final String TITLE = "title"; public static final String TYPE = "type"; diff --git a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java index ea36a61b48..27423259cd 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java +++ b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java @@ -115,6 +115,11 @@ public class InstallScripts { } } + public void createDefaultEdgeRuleChains(TenantId tenantId) { + Path tenantChainsDir = getTenantRuleChainsDir(); + loadRuleChainFromFile(tenantId, tenantChainsDir.resolve("edge_root_rule_chain.json")); + } + public void loadSystemWidgets() throws Exception { Path widgetBundlesDir = Paths.get(getDataDir(), JSON_DIR, SYSTEM_DIR, WIDGET_BUNDLES_DIR); try (DirectoryStream dirStream = Files.newDirectoryStream(widgetBundlesDir, path -> path.toString().endsWith(JSON_EXT))) { diff --git a/application/src/main/java/org/thingsboard/server/service/install/PsqlTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/PsqlTsDatabaseUpgradeService.java index 396f84664a..0bfa28e03a 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/PsqlTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/PsqlTsDatabaseUpgradeService.java @@ -94,7 +94,7 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe log.info("PostgreSQL version is valid!"); if (isOldSchema(conn, 2004003)) { log.info("Load upgrade functions ..."); - loadSql(conn, LOAD_FUNCTIONS_SQL); + loadSql(conn, "2.4.3", LOAD_FUNCTIONS_SQL); log.info("Updating timeseries schema ..."); executeQuery(conn, CALL_CREATE_PARTITION_TS_KV_TABLE); if (!partitionType.equals("INDEFINITE")) { @@ -179,9 +179,9 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe } log.info("Load TTL functions ..."); - loadSql(conn, LOAD_TTL_FUNCTIONS_SQL); + loadSql(conn, "2.4.3", LOAD_TTL_FUNCTIONS_SQL); log.info("Load Drop Partitions functions ..."); - loadSql(conn, LOAD_DROP_PARTITIONS_FUNCTIONS_SQL); + loadSql(conn, "2.4.3", LOAD_DROP_PARTITIONS_FUNCTIONS_SQL); executeQuery(conn, "UPDATE tb_schema_settings SET schema_version = 2005000"); @@ -198,7 +198,13 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe case "2.5.4": try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { log.info("Load Drop Partitions functions ..."); - loadSql(conn, LOAD_DROP_PARTITIONS_FUNCTIONS_SQL); + loadSql(conn, "2.4.3", LOAD_DROP_PARTITIONS_FUNCTIONS_SQL); + } + break; + case "2.5.5": + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { + log.info("Load TTL functions ..."); + loadSql(conn, "2.6.0", LOAD_TTL_FUNCTIONS_SQL); } break; default: @@ -236,8 +242,8 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe } @Override - protected void loadSql(Connection conn, String fileName) { - Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.4.3", fileName); + protected void loadSql(Connection conn, String version, String fileName) { + Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", version, fileName); try { loadFunctions(schemaUpdateFile, conn); log.info("Functions successfully loaded!"); diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java index eda9cf88cb..a0c1456e0f 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java @@ -233,7 +233,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService log.info("Schema updated."); } break; - case "2.5.0": + case "2.5.5": try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { log.info("Updating schema ..."); schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.6.0", SCHEMA_UPDATE_SQL); diff --git a/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java index a929a51fb5..e47d6d7083 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java @@ -89,7 +89,7 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr log.info("PostgreSQL version is valid!"); if (isOldSchema(conn, 2004003)) { log.info("Load upgrade functions ..."); - loadSql(conn, LOAD_FUNCTIONS_SQL); + loadSql(conn, "2.4.3", LOAD_FUNCTIONS_SQL); log.info("Updating timescale schema ..."); executeQuery(conn, CALL_CREATE_TS_KV_LATEST_TABLE); executeQuery(conn, CALL_CREATE_NEW_TENANT_TS_KV_TABLE); @@ -165,7 +165,7 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr } log.info("Load TTL functions ..."); - loadSql(conn, LOAD_TTL_FUNCTIONS_SQL); + loadSql(conn, "2.4.3", LOAD_TTL_FUNCTIONS_SQL); executeQuery(conn, "UPDATE tb_schema_settings SET schema_version = 2005000"); log.info("schema timescale updated!"); @@ -179,6 +179,8 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr break; case "2.5.4": break; + case "2.5.5": + break; default: throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); } @@ -200,8 +202,8 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr } @Override - protected void loadSql(Connection conn, String fileName) { - Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.4.3", fileName); + protected void loadSql(Connection conn, String version, String fileName) { + Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", version, fileName); try { loadFunctions(schemaUpdateFile, conn); log.info("Functions successfully loaded!"); diff --git a/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java b/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java index fb75a12dac..0e43a6bd5f 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java +++ b/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java @@ -157,6 +157,8 @@ public class CassandraDbHelper { str = new Float(row.getFloat(index)).toString(); } else if (type == DataType.timestamp()) { str = ""+row.getTimestamp(index).getTime(); + } else if (type == DataType.cboolean()) { + str = ""+ row.getBool(index); } else { str = row.getString(index); } @@ -205,6 +207,8 @@ public class CassandraDbHelper { boundStatement.setFloat(column, Float.valueOf(value)); } else if (type == DataType.timestamp()) { boundStatement.setTimestamp(column, new Date(Long.valueOf(value))); + } else if (type == DataType.cboolean()) { + boundStatement.setBool(column, Boolean.valueOf(value)); } else { boundStatement.setString(column, value); } diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java index 0d2401b0fd..77b356797c 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java @@ -19,9 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.SearchTextBased; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.rule.RuleChain; @@ -50,6 +48,10 @@ public class DefaultDataUpdateService implements DataUpdateService { log.info("Updating data from version 1.4.0 to 2.0.0 ..."); tenantsDefaultRuleChainUpdater.updateEntities(null); break; + case "2.5.5": + log.info("Updating data from version 2.5.5 to 2.6.0 ..."); + tenantsDefaultEdgeRuleChainUpdater.updateEntities(null); + break; default: throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); } @@ -76,4 +78,24 @@ public class DefaultDataUpdateService implements DataUpdateService { } }; + private PaginatedUpdater tenantsDefaultEdgeRuleChainUpdater = + new PaginatedUpdater() { + + @Override + protected TextPageData findEntities(String region, TextPageLink pageLink) { + return tenantService.findTenants(pageLink); + } + + @Override + protected void updateEntity(Tenant tenant) { + try { + RuleChain defaultEdgeRuleChain = ruleChainService.getDefaultRootEdgeRuleChain(tenant.getId()); + if (defaultEdgeRuleChain == null) { + installScripts.createDefaultEdgeRuleChains(tenant.getId()); + } + } catch (Exception e) { + log.error("Unable to update Tenant", e); + } + } + }; } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java index 3d77b5fa78..7705188132 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/CassandraEdgeDao.java @@ -27,7 +27,6 @@ import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.Edge; @@ -57,8 +56,8 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.in; import static com.datastax.driver.core.querybuilder.QueryBuilder.select; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_ROUTING_KEY_VIEW_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_NAME_VIEW_NAME; -import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_ROUTING_KEY_VIEW_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; @@ -203,9 +202,8 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao findByRoutingKey(UUID tenantId, String routingKey) { - Select select = select().from(EDGE_BY_TENANT_AND_ROUTING_KEY_VIEW_NAME); + Select select = select().from(EDGE_BY_ROUTING_KEY_VIEW_NAME); Select.Where query = select.where(); - query.and(eq(EDGE_TENANT_ID_PROPERTY, tenantId)); query.and(eq(EDGE_ROUTING_KEY_PROPERTY, routingKey)); return Optional.ofNullable(DaoUtil.getData(findOneByStatement(new TenantId(tenantId), query))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 98e7177d33..54a65077c5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -373,7 +373,7 @@ public class ModelConstants { public static final String EDGE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_customer_and_search_text"; public static final String EDGE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_customer_by_type_and_search_text"; public static final String EDGE_BY_TENANT_AND_NAME_VIEW_NAME = "edge_by_tenant_and_name"; - public static final String EDGE_BY_TENANT_AND_ROUTING_KEY_VIEW_NAME = "edge_by_tenant_and_routing_key"; + public static final String EDGE_BY_ROUTING_KEY_VIEW_NAME = "edge_by_routing_key"; public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key"; public static final String EDGE_SECRET_PROPERTY = "secret"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java index d636281c2a..9dfc869afd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java @@ -22,9 +22,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageLink; @@ -45,8 +43,6 @@ import java.util.List; import java.util.UUID; import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; -import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TENANT_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TYPE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.RULE_CHAIN_COLUMN_FAMILY_NAME; diff --git a/dao/src/main/resources/cassandra/schema-entities.cql b/dao/src/main/resources/cassandra/schema-entities.cql index 7375f7e9e7..a5518662ae 100644 --- a/dao/src/main/resources/cassandra/schema-entities.cql +++ b/dao/src/main/resources/cassandra/schema-entities.cql @@ -749,12 +749,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS PRIMARY KEY ( tenant_id, name, id, customer_id, type) WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_routing_key AS +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_routing_key AS SELECT * from thingsboard.edge WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND routing_key IS NOT NULL AND id IS NOT NULL - PRIMARY KEY ( tenant_id, routing_key, id, customer_id, type) - WITH CLUSTERING ORDER BY ( routing_key ASC, id DESC, customer_id DESC); + PRIMARY KEY ( routing_key, tenant_id, id, customer_id, type) + WITH CLUSTERING ORDER BY ( tenant_id DESC, id DESC, customer_id DESC); CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS SELECT * From b637d606a81ab81b690160c3a7936afd105e3b66 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 17:31:47 +0300 Subject: [PATCH 107/156] Code review and refactoring 3 --- ui/src/app/entity-view/entity-view.routes.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/src/app/entity-view/entity-view.routes.js b/ui/src/app/entity-view/entity-view.routes.js index c55add94fa..4da8c80500 100644 --- a/ui/src/app/entity-view/entity-view.routes.js +++ b/ui/src/app/entity-view/entity-view.routes.js @@ -68,5 +68,4 @@ export default function EntityViewRoutes($stateProvider, types) { label: '{"icon": "view_quilt", "label": "{{ vm.customerEntityViewsTitle }}", "translate": "false"}' } }); - } From 4a71e8e6a441d8b580712e3fe3dba2b1ed89ef68 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 18 Sep 2020 17:32:04 +0300 Subject: [PATCH 108/156] Rename edgeEventAction and edgeEventType to action and type --- .../server/controller/BaseController.java | 38 ++++----- .../edge/DefaultEdgeNotificationService.java | 82 +++++++++---------- .../service/edge/rpc/EdgeGrpcSession.java | 48 +++++------ .../edge/rpc/init/DefaultSyncEdgeService.java | 28 +++---- .../edge/rpc/processor/BaseProcessor.java | 18 ++-- common/queue/src/main/proto/queue.proto | 6 +- 6 files changed, 110 insertions(+), 110 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 6b43b83549..b0f0e0867f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -747,65 +747,65 @@ public abstract class BaseController { return null; } - protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, CustomerId customerId, ActionType edgeEventAction) { + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, CustomerId customerId, ActionType action) { if (!edgesSupportEnabled) { return; } try { - sendNotificationMsgToEdgeService(tenantId, edgeId, null, json.writeValueAsString(customerId), EdgeEventType.EDGE, edgeEventAction); + sendNotificationMsgToEdgeService(tenantId, edgeId, null, json.writeValueAsString(customerId), EdgeEventType.EDGE, action); } catch (Exception e) { log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); } } - protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, CustomerId customerId, ActionType edgeEventAction) { + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, CustomerId customerId, ActionType action) { if (!edgesSupportEnabled) { return; } - EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); + EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); try { - if (edgeEventType != null) { - sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), edgeEventType, edgeEventAction); + if (type != null) { + sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), type, action); } } catch (Exception e) { log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); } } - protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) { + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType action) { if (!edgesSupportEnabled) { return; } try { if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && !relation.getTo().getEntityType().equals(EntityType.EDGE)) { - sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction); + sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), EdgeEventType.RELATION, action); } } catch (Exception e) { log.warn("Failed to push relation to core: {}", relation, e); } } - protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) { - sendNotificationMsgToEdgeService(tenantId, null, entityId, edgeEventAction); + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType action) { + sendNotificationMsgToEdgeService(tenantId, null, entityId, action); } - protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, ActionType edgeEventAction) { + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, ActionType action) { if (!edgesSupportEnabled) { return; } - EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); - if (edgeEventType != null) { - sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, edgeEventType, edgeEventAction); + EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); + if (type != null) { + sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, type, action); } } - private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String entityBody, EdgeEventType edgeEventType, ActionType edgeEventAction) { + private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, ActionType action) { TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder(); builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); - builder.setEdgeEventType(edgeEventType.name()); - builder.setEdgeEventAction(edgeEventAction.name()); + builder.setType(type.name()); + builder.setAction(action.name()); if (entityId != null) { builder.setEntityIdMSB(entityId.getId().getMostSignificantBits()); builder.setEntityIdLSB(entityId.getId().getLeastSignificantBits()); @@ -815,8 +815,8 @@ public abstract class BaseController { builder.setEdgeIdMSB(edgeId.getId().getMostSignificantBits()); builder.setEdgeIdLSB(edgeId.getId().getLeastSignificantBits()); } - if (entityBody != null) { - builder.setEntityBody(entityBody); + if (body != null) { + builder.setBody(body); } TransportProtos.EdgeNotificationMsgProto msg = builder.build(); tbClusterService.pushMsgToCore(tenantId, entityId != null ? entityId : tenantId, diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index a014ec3d30..e9ac598cfa 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -122,22 +122,22 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { private void saveEdgeEvent(TenantId tenantId, EdgeId edgeId, - EdgeEventType edgeEventType, - ActionType edgeEventAction, + EdgeEventType type, + ActionType action, EntityId entityId, - JsonNode entityBody) { - log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], edgeEventType [{}], edgeEventAction[{}], entityId [{}], entityBody [{}]", - tenantId, edgeId, edgeEventType, edgeEventAction, entityId, entityBody); + JsonNode body) { + log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], type [{}], action[{}], entityId [{}], body [{}]", + tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setEdgeId(edgeId); edgeEvent.setTenantId(tenantId); - edgeEvent.setType(edgeEventType); - edgeEvent.setAction(edgeEventAction.name()); + edgeEvent.setType(type); + edgeEvent.setAction(action.name()); if (entityId != null) { edgeEvent.setEntityId(entityId.getId()); } - edgeEvent.setBody(entityBody); + edgeEvent.setBody(body); edgeEventService.saveAsync(edgeEvent); } @@ -145,8 +145,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) { try { TenantId tenantId = new TenantId(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB())); - EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); - switch (edgeEventType) { + EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); + switch (type) { case EDGE: processEdge(tenantId, edgeNotificationMsg); break; @@ -172,7 +172,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { processRelation(tenantId, edgeNotificationMsg); break; default: - log.debug("Edge event type [{}] is not designed to be pushed to edge", edgeEventType); + log.debug("Edge event type [{}] is not designed to be pushed to edge", type); } } catch (Exception e) { callback.onFailure(e); @@ -184,12 +184,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { private void processEdge(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { try { - ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); + ActionType actionType = ActionType.valueOf(edgeNotificationMsg.getAction()); EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); ListenableFuture edgeFuture; - switch (edgeEventActionType) { + switch (actionType) { case ASSIGNED_TO_CUSTOMER: - CustomerId customerId = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); + CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); Futures.addCallback(edgeFuture, new FutureCallback() { @Override @@ -213,7 +213,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { }, dbCallbackExecutorService); break; case UNASSIGNED_FROM_CUSTOMER: - CustomerId customerIdToDelete = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); + CustomerId customerIdToDelete = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); Futures.addCallback(edgeFuture, new FutureCallback() { @Override @@ -236,17 +236,17 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } private void processWidgetBundleOrWidgetType(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { - ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); - EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); - EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); - switch (edgeEventActionType) { + ActionType actionType = ActionType.valueOf(edgeNotificationMsg.getAction()); + EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); + EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); + switch (actionType) { case ADDED: case UPDATED: case DELETED: TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { for (Edge edge : edgesByTenantId.getData()) { - saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); } } break; @@ -254,20 +254,20 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } private void processCustomer(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { - ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); - EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); - EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); + ActionType actionType = ActionType.valueOf(edgeNotificationMsg.getAction()); + EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); + EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { for (Edge edge : edgesByTenantId.getData()) { - switch (edgeEventActionType) { + switch (actionType) { case UPDATED: if (!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(entityId)) { - saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); } break; case DELETED: - saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); break; } } @@ -275,12 +275,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { - ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); - EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); - EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, + ActionType actionType = ActionType.valueOf(edgeNotificationMsg.getAction()); + EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); + EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); ListenableFuture> edgeIdsFuture; - switch (edgeEventActionType) { + switch (actionType) { case ADDED: // used only for USER entity case UPDATED: case CREDENTIALS_UPDATED: @@ -290,7 +290,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { public void onSuccess(@Nullable List edgeIds) { if (edgeIds != null && !edgeIds.isEmpty()) { for (EdgeId edgeId : edgeIds) { - saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); } } } @@ -309,14 +309,14 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { if (edgeIds != null && !edgeIds.isEmpty()) { for (EdgeId edgeId : edgeIds) { try { - CustomerId customerId = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class); + CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); ListenableFuture future = edgeService.findEdgeByIdAsync(tenantId, edgeId); Futures.addCallback(future, new FutureCallback() { @Override public void onSuccess(@Nullable Edge edge) { if (edge != null && edge.getCustomerId() != null && !edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(customerId)) { - saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); + saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); } } @Override @@ -341,15 +341,15 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { TextPageData edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { for (Edge edge : edgesByTenantId.getData()) { - saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null); + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); } } break; case ASSIGNED_TO_EDGE: case UNASSIGNED_FROM_EDGE: EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); - saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); - if (edgeEventType.equals(EdgeEventType.RULE_CHAIN)) { + saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); + if (type.equals(EdgeEventType.RULE_CHAIN)) { updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId); } break; @@ -395,8 +395,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { ListenableFuture alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId); Futures.transform(alarmFuture, alarm -> { if (alarm != null) { - EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType()); - if (edgeEventType != null) { + EdgeEventType type = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType()); + if (type != null) { ListenableFuture> relatedEdgeIdsByEntityIdFuture = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator()); Futures.transform(relatedEdgeIdsByEntityIdFuture, relatedEdgeIdsByEntityId -> { if (relatedEdgeIdsByEntityId != null) { @@ -404,7 +404,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, - ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()), + ActionType.valueOf(edgeNotificationMsg.getAction()), alarmId, null); } @@ -418,7 +418,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { } private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException { - EntityRelation relation = mapper.readValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class); + EntityRelation relation = mapper.readValue(edgeNotificationMsg.getBody(), EntityRelation.class); if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && !relation.getTo().getEntityType().equals(EntityType.EDGE)) { List>> futures = new ArrayList<>(); @@ -439,7 +439,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { saveEdgeEvent(tenantId, edgeId, EdgeEventType.RELATION, - ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()), + ActionType.valueOf(edgeNotificationMsg.getAction()), null, mapper.valueToTree(relation)); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 4b76fb9731..d56f2b871b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -309,8 +309,8 @@ public final class EdgeGrpcSession implements Closeable { log.trace("Processing edge event [{}]", edgeEvent); try { DownlinkMsg downlinkMsg = null; - ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getAction()); - switch (edgeEventAction) { + ActionType action = ActionType.valueOf(edgeEvent.getAction()); + switch (action) { case UPDATED: case ADDED: case DELETED: @@ -323,7 +323,7 @@ public final class EdgeGrpcSession implements Closeable { case RELATION_DELETED: case ASSIGNED_TO_CUSTOMER: case UNASSIGNED_FROM_CUSTOMER: - downlinkMsg = processEntityMessage(edgeEvent, edgeEventAction); + downlinkMsg = processEntityMessage(edgeEvent, action); break; case ATTRIBUTES_UPDATED: case ATTRIBUTES_DELETED: @@ -444,37 +444,37 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private DownlinkMsg processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) { + private DownlinkMsg processEntityMessage(EdgeEvent edgeEvent, ActionType action) { UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getAction())); - log.trace("Executing processEntityMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType); + log.trace("Executing processEntityMessage, edgeEvent [{}], action [{}], msgType [{}]", edgeEvent, action, msgType); switch (edgeEvent.getType()) { case EDGE: // TODO: voba - add edge update logic return null; case DEVICE: - return processDevice(edgeEvent, msgType, edgeEventAction); + return processDevice(edgeEvent, msgType, action); case ASSET: - return processAsset(edgeEvent, msgType, edgeEventAction); + return processAsset(edgeEvent, msgType, action); case ENTITY_VIEW: - return processEntityView(edgeEvent, msgType, edgeEventAction); + return processEntityView(edgeEvent, msgType, action); case DASHBOARD: - return processDashboard(edgeEvent, msgType, edgeEventAction); + return processDashboard(edgeEvent, msgType, action); case CUSTOMER: - return processCustomer(edgeEvent, msgType, edgeEventAction); + return processCustomer(edgeEvent, msgType, action); case RULE_CHAIN: - return processRuleChain(edgeEvent, msgType, edgeEventAction); + return processRuleChain(edgeEvent, msgType, action); case RULE_CHAIN_METADATA: return processRuleChainMetadata(edgeEvent, msgType); case ALARM: return processAlarm(edgeEvent, msgType); case USER: - return processUser(edgeEvent, msgType, edgeEventAction); + return processUser(edgeEvent, msgType, action); case RELATION: return processRelation(edgeEvent, msgType); case WIDGETS_BUNDLE: - return processWidgetsBundle(edgeEvent, msgType, edgeEventAction); + return processWidgetsBundle(edgeEvent, msgType, action); case WIDGET_TYPE: - return processWidgetType(edgeEvent, msgType, edgeEventAction); + return processWidgetType(edgeEvent, msgType, action); case ADMIN_SETTINGS: return processAdminSettings(edgeEvent); default: @@ -524,10 +524,10 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private DownlinkMsg processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType action) { AssetId assetId = new AssetId(edgeEvent.getEntityId()); DownlinkMsg downlinkMsg = null; - switch (edgeEventAction) { + switch (action) { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: @@ -555,10 +555,10 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private DownlinkMsg processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType action) { EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId()); DownlinkMsg downlinkMsg = null; - switch (edgeEventAction) { + switch (action) { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: @@ -586,10 +586,10 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private DownlinkMsg processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType action) { DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId()); DownlinkMsg downlinkMsg = null; - switch (edgeEventAction) { + switch (action) { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: @@ -620,10 +620,10 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private DownlinkMsg processCustomer(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processCustomer(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType action) { CustomerId customerId = new CustomerId(edgeEvent.getEntityId()); DownlinkMsg downlinkMsg = null; - switch (edgeEventAction) { + switch (action) { case ADDED: case UPDATED: Customer customer = ctx.getCustomerService().findCustomerById(edgeEvent.getTenantId(), customerId); @@ -646,10 +646,10 @@ public final class EdgeGrpcSession implements Closeable { return downlinkMsg; } - private DownlinkMsg processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) { + private DownlinkMsg processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType action) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); DownlinkMsg downlinkMsg = null; - switch (edgeEventAction) { + switch (action) { case ADDED: case UPDATED: case ASSIGNED_TO_EDGE: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java index 2195d15236..0c9b29a386 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java @@ -412,8 +412,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { EntityId entityId = EntityIdFactory.getByTypeAndUuid( EntityType.valueOf(attributesRequestMsg.getEntityType()), new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB())); - final EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(entityId.getEntityType()); - if (edgeEventType != null) { + final EdgeEventType type = getEdgeQueueTypeByEntityType(entityId.getEntityType()); + if (type != null) { SettableFuture futureToSet = SettableFuture.create(); ListenableFuture> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); Futures.addCallback(ssAttrFuture, new FutureCallback>() { @@ -436,14 +436,14 @@ public class DefaultSyncEdgeService implements SyncEdgeService { } entityData.put("kv", attributes); entityData.put("scope", DataConstants.SERVER_SCOPE); - JsonNode entityBody = mapper.valueToTree(entityData); - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody); + JsonNode body = mapper.valueToTree(entityData); + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, body); saveEdgeEvent(edge.getTenantId(), edge.getId(), - edgeEventType, + type, ActionType.ATTRIBUTES_UPDATED, entityId, - entityBody); + body); } catch (Exception e) { log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); @@ -572,22 +572,22 @@ public class DefaultSyncEdgeService implements SyncEdgeService { private ListenableFuture saveEdgeEvent(TenantId tenantId, EdgeId edgeId, - EdgeEventType edgeEventType, - ActionType edgeEventAction, + EdgeEventType type, + ActionType action, EntityId entityId, - JsonNode entityBody) { - log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], edgeEventType [{}], edgeEventAction[{}], entityId [{}], entityBody [{}]", - tenantId, edgeId, edgeEventType, edgeEventAction, entityId, entityBody); + JsonNode body) { + log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], type [{}], action[{}], entityId [{}], body [{}]", + tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setTenantId(tenantId); edgeEvent.setEdgeId(edgeId); - edgeEvent.setType(edgeEventType); - edgeEvent.setAction(edgeEventAction.name()); + edgeEvent.setType(type); + edgeEvent.setAction(action.name()); if (entityId != null) { edgeEvent.setEntityId(entityId.getId()); } - edgeEvent.setBody(entityBody); + edgeEvent.setBody(body); return edgeEventService.saveAsync(edgeEvent); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java index 6809501a0e..576c8ba667 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseProcessor.java @@ -91,23 +91,23 @@ public abstract class BaseProcessor { protected ListenableFuture saveEdgeEvent(TenantId tenantId, EdgeId edgeId, - EdgeEventType edgeEventType, - ActionType edgeEventAction, + EdgeEventType type, + ActionType action, EntityId entityId, - JsonNode entityBody) { - log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], edgeEventType[{}], " + - "edgeEventAction [{}], entityId [{}], entityBody [{}]", - tenantId, edgeId, edgeEventType, edgeEventAction, entityId, entityBody); + JsonNode body) { + log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], type[{}], " + + "action [{}], entityId [{}], body [{}]", + tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = new EdgeEvent(); edgeEvent.setTenantId(tenantId); edgeEvent.setEdgeId(edgeId); - edgeEvent.setType(edgeEventType); - edgeEvent.setAction(edgeEventAction.name()); + edgeEvent.setType(type); + edgeEvent.setAction(action.name()); if (entityId != null) { edgeEvent.setEntityId(entityId.getId()); } - edgeEvent.setBody(entityBody); + edgeEvent.setBody(body); return edgeEventService.saveAsync(edgeEvent); } } diff --git a/common/queue/src/main/proto/queue.proto b/common/queue/src/main/proto/queue.proto index c32a72630d..b18907dd04 100644 --- a/common/queue/src/main/proto/queue.proto +++ b/common/queue/src/main/proto/queue.proto @@ -357,12 +357,12 @@ message EdgeNotificationMsgProto { int64 tenantIdLSB = 2; int64 edgeIdMSB = 3; int64 edgeIdLSB = 4; - string edgeEventType = 5; - string edgeEventAction = 6; + string type = 5; + string action = 6; int64 entityIdMSB = 7; int64 entityIdLSB = 8; string entityType = 9; - string entityBody = 10; + string body = 10; PostTelemetryMsg postTelemetryMsg = 11; PostAttributeMsg postAttributesMsg = 12; } From 1c5505396f7c8725012b15642fec8f88061ef81e Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 17:33:14 +0300 Subject: [PATCH 109/156] Code review and refactoring 4 --- ui/src/app/rulechain/rulechain.directive.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/app/rulechain/rulechain.directive.js b/ui/src/app/rulechain/rulechain.directive.js index a4951c2f8b..b9cb20d0fb 100644 --- a/ui/src/app/rulechain/rulechain.directive.js +++ b/ui/src/app/rulechain/rulechain.directive.js @@ -23,6 +23,7 @@ import ruleChainFieldsetTemplate from './rulechain-fieldset.tpl.html'; export default function RuleChainDirective($compile, $templateCache, $mdDialog, $document, $q, $translate, types, toast) { var linker = function (scope, element) { var template = $templateCache.get(ruleChainFieldsetTemplate); + element.html(template); scope.onRuleChainIdCopied = function() { From 45d1c0e223ebabeb36d63d2c867f1cfce9de2dba Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:09:17 +0300 Subject: [PATCH 110/156] types refactored --- ui/src/app/common/types.constant.js | 16 +++------------- ui/src/app/rulechain/rulechain.directive.js | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 680d295687..7654b5d249 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -393,15 +393,7 @@ export default angular.module('thingsboard.types', []) edge: "EDGE", user: "USER", customer: "CUSTOMER", - relation: "RELATION", - entityGroup: "ENTITY_GROUP", - schedulerEvent: "SCHEDULER_EVENT", - whiteLabeling: "WHITE_LABELING", - loginWhiteLabeling: "LOGIN_WHITE_LABELING", - customTranslation: "CUSTOM_TRANSLATION", - widgetsBundle: "WIDGETS_BUNDLE", - widgetType: "WIDGET_TYPE", - adminSettings: "ADMIN_SETTINGS" + relation: "RELATION" }, edgeEventAction: { updated: "UPDATED", @@ -794,10 +786,8 @@ export default angular.module('thingsboard.types', []) clientSide: false } }, - ruleChainType: { - core: "CORE", - edge: "EDGE" - }, + coreRuleChainType: "CORE", + edgeRuleChainType: "EDGE", ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], ruleChainNodeComponent: { type: 'RULE_CHAIN', diff --git a/ui/src/app/rulechain/rulechain.directive.js b/ui/src/app/rulechain/rulechain.directive.js index b9cb20d0fb..105c888063 100644 --- a/ui/src/app/rulechain/rulechain.directive.js +++ b/ui/src/app/rulechain/rulechain.directive.js @@ -23,7 +23,7 @@ import ruleChainFieldsetTemplate from './rulechain-fieldset.tpl.html'; export default function RuleChainDirective($compile, $templateCache, $mdDialog, $document, $q, $translate, types, toast) { var linker = function (scope, element) { var template = $templateCache.get(ruleChainFieldsetTemplate); - + element.html(template); scope.onRuleChainIdCopied = function() { From ed829a30f378535280090fd2e8267c4b05308159 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:10:22 +0300 Subject: [PATCH 111/156] types refactored --- ui/src/app/common/types.constant.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 7654b5d249..7f98830a2e 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -223,12 +223,6 @@ export default angular.module('thingsboard.types', []) "LOCKOUT": { name: "audit-log.type-lockout" }, - "ASSIGNED_FROM_TENANT": { - name: "audit-log.type-assigned-from-tenant" - }, - "ASSIGNED_TO_TENANT": { - name: "audit-log.type-assigned-to-tenant" - }, "ASSIGNED_TO_EDGE": { name: "audit-log.type-assigned-to-edge" }, From 5412a8109c672c9256354cfc94c67bb03c475113 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:11:48 +0300 Subject: [PATCH 112/156] types refactored --- ui/src/app/common/types.constant.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 7f98830a2e..b6fa1e3ee7 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -1047,4 +1047,4 @@ export default angular.module('thingsboard.types', []) customTranslationsPrefix: "custom." } } - ).name; + ).name; \ No newline at end of file From 8aa5055c702515cdc1d8029e159eb2f3834988f9 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:14:35 +0300 Subject: [PATCH 113/156] types refactored --- ui/src/app/common/types.constant.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index b6fa1e3ee7..7654b5d249 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -223,6 +223,12 @@ export default angular.module('thingsboard.types', []) "LOCKOUT": { name: "audit-log.type-lockout" }, + "ASSIGNED_FROM_TENANT": { + name: "audit-log.type-assigned-from-tenant" + }, + "ASSIGNED_TO_TENANT": { + name: "audit-log.type-assigned-to-tenant" + }, "ASSIGNED_TO_EDGE": { name: "audit-log.type-assigned-to-edge" }, @@ -1047,4 +1053,4 @@ export default angular.module('thingsboard.types', []) customTranslationsPrefix: "custom." } } - ).name; \ No newline at end of file + ).name; From bcf635950766f6276837eb88e20f80218c97f63c Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:29:48 +0300 Subject: [PATCH 114/156] Types reverted --- ui/src/app/common/types.constant.js | 2112 +++++++++++++-------------- 1 file changed, 1056 insertions(+), 1056 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 7654b5d249..969042bbd4 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -1,1056 +1,1056 @@ -/* - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export default angular.module('thingsboard.types', []) - .constant('types', - { - serverErrorCode: { - general: 2, - authentication: 10, - jwtTokenExpired: 11, - credentialsExpired: 15, - permissionDenied: 20, - invalidArguments: 30, - badRequestParams: 31, - itemNotFound: 32, - tooManyRequests: 33, - tooManyUpdates: 34 - }, - entryPoints: { - login: "/api/auth/login", - tokenRefresh: "/api/auth/token", - nonTokenBased: "/api/noauth" - }, - id: { - nullUid: "13814000-1dd2-11b2-8080-808080808080", - }, - aggregation: { - min: { - value: "MIN", - name: "aggregation.min" - }, - max: { - value: "MAX", - name: "aggregation.max" - }, - avg: { - value: "AVG", - name: "aggregation.avg" - }, - sum: { - value: "SUM", - name: "aggregation.sum" - }, - count: { - value: "COUNT", - name: "aggregation.count" - }, - none: { - value: "NONE", - name: "aggregation.none" - } - }, - alarmFields: { - createdTime: { - keyName: 'createdTime', - value: "createdTime", - name: "alarm.created-time", - time: true - }, - startTime: { - keyName: 'startTime', - value: "startTs", - name: "alarm.start-time", - time: true - }, - endTime: { - keyName: 'endTime', - value: "endTs", - name: "alarm.end-time", - time: true - }, - ackTime: { - keyName: 'ackTime', - value: "ackTs", - name: "alarm.ack-time", - time: true - }, - clearTime: { - keyName: 'clearTime', - value: "clearTs", - name: "alarm.clear-time", - time: true - }, - originator: { - keyName: 'originator', - value: "originatorName", - name: "alarm.originator" - }, - originatorType: { - keyName: 'originatorType', - value: "originator.entityType", - name: "alarm.originator-type" - }, - type: { - keyName: 'type', - value: "type", - name: "alarm.type" - }, - severity: { - keyName: 'severity', - value: "severity", - name: "alarm.severity" - }, - status: { - keyName: 'status', - value: "status", - name: "alarm.status" - } - }, - alarmStatus: { - activeUnack: "ACTIVE_UNACK", - activeAck: "ACTIVE_ACK", - clearedUnack: "CLEARED_UNACK", - clearedAck: "CLEARED_ACK" - }, - alarmSearchStatus: { - any: "ANY", - active: "ACTIVE", - cleared: "CLEARED", - ack: "ACK", - unack: "UNACK" - }, - alarmSeverity: { - "CRITICAL": { - name: "alarm.severity-critical", - class: "tb-critical", - color: "red" - }, - "MAJOR": { - name: "alarm.severity-major", - class: "tb-major", - color: "orange" - }, - "MINOR": { - name: "alarm.severity-minor", - class: "tb-minor", - color: "#ffca3d" - }, - "WARNING": { - name: "alarm.severity-warning", - class: "tb-warning", - color: "#abab00" - }, - "INDETERMINATE": { - name: "alarm.severity-indeterminate", - class: "tb-indeterminate", - color: "green" - } - }, - auditLogActionType: { - "ADDED": { - name: "audit-log.type-added" - }, - "DELETED": { - name: "audit-log.type-deleted" - }, - "UPDATED": { - name: "audit-log.type-updated" - }, - "ATTRIBUTES_UPDATED": { - name: "audit-log.type-attributes-updated" - }, - "ATTRIBUTES_DELETED": { - name: "audit-log.type-attributes-deleted" - }, - "RPC_CALL": { - name: "audit-log.type-rpc-call" - }, - "CREDENTIALS_UPDATED": { - name: "audit-log.type-credentials-updated" - }, - "ASSIGNED_TO_CUSTOMER": { - name: "audit-log.type-assigned-to-customer" - }, - "UNASSIGNED_FROM_CUSTOMER": { - name: "audit-log.type-unassigned-from-customer" - }, - "ACTIVATED": { - name: "audit-log.type-activated" - }, - "SUSPENDED": { - name: "audit-log.type-suspended" - }, - "CREDENTIALS_READ": { - name: "audit-log.type-credentials-read" - }, - "ATTRIBUTES_READ": { - name: "audit-log.type-attributes-read" - }, - "RELATION_ADD_OR_UPDATE": { - name: "audit-log.type-relation-add-or-update" - }, - "RELATION_DELETED": { - name: "audit-log.type-relation-delete" - }, - "RELATIONS_DELETED": { - name: "audit-log.type-relations-delete" - }, - "ALARM_ACK": { - name: "audit-log.type-alarm-ack" - }, - "ALARM_CLEAR": { - name: "audit-log.type-alarm-clear" - }, - "LOGIN": { - name: "audit-log.type-login" - }, - "LOGOUT": { - name: "audit-log.type-logout" - }, - "LOCKOUT": { - name: "audit-log.type-lockout" - }, - "ASSIGNED_FROM_TENANT": { - name: "audit-log.type-assigned-from-tenant" - }, - "ASSIGNED_TO_TENANT": { - name: "audit-log.type-assigned-to-tenant" - }, - "ASSIGNED_TO_EDGE": { - name: "audit-log.type-assigned-to-edge" - }, - "UNASSIGNED_FROM_EDGE": { - name: "audit-log.type-unassigned-from-edge" - } - }, - auditLogActionStatus: { - "SUCCESS": { - value: "SUCCESS", - name: "audit-log.status-success" - }, - "FAILURE": { - value: "FAILURE", - name: "audit-log.status-failure" - } - }, - auditLogMode: { - tenant: "tenant", - entity: "entity", - user: "user", - customer: "customer" - }, - aliasFilterType: { - singleEntity: { - value: 'singleEntity', - name: 'alias.filter-type-single-entity' - }, - entityList: { - value: 'entityList', - name: 'alias.filter-type-entity-list' - }, - entityName: { - value: 'entityName', - name: 'alias.filter-type-entity-name' - }, - stateEntity: { - value: 'stateEntity', - name: 'alias.filter-type-state-entity' - }, - assetType: { - value: 'assetType', - name: 'alias.filter-type-asset-type' - }, - deviceType: { - value: 'deviceType', - name: 'alias.filter-type-device-type' - }, - entityViewType: { - value: 'entityViewType', - name: 'alias.filter-type-entity-view-type' - }, - edgeType: { - value: 'edgeType', - name: 'alias.filter-type-edge-type' - }, - relationsQuery: { - value: 'relationsQuery', - name: 'alias.filter-type-relations-query' - }, - assetSearchQuery: { - value: 'assetSearchQuery', - name: 'alias.filter-type-asset-search-query' - }, - deviceSearchQuery: { - value: 'deviceSearchQuery', - name: 'alias.filter-type-device-search-query' - }, - entityViewSearchQuery: { - value: 'entityViewSearchQuery', - name: 'alias.filter-type-entity-view-search-query' - }, - edgeSearchQuery: { - value: 'edgeSearchQuery', - name: 'alias.filter-type-edge-search-query' - } - }, - direction: { - column: { - value: "column", - name: "direction.column" - }, - row: { - value: "row", - name: "direction.row" - } - }, - position: { - top: { - value: "top", - name: "position.top" - }, - bottom: { - value: "bottom", - name: "position.bottom" - }, - left: { - value: "left", - name: "position.left" - }, - right: { - value: "right", - name: "position.right" - } - }, - datasourceType: { - function: "function", - entity: "entity" - }, - dataKeyType: { - timeseries: "timeseries", - attribute: "attribute", - function: "function", - alarm: "alarm", - entityField: "entityField" - }, - contentType: { - "JSON": { - value: "JSON", - name: "content-type.json", - code: "json" - }, - "TEXT": { - value: "TEXT", - name: "content-type.text", - code: "text" - }, - "BINARY": { - value: "BINARY", - name: "content-type.binary", - code: "text" - } - }, - componentType: { - enrichment: "ENRICHMENT", - filter: "FILTER", - transformation: "TRANSFORMATION", - action: "ACTION", - external: "EXTERNAL" - }, - entityType: { - device: "DEVICE", - asset: "ASSET", - tenant: "TENANT", - customer: "CUSTOMER", - user: "USER", - dashboard: "DASHBOARD", - alarm: "ALARM", - rulechain: "RULE_CHAIN", - rulenode: "RULE_NODE", - entityView: "ENTITY_VIEW", - edge: "EDGE" - }, - edgeEventType:{ - dashboard: "DASHBOARD", - asset: "ASSET", - device: "DEVICE", - entityView: "ENTITY_VIEW", - alarm: "ALARM", - rulechain: "RULE_CHAIN", - ruleChainMetaData: "RULE_CHAIN_METADATA", - edge: "EDGE", - user: "USER", - customer: "CUSTOMER", - relation: "RELATION" - }, - edgeEventAction: { - updated: "UPDATED", - added: "ADDED", - assignedToEdge: "ASSIGNED_TO_EDGE", - deleted: "DELETED", - unassignedFromEdge: "UNASSIGNED_FROM_EDGE", - alarmAck: "ALARM_ACK", - alarmClear: "ALARM_CLEAR", - credentialsUpdated: "CREDENTIALS_UPDATED", - attributesUpdated: "ATTRIBUTES_UPDATED", - attributesDeleted: "ATTRIBUTES_DELETED", - timeseriesUpdated: "TIMESERIES_UPDATED" - }, - edgeAttributeKeys: { - active: "active", - lastConnectTime: "lastConnectTime", - lastDisconnectTime: "lastDisconnectTime", - queueStartTs: "queueStartTs" - }, - importEntityColumnType: { - name: { - name: 'import.column-type.name', - value: 'name' - }, - type: { - name: 'import.column-type.type', - value: 'type' - }, - label: { - name: 'import.column-type.label', - value: 'label' - }, - clientAttribute: { - name: 'import.column-type.client-attribute', - value: 'CLIENT_ATTRIBUTE' - }, - sharedAttribute: { - name: 'import.column-type.shared-attribute', - value: 'SHARED_ATTRIBUTE' - }, - serverAttribute: { - name: 'import.column-type.server-attribute', - value: 'SERVER_ATTRIBUTE' - }, - timeseries: { - name: 'import.column-type.timeseries', - value: 'TIMESERIES' - }, - entityField: { - name: 'import.column-type.entity-field', - value: 'ENTITY_FIELD' - }, - accessToken: { - name: 'import.column-type.access-token', - value: 'ACCESS_TOKEN' - }, - isGateway: { - name: 'import.column-type.isgateway', - value: 'gateway' - }, - description: { - name: 'import.column-type.description', - value: 'description' - } - }, - aliasEntityType: { - current_customer: "CURRENT_CUSTOMER", - current_tenant: "CURRENT_TENANT" - }, - entityTypeTranslations: { - "DEVICE": { - type: 'entity.type-device', - typePlural: 'entity.type-devices', - list: 'entity.list-of-devices', - nameStartsWith: 'entity.device-name-starts-with' - }, - "ASSET": { - type: 'entity.type-asset', - typePlural: 'entity.type-assets', - list: 'entity.list-of-assets', - nameStartsWith: 'entity.asset-name-starts-with' - }, - "ENTITY_VIEW": { - type: 'entity.type-entity-view', - typePlural: 'entity.type-entity-views', - list: 'entity.list-of-entity-views', - nameStartsWith: 'entity.entity-view-name-starts-with' - }, - "TENANT": { - type: 'entity.type-tenant', - typePlural: 'entity.type-tenants', - list: 'entity.list-of-tenants', - nameStartsWith: 'entity.tenant-name-starts-with' - }, - "CUSTOMER": { - type: 'entity.type-customer', - typePlural: 'entity.type-customers', - list: 'entity.list-of-customers', - nameStartsWith: 'entity.customer-name-starts-with' - }, - "USER": { - type: 'entity.type-user', - typePlural: 'entity.type-users', - list: 'entity.list-of-users', - nameStartsWith: 'entity.user-name-starts-with' - }, - "DASHBOARD": { - type: 'entity.type-dashboard', - typePlural: 'entity.type-dashboards', - list: 'entity.list-of-dashboards', - nameStartsWith: 'entity.dashboard-name-starts-with' - }, - "ALARM": { - type: 'entity.type-alarm', - typePlural: 'entity.type-alarms', - list: 'entity.list-of-alarms', - nameStartsWith: 'entity.alarm-name-starts-with' - }, - "RULE_CHAIN": { - type: 'entity.type-rulechain', - typePlural: 'entity.type-rulechains', - list: 'entity.list-of-rulechains', - nameStartsWith: 'entity.rulechain-name-starts-with' - }, - "RULE_NODE": { - type: 'entity.type-rulenode', - typePlural: 'entity.type-rulenodes', - list: 'entity.list-of-rulenodes', - nameStartsWith: 'entity.rulenode-name-starts-with' - }, - "CURRENT_CUSTOMER": { - type: 'entity.type-current-customer', - list: 'entity.type-current-customer' - }, - "CURRENT_TENANT": { - type: 'entity.type-current-tenant', - list: 'entity.type-current-tenant' - }, - "EDGE": { - type: 'entity.type-edge', - typePlural: 'entity.type-edges', - list: 'entity.list-of-edges', - nameStartsWith: 'entity.edge-name-starts-with' - } - }, - entityField: { - createdTime: { - keyName: 'createdTime', - name: 'entity-field.created-time', - value: 'createdTime', - time: true - }, - name: { - keyName: 'name', - name: 'entity-field.name', - value: 'name' - }, - type: { - keyName: 'type', - name: 'entity-field.type', - value: 'type' - }, - firstName: { - keyName: 'firstName', - name: 'entity-field.first-name', - value: 'firstName' - }, - lastName: { - keyName: 'lastName', - name: 'entity-field.last-name', - value: 'lastName' - }, - email: { - keyName: 'email', - name: 'entity-field.email', - value: 'email' - }, - title: { - keyName: 'title', - name: 'entity-field.title', - value: 'title' - }, - country: { - keyName: 'country', - name: 'entity-field.country', - value: 'country' - }, - state: { - keyName: 'state', - name: 'entity-field.state', - value: 'state' - }, - city: { - keyName: 'city', - name: 'entity-field.city', - value: 'city' - }, - address: { - keyName: 'address', - name: 'entity-field.address', - value: 'address' - }, - address2: { - keyName: 'address2', - name: 'entity-field.address2', - value: 'address2' - }, - zip: { - keyName: 'zip', - name: 'entity-field.zip', - value: 'zip' - }, - phone: { - keyName: 'phone', - name: 'entity-field.phone', - value: 'phone' - }, - label: { - keyName: 'label', - name: 'entity-field.label', - value: 'label' - } - }, - entitySearchDirection: { - from: "FROM", - to: "TO" - }, - entityRelationType: { - contains: "Contains", - manages: "Manages" - }, - eventType: { - error: { - value: "ERROR", - name: "event.type-error" - }, - lcEvent: { - value: "LC_EVENT", - name: "event.type-lc-event" - }, - stats: { - value: "STATS", - name: "event.type-stats" - }, - edgeEvent: { - value: "EDGE_EVENT", - name: "event.type-edge-event" - } - }, - debugEventType: { - debugRuleNode: { - value: "DEBUG_RULE_NODE", - name: "event.type-debug-rule-node" - }, - debugRuleChain: { - value: "DEBUG_RULE_CHAIN", - name: "event.type-debug-rule-chain" - } - }, - extensionType: { - http: "HTTP", - mqtt: "MQTT", - opc: "OPC UA", - modbus: "MODBUS" - }, - gatewayConfigType: { - mqtt: { - value: "mqtt", - name: "MQTT" - }, - modbus: { - value: "modbus", - name: "Modbus" - }, - opcua: { - value: "opcua", - name: "OPC-UA" - }, - ble: { - value: "ble", - name: "BLE" - }, - request: { - value: "request", - name: "Request" - }, - can: { - value: "can", - name: "CAN" - }, - bacnet: { - value: "bacnet", - name: "BACnet" - }, - custom: { - value: "custom", - name: "Custom" - } - }, - gatewayLogLevel: { - none: "NONE", - critical: "CRITICAL", - error: "ERROR", - warning: "WARNING", - info: "INFO", - debug: "DEBUG" - }, - extensionValueType: { - string: 'value.string', - long: 'value.long', - double: 'value.double', - boolean: 'value.boolean' - }, - extensionTransformerType: { - toDouble: 'extension.to-double', - custom: 'extension.custom' - }, - mqttConverterTypes: { - json: 'extension.converter-json', - custom: 'extension.custom' - }, - mqttCredentialTypes: { - anonymous: { - value: "anonymous", - name: "extension.anonymous" - }, - basic: { - value: "basic", - name: "extension.basic" - }, - pem: { - value: "cert.PEM", - name: "extension.pem" - } - }, - extensionOpcSecurityTypes: { - Basic128Rsa15: "Basic128Rsa15", - Basic256: "Basic256", - Basic256Sha256: "Basic256Sha256", - None: "None" - }, - extensionIdentityType: { - anonymous: "extension.anonymous", - username: "extension.username" - }, - extensionKeystoreType: { - PKCS12: "PKCS12", - JKS: "JKS" - }, - extensionModbusFunctionCodes: { - 1: "Read Coils (1)", - 2: "Read Discrete Inputs (2)", - 3: "Read Multiple Holding Registers (3)", - 4: "Read Input Registers (4)" - }, - extensionModbusTransports: { - tcp: "TCP", - udp: "UDP", - rtu: "RTU" - }, - extensionModbusRtuParities: { - none: "none", - even: "even", - odd: "odd" - }, - extensionModbusRtuEncodings: { - ascii: "ascii", - rtu: "rtu" - }, - latestTelemetry: { - value: "LATEST_TELEMETRY", - name: "attribute.scope-latest-telemetry", - clientSide: true - }, - attributesScope: { - client: { - value: "CLIENT_SCOPE", - name: "attribute.scope-client", - clientSide: true - }, - server: { - value: "SERVER_SCOPE", - name: "attribute.scope-server", - clientSide: false - }, - shared: { - value: "SHARED_SCOPE", - name: "attribute.scope-shared", - clientSide: false - } - }, - coreRuleChainType: "CORE", - edgeRuleChainType: "EDGE", - ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], - ruleChainNodeComponent: { - type: 'RULE_CHAIN', - name: 'rule chain', - clazz: 'tb.internal.RuleChain', - configurationDescriptor: { - nodeDefinition: { - description: "", - details: "Forwards incoming messages to specified Rule Chain", - inEnabled: true, - outEnabled: false, - relationTypes: [], - customRelations: false, - defaultConfiguration: {} - } - } - }, - unknownNodeComponent: { - type: 'UNKNOWN', - name: 'unknown', - clazz: 'tb.internal.Unknown', - configurationDescriptor: { - nodeDefinition: { - description: "", - details: "", - inEnabled: true, - outEnabled: true, - relationTypes: [], - customRelations: false, - defaultConfiguration: {} - } - } - }, - inputNodeComponent: { - type: 'INPUT', - name: 'Input', - clazz: 'tb.internal.Input' - }, - ruleNodeType: { - FILTER: { - value: "FILTER", - name: "rulenode.type-filter", - details: "rulenode.type-filter-details", - nodeClass: "tb-filter-type", - icon: "filter_list" - }, - ENRICHMENT: { - value: "ENRICHMENT", - name: "rulenode.type-enrichment", - details: "rulenode.type-enrichment-details", - nodeClass: "tb-enrichment-type", - icon: "playlist_add" - }, - TRANSFORMATION: { - value: "TRANSFORMATION", - name: "rulenode.type-transformation", - details: "rulenode.type-transformation-details", - nodeClass: "tb-transformation-type", - icon: "transform" - }, - ACTION: { - value: "ACTION", - name: "rulenode.type-action", - details: "rulenode.type-action-details", - nodeClass: "tb-action-type", - icon: "flash_on" - }, - EXTERNAL: { - value: "EXTERNAL", - name: "rulenode.type-external", - details: "rulenode.type-external-details", - nodeClass: "tb-external-type", - icon: "cloud_upload" - }, - RULE_CHAIN: { - value: "RULE_CHAIN", - name: "rulenode.type-rule-chain", - details: "rulenode.type-rule-chain-details", - nodeClass: "tb-rule-chain-type", - icon: "settings_ethernet" - }, - INPUT: { - value: "INPUT", - name: "rulenode.type-input", - details: "rulenode.type-input-details", - nodeClass: "tb-input-type", - icon: "input", - special: true - }, - UNKNOWN: { - value: "UNKNOWN", - name: "rulenode.type-unknown", - details: "rulenode.type-unknown-details", - nodeClass: "tb-unknown-type", - icon: "help_outline" - } - }, - messageType: { - 'POST_ATTRIBUTES_REQUEST': { - name: 'Post attributes', - value: 'POST_ATTRIBUTES_REQUEST' - }, - 'POST_TELEMETRY_REQUEST': { - name: 'Post telemetry', - value: 'POST_TELEMETRY_REQUEST' - }, - 'TO_SERVER_RPC_REQUEST': { - name: 'RPC Request from Device', - value: 'TO_SERVER_RPC_REQUEST' - }, - 'RPC_CALL_FROM_SERVER_TO_DEVICE': { - name: 'RPC Request to Device', - value: 'RPC_CALL_FROM_SERVER_TO_DEVICE' - }, - 'ACTIVITY_EVENT': { - name: 'Activity Event', - value: 'ACTIVITY_EVENT' - }, - 'INACTIVITY_EVENT': { - name: 'Inactivity Event', - value: 'INACTIVITY_EVENT' - }, - 'CONNECT_EVENT': { - name: 'Connect Event', - value: 'CONNECT_EVENT' - }, - 'DISCONNECT_EVENT': { - name: 'Disconnect Event', - value: 'DISCONNECT_EVENT' - }, - 'ENTITY_CREATED': { - name: 'Entity Created', - value: 'ENTITY_CREATED' - }, - 'ENTITY_UPDATED': { - name: 'Entity Updated', - value: 'ENTITY_UPDATED' - }, - 'ENTITY_DELETED': { - name: 'Entity Deleted', - value: 'ENTITY_DELETED' - }, - 'ENTITY_ASSIGNED': { - name: 'Entity Assigned', - value: 'ENTITY_ASSIGNED' - }, - 'ENTITY_UNASSIGNED': { - name: 'Entity Unassigned', - value: 'ENTITY_UNASSIGNED' - }, - 'ATTRIBUTES_UPDATED': { - name: 'Attributes Updated', - value: 'ATTRIBUTES_UPDATED' - }, - 'ATTRIBUTES_DELETED': { - name: 'Attributes Deleted', - value: 'ATTRIBUTES_DELETED' - } - }, - valueType: { - string: { - value: "string", - name: "value.string", - icon: "mdi:format-text" - }, - integer: { - value: "integer", - name: "value.integer", - icon: "mdi:numeric" - }, - double: { - value: "double", - name: "value.double", - icon: "mdi:numeric" - }, - boolean: { - value: "boolean", - name: "value.boolean", - icon: "mdi:checkbox-marked-outline" - }, - json: { - value: "json", - name: "value.json", - icon: "mdi:json" - } - }, - widgetType: { - timeseries: { - value: "timeseries", - name: "widget.timeseries", - template: { - bundleAlias: "charts", - alias: "basic_timeseries" - } - }, - latest: { - value: "latest", - name: "widget.latest-values", - template: { - bundleAlias: "cards", - alias: "attributes_card" - } - }, - rpc: { - value: "rpc", - name: "widget.rpc", - template: { - bundleAlias: "gpio_widgets", - alias: "basic_gpio_control" - } - }, - alarm: { - value: "alarm", - name: "widget.alarm", - template: { - bundleAlias: "alarm_widgets", - alias: "alarms_table" - } - }, - static: { - value: "static", - name: "widget.static", - template: { - bundleAlias: "cards", - alias: "html_card" - } - } - }, - widgetActionSources: { - headerButton: { - name: 'widget-action.header-button', - value: 'headerButton', - multiple: true - } - }, - widgetActionTypes: { - openDashboardState: { - name: 'widget-action.open-dashboard-state', - value: 'openDashboardState' - }, - updateDashboardState: { - name: 'widget-action.update-dashboard-state', - value: 'updateDashboardState' - }, - openDashboard: { - name: 'widget-action.open-dashboard', - value: 'openDashboard' - }, - custom: { - name: 'widget-action.custom', - value: 'custom' - }, - customPretty: { - name: 'widget-action.custom-pretty', - value: 'customPretty' - } - }, - systemBundleAlias: { - charts: "charts", - cards: "cards" - }, - translate: { - customTranslationsPrefix: "custom." - } - } - ).name; +/* + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export default angular.module('thingsboard.types', []) + .constant('types', + { + serverErrorCode: { + general: 2, + authentication: 10, + jwtTokenExpired: 11, + credentialsExpired: 15, + permissionDenied: 20, + invalidArguments: 30, + badRequestParams: 31, + itemNotFound: 32, + tooManyRequests: 33, + tooManyUpdates: 34 + }, + entryPoints: { + login: "/api/auth/login", + tokenRefresh: "/api/auth/token", + nonTokenBased: "/api/noauth" + }, + id: { + nullUid: "13814000-1dd2-11b2-8080-808080808080", + }, + aggregation: { + min: { + value: "MIN", + name: "aggregation.min" + }, + max: { + value: "MAX", + name: "aggregation.max" + }, + avg: { + value: "AVG", + name: "aggregation.avg" + }, + sum: { + value: "SUM", + name: "aggregation.sum" + }, + count: { + value: "COUNT", + name: "aggregation.count" + }, + none: { + value: "NONE", + name: "aggregation.none" + } + }, + alarmFields: { + createdTime: { + keyName: 'createdTime', + value: "createdTime", + name: "alarm.created-time", + time: true + }, + startTime: { + keyName: 'startTime', + value: "startTs", + name: "alarm.start-time", + time: true + }, + endTime: { + keyName: 'endTime', + value: "endTs", + name: "alarm.end-time", + time: true + }, + ackTime: { + keyName: 'ackTime', + value: "ackTs", + name: "alarm.ack-time", + time: true + }, + clearTime: { + keyName: 'clearTime', + value: "clearTs", + name: "alarm.clear-time", + time: true + }, + originator: { + keyName: 'originator', + value: "originatorName", + name: "alarm.originator" + }, + originatorType: { + keyName: 'originatorType', + value: "originator.entityType", + name: "alarm.originator-type" + }, + type: { + keyName: 'type', + value: "type", + name: "alarm.type" + }, + severity: { + keyName: 'severity', + value: "severity", + name: "alarm.severity" + }, + status: { + keyName: 'status', + value: "status", + name: "alarm.status" + } + }, + alarmStatus: { + activeUnack: "ACTIVE_UNACK", + activeAck: "ACTIVE_ACK", + clearedUnack: "CLEARED_UNACK", + clearedAck: "CLEARED_ACK" + }, + alarmSearchStatus: { + any: "ANY", + active: "ACTIVE", + cleared: "CLEARED", + ack: "ACK", + unack: "UNACK" + }, + alarmSeverity: { + "CRITICAL": { + name: "alarm.severity-critical", + class: "tb-critical", + color: "red" + }, + "MAJOR": { + name: "alarm.severity-major", + class: "tb-major", + color: "orange" + }, + "MINOR": { + name: "alarm.severity-minor", + class: "tb-minor", + color: "#ffca3d" + }, + "WARNING": { + name: "alarm.severity-warning", + class: "tb-warning", + color: "#abab00" + }, + "INDETERMINATE": { + name: "alarm.severity-indeterminate", + class: "tb-indeterminate", + color: "green" + } + }, + auditLogActionType: { + "ADDED": { + name: "audit-log.type-added" + }, + "DELETED": { + name: "audit-log.type-deleted" + }, + "UPDATED": { + name: "audit-log.type-updated" + }, + "ATTRIBUTES_UPDATED": { + name: "audit-log.type-attributes-updated" + }, + "ATTRIBUTES_DELETED": { + name: "audit-log.type-attributes-deleted" + }, + "RPC_CALL": { + name: "audit-log.type-rpc-call" + }, + "CREDENTIALS_UPDATED": { + name: "audit-log.type-credentials-updated" + }, + "ASSIGNED_TO_CUSTOMER": { + name: "audit-log.type-assigned-to-customer" + }, + "UNASSIGNED_FROM_CUSTOMER": { + name: "audit-log.type-unassigned-from-customer" + }, + "ACTIVATED": { + name: "audit-log.type-activated" + }, + "SUSPENDED": { + name: "audit-log.type-suspended" + }, + "CREDENTIALS_READ": { + name: "audit-log.type-credentials-read" + }, + "ATTRIBUTES_READ": { + name: "audit-log.type-attributes-read" + }, + "RELATION_ADD_OR_UPDATE": { + name: "audit-log.type-relation-add-or-update" + }, + "RELATION_DELETED": { + name: "audit-log.type-relation-delete" + }, + "RELATIONS_DELETED": { + name: "audit-log.type-relations-delete" + }, + "ALARM_ACK": { + name: "audit-log.type-alarm-ack" + }, + "ALARM_CLEAR": { + name: "audit-log.type-alarm-clear" + }, + "LOGIN": { + name: "audit-log.type-login" + }, + "LOGOUT": { + name: "audit-log.type-logout" + }, + "LOCKOUT": { + name: "audit-log.type-lockout" + }, + "ASSIGNED_FROM_TENANT": { + name: "audit-log.type-assigned-from-tenant" + }, + "ASSIGNED_TO_TENANT": { + name: "audit-log.type-assigned-to-tenant" + }, + "ASSIGNED_TO_EDGE": { + name: "audit-log.type-assigned-to-edge" + }, + "UNASSIGNED_FROM_EDGE": { + name: "audit-log.type-unassigned-from-edge" + } + }, + auditLogActionStatus: { + "SUCCESS": { + value: "SUCCESS", + name: "audit-log.status-success" + }, + "FAILURE": { + value: "FAILURE", + name: "audit-log.status-failure" + } + }, + auditLogMode: { + tenant: "tenant", + entity: "entity", + user: "user", + customer: "customer" + }, + aliasFilterType: { + singleEntity: { + value: 'singleEntity', + name: 'alias.filter-type-single-entity' + }, + entityList: { + value: 'entityList', + name: 'alias.filter-type-entity-list' + }, + entityName: { + value: 'entityName', + name: 'alias.filter-type-entity-name' + }, + stateEntity: { + value: 'stateEntity', + name: 'alias.filter-type-state-entity' + }, + assetType: { + value: 'assetType', + name: 'alias.filter-type-asset-type' + }, + deviceType: { + value: 'deviceType', + name: 'alias.filter-type-device-type' + }, + entityViewType: { + value: 'entityViewType', + name: 'alias.filter-type-entity-view-type' + }, + edgeType: { + value: 'edgeType', + name: 'alias.filter-type-edge-type' + }, + relationsQuery: { + value: 'relationsQuery', + name: 'alias.filter-type-relations-query' + }, + assetSearchQuery: { + value: 'assetSearchQuery', + name: 'alias.filter-type-asset-search-query' + }, + deviceSearchQuery: { + value: 'deviceSearchQuery', + name: 'alias.filter-type-device-search-query' + }, + entityViewSearchQuery: { + value: 'entityViewSearchQuery', + name: 'alias.filter-type-entity-view-search-query' + }, + edgeSearchQuery: { + value: 'edgeSearchQuery', + name: 'alias.filter-type-edge-search-query' + } + }, + direction: { + column: { + value: "column", + name: "direction.column" + }, + row: { + value: "row", + name: "direction.row" + } + }, + position: { + top: { + value: "top", + name: "position.top" + }, + bottom: { + value: "bottom", + name: "position.bottom" + }, + left: { + value: "left", + name: "position.left" + }, + right: { + value: "right", + name: "position.right" + } + }, + datasourceType: { + function: "function", + entity: "entity" + }, + dataKeyType: { + timeseries: "timeseries", + attribute: "attribute", + function: "function", + alarm: "alarm", + entityField: "entityField" + }, + contentType: { + "JSON": { + value: "JSON", + name: "content-type.json", + code: "json" + }, + "TEXT": { + value: "TEXT", + name: "content-type.text", + code: "text" + }, + "BINARY": { + value: "BINARY", + name: "content-type.binary", + code: "text" + } + }, + componentType: { + enrichment: "ENRICHMENT", + filter: "FILTER", + transformation: "TRANSFORMATION", + action: "ACTION", + external: "EXTERNAL" + }, + entityType: { + device: "DEVICE", + asset: "ASSET", + tenant: "TENANT", + customer: "CUSTOMER", + user: "USER", + dashboard: "DASHBOARD", + alarm: "ALARM", + rulechain: "RULE_CHAIN", + rulenode: "RULE_NODE", + entityView: "ENTITY_VIEW", + edge: "EDGE" + }, + edgeEventType:{ + dashboard: "DASHBOARD", + asset: "ASSET", + device: "DEVICE", + entityView: "ENTITY_VIEW", + alarm: "ALARM", + rulechain: "RULE_CHAIN", + ruleChainMetaData: "RULE_CHAIN_METADATA", + edge: "EDGE", + user: "USER", + customer: "CUSTOMER", + relation: "RELATION" + }, + edgeEventAction: { + updated: "UPDATED", + added: "ADDED", + assignedToEdge: "ASSIGNED_TO_EDGE", + deleted: "DELETED", + unassignedFromEdge: "UNASSIGNED_FROM_EDGE", + alarmAck: "ALARM_ACK", + alarmClear: "ALARM_CLEAR", + credentialsUpdated: "CREDENTIALS_UPDATED", + attributesUpdated: "ATTRIBUTES_UPDATED", + attributesDeleted: "ATTRIBUTES_DELETED", + timeseriesUpdated: "TIMESERIES_UPDATED" + }, + edgeAttributeKeys: { + active: "active", + lastConnectTime: "lastConnectTime", + lastDisconnectTime: "lastDisconnectTime", + queueStartTs: "queueStartTs" + }, + importEntityColumnType: { + name: { + name: 'import.column-type.name', + value: 'name' + }, + type: { + name: 'import.column-type.type', + value: 'type' + }, + label: { + name: 'import.column-type.label', + value: 'label' + }, + clientAttribute: { + name: 'import.column-type.client-attribute', + value: 'CLIENT_ATTRIBUTE' + }, + sharedAttribute: { + name: 'import.column-type.shared-attribute', + value: 'SHARED_ATTRIBUTE' + }, + serverAttribute: { + name: 'import.column-type.server-attribute', + value: 'SERVER_ATTRIBUTE' + }, + timeseries: { + name: 'import.column-type.timeseries', + value: 'TIMESERIES' + }, + entityField: { + name: 'import.column-type.entity-field', + value: 'ENTITY_FIELD' + }, + accessToken: { + name: 'import.column-type.access-token', + value: 'ACCESS_TOKEN' + }, + isGateway: { + name: 'import.column-type.isgateway', + value: 'gateway' + }, + description: { + name: 'import.column-type.description', + value: 'description' + } + }, + aliasEntityType: { + current_customer: "CURRENT_CUSTOMER", + current_tenant: "CURRENT_TENANT" + }, + entityTypeTranslations: { + "DEVICE": { + type: 'entity.type-device', + typePlural: 'entity.type-devices', + list: 'entity.list-of-devices', + nameStartsWith: 'entity.device-name-starts-with' + }, + "ASSET": { + type: 'entity.type-asset', + typePlural: 'entity.type-assets', + list: 'entity.list-of-assets', + nameStartsWith: 'entity.asset-name-starts-with' + }, + "ENTITY_VIEW": { + type: 'entity.type-entity-view', + typePlural: 'entity.type-entity-views', + list: 'entity.list-of-entity-views', + nameStartsWith: 'entity.entity-view-name-starts-with' + }, + "TENANT": { + type: 'entity.type-tenant', + typePlural: 'entity.type-tenants', + list: 'entity.list-of-tenants', + nameStartsWith: 'entity.tenant-name-starts-with' + }, + "CUSTOMER": { + type: 'entity.type-customer', + typePlural: 'entity.type-customers', + list: 'entity.list-of-customers', + nameStartsWith: 'entity.customer-name-starts-with' + }, + "USER": { + type: 'entity.type-user', + typePlural: 'entity.type-users', + list: 'entity.list-of-users', + nameStartsWith: 'entity.user-name-starts-with' + }, + "DASHBOARD": { + type: 'entity.type-dashboard', + typePlural: 'entity.type-dashboards', + list: 'entity.list-of-dashboards', + nameStartsWith: 'entity.dashboard-name-starts-with' + }, + "ALARM": { + type: 'entity.type-alarm', + typePlural: 'entity.type-alarms', + list: 'entity.list-of-alarms', + nameStartsWith: 'entity.alarm-name-starts-with' + }, + "RULE_CHAIN": { + type: 'entity.type-rulechain', + typePlural: 'entity.type-rulechains', + list: 'entity.list-of-rulechains', + nameStartsWith: 'entity.rulechain-name-starts-with' + }, + "RULE_NODE": { + type: 'entity.type-rulenode', + typePlural: 'entity.type-rulenodes', + list: 'entity.list-of-rulenodes', + nameStartsWith: 'entity.rulenode-name-starts-with' + }, + "CURRENT_CUSTOMER": { + type: 'entity.type-current-customer', + list: 'entity.type-current-customer' + }, + "CURRENT_TENANT": { + type: 'entity.type-current-tenant', + list: 'entity.type-current-tenant' + }, + "EDGE": { + type: 'entity.type-edge', + typePlural: 'entity.type-edges', + list: 'entity.list-of-edges', + nameStartsWith: 'entity.edge-name-starts-with' + } + }, + entityField: { + createdTime: { + keyName: 'createdTime', + name: 'entity-field.created-time', + value: 'createdTime', + time: true + }, + name: { + keyName: 'name', + name: 'entity-field.name', + value: 'name' + }, + type: { + keyName: 'type', + name: 'entity-field.type', + value: 'type' + }, + firstName: { + keyName: 'firstName', + name: 'entity-field.first-name', + value: 'firstName' + }, + lastName: { + keyName: 'lastName', + name: 'entity-field.last-name', + value: 'lastName' + }, + email: { + keyName: 'email', + name: 'entity-field.email', + value: 'email' + }, + title: { + keyName: 'title', + name: 'entity-field.title', + value: 'title' + }, + country: { + keyName: 'country', + name: 'entity-field.country', + value: 'country' + }, + state: { + keyName: 'state', + name: 'entity-field.state', + value: 'state' + }, + city: { + keyName: 'city', + name: 'entity-field.city', + value: 'city' + }, + address: { + keyName: 'address', + name: 'entity-field.address', + value: 'address' + }, + address2: { + keyName: 'address2', + name: 'entity-field.address2', + value: 'address2' + }, + zip: { + keyName: 'zip', + name: 'entity-field.zip', + value: 'zip' + }, + phone: { + keyName: 'phone', + name: 'entity-field.phone', + value: 'phone' + }, + label: { + keyName: 'label', + name: 'entity-field.label', + value: 'label' + } + }, + entitySearchDirection: { + from: "FROM", + to: "TO" + }, + entityRelationType: { + contains: "Contains", + manages: "Manages" + }, + eventType: { + error: { + value: "ERROR", + name: "event.type-error" + }, + lcEvent: { + value: "LC_EVENT", + name: "event.type-lc-event" + }, + stats: { + value: "STATS", + name: "event.type-stats" + }, + edgeEvent: { + value: "EDGE_EVENT", + name: "event.type-edge-event" + } + }, + debugEventType: { + debugRuleNode: { + value: "DEBUG_RULE_NODE", + name: "event.type-debug-rule-node" + }, + debugRuleChain: { + value: "DEBUG_RULE_CHAIN", + name: "event.type-debug-rule-chain" + } + }, + extensionType: { + http: "HTTP", + mqtt: "MQTT", + opc: "OPC UA", + modbus: "MODBUS" + }, + gatewayConfigType: { + mqtt: { + value: "mqtt", + name: "MQTT" + }, + modbus: { + value: "modbus", + name: "Modbus" + }, + opcua: { + value: "opcua", + name: "OPC-UA" + }, + ble: { + value: "ble", + name: "BLE" + }, + request: { + value: "request", + name: "Request" + }, + can: { + value: "can", + name: "CAN" + }, + bacnet: { + value: "bacnet", + name: "BACnet" + }, + custom: { + value: "custom", + name: "Custom" + } + }, + gatewayLogLevel: { + none: "NONE", + critical: "CRITICAL", + error: "ERROR", + warning: "WARNING", + info: "INFO", + debug: "DEBUG" + }, + extensionValueType: { + string: 'value.string', + long: 'value.long', + double: 'value.double', + boolean: 'value.boolean' + }, + extensionTransformerType: { + toDouble: 'extension.to-double', + custom: 'extension.custom' + }, + mqttConverterTypes: { + json: 'extension.converter-json', + custom: 'extension.custom' + }, + mqttCredentialTypes: { + anonymous: { + value: "anonymous", + name: "extension.anonymous" + }, + basic: { + value: "basic", + name: "extension.basic" + }, + pem: { + value: "cert.PEM", + name: "extension.pem" + } + }, + extensionOpcSecurityTypes: { + Basic128Rsa15: "Basic128Rsa15", + Basic256: "Basic256", + Basic256Sha256: "Basic256Sha256", + None: "None" + }, + extensionIdentityType: { + anonymous: "extension.anonymous", + username: "extension.username" + }, + extensionKeystoreType: { + PKCS12: "PKCS12", + JKS: "JKS" + }, + extensionModbusFunctionCodes: { + 1: "Read Coils (1)", + 2: "Read Discrete Inputs (2)", + 3: "Read Multiple Holding Registers (3)", + 4: "Read Input Registers (4)" + }, + extensionModbusTransports: { + tcp: "TCP", + udp: "UDP", + rtu: "RTU" + }, + extensionModbusRtuParities: { + none: "none", + even: "even", + odd: "odd" + }, + extensionModbusRtuEncodings: { + ascii: "ascii", + rtu: "rtu" + }, + latestTelemetry: { + value: "LATEST_TELEMETRY", + name: "attribute.scope-latest-telemetry", + clientSide: true + }, + attributesScope: { + client: { + value: "CLIENT_SCOPE", + name: "attribute.scope-client", + clientSide: true + }, + server: { + value: "SERVER_SCOPE", + name: "attribute.scope-server", + clientSide: false + }, + shared: { + value: "SHARED_SCOPE", + name: "attribute.scope-shared", + clientSide: false + } + }, + coreRuleChainType: "CORE", + edgeRuleChainType: "EDGE", + ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], + ruleChainNodeComponent: { + type: 'RULE_CHAIN', + name: 'rule chain', + clazz: 'tb.internal.RuleChain', + configurationDescriptor: { + nodeDefinition: { + description: "", + details: "Forwards incoming messages to specified Rule Chain", + inEnabled: true, + outEnabled: false, + relationTypes: [], + customRelations: false, + defaultConfiguration: {} + } + } + }, + unknownNodeComponent: { + type: 'UNKNOWN', + name: 'unknown', + clazz: 'tb.internal.Unknown', + configurationDescriptor: { + nodeDefinition: { + description: "", + details: "", + inEnabled: true, + outEnabled: true, + relationTypes: [], + customRelations: false, + defaultConfiguration: {} + } + } + }, + inputNodeComponent: { + type: 'INPUT', + name: 'Input', + clazz: 'tb.internal.Input' + }, + ruleNodeType: { + FILTER: { + value: "FILTER", + name: "rulenode.type-filter", + details: "rulenode.type-filter-details", + nodeClass: "tb-filter-type", + icon: "filter_list" + }, + ENRICHMENT: { + value: "ENRICHMENT", + name: "rulenode.type-enrichment", + details: "rulenode.type-enrichment-details", + nodeClass: "tb-enrichment-type", + icon: "playlist_add" + }, + TRANSFORMATION: { + value: "TRANSFORMATION", + name: "rulenode.type-transformation", + details: "rulenode.type-transformation-details", + nodeClass: "tb-transformation-type", + icon: "transform" + }, + ACTION: { + value: "ACTION", + name: "rulenode.type-action", + details: "rulenode.type-action-details", + nodeClass: "tb-action-type", + icon: "flash_on" + }, + EXTERNAL: { + value: "EXTERNAL", + name: "rulenode.type-external", + details: "rulenode.type-external-details", + nodeClass: "tb-external-type", + icon: "cloud_upload" + }, + RULE_CHAIN: { + value: "RULE_CHAIN", + name: "rulenode.type-rule-chain", + details: "rulenode.type-rule-chain-details", + nodeClass: "tb-rule-chain-type", + icon: "settings_ethernet" + }, + INPUT: { + value: "INPUT", + name: "rulenode.type-input", + details: "rulenode.type-input-details", + nodeClass: "tb-input-type", + icon: "input", + special: true + }, + UNKNOWN: { + value: "UNKNOWN", + name: "rulenode.type-unknown", + details: "rulenode.type-unknown-details", + nodeClass: "tb-unknown-type", + icon: "help_outline" + } + }, + messageType: { + 'POST_ATTRIBUTES_REQUEST': { + name: 'Post attributes', + value: 'POST_ATTRIBUTES_REQUEST' + }, + 'POST_TELEMETRY_REQUEST': { + name: 'Post telemetry', + value: 'POST_TELEMETRY_REQUEST' + }, + 'TO_SERVER_RPC_REQUEST': { + name: 'RPC Request from Device', + value: 'TO_SERVER_RPC_REQUEST' + }, + 'RPC_CALL_FROM_SERVER_TO_DEVICE': { + name: 'RPC Request to Device', + value: 'RPC_CALL_FROM_SERVER_TO_DEVICE' + }, + 'ACTIVITY_EVENT': { + name: 'Activity Event', + value: 'ACTIVITY_EVENT' + }, + 'INACTIVITY_EVENT': { + name: 'Inactivity Event', + value: 'INACTIVITY_EVENT' + }, + 'CONNECT_EVENT': { + name: 'Connect Event', + value: 'CONNECT_EVENT' + }, + 'DISCONNECT_EVENT': { + name: 'Disconnect Event', + value: 'DISCONNECT_EVENT' + }, + 'ENTITY_CREATED': { + name: 'Entity Created', + value: 'ENTITY_CREATED' + }, + 'ENTITY_UPDATED': { + name: 'Entity Updated', + value: 'ENTITY_UPDATED' + }, + 'ENTITY_DELETED': { + name: 'Entity Deleted', + value: 'ENTITY_DELETED' + }, + 'ENTITY_ASSIGNED': { + name: 'Entity Assigned', + value: 'ENTITY_ASSIGNED' + }, + 'ENTITY_UNASSIGNED': { + name: 'Entity Unassigned', + value: 'ENTITY_UNASSIGNED' + }, + 'ATTRIBUTES_UPDATED': { + name: 'Attributes Updated', + value: 'ATTRIBUTES_UPDATED' + }, + 'ATTRIBUTES_DELETED': { + name: 'Attributes Deleted', + value: 'ATTRIBUTES_DELETED' + } + }, + valueType: { + string: { + value: "string", + name: "value.string", + icon: "mdi:format-text" + }, + integer: { + value: "integer", + name: "value.integer", + icon: "mdi:numeric" + }, + double: { + value: "double", + name: "value.double", + icon: "mdi:numeric" + }, + boolean: { + value: "boolean", + name: "value.boolean", + icon: "mdi:checkbox-marked-outline" + }, + json: { + value: "json", + name: "value.json", + icon: "mdi:json" + } + }, + widgetType: { + timeseries: { + value: "timeseries", + name: "widget.timeseries", + template: { + bundleAlias: "charts", + alias: "basic_timeseries" + } + }, + latest: { + value: "latest", + name: "widget.latest-values", + template: { + bundleAlias: "cards", + alias: "attributes_card" + } + }, + rpc: { + value: "rpc", + name: "widget.rpc", + template: { + bundleAlias: "gpio_widgets", + alias: "basic_gpio_control" + } + }, + alarm: { + value: "alarm", + name: "widget.alarm", + template: { + bundleAlias: "alarm_widgets", + alias: "alarms_table" + } + }, + static: { + value: "static", + name: "widget.static", + template: { + bundleAlias: "cards", + alias: "html_card" + } + } + }, + widgetActionSources: { + headerButton: { + name: 'widget-action.header-button', + value: 'headerButton', + multiple: true + } + }, + widgetActionTypes: { + openDashboardState: { + name: 'widget-action.open-dashboard-state', + value: 'openDashboardState' + }, + updateDashboardState: { + name: 'widget-action.update-dashboard-state', + value: 'updateDashboardState' + }, + openDashboard: { + name: 'widget-action.open-dashboard', + value: 'openDashboard' + }, + custom: { + name: 'widget-action.custom', + value: 'custom' + }, + customPretty: { + name: 'widget-action.custom-pretty', + value: 'customPretty' + } + }, + systemBundleAlias: { + charts: "charts", + cards: "cards" + }, + translate: { + customTranslationsPrefix: "custom." + } + } + ).name; From ef94f7979aa94b3e27147b42ca874d0fb3183bbf Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:32:38 +0300 Subject: [PATCH 115/156] Types reverted 2 --- ui/src/app/common/types.constant.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 969042bbd4..2f3f42c2ad 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -393,7 +393,15 @@ export default angular.module('thingsboard.types', []) edge: "EDGE", user: "USER", customer: "CUSTOMER", - relation: "RELATION" + relation: "RELATION", + entityGroup: "ENTITY_GROUP", + schedulerEvent: "SCHEDULER_EVENT", + whiteLabeling: "WHITE_LABELING", + loginWhiteLabeling: "LOGIN_WHITE_LABELING", + customTranslation: "CUSTOM_TRANSLATION", + widgetsBundle: "WIDGETS_BUNDLE", + widgetType: "WIDGET_TYPE", + adminSettings: "ADMIN_SETTINGS" }, edgeEventAction: { updated: "UPDATED", @@ -786,8 +794,10 @@ export default angular.module('thingsboard.types', []) clientSide: false } }, - coreRuleChainType: "CORE", - edgeRuleChainType: "EDGE", + ruleChainType: { + core: "CORE", + edge: "EDGE" + }, ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION", "EXTERNAL"], ruleChainNodeComponent: { type: 'RULE_CHAIN', From 60bd2600cc86e7f8f3c3f20a242f6bb9a1a475c1 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:37:47 +0300 Subject: [PATCH 116/156] Edge events reverted --- ui/src/app/event/event-row.directive.js | 383 ++++++++++++------------ 1 file changed, 190 insertions(+), 193 deletions(-) diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index c08048379e..616a27217a 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -1,193 +1,190 @@ -/* - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* eslint-disable import/no-unresolved, import/default */ - -import eventErrorDialogTemplate from './event-content-dialog.tpl.html'; - -import eventRowLcEventTemplate from './event-row-lc-event.tpl.html'; -import eventRowStatsTemplate from './event-row-stats.tpl.html'; -import eventRowErrorTemplate from './event-row-error.tpl.html'; -import eventRowDebugRuleNodeTemplate from './event-row-debug-rulenode.tpl.html'; -import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; - -/* eslint-enable import/no-unresolved, import/default */ - -/*@ngInject*/ -export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, - types, utils, toast, entityService, ruleChainService) { - - var linker = function (scope, element, attrs) { - - var getTemplate = function(eventType) { - var template = ''; - switch(eventType) { - case types.eventType.lcEvent.value: - template = eventRowLcEventTemplate; - break; - case types.eventType.stats.value: - template = eventRowStatsTemplate; - break; - case types.eventType.error.value: - template = eventRowErrorTemplate; - break; - case types.debugEventType.debugRuleNode.value: - template = eventRowDebugRuleNodeTemplate; - break; - case types.debugEventType.debugRuleChain.value: - template = eventRowDebugRuleNodeTemplate; - break; - case types.eventType.edgeEvent.value: - template = eventRowEdgeEventTemplate; - break; - } - return $templateCache.get(template); - } - - scope.loadTemplate = function() { - element.html(getTemplate(attrs.eventType)); - $compile(element.contents())(scope); - } - - attrs.$observe('eventType', function() { - scope.loadTemplate(); - }); - - scope.types = types; - - scope.event = attrs.event; - - scope.showContent = function($event, content, title, contentType) { - var onShowingCallback = { - onShowing: function(){} - } - if (!contentType) { - contentType = null; - } - var sortedContent; - try { - sortedContent = angular.toJson(utils.sortObjectKeys(angular.fromJson(content))); - } - catch(err) { - sortedContent = content; - } - $mdDialog.show({ - controller: 'EventContentDialogController', - controllerAs: 'vm', - templateUrl: eventErrorDialogTemplate, - locals: {content: sortedContent, title: title, contentType: contentType, showingCallback: onShowingCallback}, - parent: angular.element($document[0].body), - fullscreen: true, - targetEvent: $event, - multiple: true, - onShowing: function(scope, element) { - onShowingCallback.onShowing(scope, element); - } - }); - } - - scope.showEdgeEntityContent = function($event, title, contentType) { - var onShowingCallback = { - onShowing: function(){} - } - if (!contentType) { - contentType = null; - } - var content = ''; - switch(scope.event.type) { - case types.edgeEventType.relation: - case types.edgeEventType.whiteLabeling: - case types.edgeEventType.loginWhiteLabeling: - case types.edgeEventType.customTranslation: - content = angular.toJson(scope.event.body); - showDialog(); - break; - case types.edgeEventType.ruleChainMetaData: - content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then( - function success(info) { - showDialog(); - return angular.toJson(info); - }, function fail() { - showError(); - }); - break; - default: - content = entityService.getEntity(scope.event.type, scope.event.entityId, {ignoreErrors: true}).then( - function success(info) { - showDialog(); - return angular.toJson(info); - }, function fail() { - showError(); - }); - break; - } - function showDialog() { - $mdDialog.show({ - controller: 'EventContentDialogController', - controllerAs: 'vm', - templateUrl: eventErrorDialogTemplate, - locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, - parent: angular.element($document[0].body), - fullscreen: true, - targetEvent: $event, - multiple: true, - onShowing: function(scope, element) { - onShowingCallback.onShowing(scope, element); - } - }); - } - function showError() { - toast.showError($translate.instant('edge.load-entity-error')); - } - } - - scope.checkEdgeEventType = function (edgeEventType) { - return !(edgeEventType === types.edgeEventType.widgetType || - edgeEventType === types.edgeEventType.adminSettings || - edgeEventType === types.edgeEventType.widgetsBundle ); - } - - scope.checkTooltip = function($event) { - var el = $event.target; - var $el = angular.element(el); - if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){ - $el.attr('title', $el.text()); - } - } - - $compile(element.contents())(scope); - - scope.updateStatus = function(eventCreatedTime) { - if (scope.queueStartTs) { - var status; - if (eventCreatedTime < scope.queueStartTs) { - status = $translate.instant('edge.success'); - scope.isPending = false; - } else { - status = $translate.instant('edge.failed'); - scope.isPending = true; - } - return status; - } - } - } - - return { - restrict: "A", - replace: false, - link: linker, - scope: false - }; -} +/* + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* eslint-disable import/no-unresolved, import/default */ + +import eventErrorDialogTemplate from './event-content-dialog.tpl.html'; + +import eventRowLcEventTemplate from './event-row-lc-event.tpl.html'; +import eventRowStatsTemplate from './event-row-stats.tpl.html'; +import eventRowErrorTemplate from './event-row-error.tpl.html'; +import eventRowDebugRuleNodeTemplate from './event-row-debug-rulenode.tpl.html'; +import eventRowEdgeEventTemplate from './event-row-edge-event.tpl.html'; + +/* eslint-enable import/no-unresolved, import/default */ + +/*@ngInject*/ +export default function EventRowDirective($compile, $templateCache, $mdDialog, $document, $translate, + types, utils, toast, entityService, ruleChainService) { + + var linker = function (scope, element, attrs) { + + var getTemplate = function(eventType) { + var template = ''; + switch(eventType) { + case types.eventType.lcEvent.value: + template = eventRowLcEventTemplate; + break; + case types.eventType.stats.value: + template = eventRowStatsTemplate; + break; + case types.eventType.error.value: + template = eventRowErrorTemplate; + break; + case types.debugEventType.debugRuleNode.value: + template = eventRowDebugRuleNodeTemplate; + break; + case types.debugEventType.debugRuleChain.value: + template = eventRowDebugRuleNodeTemplate; + break; + case types.eventType.edgeEvent.value: + template = eventRowEdgeEventTemplate; + break; + } + return $templateCache.get(template); + } + + scope.loadTemplate = function() { + element.html(getTemplate(attrs.eventType)); + $compile(element.contents())(scope); + } + + attrs.$observe('eventType', function() { + scope.loadTemplate(); + }); + + scope.types = types; + + scope.event = attrs.event; + + scope.showContent = function($event, content, title, contentType) { + var onShowingCallback = { + onShowing: function(){} + } + if (!contentType) { + contentType = null; + } + var sortedContent; + try { + sortedContent = angular.toJson(utils.sortObjectKeys(angular.fromJson(content))); + } + catch(err) { + sortedContent = content; + } + $mdDialog.show({ + controller: 'EventContentDialogController', + controllerAs: 'vm', + templateUrl: eventErrorDialogTemplate, + locals: {content: sortedContent, title: title, contentType: contentType, showingCallback: onShowingCallback}, + parent: angular.element($document[0].body), + fullscreen: true, + targetEvent: $event, + multiple: true, + onShowing: function(scope, element) { + onShowingCallback.onShowing(scope, element); + } + }); + } + + scope.showEdgeEntityContent = function($event, title, contentType) { + var onShowingCallback = { + onShowing: function(){} + } + if (!contentType) { + contentType = null; + } + var content = ''; + switch(scope.event.type) { + case types.edgeEventType.relation: + content = angular.toJson(scope.event.body); + showDialog(); + break; + case types.edgeEventType.ruleChainMetaData: + content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then( + function success(info) { + showDialog(); + return angular.toJson(info); + }, function fail() { + showError(); + }); + break; + default: + content = entityService.getEntity(scope.event.type, scope.event.entityId, {ignoreErrors: true}).then( + function success(info) { + showDialog(); + return angular.toJson(info); + }, function fail() { + showError(); + }); + break; + } + function showDialog() { + $mdDialog.show({ + controller: 'EventContentDialogController', + controllerAs: 'vm', + templateUrl: eventErrorDialogTemplate, + locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, + parent: angular.element($document[0].body), + fullscreen: true, + targetEvent: $event, + multiple: true, + onShowing: function(scope, element) { + onShowingCallback.onShowing(scope, element); + } + }); + } + function showError() { + toast.showError($translate.instant('edge.load-entity-error')); + } + } + + scope.checkEdgeEventType = function (edgeEventType) { + return !(edgeEventType === types.edgeEventType.widgetType || + edgeEventType === types.edgeEventType.adminSettings || + edgeEventType === types.edgeEventType.widgetsBundle ); + } + + scope.checkTooltip = function($event) { + var el = $event.target; + var $el = angular.element(el); + if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){ + $el.attr('title', $el.text()); + } + } + + $compile(element.contents())(scope); + + scope.updateStatus = function(eventCreatedTime) { + if (scope.queueStartTs) { + var status; + if (eventCreatedTime < scope.queueStartTs) { + status = $translate.instant('edge.success'); + scope.isPending = false; + } else { + status = $translate.instant('edge.failed'); + scope.isPending = true; + } + return status; + } + } + } + + return { + restrict: "A", + replace: false, + link: linker, + scope: false + }; +} From 3bfb604aab8546b5480bcb36b983859a1c1cff0f Mon Sep 17 00:00:00 2001 From: deaflynx Date: Fri, 18 Sep 2020 18:44:59 +0300 Subject: [PATCH 117/156] Edge events refactored --- ui/src/app/event/event-row.directive.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js index 616a27217a..39f3f46622 100644 --- a/ui/src/app/event/event-row.directive.js +++ b/ui/src/app/event/event-row.directive.js @@ -150,10 +150,10 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ } } - scope.checkEdgeEventType = function (edgeEventType) { - return !(edgeEventType === types.edgeEventType.widgetType || - edgeEventType === types.edgeEventType.adminSettings || - edgeEventType === types.edgeEventType.widgetsBundle ); + scope.checkEdgeEventType = function (type) { + return !(type === types.edgeEventType.widgetType || + type === types.edgeEventType.adminSettings || + type === types.edgeEventType.widgetsBundle ); } scope.checkTooltip = function($event) { From 8980efd62ecc528156a75a928f7fef6a925b67f3 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 18 Sep 2020 18:45:31 +0300 Subject: [PATCH 118/156] Added sleep for correct sequence of edge events --- .../server/controller/BaseEdgeEventControllerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java index 2d838d3ae4..bd141f64e8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeEventControllerTest.java @@ -76,6 +76,7 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { @Test public void testGetEdgeEvents() throws Exception { + Thread.sleep(1000); Edge edge = constructEdge("TestEdge", "default"); edge = doPost("/api/edge", edge, Edge.class); From 5ad022a5fc703292fe39e13d909005336c31e6d3 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 22 Sep 2020 11:51:15 +0300 Subject: [PATCH 119/156] Updated US,FR,ES,DE locales --- ui/src/app/asset/add-assets-to-edge.tpl.html | 2 +- ui/src/app/asset/asset.controller.js | 2 +- ui/src/app/dashboard/dashboards.controller.js | 2 +- .../app/device/add-devices-to-edge.tpl.html | 2 +- ui/src/app/device/device.controller.js | 2 +- .../add-entity-views-to-edge.tpl.html | 2 +- .../app/entity-view/entity-view.controller.js | 2 +- ui/src/app/locale/locale.constant-de_DE.json | 47 ++++------- ui/src/app/locale/locale.constant-en_US.json | 30 +------ ui/src/app/locale/locale.constant-es_ES.json | 78 +++++++++---------- ui/src/app/locale/locale.constant-fr_FR.json | 61 ++++++--------- ui/src/app/rulechain/rulechains.controller.js | 2 +- 12 files changed, 85 insertions(+), 147 deletions(-) diff --git a/ui/src/app/asset/add-assets-to-edge.tpl.html b/ui/src/app/asset/add-assets-to-edge.tpl.html index 2e24411211..635a6915d7 100644 --- a/ui/src/app/asset/add-assets-to-edge.tpl.html +++ b/ui/src/app/asset/add-assets-to-edge.tpl.html @@ -15,7 +15,7 @@ limitations under the License. --> - +
diff --git a/ui/src/app/asset/asset.controller.js b/ui/src/app/asset/asset.controller.js index 27190f18eb..84c8334bb2 100644 --- a/ui/src/app/asset/asset.controller.js +++ b/ui/src/app/asset/asset.controller.js @@ -339,7 +339,7 @@ export function AssetController($rootScope, userService, assetService, customerS unassignFromEdge($event, item, false); }, name: function() { return $translate.instant('action.unassign') }, - details: function() { return $translate.instant('asset.unassign-from-edge') }, + details: function() { return $translate.instant('edge.unassign-from-edge') }, icon: "assignment_return" } ); diff --git a/ui/src/app/dashboard/dashboards.controller.js b/ui/src/app/dashboard/dashboards.controller.js index 12a4d1cee0..47d5bdf0d5 100644 --- a/ui/src/app/dashboard/dashboards.controller.js +++ b/ui/src/app/dashboard/dashboards.controller.js @@ -415,7 +415,7 @@ export function DashboardsController(userService, dashboardService, customerServ unassignFromEdge($event, item, edgeId); }, name: function() { return $translate.instant('action.unassign') }, - details: function() { return $translate.instant('dashboard.unassign-from-edge') }, + details: function() { return $translate.instant('edge.unassign-from-edge') }, icon: "assignment_return" } ); diff --git a/ui/src/app/device/add-devices-to-edge.tpl.html b/ui/src/app/device/add-devices-to-edge.tpl.html index 97ed4c937b..a9166a30a2 100644 --- a/ui/src/app/device/add-devices-to-edge.tpl.html +++ b/ui/src/app/device/add-devices-to-edge.tpl.html @@ -15,7 +15,7 @@ limitations under the License. --> - +
diff --git a/ui/src/app/device/device.controller.js b/ui/src/app/device/device.controller.js index 05f7b54226..dc71090d76 100644 --- a/ui/src/app/device/device.controller.js +++ b/ui/src/app/device/device.controller.js @@ -372,7 +372,7 @@ export function DeviceController($rootScope, userService, deviceService, custome unassignFromEdge($event, item, false); }, name: function() { return $translate.instant('action.unassign') }, - details: function() { return $translate.instant('device.unassign-from-edge') }, + details: function() { return $translate.instant('edge.unassign-from-edge') }, icon: "assignment_return" } ); diff --git a/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html b/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html index 1f054d928e..0e14c3fe6a 100644 --- a/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html +++ b/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html @@ -15,7 +15,7 @@ limitations under the License. --> - +
diff --git a/ui/src/app/entity-view/entity-view.controller.js b/ui/src/app/entity-view/entity-view.controller.js index 3d382346de..63dbaa2a47 100644 --- a/ui/src/app/entity-view/entity-view.controller.js +++ b/ui/src/app/entity-view/entity-view.controller.js @@ -299,7 +299,7 @@ export function EntityViewController($rootScope, userService, entityViewService, unassignFromEdge($event, item, false); }, name: function() { return $translate.instant('action.unassign') }, - details: function() { return $translate.instant('entity-view.unassign-from-edge') }, + details: function() { return $translate.instant('edge.unassign-from-edge') }, icon: "assignment_return" } ); diff --git a/ui/src/app/locale/locale.constant-de_DE.json b/ui/src/app/locale/locale.constant-de_DE.json index 9e822188ee..bdd51cadf0 100644 --- a/ui/src/app/locale/locale.constant-de_DE.json +++ b/ui/src/app/locale/locale.constant-de_DE.json @@ -276,11 +276,12 @@ "label": "Bezeichnung", "assign-asset-to-edge": "Objekte dem Rand zuordnen", "assign-asset-to-edge-text":"Bitte wählen Sie die Objekte aus, die dem Rand zugeordnet werden sollen", - "unassign-from-edge": "Randzuordnung aufheben", - "assign-to-edge": "Einem Rand zuordnen", + "unassign-asset-from-edge": "Objekte von Rand entfernen", "unassign-asset-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung für das Objekt '{{assetName}}' aufheben möchten?", "unassign-asset-from-edge-text": "Nach Bestätigung wird die Zuordnung des Objekts aufgehoben und es ist für den Kunden nicht mehr zugänglich.", - "unassign-assets-from-edge-action-title": "Rand { count, plural, 1 {1 Objektzuordnung} other {# Objektzuordnungen} } aufheben" + "unassign-assets-from-edge-action-title": "Rand { count, plural, 1 {1 Objektzuordnung} other {# Objektzuordnungen} } aufheben", + "unassign-assets-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung für das Objekt '{{assetName}}' wirklich aufheben möchten?", + "unassign-assets-from-edge-text": "Nach der Bestätigung werden alle ausgewählten Objekte nicht zugewiesen und sind für den Rand nicht zugänglich." }, "attribute": { "attributes": "Eigenschaften", @@ -417,6 +418,7 @@ "manage-assets": "Objekte verwalten", "manage-devices": "Geräte verwalten", "manage-dashboards": "Dashboards verwalten", + "manage-edges": "Öffentliche Rand", "title": "Titel", "title-required": "Titel ist erforderlich.", "description": "Beschreibung", @@ -578,20 +580,11 @@ "hide-details": "Details ausblenden", "select-state": "Soll-Zustand auswählen", "state-controller": "Zustandssteuerung", - "manage-assigned-edges": "Zugeordnete Rand verwalten", "unassign-dashboard-from-edge-text": "Nach der Bestätigung wird die Zuordnung des Dashboards aufgehoben und es ist für der Rand nicht mehr zugänglich.", - "assigned-edges": "Zugeordnete Rand", - "unassign-from-edge": "Zuordnung von Rand aufheben", "unassign-dashboards-from-edge-action-title": "Zuordnung { count, plural, 1 {1 Dashboard} other {# Dashboards} } vom Rand aufheben", "unassign-dashboards-from-edge-text": "Nach der Bestätigung wird die Zuordnung aller ausgewählten Dashboards aufgehoben und sie sind für den Rand nicht mehr zugänglich.", "assign-dashboard-to-edge": "Dashboard(s) dem Rand zuordnen", - "assign-dashboard-to-edge-text": "Bitte wählen Sie die Dashboards aus, die Sie dem Rand zuordnen möchten", - "assign-dashboards-to-edge-text": "Zuordnen { count, plural, 1 {1 Dashboard} other {# Dashboards} } zum Rand", - "unassign-dashboards-from-edge-action-text": "Zuordnung { count, plural, 1 {1 Dashboard} other {# Dashboards} } vom Rand aufheben", - "assign-to-edges": "Dashboard(s) den Rand zuordnen", - "assign-to-edges-text": "Bitte wählen Sie den Rand aus, dem die Dashboards zugeordnet werden sollen", - "unassign-from-edges": "Zuordnung von Dashboard(s) zum Rand aufheben", - "unassign-from-edges-text": "Bitte wählen Sie die Rand aus, für die die Zuordnung von Dashboard(s) aufgehoben werden soll" + "assign-dashboard-to-edge-text": "Bitte wählen Sie die Dashboards aus, die Sie dem Rand zuordnen möchten" }, "datakey": { "settings": "Einstellungen", @@ -725,9 +718,6 @@ "select-device": "Gerät auswählen", "assign-device-to-edge": "Dashboard(s) dem Gerät zuordnen", "assign-device-to-edge-text":"Bitte wählen Sie die Geräte aus, die Sie dem Rand zuordnen möchten", - "unassign-from-edge": "Zuordnung von Rand aufheben", - "assign-to-edge": "Einem Rand zuordnen", - "assign-to-edge-text": "Bitte wählen Sie die Geräte aus, die Sie dem Rand zuordnen möchten", "unassign-device-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung zum Gerät '{{deviceName}}' wirklich aufheben möchten?", "unassign-device-from-edge-text": "Nach der Bestätigung ist das Gerät nicht zugeordnet und für den Kunden nicht zugänglich.", "unassign-devices-from-edge-action-title": "Zuordnung { count, plural, 1 {1 Gerät} other {# Geräte} } vom Rand aufheben", @@ -806,7 +796,16 @@ "entity-views": "Objekte Entitätsansichten", "set-root-rule-chain-text": "Bitte wählen Sie die Regelkette zur Wurzel rule chain für die Rand", "set-root-rule-chain-to-edges": "Regelkette zur Wurzel machen für die Rand", - "set-root-rule-chain-to-edges-text": "Die Regelkette zur Wurzel für { count, plural, 1 {1 Rand} other {# Rand} } machen" + "set-root-rule-chain-to-edges-text": "Die Regelkette zur Wurzel für { count, plural, 1 {1 Rand} other {# Rand} } machen", + "status": "Von Rand empfangen", + "success": "Bereitgestellt", + "failed": "Steht aus", + "entity-id": "Entität ID", + "entity-info": "Entitätsinfo", + "event-action": "Ereignisaktion", + "load-entity-error": "Entität nicht gefunden. Fehler beim Laden der Informationen", + "unassign-edges-text": "Nach der Bestätigung werden alle ausgewählten Kanten nicht zugewiesen und sind für den Kunden nicht zugänglich.", + "unassign-edges-title": "Sind Sie sicher, dass Sie die Zuordnung aufheben möchten { count, plural, 1 {1 Rand} other {# Rand} }?" }, "error": { "unable-to-connect": "Es konnte keine Verbindung zum Server hergestellt werden! Bitte überprüfen Sie Ihre Internetverbindung.", @@ -979,9 +978,6 @@ "name-required": "Name ist erforderlich.", "assign-entity-view-to-edge": "Entitätsansicht dem Rand zuordnen", "assign-entity-view-to-edge-text":"Bitte wählen Sie die Entitätsansicht aus, die dem Rand zugeordnet werden sollen", - "unassign-from-edge": "Randzuordnung aufheben", - "assign-to-edge": "Einem Rand zuordnen", - "assign-to-edge-text": "Bitte wählen Sie die Entitätsansichte aus, die dem Rand zugeordnet werden sollen", "unassign-entity-view-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung für Entitätsansicht '{{entityViewName}}' aufheben möchten?", "unassign-entity-view-from-edge-text": "Nach Bestätigung wird die Zuordnung des Entitätsansichts aufgehoben und es ist für den Kunden nicht mehr zugänglich.", "unassign-entity-views-from-edge-action-title": "Rand { count, plural, 1 {1 Entitätsansicht} other {# Entitätsansichte} } aufheben", @@ -1025,6 +1021,7 @@ "type-debug-rule-chain": "Fehlersuche", "no-events-prompt": "Keine Ereignisse gefunden", "error": "Fehler", + "type-edge-event": "Downlink", "alarm": "Alarm", "event-time": "Ereigniszeit", "server": "Server", @@ -1394,21 +1391,11 @@ "unassign-rulechains": "Nicht zugeordnete Regelketten", "unassign-rulechain-title": "Möchten Sie die Zuordnung die Regelkette '{{ruleChainTitle}}' wirklich aufheben?", "unassign-rulechains-title": "Sind Sie sicher, dass Sie die Zuordnung aufheben möchten { count, plural, 1 {1 Regelkette} other {# Regelketten} }?", - "manage-assigned-edges": "Zugeordnete Rand verwalten", "unassign-rulechain-from-edge-text": "Nach der Bestätigung wird die Zuordnung aller ausgewählten Regelkette aufgehoben und sie sind für den Rand nicht mehr zugänglich.", - "assigned-edges": "Zugeordnete Rand", - "unassign-from-edge": "Randzuordnung aufheben", "unassign-rulechains-from-edge-action-title": "Zuordnung { count, plural, 1 {1 Regelkette} other {# Regelketten} } vom Rand aufheben", "unassign-rulechains-from-edge-text": "Nach der Bestätigung wird die Zuordnung aller ausgewählten Regelketten aufgehoben und sie sind für den Rand nicht mehr zugänglich.", - "assign-rulechains-to-edge-text": "Zuordnen { count, plural, 1 {1 Regelkette} other {# Regelketten} } zum Rand", "assign-rulechain-to-edge": "Regelkette(n) dem Rand zuordnen", "assign-rulechain-to-edge-text": "Bitte wählen Sie die Regelketten aus, die Sie dem Rand zuordnen möchten", - "unassign-rulechains-from-edge-action-text": "Zuordnung { count, plural, 1 {1 Regelkette} other {# Regelketten} } vom Rand aufheben", - "assign-to-edges": "Regelkette(n) den Rand zuordnen", - "assign-to-edges-text": "Zuordnung von Regelkette(n) zum Rand aufheben", - "unassign-from-edges": "Unassign Rule Chain(s) From Edges", - "unassign-from-edges-text": "Bitte wählen Sie die Rand aus, für die die Zuordnung von Regelkette(n) aufgehoben werden soll", - "assigned-to-edges": "Regelketten Zuordnung", "set-default-root-edge": "Machen Sie Randregelkette zur Wurzel Standard", "set-default-root-edge-rulechain-title": "Sind Sie sicher, dass Sie die Randregelkette '{{ruleChainName}}' zur Wurzel machen Standard?", "set-default-root-edge-rulechain-text": "Nach der Bestätigung wird die Randregelkette zur Wurzel Standard und behandelt alle eingehenden Transportnachrichten.", diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 80c09a7348..2397bf811c 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -296,9 +296,6 @@ "label": "Label", "assign-asset-to-edge": "Assign Asset(s) To Edge", "assign-asset-to-edge-text":"Please select the assets to assign to the edge", - "unassign-from-edge": "Unassign from edge", - "assign-to-edge": "Assign to edge", - "assign-to-edge-text": "Please select the edge to assign the asset(s)", "unassign-asset-from-edge": "Unassign asset", "unassign-asset-from-edge-title": "Are you sure you want to unassign the asset '{{assetName}}'?", "unassign-asset-from-edge-text": "After the confirmation the asset will be unassigned and won't be accessible by the edge.", @@ -605,20 +602,11 @@ "hide-details": "Hide details", "select-state": "Select target state", "state-controller": "State controller", - "manage-assigned-edges": "Manage assigned edges", "unassign-dashboard-from-edge-text": "After the confirmation the dashboard will be unassigned and won't be accessible by the edge.", - "assigned-edges": "Assigned edges", - "unassign-from-edge": "Unassign from edge", "unassign-dashboards-from-edge-action-title": "Unassign { count, plural, 1 {1 dashboard} other {# dashboards} } from edge", "unassign-dashboards-from-edge-text": "After the confirmation all selected dashboards will be unassigned and won't be accessible by the edge.", "assign-dashboard-to-edge": "Assign Dashboard(s) To Edge", - "assign-dashboard-to-edge-text": "Please select the dashboards to assign to the edge", - "assign-dashboards-to-edge-text": "Assign { count, plural, 1 {1 dashboard} other {# dashboards} } to edges", - "unassign-dashboards-from-edge-action-text": "Unassign { count, plural, 1 {1 dashboard} other {# dashboards} } from edges", - "assign-to-edges": "Assign Dashboard(s) To Edges", - "assign-to-edges-text": "Please select the edges to assign the dashboard(s)", - "unassign-from-edges": "Unassign Dashboard(s) From Edges", - "unassign-from-edges-text": "Please select the edges to unassign from the dashboard(s)" + "assign-dashboard-to-edge-text": "Please select the dashboards to assign to the edge" }, "datakey": { "settings": "Settings", @@ -757,9 +745,6 @@ "device-file": "Device file", "assign-device-to-edge": "Assign Device(s) To Edge", "assign-device-to-edge-text":"Please select the devices to assign to the edge", - "unassign-from-edge": "Unassign from edge", - "assign-to-edge": "Assign to edge", - "assign-to-edge-text": "Please select the edge to assign the device(s)", "unassign-device-from-edge-title": "Are you sure you want to unassign the device '{{deviceName}}'?", "unassign-device-from-edge-text": "After the confirmation the device will be unassigned and won't be accessible by the edge.", "unassign-devices-from-edge-action-title": "Unassign { count, plural, 1 {1 device} other {# devices} } from edge", @@ -1075,9 +1060,6 @@ "make-private-entity-view-text": "After the confirmation the entity view and all its data will be made private and won't be accessible by others.", "assign-entity-view-to-edge": "Assign Entity View(s) To Edge", "assign-entity-view-to-edge-text":"Please select the entity views to assign to the edge", - "unassign-from-edge": "Unassign from edge", - "assign-to-edge": "Assign to edge", - "assign-to-edge-text": "Please select the edge to assign the entity view(s)", "unassign-entity-view-from-edge-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?", "unassign-entity-view-from-edge-text": "After the confirmation the entity view will be unassigned and won't be accessible by the edge.", "unassign-entity-views-from-edge-action-title": "Unassign { count, plural, 1 {1 entity view} other {# entity views} } from edge", @@ -1589,21 +1571,11 @@ "unassign-rulechains": "Unassign rulechains", "unassign-rulechain-title": "Are you sure you want to unassign the rulechain '{{ruleChainTitle}}'?", "unassign-rulechains-title": "Are you sure you want to unassign { count, plural, 1 {1 rulechain} other {# rulechains} }?", - "manage-assigned-edges": "Manage assigned edges", "unassign-rulechain-from-edge-text": "After the confirmation the rulechain will be unassigned and won't be accessible by the edge.", - "assigned-edges": "Assigned edges", - "unassign-from-edge": "Unassign from edge", "unassign-rulechains-from-edge-action-title": "Unassign { count, plural, 1 {1 rulechain} other {# rulechains} } from edge", "unassign-rulechains-from-edge-text": "After the confirmation all selected rulechains will be unassigned and won't be accessible by the edge.", - "assign-rulechains-to-edge-text": "Assign { count, plural, 1 {1 rulechain} other {# rulechains} } to edges", "assign-rulechain-to-edge": "Assign Rule Chain(s) To Edge", "assign-rulechain-to-edge-text": "Please select the rulechains to assign to the edge", - "unassign-rulechains-from-edge-action-text": "Unassign { count, plural, 1 {1 rulechain} other {# rulechains} } from edges", - "assign-to-edges": "Assign Rule Chain(s) To Edges", - "assign-to-edges-text": "Please select the edges to assign the rulechain(s)", - "unassign-from-edges": "Unassign Rule Chain(s) From Edges", - "unassign-from-edges-text": "Please select the edges to unassign from the rulechain(s)", - "assigned-to-edges": "Assigned to edges", "set-default-root-edge": "Make rule chain default root", "set-default-root-edge-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' default edge root?", "set-default-root-edge-rulechain-text": "After the confirmation the rule chain will become default edge root and will handle all incoming transport messages.", diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json index 75fed86ed1..4d735561c2 100644 --- a/ui/src/app/locale/locale.constant-es_ES.json +++ b/ui/src/app/locale/locale.constant-es_ES.json @@ -195,6 +195,8 @@ "filter-type-device-search-query-description": "Dispositivos con tipos {{deviceTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "filter-type-entity-view-search-query": "Consultar vista de entidad", "filter-type-entity-view-search-query-description": "Las vista de entidad de tipo {{entityViewTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", + "filter-type-edge-search-query": "Consultar búsqueda de borde", + "filter-type-edge-search-query-description": "Bordes con tipos {{edgeTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "type-assigned-to-edge": "Asignado a borde", "type-unassigned-from-edge": "Sin asignar desde bordes", "entity-filter": "Filtro de entidad", @@ -279,7 +281,15 @@ "name-starts-with": "El nombre del activo comienza con", "import": "Importar activos", "asset-file": "Archivo del activo", - "label": "Etiqueta" + "label": "Etiqueta", + "assign-asset-to-edge": "Asignar activo(s) al borde", + "assign-asset-to-edge-text":"Por favor, seleccione los activos para asignar al borde", + "unassign-asset-from-edge": "Anular activo de bodre", + "unassign-asset-from-edge-title": "¿Está seguro de que desea desasignar el activo '{{assetName}}'?", + "unassign-asset-from-edge-text": "Después de la confirmación, el activo no será asignado y el borde no podrá acceder a él", + "unassign-assets-from-edge-action-title": "Anular asignación {count, plural, 1 {1 activo} other {# activos}} desde el borde", + "unassign-assets-from-edge-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 activo} other {# activos}}?", + "unassign-assets-from-edge-text": "Después de la confirmación, todos los activos seleccionados quedarán sin asignar y el borde no podrá acceder a ellos." }, "attribute": { "attributes": "Atributos", @@ -390,7 +400,7 @@ "public-devices": "Dispositivos públicos", "public-assets": "Activos públicos", "public-entity-views": "Vista de entidad públicas", - "public-edge": "Bordes públicos", + "public-edges": "Bordes públicos", "add": "Agregar cliente", "delete": "Eliminar cliente", "manage-customer-users": "Gestionar usuarios del cliente", @@ -399,8 +409,8 @@ "manage-public-devices": "Gestionar dispositivos públicos", "manage-public-dashboards": "Gestionar paneles públicos", "manage-customer-assets": "Gestionar activos del cliente", - "manage-customer-edge": "Administrar bordes de clientes", - "manage-public-edge": "Administrar bordes públicos", + "manage-customer-edges": "Administrar bordes de clientes", + "manage-public-edges": "Administrar bordes públicos", "manage-public-assets": "Gestionar activos públicos", "add-customer-text": "Agregar nuevo cliente", "no-customers-text": "No se encontraron clientes", @@ -414,12 +424,13 @@ "manage-assets": "Gestionar activos", "manage-devices": "Gestionar dispositivos", "manage-dashboards": "Gestionar paneles", + "manage-edges": "Administrar bordes", "title": "Título", "title-required": "El título es requerido.", "description": "Descripción", "details": "Detalles", "events": "Eventos", - "edge": "Bordes del cliente", + "edges": "Bordes del cliente", "copyId": "Copiar ID del cliente", "idCopiedMessage": "ID del cliente ha sido copiada al portapapeles", "select-customer": "Seleccionar cliente", @@ -575,20 +586,11 @@ "hide-details": "Ocultar detalles", "select-state": "Seleccionar estado objetivo", "state-controller": "Estado del controlador", - "manage-assigned-edges": "Administrar bordes asignados", "unassign-dashboard-from-edge-text": "Después de la confirmación, el tablero no será asignado y el borde no podrá acceder a él", - "assigned-edges": "bordes asignados", - "unassign-from-edge": "Anular asignación de borde", "unassign-dashboards-from-edge-action-title": "Anular asignación { count, plural, 1 {1 panel} other {# paneles} } de borde", "unassign-dashboards-from-edge-text": "Después de la confirmación, se anulará la asignación de todos los paneles seleccionados y no serán accesibles por de borde", "assign-dashboard-to-edge": "Asignar panel(es) al borde", - "assign-dashboard-to-edge-text": "Por favor selecciona los paneles para asignar al borde", - "assign-dashboards-to-edge-text": "Asignar { count, plural, 1 {1 panel} other {# paneles} } a los bordes", - "unassign-dashboards-from-edge-action-text": "Anular asignación { count, plural, 1 {1 dashboard} other {# dashboards} } de los bordes", - "assign-to-edges": "Asignar paneles a los bordes", - "assign-to-edges-text": "Seleccione los bordes para asignar los paneles", - "unassign-from-edges": "Desasignar panel (s) de los bordes", - "unassign-from-edge-text": "Seleccione los bordes para desasignar del panel(es)" + "assign-dashboard-to-edge-text": "Por favor selecciona los paneles para asignar al borde" }, "datakey": { "settings": "Configuración", @@ -725,15 +727,12 @@ "import": "Importar dispositivo", "assign-device-to-edge": "Asignar dispositivo (s) a borde", "assign-device-to-edge-text": "Seleccione los dispositivos para asignar al borde", - "unassign-from-edge": "Anular asignación de borde", - "assign-to-edge": "Asignar al borde", - "assign-to-edge-text": "Seleccione el borde para asignar los dispositivos", "unassign-device-from-edge-title": "¿Está seguro de que desea desasignar el dispositivo '{{deviceName}}'?", "unassign-device-from-edge-text": "Después de la confirmación, el dispositivo no será asignado y el borde no podrá acceder a él", - "unassign-devices-from-edge-action-title": "Anular asignación {count, plural, 1 {1 device} other {# devices}} from edge", + "unassign-devices-from-edge-action-title": "Anular asignación {count, plural, 1 {1 dispositivo} other {# dispositivos}} desde el borde", "unassign-device-from-edge": "Desasignar dispositivo", - "unassign-devices-from-edge-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 device} other {# devices}}?", - "unassign-devices-from-edge-text": "Después de la confirmación, todos los dispositivos seleccionados quedarán sin asignar y el borde no podrá acceder a ellos" + "unassign-devices-from-edge-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 dispositivo} other {# dispositivos}}?", + "unassign-devices-from-edge-text": "Después de la confirmación, todos los dispositivos seleccionados quedarán sin asignar y el borde no podrá acceder a ellos." }, "dialog": { "close": "Cerrar diálogo" @@ -746,10 +745,10 @@ "edge": "Borde", "edges": "Bordes", "management": "Gestión de bordes", - "no-edge-matching": "No se encontraron bordes que coincidan con '{{entity}}'", + "no-edges-matching": "No se encontraron bordes que coincidan con '{{entity}}'", "add": "Agregar borde", "view": "Ver borde", - "no-edge-text": "No se encontraron bordes", + "no-edges-text": "No se encontraron bordes", "edge-details": "Detalles del borde", "add-edge-text": "Agregar nuevo borde", "delete": "Eliminar borde", @@ -757,7 +756,7 @@ "delete-edge-title": "¿Está seguro de que desea eliminar el borde '{{edgeName}}'?", "delete-edge-text": "Tenga cuidado, después de la confirmación, el borde y todos los datos relacionados serán irrecuperables", "delete-edges-title": "¿Está seguro de que desea edge {count, plural, 1 {1 borde} other {# bordes}}?", - "delete-edge-action-title": "Eliminar {cuenta, plural, 1 {1 borde} otro {# bordes}}", + "delete-edges-action-title": "Eliminar {cuenta, plural, 1 {1 borde} other {# bordes}}", "delete-edges-text": "Tenga cuidado, después de la confirmación se eliminarán todos los bordes seleccionados y todos los datos relacionados se volverán irrecuperables", "name": "Nombre", "name-required": "Se requiere nombre", @@ -777,7 +776,7 @@ "assign-edge-to-customer-text": "Seleccione los bordes para asignar al cliente", "assigned-to-customer": "Asignado al cliente", "unassign-from-customer": "Anular asignación del cliente", - "assign-edges-text": "Asignar {cuenta, plural, 1 {1 borde} otro {# bordes}} al cliente", + "assign-edges-text": "Asignar {cuenta, plural, 1 {1 borde} other {# bordes}} al cliente", "unassign-edge-title": "¿Está seguro de que desea desasignar el borde '{{edgeName}}'?", "unassign-edge-text": "Después de la confirmación, el borde quedará sin asignar y el cliente no podrá acceder a él", "make-public": "Hacer público el borde", @@ -809,8 +808,17 @@ "devices": "Dispositivos de borde", "entity-views": "Vistas de entidad de borde", "set-root-rule-chain-text": "Seleccione la cadena de reglas raíz para los bordes", - "set-root-rule-chain-to-edge": "Establecer la cadena de reglas raíz para Edge (s)", - "set-root-rule-chain-to-edge-text": "Establecer la cadena de la regla raíz para {count, plural, 1 {1 borde} other {# bordes}}" + "set-root-rule-chain-to-edges": "Establecer la cadena de reglas raíz para Edge (s)", + "set-root-rule-chain-to-edges-text": "Establecer la cadena de la regla raíz para {count, plural, 1 {1 borde} other {# bordes}}", + "status": "Recibido por borde", + "success": "Desplegada", + "failed": "Pendiente", + "entity-id": "ID de entidad", + "entity-info": "Entity info", + "event-action": "Información de la entidad", + "load-entity-error": "Entidad no encontrada. No se pudo cargar la información", + "unassign-edges-text": "Después de la confirmación de todos los bordes seleccionados, se anulará la asignación y el cliente no podrá acceder a ellos.", + "unassign-edges-title": "¿Está seguro de que desea anular la asignación de {count, plural, 1 {1 borde} other {# bordes}}?" }, "error": { "unable-to-connect": "¡No se puede conectar al servidor! Por favor, revise su conexión a Internet.", @@ -907,7 +915,7 @@ "rulenode-name-starts-with": "Nodos de reglas cuyos nombres comienzan con '{{prefix}}'", "type-edge": "Borde", "type-edges": "Bordes", - "list-of-edges": "{cuenta, plural, 1 {Un borde} otro {Lista de # bordes}}", + "list-of-edges": "{cuenta, plural, 1 {Un borde} other {Lista de # bordes}}", "edge-name-starts-with": "Bordes cuyos nombres comienzan con '{{prefijo}}'", "type-current-customer": "Cliente Actual", "search": "Buscar entidades", @@ -1031,9 +1039,6 @@ "make-private-entity-view-text": "Después de la confirmación, la vista de la entidad y todos sus datos se harán privados y no serán accesibles para otros.", "assign-entity-view-to-edge": "Asignar vista (s) de entidad a borde", "assign-entity-view-to-edge-text": "Seleccione las vistas de entidad para asignar al borde", - "unassign-from-edge": "Anular asignación de borde", - "assign-to-edge": "Asignar al borde", - "assign-to-edge-text": "Seleccione el borde para asignar las vistas de entidad", "unassign-entity-view-from-edge-title": "¿Está seguro de que desea anular la asignación de la vista de entidad '{{entityViewName}}'?", "unassign-entity-view-from-edge-text": "Después de la confirmación, la vista de entidad quedará sin asignar y el borde no podrá acceder a ella", "unassign-entity-views-from-edge-action-title": "Anular asignación {recuento, plural, 1 {1 vista de entidad} otras {# vistas de entidad}} del borde", @@ -1050,6 +1055,7 @@ "type-debug-rule-chain": "Depurar", "no-events-prompt": "No se encontraron eventos", "error": "Error", + "type-edge-event": "Downlink", "alarm": "Alarma", "event-time": "Tiempo del evento", "server": "Servidor", @@ -1453,21 +1459,11 @@ "unassign-rulechains": "Anular asignación de cadenas de reglas", "unassign-rulechain-title": "¿Está seguro de que desea desasignar la cadena de reglas '{{ruleChainTitle}}'?", "unassign-rulechains-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 cadena de reglas} other {# cadenas de reglas}}?", - "manage-assigned-edges": "Gestionar bordes asignados", "unassign-rulechain-from-edge-text": "Después de la confirmación, la cadena de reglas quedará sin asignar y el borde no podrá acceder a ella", - "assigned-edges": "Bordes asignados", - "unassign-from-edge": "Anular asignación de borde", "unassign-rulechains-from-edge-action-title": "Anular asignación {count, plural, 1 {1 cadena de reglas} other {# cadenas de reglas}} des bordes", "unassign-rulechains-from-edge-text": "Después de la confirmación, todas las cadenas de reglas seleccionadas quedarán sin asignar y el borde no podrá acceder a ellas", - "assign-rulechains-to-edge-text": "Asignar {cuenta, plural, 1 {1 cadena de reglas} otras {# cadenas de reglas}} a las aristas", "assign-rulechain-to-edge": "Asignar cadena (s) de reglas a borde", "assign-rulechain-to-edge-text": "Seleccione las cadenas de reglas para asignar al borde", - "unassign-rulechains-from-edge-action-text": "Anular asignación {cuenta, plural, 1 {1 cadena de reglas} otro {# cadenas de reglas}} de los bordes", - "assign-to-edges": "Asignar cadena (s) de reglas a los bordes", - "assign-to-edges-text": "Seleccione los bordes para asignar las cadenas de reglas", - "unassign-from-edges": "Desasignar cadena (s) de reglas de los bordes", - "unassign-from-edges-text": "Seleccione los bordes para desasignar de la (s) cadena (s) de reglas", - "assigned-to-edges": "Asignado a bordes", "set-default-root-edge": "Hacer que la cadena de reglas sea la raíz predeterminada", "set-default-root-edge-rulechain-title": "¿Está seguro de que desea hacer que la cadena de reglas '{{ruleChainName}}' sea la raíz de borde predeterminada?", "set-default-root-edge-rulechain-text": "Después de la confirmación, la cadena de reglas se convertirá en raíz raíz predeterminada y manejará todos los mensajes de transporte entrantes", diff --git a/ui/src/app/locale/locale.constant-fr_FR.json b/ui/src/app/locale/locale.constant-fr_FR.json index 0a0e385350..3cf911e3a5 100644 --- a/ui/src/app/locale/locale.constant-fr_FR.json +++ b/ui/src/app/locale/locale.constant-fr_FR.json @@ -260,17 +260,6 @@ "name": "Nom", "name-required": "Nom est requis.", "name-starts-with": "Le nom de l'actif commence par", - "assign-asset-to-edge": "Attribuer des actifs a la bordure", - "assign-asset-to-edge-text": "Veuillez sélectionner les actifs à attribuer a la bordure", - "unassign-from-edge": "Retirer de la bordure", - "assign-to-edge": "Attribuer a la bordure", - "assign-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les actifs", - "unassign-asset-from-edge": "Retirer de la bordure", - "unassign-asset-from-edge-title": "Êtes-vous sûr de vouloir retirer l'attribution de l'actif '{{assetName}}'?", - "unassign-asset-from-edge-text": "Après la confirmation, l'actif sera non attribué et ne sera pas accessible a la bordure.", - "unassign-assets-from-edge-action-title": "Retirer {count, plural, 1 {1 asset} other {# assets}} de la bordure", - "unassign-assets-from-edge-title": "Êtes-vous sûr de vouloir retirer l'attribution de {count, plural, 1 {1 asset} other {# assets}}?", - "unassign-assets-from-edge-text": "Après la confirmation, tous les actifs sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure.", "no-asset-types-matching": "Aucun type d'actif correspondant à {{entitySubtype}} n'a été trouvé. ", "no-assets-matching": "Aucun actif correspondant à {{entity}} n'a été trouvé. ", "no-assets-text": "Aucun actif trouvé", @@ -288,7 +277,15 @@ "unassign-assets-title": "Êtes-vous sûr de vouloir retirer l'attribution de {count, plural, 1 {1 asset} other {# assets}}?", "unassign-from-customer": "Retirer du client", "view-assets": "Afficher les actifs", - "label": "Label" + "label": "Label", + "assign-asset-to-edge": "Attribuer des actifs a la bordure", + "assign-asset-to-edge-text": "Veuillez sélectionner les actifs à attribuer a la bordure", + "unassign-asset-from-edge": "Retirer de la bordure", + "unassign-asset-from-edge-title": "Êtes-vous sûr de vouloir retirer l'attribution de l'actif '{{assetName}}'?", + "unassign-asset-from-edge-text": "Après la confirmation, l'actif sera non attribué et ne sera pas accessible a la bordure.", + "unassign-assets-from-edge-action-title": "Retirer {count, plural, 1 {1 asset} other {# assets}} de la bordure", + "unassign-assets-from-edge-title": "Êtes-vous sûr de vouloir retirer l'attribution de {count, plural, 1 {1 asset} other {# assets}}?", + "unassign-assets-from-edge-text": "Après la confirmation, tous les actifs sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure." }, "attribute": { "add": "Ajouter un attribut", @@ -435,6 +432,7 @@ "manage-customer-users": "Gérer les utilisateurs du client", "manage-dashboards": "Gérer les tableaux de bord", "manage-devices": "Gérer les dispositifs", + "manage-edges": "Gérer les bordures ", "manage-public-assets": "Gérer les actifs publics", "manage-public-dashboards": "Gérer les tableaux de bord publics", "manage-public-devices": "Gérer les dispositifs publics", @@ -593,20 +591,11 @@ "widget-file": "Fichier du Widget", "widget-import-missing-aliases-title": "Configurer les alias utilisés par le widget importé", "widgets-margins": "Marge entre les widgets", - "manage-assigned-edges": "Gérer les bordures affectés", "unassign-dashboard-from-edge-text": "Après la confirmation, tableau de bord sera non attribué et ne sera pas accessible a la bordure.", - "assigned-edges": "Bordures affectés", - "unassign-from-edge": "Retirer de la bordure", "unassign-dashboards-from-edge-action-title": "Annuler l'affectation {count, plural, 1 {1 tableau de bord} other {# tableaux de bord}} de la bordure", "unassign-dashboards-from-edge-text": "Après la confirmation, tous les tableaux de bord sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure.", "assign-dashboard-to-edge": "Attribuer des tableaux de bord a la bordure", - "assign-dashboard-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les tableaux de bord", - "assign-dashboards-to-edge-text": "Attribuer {count, plural, 1 {1 tableau de bord} other {# tableaux de bord}} aux bordures", - "unassign-dashboards-from-edge-action-text": "Annuler l'affectation {count, plural, 1 {1 tableau de bord} other {# tableaux de bord}} des bordures", - "assign-to-edges": "Attribuer des tableaux de bord a la bordures", - "assign-to-edges-text": "Veuillez sélectionner les bordures pour attribuer les tableaux de bord", - "unassign-from-edges": "Retirer de la bordure", - "unassign-from-edges-text": "Veuillez sélectionner les bordures à annuler l'affectation du ou des tableaux de bord" + "assign-dashboard-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les tableaux de bord" }, "datakey": { "advanced": "Avancé", @@ -747,9 +736,6 @@ "view-devices": "Afficher les dispositifs", "assign-device-to-edge": "Attribuer a la bordure", "assign-device-to-edge-text":"Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", - "unassign-from-edge": "Retirer de la bordure", - "assign-to-edge": "Attribuer a la bordure", - "assign-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", "unassign-device-from-edge-title": "Êtes-vous sûr de vouloir annuler l'affection du dispositif {{deviceName}} '?", "unassign-device-from-edge-text": "Après la confirmation, dispositif sera non attribué et ne sera pas accessible a la bordure.", "unassign-devices-from-edge-action-title": "Annuler l'affectation de {count, plural, 1 {1 device} other {#devices}} de la bordure", @@ -828,7 +814,16 @@ "entity-views": "Vues de l'entité bordure", "set-root-rule-chain-text": "Veuillez sélectionner la chaîne de règles racine pour les bordure(s)", "set-root-rule-chain-to-edges": "Définir la chaîne de règles racine pour bordure(s)", - "set-root-rule-chain-to-edges-text": "Définir la chaîne de règles racine pour {count, plural, 1 {1 bordure} other {# bordures} }" + "set-root-rule-chain-to-edges-text": "Définir la chaîne de règles racine pour {count, plural, 1 {1 bordure} other {# bordures} }", + "status": "Reçu par bord", + "success": "Déployée", + "failed": "En attente", + "entity-id": "ID d'entité", + "entity-info": "Informations sur l'entité", + "event-action": "Action d'événement", + "load-entity-error": "Entité introuvable. Échec du chargement des informations", + "unassign-edges-text": "Après la confirmation, tous les bordures sélectionnés ne seront plus attribués et ne seront pas accessibles par le client.", + "unassign-edges-title": "Voulez-vous vraiment annuler l'attribution de {count, plural, 1 {1 bordure} other {# bordures}}?" }, "entity": { "add-alias": "Ajouter un alias d'entité", @@ -1006,9 +1001,6 @@ "make-public-entity-view-title": "Voulez-vous vraiment que la vue de l'entité '{{entityViewName}}' soit publique?", "assign-entity-view-to-edge": "Attribuer a la bordure", "assign-entity-view-to-edge-text":"Veuillez sélectionner la bordure auquel attribuer la ou les vues d'entité.", - "unassign-from-edge": "Retirer de la bordure", - "assign-to-edge": "Attribuer a la bordure", - "assign-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les actifs", "unassign-entity-view-from-edge-title": "Voulez-vous vraiment annuler l'attribution de la vue d'entité '{{entityViewName}}'?", "unassign-entity-view-from-edge-text": "Après la confirmation, la vue de l'entité sera non attribuée et ne sera pas accessible par la bordure.", "unassign-entity-views-from-edge-action-title": "Annuler l'attribution { count, plural, 1 {1 entityView} other {# entityViews} } de la bordure", @@ -1065,6 +1057,7 @@ "data-type": "Type de données", "entity": "Entité", "error": "erreur", + "type-edge-event": "Downlink", "errors-occurred": "Des erreurs sont survenues", "event": "événement", "event-time": "Heure de l'événement", @@ -1443,21 +1436,11 @@ "unassign-rulechains": "Retirer chaînes de règles", "unassign-rulechain-title": "AÊtes-vous sûr de vouloir retirer l'attribution de chaînes de règles '{{ruleChainTitle}}'?", "unassign-rulechains-title": "Êtes-vous sûr de vouloir retirer l'attribution de {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}}?", - "manage-assigned-edges": "Gérer les bordures affectés", "unassign-rulechain-from-edge-text": "Après la confirmation, l'actif sera non attribué et ne sera pas accessible a la bordure.", - "assigned-edges": "Bordures affectés", - "unassign-from-edge": "Retirer de la bordure", "unassign-rulechains-from-edge-action-title": "Retirer {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}} de la bordure", "unassign-rulechains-from-edge-text": "Après la confirmation, tous les chaînes de règles sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure.", - "assign-rulechains-to-edge-text": "Attribuer {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}} aux bordures", "assign-rulechain-to-edge": "Attribuer les chaînes de règles a la bordure", "assign-rulechain-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les chaînes de règles", - "unassign-rulechains-from-edge-action-text": "Annuler l'affectation {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}} des bordures", - "assign-to-edges": "Attribuer des tableaux de bord a la bordures", - "assign-to-edges-text": "Please select the edges to assign the rulechain(s)", - "unassign-from-edges": "Retirer de la bordure", - "unassign-from-edges-text": "Veuillez sélectionner les bordures à annuler l'affectation du ou des chaînes de règles", - "assigned-to-edges": "Attribué chaînes de règles", "set-default-root-edge": "Définir la racine par défaut de la chaîne de règles", "set-default-root-edge-rulechain-title": "AVoulez-vous vraiment créer de chaînes de règles par défaut '{{ruleChainName}}'?", "set-default-root-edge-rulechain-text": "Après la confirmation, la chaîne de règles deviendra la racine de la bordure par défaut et gérera tous les messages de transport entrants.", diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index 16ee29bd1a..bc85f20c61 100644 --- a/ui/src/app/rulechain/rulechains.controller.js +++ b/ui/src/app/rulechain/rulechains.controller.js @@ -278,7 +278,7 @@ export default function RuleChainsController(ruleChainService, userService, impo unassignFromEdge($event, item, edgeId); }, name: function() { return $translate.instant('action.unassign') }, - details: function() { return $translate.instant('rulechain.unassign-from-edge') }, + details: function() { return $translate.instant('edge.unassign-from-edge') }, icon: "assignment_return", isEnabled: isNonRootRuleChain } From a6ae072bc9223a16b22751245058debc41a23014 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 22 Sep 2020 12:41:49 +0300 Subject: [PATCH 120/156] edge services code coverage --- .../src/main/resources/thingsboard.yml | 2 +- msa/black-box-tests/pom.xml | 5 + .../server/msa/ContainerTestSuite.java | 2 +- .../server/msa/edge/EdgeImitator.java | 156 ++++++++ .../server/msa/edge/EdgeStorage.java | 120 ++++++ .../thingsboard/server/msa/edge/EdgeTest.java | 341 ++++++++++++++++++ .../src/test/resources/RootRuleChain.json | 133 +++++++ 7 files changed, 757 insertions(+), 2 deletions(-) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java create mode 100644 msa/black-box-tests/src/test/resources/RootRuleChain.json diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index bcf3425f53..db83fd700a 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -588,7 +588,7 @@ transport: # Edges parameters edges: rpc: - enabled: "${EDGES_RPC_ENABLED:false}" + enabled: "${EDGES_RPC_ENABLED:true}" port: "${EDGES_RPC_PORT:7070}" ssl: # Enable/disable SSL support diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index d24f38bc36..1602d24185 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -94,6 +94,11 @@ org.thingsboard rest-client + + org.thingsboard.common + edge-api + test + diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java index 647c8878b7..5a798a8cc8 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Map; @RunWith(ClasspathSuite.class) -@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*Test"}) +@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*EdgeTest"}) public class ContainerTestSuite { private static DockerComposeContainer testContainer; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java new file mode 100644 index 0000000000..823d180261 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java @@ -0,0 +1,156 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.edge; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.thingsboard.edge.rpc.EdgeGrpcClient; +import org.thingsboard.edge.rpc.EdgeRpcClient; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceUpdateMsg; +import org.thingsboard.server.gen.edge.DownlinkMsg; +import org.thingsboard.server.gen.edge.DownlinkResponseMsg; +import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; +import org.thingsboard.server.gen.edge.UplinkResponseMsg; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Slf4j +public class EdgeImitator { + + private String routingKey; + private String routingSecret; + + private EdgeRpcClient edgeRpcClient; + + @Getter + private EdgeStorage storage; + + + public EdgeImitator(String host, int port, String routingKey, String routingSecret) throws NoSuchFieldException, IllegalAccessException { + edgeRpcClient = new EdgeGrpcClient(); + storage = new EdgeStorage(); + this.routingKey = routingKey; + this.routingSecret = routingSecret; + setEdgeCredentials("rpcHost", host); + setEdgeCredentials("rpcPort", port); + } + + private void setEdgeCredentials(String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { + Field fieldToSet = edgeRpcClient.getClass().getDeclaredField(fieldName); + fieldToSet.setAccessible(true); + fieldToSet.set(edgeRpcClient, value); + fieldToSet.setAccessible(false); + } + + public void connect() { + edgeRpcClient.connect(routingKey, routingSecret, + this::onUplinkResponse, + this::onEdgeUpdate, + this::onDownlink, + this::onError); + } + + public void disconnect() throws InterruptedException { + edgeRpcClient.disconnect(); + } + + private void onUplinkResponse(UplinkResponseMsg msg) { + log.info("onUplinkResponse: {}", msg); + } + + private void onEdgeUpdate(EdgeConfiguration edgeConfiguration) { + storage.setConfiguration(edgeConfiguration); + } + + private void onDownlink(DownlinkMsg downlinkMsg) { + ListenableFuture> future = processDownlinkMsg(downlinkMsg); + Futures.addCallback(future, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List result) { + DownlinkResponseMsg downlinkResponseMsg = DownlinkResponseMsg.newBuilder().setSuccess(true).build(); + edgeRpcClient.sendDownlinkResponseMsg(downlinkResponseMsg); + } + + @Override + public void onFailure(Throwable t) { + DownlinkResponseMsg downlinkResponseMsg = DownlinkResponseMsg.newBuilder().setSuccess(false).setErrorMsg(t.getMessage()).build(); + edgeRpcClient.sendDownlinkResponseMsg(downlinkResponseMsg); + } + }, MoreExecutors.directExecutor()); + } + + private void onError(Exception e) { + log.error("Error during Edge lifecycle: ", e); + } + + private ListenableFuture> processDownlinkMsg(DownlinkMsg downlinkMsg) { + List> result = new ArrayList<>(); + if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { + for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { + result.add(storage.processEntity(deviceUpdateMsg.getMsgType(), EdgeEventType.DEVICE, new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()))); + } + } + if (downlinkMsg.getAssetUpdateMsgList() != null && !downlinkMsg.getAssetUpdateMsgList().isEmpty()) { + for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) { + result.add(storage.processEntity(assetUpdateMsg.getMsgType(), EdgeEventType.ASSET, new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB()))); + } + } + if (downlinkMsg.getRuleChainUpdateMsgList() != null && !downlinkMsg.getRuleChainUpdateMsgList().isEmpty()) { + for (RuleChainUpdateMsg ruleChainUpdateMsg: downlinkMsg.getRuleChainUpdateMsgList()) { + result.add(storage.processEntity(ruleChainUpdateMsg.getMsgType(), EdgeEventType.RULE_CHAIN, new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB()))); + } + } + if (downlinkMsg.getDashboardUpdateMsgList() != null && !downlinkMsg.getDashboardUpdateMsgList().isEmpty()) { + for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) { + result.add(storage.processEntity(dashboardUpdateMsg.getMsgType(), EdgeEventType.DASHBOARD, new UUID(dashboardUpdateMsg.getIdMSB(), dashboardUpdateMsg.getIdLSB()))); + } + } + if (downlinkMsg.getRelationUpdateMsgList() != null && !downlinkMsg.getRelationUpdateMsgList().isEmpty()) { + for (RelationUpdateMsg relationUpdateMsg: downlinkMsg.getRelationUpdateMsgList()) { + result.add(storage.processRelation(relationUpdateMsg)); + } + } + if (downlinkMsg.getAlarmUpdateMsgList() != null && !downlinkMsg.getAlarmUpdateMsgList().isEmpty()) { + for (AlarmUpdateMsg alarmUpdateMsg: downlinkMsg.getAlarmUpdateMsgList()) { + result.add(storage.processAlarm(alarmUpdateMsg)); + } + } + if (downlinkMsg.getEntityDataList() != null && !downlinkMsg.getEntityDataList().isEmpty()) { + for (EntityDataProto entityDataProto: downlinkMsg.getEntityDataList()) { + if (entityDataProto.hasPostTelemetryMsg()) { + result.add(storage.processTelemetry(new UUID(entityDataProto.getEntityIdMSB(), entityDataProto.getEntityIdLSB()), entityDataProto.getPostTelemetryMsg())); + } + } + } + return Futures.allAsList(result); + } + +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java new file mode 100644 index 0000000000..0bad7473cf --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java @@ -0,0 +1,120 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.edge; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.transport.TransportProtos; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +@Slf4j +@Getter +@Setter +public class EdgeStorage { + + private EdgeConfiguration configuration; + + private Map entities; + private Map alarms; + private List relations; + private Map latestTelemetry; + + + public EdgeStorage() { + entities = new HashMap<>(); + alarms = new HashMap<>(); + relations = new ArrayList<>(); + latestTelemetry = new HashMap<>(); + } + + public ListenableFuture processEntity(UpdateMsgType msgType, EdgeEventType type, UUID uuid) { + switch (msgType) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + entities.put(uuid, type); + break; + case ENTITY_DELETED_RPC_MESSAGE: + entities.remove(uuid); + break; + } + return Futures.immediateFuture(null); + } + + public ListenableFuture processRelation(RelationUpdateMsg relationMsg) { + EntityRelation relation = new EntityRelation(); + relation.setType(relationMsg.getType()); + relation.setTypeGroup(RelationTypeGroup.valueOf(relationMsg.getTypeGroup())); + relation.setTo(EntityIdFactory.getByTypeAndUuid(relationMsg.getToEntityType(), new UUID(relationMsg.getToIdMSB(), relationMsg.getToIdLSB()))); + relation.setFrom(EntityIdFactory.getByTypeAndUuid(relationMsg.getFromEntityType(), new UUID(relationMsg.getFromIdMSB(), relationMsg.getFromIdLSB()))); + switch (relationMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + relations.add(relation); + break; + case ENTITY_DELETED_RPC_MESSAGE: + relations.remove(relation); + break; + } + return Futures.immediateFuture(null); + } + + public ListenableFuture processAlarm(AlarmUpdateMsg alarmMsg) { + switch (alarmMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE: + case ENTITY_UPDATED_RPC_MESSAGE: + case ALARM_ACK_RPC_MESSAGE: + case ALARM_CLEAR_RPC_MESSAGE: + alarms.put(alarmMsg.getType(), AlarmStatus.valueOf(alarmMsg.getStatus())); + break; + case ENTITY_DELETED_RPC_MESSAGE: + alarms.remove(alarmMsg.getName()); + break; + } + return Futures.immediateFuture(null); + } + + public ListenableFuture processTelemetry(UUID uuid, TransportProtos.PostTelemetryMsg telemetryMsg) { + latestTelemetry.put(uuid, telemetryMsg); + return Futures.immediateFuture(null); + } + + public Set getEntitiesByType(EdgeEventType type) { + Map filtered = entities.entrySet().stream() + .filter(entry -> entry.getValue().equals(type)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return filtered.keySet(); + } + +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java new file mode 100644 index 0000000000..a1f8c8e374 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java @@ -0,0 +1,341 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.edge; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.junit.*; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmInfo; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.kv.TsKvEntry; +import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainMetaData; +import org.thingsboard.server.common.data.rule.RuleChainType; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.msa.AbstractContainerTest; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +@Slf4j +public class EdgeTest extends AbstractContainerTest { + + private static EdgeImitator edgeImitator; + + @BeforeClass + public static void init() throws NoSuchFieldException, IllegalAccessException, InterruptedException, IOException { + restClient.login("tenant@thingsboard.org", "tenant"); + installation(); + edgeImitator = new EdgeImitator("localhost", 7070, "routing", "secret"); + edgeImitator.connect(); + Thread.sleep(10000); + } + + @Test + public void testReceivedData() { + Edge edge = restClient.getTenantEdge("Edge1").get(); + + EdgeConfiguration configuration = edgeImitator.getStorage().getConfiguration(); + Assert.assertNotNull(configuration); + + Map entities = edgeImitator.getStorage().getEntities(); + Assert.assertFalse(entities.isEmpty()); + + Set devices = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DEVICE); + Assert.assertEquals(1, devices.size()); + for (Device device: restClient.getEdgeDevices(edge.getId(), new TextPageLink(1)).getData()) { + Assert.assertTrue(devices.contains(device.getUuidId())); + } + + Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.RULE_CHAIN); + Assert.assertEquals(1, ruleChains.size()); + for (RuleChain ruleChain: restClient.getEdgeRuleChains(edge.getId(), new TimePageLink(1)).getData()) { + Assert.assertTrue(ruleChains.contains(ruleChain.getUuidId())); + } + + Set assets = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.ASSET); + Assert.assertEquals(1, assets.size()); + for (Asset asset: restClient.getEdgeAssets(edge.getId(), new TextPageLink(1)).getData()) { + Assert.assertTrue(assets.contains(asset.getUuidId())); + } + } + + @Test + public void testDevices() throws Exception { + Edge edge = restClient.getTenantEdge("Edge1").get(); + + Device device = new Device(); + device.setName("Edge Device 2"); + device.setType("test"); + Device savedDevice = restClient.saveDevice(device); + restClient.assignDeviceToEdge(edge.getId(), savedDevice.getId()); + + Thread.sleep(1000); + Assert.assertTrue(restClient.getEdgeDevices(edge.getId(), new TextPageLink(2)).getData().contains(savedDevice)); + Set devices = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DEVICE); + Assert.assertEquals(2, devices.size()); + Assert.assertTrue(devices.contains(savedDevice.getUuidId())); + + restClient.unassignDeviceFromEdge(edge.getId(), savedDevice.getId()); + Thread.sleep(1000); + Assert.assertFalse(restClient.getEdgeDevices(edge.getId(), new TextPageLink(2)).getData().contains(savedDevice)); + devices = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DEVICE); + Assert.assertEquals(1, devices.size()); + Assert.assertFalse(devices.contains(savedDevice.getUuidId())); + + restClient.deleteDevice(savedDevice.getId()); + } + + @Test + public void testAssets() throws Exception { + Edge edge = restClient.getTenantEdge("Edge1").get(); + + Asset asset = new Asset(); + asset.setName("Edge Asset 2"); + asset.setType("test"); + Asset savedAsset = restClient.saveAsset(asset); + restClient.assignAssetToEdge(edge.getId(), savedAsset.getId()); + + Thread.sleep(1000); + Assert.assertTrue(restClient.getEdgeAssets(edge.getId(), new TextPageLink(2)).getData().contains(savedAsset)); + Set assets = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.ASSET); + Assert.assertEquals(2, assets.size()); + Assert.assertTrue(assets.contains(savedAsset.getUuidId())); + + restClient.unassignAssetFromEdge(edge.getId(), savedAsset.getId()); + Thread.sleep(1000); + Assert.assertFalse(restClient.getEdgeAssets(edge.getId(), new TextPageLink(2)).getData().contains(savedAsset)); + assets = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.ASSET); + Assert.assertEquals(1, assets.size()); + Assert.assertFalse(assets.contains(savedAsset.getUuidId())); + + restClient.deleteAsset(savedAsset.getId()); + } + + @Test + public void testRuleChains() throws Exception { + Edge edge = restClient.getTenantEdge("Edge1").get(); + + RuleChain ruleChain = new RuleChain(); + ruleChain.setName("Edge Test Rule Chain"); + ruleChain.setType(RuleChainType.EDGE); + RuleChain savedRuleChain = restClient.saveRuleChain(ruleChain); + restClient.assignRuleChainToEdge(edge.getId(), savedRuleChain.getId()); + + Thread.sleep(1000); + Assert.assertTrue(restClient.getEdgeRuleChains(edge.getId(), new TimePageLink(2)).getData().contains(savedRuleChain)); + Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.RULE_CHAIN); + Assert.assertEquals(2, ruleChains.size()); + Assert.assertTrue(ruleChains.contains(savedRuleChain.getUuidId())); + + restClient.unassignRuleChainFromEdge(edge.getId(), savedRuleChain.getId()); + Thread.sleep(1000); + Assert.assertFalse(restClient.getEdgeRuleChains(edge.getId(), new TimePageLink(2)).getData().contains(savedRuleChain)); + ruleChains = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.RULE_CHAIN); + Assert.assertEquals(1, ruleChains.size()); + Assert.assertFalse(ruleChains.contains(savedRuleChain.getUuidId())); + + restClient.deleteRuleChain(savedRuleChain.getId()); + + } + + @Test + public void testDashboards() throws Exception { + Edge edge = restClient.getTenantEdge("Edge1").get(); + + Dashboard dashboard = new Dashboard(); + dashboard.setTitle("Edge Test Dashboard"); + Dashboard savedDashboard = restClient.saveDashboard(dashboard); + restClient.assignDashboardToEdge(edge.getId(), savedDashboard.getId()); + + Thread.sleep(1000); + Assert.assertTrue(restClient.getEdgeDashboards(edge.getId(), new TimePageLink(2)).getData().stream().allMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); + Set dashboards = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DASHBOARD); + Assert.assertEquals(1, dashboards.size()); + Assert.assertTrue(dashboards.contains(savedDashboard.getUuidId())); + + restClient.unassignDashboardFromEdge(edge.getId(), savedDashboard.getId()); + Thread.sleep(1000); + Assert.assertFalse(restClient.getEdgeDashboards(edge.getId(), new TimePageLink(2)).getData().stream().anyMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); + dashboards = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DASHBOARD); + Assert.assertEquals(0, dashboards.size()); + Assert.assertFalse(dashboards.contains(savedDashboard.getUuidId())); + + restClient.deleteDashboard(savedDashboard.getId()); + + } + + @Test + public void testRelations() throws InterruptedException { + Device device = restClient.getTenantDevice("Edge Device 1").get(); + Asset asset = restClient.getTenantAsset("Edge Asset 1").get(); + + EntityRelation relation = new EntityRelation(); + relation.setType("test"); + relation.setFrom(device.getId()); + relation.setTo(asset.getId()); + relation.setTypeGroup(RelationTypeGroup.COMMON); + restClient.saveRelation(relation); + + Thread.sleep(1000); + List relations = edgeImitator.getStorage().getRelations(); + Assert.assertEquals(1, relations.size()); + Assert.assertTrue(relations.contains(relation)); + restClient.deleteRelation(relation.getFrom(), relation.getType(), relation.getTypeGroup(), relation.getTo()); + + Thread.sleep(1000); + relations = edgeImitator.getStorage().getRelations(); + Assert.assertEquals(0, relations.size()); + Assert.assertFalse(relations.contains(relation)); + } + + @Test + public void testAlarms() throws Exception { + Device device = restClient.getTenantDevice("Edge Device 1").get(); + Alarm alarm = new Alarm(); + alarm.setOriginator(device.getId()); + alarm.setStatus(AlarmStatus.ACTIVE_UNACK); + alarm.setType("alarm"); + alarm.setSeverity(AlarmSeverity.CRITICAL); + + Alarm savedAlarm = restClient.saveAlarm(alarm); + AlarmInfo alarmInfo = restClient.getAlarmInfoById(savedAlarm.getId()).get(); + Thread.sleep(1000); + + Assert.assertEquals(1, edgeImitator.getStorage().getAlarms().size()); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().containsKey(alarmInfo.getType())); + Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + restClient.ackAlarm(savedAlarm.getId()); + + Thread.sleep(1000); + alarmInfo = restClient.getAlarmInfoById(savedAlarm.getId()).get(); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); + Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + restClient.clearAlarm(savedAlarm.getId()); + + Thread.sleep(1000); + alarmInfo = restClient.getAlarmInfoById(savedAlarm.getId()).get(); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isCleared()); + Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + + restClient.deleteAlarm(savedAlarm.getId()); + + } + + @Ignore + @Test + public void testTelemetry() throws Exception { + Device device = restClient.getTenantDevice("Edge Device 1").get(); + DeviceCredentials deviceCredentials = restClient.getDeviceCredentialsByDeviceId(device.getId()).get(); + ResponseEntity response = restClient.getRestTemplate() + .postForEntity(HTTPS_URL + "/api/v1/{credentialsId}/telemetry", + "{'test': 25}", + ResponseEntity.class, + deviceCredentials.getCredentialsId()); + Assert.assertEquals(response.getStatusCode(), HttpStatus.OK); + Thread.sleep(1000); + List keys = restClient.getTimeseriesKeys(device.getId()); + List latestTimeseries = restClient.getLatestTimeseries(device.getId(), keys); + Assert.assertEquals(1, latestTimeseries.size()); + TsKvEntry tsKvEntry = latestTimeseries.get(0); + Map telemetry = edgeImitator.getStorage().getLatestTelemetry(); + Assert.assertEquals(1, telemetry.size()); + Assert.assertTrue(telemetry.containsKey(device.getUuidId())); + TransportProtos.PostTelemetryMsg telemetryMsg = telemetry.get(device.getUuidId()); + Assert.assertEquals(1, telemetryMsg.getTsKvListCount()); + TransportProtos.TsKvListProto tsKv = telemetryMsg.getTsKvListList().get(0); + Assert.assertEquals(tsKvEntry.getTs(), tsKv.getTs()); + Assert.assertEquals(1, tsKv.getKvCount()); + TransportProtos.KeyValueProto keyValue = tsKv.getKvList().get(0); + Assert.assertEquals(tsKvEntry.getKey(), keyValue.getKey()); + Assert.assertEquals(tsKvEntry.getValueAsString(), Long.toString(keyValue.getLongV())); + } + + @AfterClass + public static void destroy() throws InterruptedException { + uninstallation(); + edgeImitator.disconnect(); + } + + private static void installation() throws IOException { + Edge edge = new Edge(); + edge.setName("Edge1"); + edge.setType("test"); + edge.setRoutingKey("routing"); + edge.setSecret("secret"); + Edge savedEdge = restClient.saveEdge(edge); + + Device device = new Device(); + device.setName("Edge Device 1"); + device.setType("test"); + Device savedDevice = restClient.saveDevice(device); + restClient.assignDeviceToEdge(savedEdge.getId(), savedDevice.getId()); + + Asset asset = new Asset(); + asset.setName("Edge Asset 1"); + asset.setType("test"); + Asset savedAsset = restClient.saveAsset(asset); + restClient.assignAssetToEdge(savedEdge.getId(), savedAsset.getId()); + + ObjectMapper mapper = new ObjectMapper(); + Class edgeTestClass = EdgeTest.class; + JsonNode configuration = mapper.readTree(edgeTestClass.getClassLoader().getResourceAsStream("RootRuleChain.json")); + RuleChain ruleChain = mapper.treeToValue(configuration.get("ruleChain"), RuleChain.class); + RuleChainMetaData ruleChainMetaData = mapper.treeToValue(configuration.get("metadata"), RuleChainMetaData.class); + RuleChain savedRuleChain = restClient.saveRuleChain(ruleChain); + ruleChainMetaData.setRuleChainId(savedRuleChain.getId()); + restClient.saveRuleChainMetaData(ruleChainMetaData); + restClient.setRootRuleChain(savedRuleChain.getId()); + } + + private static void uninstallation() { + Device device = restClient.getTenantDevice("Edge Device 1").get(); + restClient.deleteDevice(device.getId()); + + Asset asset = restClient.getTenantAsset("Edge Asset 1").get(); + restClient.deleteAsset(asset.getId()); + + Edge edge = restClient.getTenantEdge("Edge1").get(); + restClient.deleteEdge(edge.getId()); + + List ruleChains = restClient.getRuleChains(new TextPageLink(3)).getData(); + RuleChain oldRoot = ruleChains.stream().filter(ruleChain -> ruleChain.getName().equals("Root Rule Chain")).findAny().get(); + RuleChain newRoot = ruleChains.stream().filter(ruleChain -> ruleChain.getName().equals("Test Root Rule Chain")).findAny().get(); + restClient.setRootRuleChain(oldRoot.getId()); + restClient.deleteRuleChain(newRoot.getId()); + } + +} diff --git a/msa/black-box-tests/src/test/resources/RootRuleChain.json b/msa/black-box-tests/src/test/resources/RootRuleChain.json new file mode 100644 index 0000000000..56324e72f5 --- /dev/null +++ b/msa/black-box-tests/src/test/resources/RootRuleChain.json @@ -0,0 +1,133 @@ +{ + "ruleChain": { + "additionalInfo": null, + "name": "Test Root Rule Chain", + "type": "CORE", + "firstRuleNodeId": null, + "root": false, + "debugMode": false, + "configuration": null + }, + "metadata": { + "firstNodeIndex": 4, + "nodes": [ + { + "additionalInfo": { + "layoutX": 1117, + "layoutY": 156 + }, + "type": "org.thingsboard.rule.engine.edge.TbMsgPushToEdgeNode", + "name": "Push to edge", + "debugMode": false, + "configuration": { + "version": 0 + } + }, + { + "additionalInfo": { + "layoutX": 825, + "layoutY": 407 + }, + "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", + "name": "RPC Call Request", + "debugMode": false, + "configuration": { + "timeoutInSeconds": 60 + } + }, + { + "additionalInfo": { + "layoutX": 826, + "layoutY": 327 + }, + "type": "org.thingsboard.rule.engine.action.TbLogNode", + "name": "Log Other", + "debugMode": false, + "configuration": { + "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" + } + }, + { + "additionalInfo": { + "layoutX": 827, + "layoutY": 244 + }, + "type": "org.thingsboard.rule.engine.action.TbLogNode", + "name": "Log RPC from Device", + "debugMode": false, + "configuration": { + "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" + } + }, + { + "additionalInfo": { + "layoutX": 347, + "layoutY": 149 + }, + "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", + "name": "Message Type Switch", + "debugMode": false, + "configuration": { + "version": 0 + } + }, + { + "additionalInfo": { + "layoutX": 821, + "layoutY": 72 + }, + "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", + "name": "Save Client Attributes", + "debugMode": false, + "configuration": { + "scope": "CLIENT_SCOPE" + } + }, + { + "additionalInfo": { + "layoutX": 824, + "layoutY": 156 + }, + "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", + "name": "Save Timeseries", + "debugMode": false, + "configuration": { + "defaultTTL": 0 + } + } + ], + "connections": [ + { + "fromIndex": 4, + "toIndex": 1, + "type": "RPC Request to Device" + }, + { + "fromIndex": 4, + "toIndex": 3, + "type": "RPC Request from Device" + }, + { + "fromIndex": 4, + "toIndex": 6, + "type": "Post telemetry" + }, + { + "fromIndex": 4, + "toIndex": 5, + "type": "Post attributes" + }, + { + "fromIndex": 4, + "toIndex": 2, + "type": "Other" + }, + { + "fromIndex": 6, + "toIndex": 0, + "type": "Success" + } + ], + "ruleChainConnections": null + } +} \ No newline at end of file From ee0b54c178f1217f986499998ac052bd17b909a3 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 22 Sep 2020 14:46:22 +0300 Subject: [PATCH 121/156] Updated US,FR,ES,DE locales --- ui/src/app/asset/add-assets-to-edge.tpl.html | 2 +- ui/src/app/device/add-devices-to-edge.tpl.html | 2 +- ui/src/app/entity-view/add-entity-views-to-edge.tpl.html | 2 +- ui/src/app/locale/locale.constant-de_DE.json | 3 ++- ui/src/app/locale/locale.constant-en_US.json | 1 + ui/src/app/locale/locale.constant-es_ES.json | 1 + ui/src/app/locale/locale.constant-fr_FR.json | 3 ++- 7 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ui/src/app/asset/add-assets-to-edge.tpl.html b/ui/src/app/asset/add-assets-to-edge.tpl.html index 635a6915d7..4c3a6c42de 100644 --- a/ui/src/app/asset/add-assets-to-edge.tpl.html +++ b/ui/src/app/asset/add-assets-to-edge.tpl.html @@ -15,7 +15,7 @@ limitations under the License. --> - +
diff --git a/ui/src/app/device/add-devices-to-edge.tpl.html b/ui/src/app/device/add-devices-to-edge.tpl.html index a9166a30a2..72bdfdbb62 100644 --- a/ui/src/app/device/add-devices-to-edge.tpl.html +++ b/ui/src/app/device/add-devices-to-edge.tpl.html @@ -15,7 +15,7 @@ limitations under the License. --> - +
diff --git a/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html b/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html index 0e14c3fe6a..4b64163ec1 100644 --- a/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html +++ b/ui/src/app/entity-view/add-entity-views-to-edge.tpl.html @@ -15,7 +15,7 @@ limitations under the License. --> - +
diff --git a/ui/src/app/locale/locale.constant-de_DE.json b/ui/src/app/locale/locale.constant-de_DE.json index bdd51cadf0..1f9bdbae58 100644 --- a/ui/src/app/locale/locale.constant-de_DE.json +++ b/ui/src/app/locale/locale.constant-de_DE.json @@ -775,9 +775,10 @@ "make-private-edge-text": "Nach der Bestätigung werden der Rand und dessen Daten privat und sind für andere nicht mehr zugänglich.", "import": "Rand importieren", "label": "Bezeichnung", + "assign-to-edge": "Assign to edge", "assign-new-edge": "Neue Rand zuordnen", "manage-edge-dashboards": "Rand-Dashboards verwalten", - "unassign-from-edge": "Zuordnung zum Rand aufheben", + "unassign-from-edge": "Rand zuweisen", "dashboards": "Rand Dashboards", "manage-edge-rulechains": "Randregelkette verwalten", "rulechains": "Rand Regelketten", diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 2397bf811c..34ef9c98ef 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -991,6 +991,7 @@ "entity-view-name-filter-required": "Entity view name filter is required.", "entity-view-name-filter-no-entity-view-matched": "No entity views starting with '{{entityView}}' were found.", "add": "Add Entity View", + "assign-to-edge": "Assign to edge", "assign-to-customer": "Assign to customer", "assign-entity-view-to-customer": "Assign Entity View(s) To Customer", "assign-entity-view-to-customer-text": "Please select the entity views to assign to the customer", diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json index 4d735561c2..de16a8ab99 100644 --- a/ui/src/app/locale/locale.constant-es_ES.json +++ b/ui/src/app/locale/locale.constant-es_ES.json @@ -770,6 +770,7 @@ "edge-type": "Type de la bordure", "edge-type-required": "El tipo de borde es requerido.", "select-edge-type": "Seleccionar tipo de borde", + "assign-to-edge": "Asignar al borde", "assign-to-customer": "Asignar al cliente", "assign-to-customer-text": "Seleccione el cliente para asignar los bordes", "assign-edge-to-customer": "Asignar borde(s) al cliente", diff --git a/ui/src/app/locale/locale.constant-fr_FR.json b/ui/src/app/locale/locale.constant-fr_FR.json index 3cf911e3a5..444228966f 100644 --- a/ui/src/app/locale/locale.constant-fr_FR.json +++ b/ui/src/app/locale/locale.constant-fr_FR.json @@ -432,7 +432,7 @@ "manage-customer-users": "Gérer les utilisateurs du client", "manage-dashboards": "Gérer les tableaux de bord", "manage-devices": "Gérer les dispositifs", - "manage-edges": "Gérer les bordures ", + "manage-edges": "Gérer les bordures", "manage-public-assets": "Gérer les actifs publics", "manage-public-dashboards": "Gérer les tableaux de bord publics", "manage-public-devices": "Gérer les dispositifs publics", @@ -775,6 +775,7 @@ "edge-type": "Type de la bordure", "edge-type-required": "Type de la bordure est requise.", "select-edge-type": "Selectionner un type de la bordure", + "assign-to-edge": "Attribuer au bord", "assign-to-customer": "Attribuer au client", "assign-to-customer-text": "Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", "assign-edge-to-customer": "Attribuer la bordure au client", From 458550b853d69eeea3d2a24372be2f80a8e8f18e Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 23 Sep 2020 12:07:16 +0300 Subject: [PATCH 122/156] Set version to 2.6.0 --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- dao/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/js-executor/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- ui/pom.xml | 2 +- 38 files changed, 39 insertions(+), 39 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 68eeb14b2c..ac75027fe7 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index ee626dac6f..9fa6bcf4bb 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 879e479c3a..c7af95b2c1 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index 8b43e5c8b1..fcd0e280b8 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index aef2fb184d..079d5662b8 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index 62802d141c..f7644599a6 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 579e495655..30f9652859 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index b302313baf..b5b1c8d739 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 8ccf34961c..f22a57f6c4 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index a237662b0d..4f819a701b 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index 715cb3d169..18bf0a0561 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index e3579876e4..afa85b8180 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index e40f3e4009..f1828cfc86 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 739aa2b068..92b6a3fe88 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index fceed3ee0e..1b94ee02cf 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 8c1cd17bf4..e2698c3419 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard dao diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index d24f38bc36..5547c18924 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 60ccd9d5bb..9d060da182 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index c627dca51a..153d089943 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index 944521f87e..77da3b0c12 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index 349cc36337..dcb58dda87 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 3e956736a1..4987c97a21 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index bc8ccc3f1f..a984e247ef 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index b2bc3ff8d9..5985487110 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index d00683c492..ba3b3d7c2c 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index 660920835b..9e9b9a2fa3 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 58cbcf4e6a..9ac7c8cd2b 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard netty-mqtt - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index ca78882a23..c511bf6997 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index 061efa390b..c170bf393e 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index 00d445cc3c..66a586ae4b 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 2c1e323165..8d648015be 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 00d8101e5a..3594daaa55 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index 91bf319b0e..2a941c4e4c 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index eeea5a378a..f75bbbe7b8 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 7540b78507..377f1a5760 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 6f4edd87b1..b15d02ef0d 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 59b5b2470b..ee901ff8b1 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard transport diff --git a/ui/pom.xml b/ui/pom.xml index b27f492c97..b9bdb2dd3b 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.5-SNAPSHOT + 2.6.0-SNAPSHOT thingsboard org.thingsboard From 4bc7f5288fbe343bfabae32c6fc797d0deea0ad6 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 23 Sep 2020 12:09:07 +0300 Subject: [PATCH 123/156] Set version to 2.6.0 --- msa/js-executor/package.json | 2 +- msa/web-ui/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index 967f55b24f..93a37fd6c5 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "2.5.5", + "version": "2.6.0", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.js", "bin": "server.js", diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 2eec7556f9..65b9226f18 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "2.5.5", + "version": "2.6.0", "description": "ThingsBoard Web UI Microservice", "main": "server.js", "bin": "server.js", diff --git a/ui/package.json b/ui/package.json index cbc4b8c6af..0fcd7a2bb5 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard", "private": true, - "version": "2.5.5", + "version": "2.6.0", "description": "ThingsBoard UI", "licenses": [ { From 43b913ffdb45b14f9a2e6cdc0b2ac1b44be37ee5 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 24 Sep 2020 12:59:58 +0300 Subject: [PATCH 124/156] edge services test --- .../thingsboard/server/edge/BaseEdgeTest.java | 403 ++++++++++++++++++ .../server/edge/EdgeNoSqlTestSuite.java | 47 ++ .../server/edge/EdgeSqlTestSuite.java | 41 ++ .../server/edge/imitator}/EdgeImitator.java | 26 +- .../server/edge/imitator}/EdgeStorage.java | 24 +- .../server/edge/nosql/EdgeNoSqlTest.java | 23 + .../server/edge/sql/EdgeSqlTest.java | 23 + msa/black-box-tests/pom.xml | 5 - .../server/msa/ContainerTestSuite.java | 2 +- .../thingsboard/server/msa/edge/EdgeTest.java | 341 --------------- .../src/test/resources/RootRuleChain.json | 133 ------ 11 files changed, 554 insertions(+), 514 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java create mode 100644 application/src/test/java/org/thingsboard/server/edge/EdgeNoSqlTestSuite.java create mode 100644 application/src/test/java/org/thingsboard/server/edge/EdgeSqlTestSuite.java rename {msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge => application/src/test/java/org/thingsboard/server/edge/imitator}/EdgeImitator.java (83%) rename {msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge => application/src/test/java/org/thingsboard/server/edge/imitator}/EdgeStorage.java (83%) create mode 100644 application/src/test/java/org/thingsboard/server/edge/nosql/EdgeNoSqlTest.java create mode 100644 application/src/test/java/org/thingsboard/server/edge/sql/EdgeSqlTest.java delete mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java delete mode 100644 msa/black-box-tests/src/test/resources/RootRuleChain.json diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java new file mode 100644 index 0000000000..3f5f9ee0e4 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -0,0 +1,403 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.edge; + +import com.fasterxml.jackson.core.type.TypeReference; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.common.data.DashboardInfo; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmInfo; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.page.TimePageData; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainType; +import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.controller.AbstractControllerTest; +import org.thingsboard.server.dao.rule.RuleChainService; +import org.thingsboard.server.edge.imitator.EdgeImitator; +import org.thingsboard.server.gen.edge.EdgeConfiguration; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@Slf4j +abstract public class BaseEdgeTest extends AbstractControllerTest { + + private Tenant savedTenant; + private TenantId tenantId; + private User tenantAdmin; + + private EdgeImitator edgeImitator; + private Edge edge; + + @Autowired + RuleChainService ruleChainService; + + @Before + public void beforeTest() throws Exception { + loginSysAdmin(); + + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + savedTenant = doPost("/api/tenant", tenant, Tenant.class); + tenantId = savedTenant.getId(); + Assert.assertNotNull(savedTenant); + + tenantAdmin = new User(); + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); + tenantAdmin.setTenantId(savedTenant.getId()); + tenantAdmin.setEmail("tenant2@thingsboard.org"); + tenantAdmin.setFirstName("Joe"); + tenantAdmin.setLastName("Downs"); + + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); + + installation(); + + edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); + edgeImitator.connect(); + Thread.sleep(5000); + } + + @After + public void afterTest() throws Exception { + edgeImitator.disconnect(); + uninstallation(); + + loginSysAdmin(); + + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) + .andExpect(status().isOk()); + } + + + @Test + public void test() throws Exception { + testReceivedData(); + testDevices(); + testAssets(); + testRuleChains(); + testDashboards(); + testRelations(); + testAlarms(); + } + + private void testReceivedData() throws Exception { + log.info("Checking received data"); + EdgeConfiguration configuration = edgeImitator.getStorage().getConfiguration(); + Assert.assertNotNull(configuration); + + Map entities = edgeImitator.getStorage().getEntities(); + Assert.assertFalse(entities.isEmpty()); + + Set devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); + Assert.assertEquals(1, devices.size()); + TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + for (Device device: pageDataDevices.getData()) { + Assert.assertTrue(devices.contains(device.getUuidId())); + } + + Set assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); + Assert.assertEquals(1, assets.size()); + TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + for (Asset asset: pageDataAssets.getData()) { + Assert.assertTrue(assets.contains(asset.getUuidId())); + } + + Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); + Assert.assertEquals(1, ruleChains.size()); + TimePageData pageDataRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", + new TypeReference>() {}, new TextPageLink(100)); + for (RuleChain ruleChain: pageDataRuleChains.getData()) { + Assert.assertTrue(ruleChains.contains(ruleChain.getUuidId())); + } + log.info("Received data checked"); + } + + private void testDevices() throws Exception { + log.info("Testing devices"); + Device device = new Device(); + device.setName("Edge Device 2"); + device.setType("test"); + Device savedDevice = doPost("/api/device", device, Device.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + + TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertTrue(pageDataDevices.getData().contains(savedDevice)); + Thread.sleep(1000); + Set devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); + Assert.assertEquals(2, devices.size()); + Assert.assertTrue(devices.contains(savedDevice.getUuidId())); + + doDelete("/api/edge/" + edge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertFalse(pageDataDevices.getData().contains(savedDevice)); + Thread.sleep(1000); + devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); + Assert.assertEquals(1, devices.size()); + Assert.assertFalse(devices.contains(savedDevice.getUuidId())); + + doDelete("/api/device/" + savedDevice.getId().getId().toString()) + .andExpect(status().isOk()); + log.info("Devices tested successfully"); + } + + private void testAssets() throws Exception { + log.info("Testing assets"); + Asset asset = new Asset(); + asset.setName("Edge Asset 2"); + asset.setType("test"); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + + TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertTrue(pageDataAssets.getData().contains(savedAsset)); + Thread.sleep(1000); + Set assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); + Assert.assertEquals(2, assets.size()); + Assert.assertTrue(assets.contains(savedAsset.getUuidId())); + + doDelete("/api/edge/" + edge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertFalse(pageDataAssets.getData().contains(savedAsset)); + Thread.sleep(1000); + assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); + Assert.assertEquals(1, assets.size()); + Assert.assertFalse(assets.contains(savedAsset.getUuidId())); + + doDelete("/api/asset/" + savedAsset.getId().getId().toString()) + .andExpect(status().isOk()); + log.info("Assets tested successfully"); + } + + private void testRuleChains() throws Exception { + log.info("Testing RuleChains"); + RuleChain ruleChain = new RuleChain(); + ruleChain.setName("Edge Test Rule Chain"); + ruleChain.setType(RuleChainType.EDGE); + RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); + + TimePageData pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertTrue(pageDataRuleChain.getData().contains(savedRuleChain)); + Thread.sleep(1000); + Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); + Assert.assertEquals(2, ruleChains.size()); + Assert.assertTrue(ruleChains.contains(savedRuleChain.getUuidId())); + + doDelete("/api/edge/" + edge.getId().getId().toString() + + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); + pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertFalse(pageDataRuleChain.getData().contains(savedRuleChain)); + Thread.sleep(1000); + ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); + Assert.assertEquals(1, ruleChains.size()); + Assert.assertFalse(ruleChains.contains(savedRuleChain.getUuidId())); + + doDelete("/api/ruleChain/" + savedRuleChain.getId().getId().toString()) + .andExpect(status().isOk()); + log.info("RuleChains tested successfully"); + + } + + private void testDashboards() throws Exception { + log.info("Testing Dashboards"); + Dashboard dashboard = new Dashboard(); + dashboard.setTitle("Edge Test Dashboard"); + Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); + + TimePageData pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertTrue(pageDataDashboard.getData().stream().allMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); + Thread.sleep(1000); + Set dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); + Assert.assertEquals(1, dashboards.size()); + Assert.assertTrue(dashboards.contains(savedDashboard.getUuidId())); + + doDelete("/api/edge/" + edge.getId().getId().toString() + + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); + pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", + new TypeReference>() {}, new TextPageLink(100)); + Assert.assertFalse(pageDataDashboard.getData().stream().anyMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); + Thread.sleep(1000); + dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); + Assert.assertEquals(0, dashboards.size()); + Assert.assertFalse(dashboards.contains(savedDashboard.getUuidId())); + + doDelete("/api/dashboard/" + savedDashboard.getId().getId().toString()) + .andExpect(status().isOk()); + log.info("Dashboards tested successfully"); + + } + + private void installation() throws Exception { + edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); + + Device device = new Device(); + device.setName("Edge Device 1"); + device.setType("test"); + Device savedDevice = doPost("/api/device", device, Device.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + + Asset asset = new Asset(); + asset.setName("Edge Asset 1"); + asset.setType("test"); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + } + + private void uninstallation() throws Exception { + + TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + for (Device device: pageDataDevices.getData()) { + doDelete("/api/device/" + device.getId().getId().toString()) + .andExpect(status().isOk()); + } + + TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + for (Asset asset: pageDataAssets.getData()) { + doDelete("/api/asset/" + asset.getId().getId().toString()) + .andExpect(status().isOk()); + } + + doDelete("/api/edge/" + edge.getId().getId().toString()) + .andExpect(status().isOk()); + } + + private void testRelations() throws Exception { + log.info("Testing Relations"); + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + List edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + + Assert.assertEquals(1, edgeDevices.size()); + Assert.assertEquals(1, edgeAssets.size()); + Device device = edgeDevices.get(0); + Asset asset = edgeAssets.get(0); + Assert.assertEquals("Edge Device 1", device.getName()); + Assert.assertEquals("Edge Asset 1", asset.getName()); + + EntityRelation relation = new EntityRelation(); + relation.setType("test"); + relation.setFrom(device.getId()); + relation.setTo(asset.getId()); + relation.setTypeGroup(RelationTypeGroup.COMMON); + doPost("/api/relation", relation); + + Thread.sleep(1000); + List relations = edgeImitator.getStorage().getRelations(); + Assert.assertEquals(1, relations.size()); + Assert.assertTrue(relations.contains(relation)); + doDelete("/api/relation?" + + "fromId=" + relation.getFrom().getId().toString() + + "&fromType=" + relation.getFrom().getEntityType().name() + + "&relationType=" + relation.getType() + + "&relationTypeGroup=" + relation.getTypeGroup().name() + + "&toId=" + relation.getTo().getId().toString() + + "&toType=" + relation.getTo().getEntityType().name()) + .andExpect(status().isOk()); + + Thread.sleep(1000); + relations = edgeImitator.getStorage().getRelations(); + Assert.assertEquals(0, relations.size()); + Assert.assertFalse(relations.contains(relation)); + log.info("Relations tested successfully"); + } + + + private void testAlarms() throws Exception { + log.info("Testing Alarms"); + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertEquals(1, edgeDevices.size()); + Device device = edgeDevices.get(0); + Assert.assertEquals("Edge Device 1", device.getName()); + + Alarm alarm = new Alarm(); + alarm.setOriginator(device.getId()); + alarm.setStatus(AlarmStatus.ACTIVE_UNACK); + alarm.setType("alarm"); + alarm.setSeverity(AlarmSeverity.CRITICAL); + + Alarm savedAlarm = doPost("/api/alarm", alarm, Alarm.class); + AlarmInfo alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); + Thread.sleep(1000); + + Assert.assertEquals(1, edgeImitator.getStorage().getAlarms().size()); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().containsKey(alarmInfo.getType())); + Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack"); + + Thread.sleep(1000); + alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); + Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear"); + + Thread.sleep(1000); + alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); + Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isCleared()); + Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + + doDelete("/api/alarm/" + savedAlarm.getId().getId().toString()) + .andExpect(status().isOk()); + log.info("Alarms tested successfully"); + } + +} diff --git a/application/src/test/java/org/thingsboard/server/edge/EdgeNoSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/edge/EdgeNoSqlTestSuite.java new file mode 100644 index 0000000000..06d566d410 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/edge/EdgeNoSqlTestSuite.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.edge; + +import org.cassandraunit.dataset.cql.ClassPathCQLDataSet; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.extensions.cpsuite.ClasspathSuite; +import org.junit.runner.RunWith; +import org.thingsboard.server.dao.CustomCassandraCQLUnit; +import org.thingsboard.server.queue.memory.InMemoryStorage; + +import java.util.Arrays; + +@RunWith(ClasspathSuite.class) +@ClasspathSuite.ClassnameFilters({ + "org.thingsboard.server.edge.nosql.*Test"}) +public class EdgeNoSqlTestSuite { + + @ClassRule + public static CustomCassandraCQLUnit cassandraUnit = + new CustomCassandraCQLUnit( + Arrays.asList( + new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false), + new ClassPathCQLDataSet("cassandra/schema-entities.cql", false, false), + new ClassPathCQLDataSet("cassandra/system-data.cql", false, false), + new ClassPathCQLDataSet("cassandra/system-test.cql", false, false)), + "cassandra-test.yaml", 30000l); + + @BeforeClass + public static void cleanupInMemStorage(){ + InMemoryStorage.getInstance().cleanup(); + } +} diff --git a/application/src/test/java/org/thingsboard/server/edge/EdgeSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/edge/EdgeSqlTestSuite.java new file mode 100644 index 0000000000..5d0e4f977c --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/edge/EdgeSqlTestSuite.java @@ -0,0 +1,41 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.edge; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.extensions.cpsuite.ClasspathSuite; +import org.junit.runner.RunWith; +import org.thingsboard.server.dao.CustomSqlUnit; +import org.thingsboard.server.queue.memory.InMemoryStorage; + +import java.util.Arrays; + +@RunWith(ClasspathSuite.class) +@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.edge.sql.*Test"}) +public class EdgeSqlTestSuite { + + @ClassRule + public static CustomSqlUnit sqlUnit = new CustomSqlUnit( + Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql"), + "sql/hsql/drop-all-tables.sql", + "sql-test.properties"); + + @BeforeClass + public static void cleanupInMemStorage(){ + InMemoryStorage.getInstance().cleanup(); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java similarity index 83% rename from msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java rename to application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 823d180261..9f6d51a601 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.msa.edge; +package org.thingsboard.server.edge.imitator; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.thingsboard.edge.rpc.EdgeGrpcClient; import org.thingsboard.edge.rpc.EdgeRpcClient; -import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; @@ -32,7 +32,6 @@ import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; -import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; @@ -75,7 +74,7 @@ public class EdgeImitator { this::onUplinkResponse, this::onEdgeUpdate, this::onDownlink, - this::onError); + this::onClose); } public void disconnect() throws InterruptedException { @@ -107,30 +106,30 @@ public class EdgeImitator { }, MoreExecutors.directExecutor()); } - private void onError(Exception e) { - log.error("Error during Edge lifecycle: ", e); + private void onClose(Exception e) { + log.info("onClose: {}", e.getMessage()); } private ListenableFuture> processDownlinkMsg(DownlinkMsg downlinkMsg) { List> result = new ArrayList<>(); if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { - result.add(storage.processEntity(deviceUpdateMsg.getMsgType(), EdgeEventType.DEVICE, new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()))); + result.add(storage.processEntity(deviceUpdateMsg.getMsgType(), EntityType.DEVICE, new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()))); } } if (downlinkMsg.getAssetUpdateMsgList() != null && !downlinkMsg.getAssetUpdateMsgList().isEmpty()) { for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) { - result.add(storage.processEntity(assetUpdateMsg.getMsgType(), EdgeEventType.ASSET, new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB()))); + result.add(storage.processEntity(assetUpdateMsg.getMsgType(), EntityType.ASSET, new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB()))); } } if (downlinkMsg.getRuleChainUpdateMsgList() != null && !downlinkMsg.getRuleChainUpdateMsgList().isEmpty()) { for (RuleChainUpdateMsg ruleChainUpdateMsg: downlinkMsg.getRuleChainUpdateMsgList()) { - result.add(storage.processEntity(ruleChainUpdateMsg.getMsgType(), EdgeEventType.RULE_CHAIN, new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB()))); + result.add(storage.processEntity(ruleChainUpdateMsg.getMsgType(), EntityType.RULE_CHAIN, new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB()))); } } if (downlinkMsg.getDashboardUpdateMsgList() != null && !downlinkMsg.getDashboardUpdateMsgList().isEmpty()) { for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) { - result.add(storage.processEntity(dashboardUpdateMsg.getMsgType(), EdgeEventType.DASHBOARD, new UUID(dashboardUpdateMsg.getIdMSB(), dashboardUpdateMsg.getIdLSB()))); + result.add(storage.processEntity(dashboardUpdateMsg.getMsgType(), EntityType.DASHBOARD, new UUID(dashboardUpdateMsg.getIdMSB(), dashboardUpdateMsg.getIdLSB()))); } } if (downlinkMsg.getRelationUpdateMsgList() != null && !downlinkMsg.getRelationUpdateMsgList().isEmpty()) { @@ -143,13 +142,6 @@ public class EdgeImitator { result.add(storage.processAlarm(alarmUpdateMsg)); } } - if (downlinkMsg.getEntityDataList() != null && !downlinkMsg.getEntityDataList().isEmpty()) { - for (EntityDataProto entityDataProto: downlinkMsg.getEntityDataList()) { - if (entityDataProto.hasPostTelemetryMsg()) { - result.add(storage.processTelemetry(new UUID(entityDataProto.getEntityIdMSB(), entityDataProto.getEntityIdLSB()), entityDataProto.getPostTelemetryMsg())); - } - } - } return Futures.allAsList(result); } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java similarity index 83% rename from msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java rename to application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java index 0bad7473cf..a52d1e7f6e 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeStorage.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.msa.edge; +package org.thingsboard.server.edge.imitator; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.AlarmStatus; -import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; @@ -29,7 +29,6 @@ import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; -import org.thingsboard.server.gen.transport.TransportProtos; import java.util.ArrayList; import java.util.HashMap; @@ -46,20 +45,17 @@ public class EdgeStorage { private EdgeConfiguration configuration; - private Map entities; + private Map entities; private Map alarms; private List relations; - private Map latestTelemetry; - public EdgeStorage() { entities = new HashMap<>(); alarms = new HashMap<>(); relations = new ArrayList<>(); - latestTelemetry = new HashMap<>(); } - public ListenableFuture processEntity(UpdateMsgType msgType, EdgeEventType type, UUID uuid) { + public ListenableFuture processEntity(UpdateMsgType msgType, EntityType type, UUID uuid) { switch (msgType) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: @@ -105,16 +101,10 @@ public class EdgeStorage { return Futures.immediateFuture(null); } - public ListenableFuture processTelemetry(UUID uuid, TransportProtos.PostTelemetryMsg telemetryMsg) { - latestTelemetry.put(uuid, telemetryMsg); - return Futures.immediateFuture(null); - } - - public Set getEntitiesByType(EdgeEventType type) { - Map filtered = entities.entrySet().stream() + public Set getEntitiesByType(EntityType type) { + return entities.entrySet().stream() .filter(entry -> entry.getValue().equals(type)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - return filtered.keySet(); + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet(); } } diff --git a/application/src/test/java/org/thingsboard/server/edge/nosql/EdgeNoSqlTest.java b/application/src/test/java/org/thingsboard/server/edge/nosql/EdgeNoSqlTest.java new file mode 100644 index 0000000000..c612eab16c --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/edge/nosql/EdgeNoSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.edge.nosql; + +import org.thingsboard.server.dao.service.DaoNoSqlTest; +import org.thingsboard.server.edge.BaseEdgeTest; + +@DaoNoSqlTest +public class EdgeNoSqlTest extends BaseEdgeTest { +} diff --git a/application/src/test/java/org/thingsboard/server/edge/sql/EdgeSqlTest.java b/application/src/test/java/org/thingsboard/server/edge/sql/EdgeSqlTest.java new file mode 100644 index 0000000000..4b2d087fc0 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/edge/sql/EdgeSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.edge.sql; + +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.edge.BaseEdgeTest; + +@DaoSqlTest +public class EdgeSqlTest extends BaseEdgeTest { +} diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 1602d24185..d24f38bc36 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -94,11 +94,6 @@ org.thingsboard rest-client - - org.thingsboard.common - edge-api - test - diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java index 5a798a8cc8..647c8878b7 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Map; @RunWith(ClasspathSuite.class) -@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*EdgeTest"}) +@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*Test"}) public class ContainerTestSuite { private static DockerComposeContainer testContainer; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java deleted file mode 100644 index a1f8c8e374..0000000000 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/edge/EdgeTest.java +++ /dev/null @@ -1,341 +0,0 @@ -/** - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.msa.edge; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.junit.*; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.thingsboard.server.common.data.Dashboard; -import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmInfo; -import org.thingsboard.server.common.data.alarm.AlarmSeverity; -import org.thingsboard.server.common.data.alarm.AlarmStatus; -import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventType; -import org.thingsboard.server.common.data.kv.TsKvEntry; -import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.common.data.relation.EntityRelation; -import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.common.data.rule.RuleChain; -import org.thingsboard.server.common.data.rule.RuleChainMetaData; -import org.thingsboard.server.common.data.rule.RuleChainType; -import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.gen.edge.EdgeConfiguration; -import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.msa.AbstractContainerTest; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -@Slf4j -public class EdgeTest extends AbstractContainerTest { - - private static EdgeImitator edgeImitator; - - @BeforeClass - public static void init() throws NoSuchFieldException, IllegalAccessException, InterruptedException, IOException { - restClient.login("tenant@thingsboard.org", "tenant"); - installation(); - edgeImitator = new EdgeImitator("localhost", 7070, "routing", "secret"); - edgeImitator.connect(); - Thread.sleep(10000); - } - - @Test - public void testReceivedData() { - Edge edge = restClient.getTenantEdge("Edge1").get(); - - EdgeConfiguration configuration = edgeImitator.getStorage().getConfiguration(); - Assert.assertNotNull(configuration); - - Map entities = edgeImitator.getStorage().getEntities(); - Assert.assertFalse(entities.isEmpty()); - - Set devices = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DEVICE); - Assert.assertEquals(1, devices.size()); - for (Device device: restClient.getEdgeDevices(edge.getId(), new TextPageLink(1)).getData()) { - Assert.assertTrue(devices.contains(device.getUuidId())); - } - - Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.RULE_CHAIN); - Assert.assertEquals(1, ruleChains.size()); - for (RuleChain ruleChain: restClient.getEdgeRuleChains(edge.getId(), new TimePageLink(1)).getData()) { - Assert.assertTrue(ruleChains.contains(ruleChain.getUuidId())); - } - - Set assets = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.ASSET); - Assert.assertEquals(1, assets.size()); - for (Asset asset: restClient.getEdgeAssets(edge.getId(), new TextPageLink(1)).getData()) { - Assert.assertTrue(assets.contains(asset.getUuidId())); - } - } - - @Test - public void testDevices() throws Exception { - Edge edge = restClient.getTenantEdge("Edge1").get(); - - Device device = new Device(); - device.setName("Edge Device 2"); - device.setType("test"); - Device savedDevice = restClient.saveDevice(device); - restClient.assignDeviceToEdge(edge.getId(), savedDevice.getId()); - - Thread.sleep(1000); - Assert.assertTrue(restClient.getEdgeDevices(edge.getId(), new TextPageLink(2)).getData().contains(savedDevice)); - Set devices = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DEVICE); - Assert.assertEquals(2, devices.size()); - Assert.assertTrue(devices.contains(savedDevice.getUuidId())); - - restClient.unassignDeviceFromEdge(edge.getId(), savedDevice.getId()); - Thread.sleep(1000); - Assert.assertFalse(restClient.getEdgeDevices(edge.getId(), new TextPageLink(2)).getData().contains(savedDevice)); - devices = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DEVICE); - Assert.assertEquals(1, devices.size()); - Assert.assertFalse(devices.contains(savedDevice.getUuidId())); - - restClient.deleteDevice(savedDevice.getId()); - } - - @Test - public void testAssets() throws Exception { - Edge edge = restClient.getTenantEdge("Edge1").get(); - - Asset asset = new Asset(); - asset.setName("Edge Asset 2"); - asset.setType("test"); - Asset savedAsset = restClient.saveAsset(asset); - restClient.assignAssetToEdge(edge.getId(), savedAsset.getId()); - - Thread.sleep(1000); - Assert.assertTrue(restClient.getEdgeAssets(edge.getId(), new TextPageLink(2)).getData().contains(savedAsset)); - Set assets = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.ASSET); - Assert.assertEquals(2, assets.size()); - Assert.assertTrue(assets.contains(savedAsset.getUuidId())); - - restClient.unassignAssetFromEdge(edge.getId(), savedAsset.getId()); - Thread.sleep(1000); - Assert.assertFalse(restClient.getEdgeAssets(edge.getId(), new TextPageLink(2)).getData().contains(savedAsset)); - assets = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.ASSET); - Assert.assertEquals(1, assets.size()); - Assert.assertFalse(assets.contains(savedAsset.getUuidId())); - - restClient.deleteAsset(savedAsset.getId()); - } - - @Test - public void testRuleChains() throws Exception { - Edge edge = restClient.getTenantEdge("Edge1").get(); - - RuleChain ruleChain = new RuleChain(); - ruleChain.setName("Edge Test Rule Chain"); - ruleChain.setType(RuleChainType.EDGE); - RuleChain savedRuleChain = restClient.saveRuleChain(ruleChain); - restClient.assignRuleChainToEdge(edge.getId(), savedRuleChain.getId()); - - Thread.sleep(1000); - Assert.assertTrue(restClient.getEdgeRuleChains(edge.getId(), new TimePageLink(2)).getData().contains(savedRuleChain)); - Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.RULE_CHAIN); - Assert.assertEquals(2, ruleChains.size()); - Assert.assertTrue(ruleChains.contains(savedRuleChain.getUuidId())); - - restClient.unassignRuleChainFromEdge(edge.getId(), savedRuleChain.getId()); - Thread.sleep(1000); - Assert.assertFalse(restClient.getEdgeRuleChains(edge.getId(), new TimePageLink(2)).getData().contains(savedRuleChain)); - ruleChains = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.RULE_CHAIN); - Assert.assertEquals(1, ruleChains.size()); - Assert.assertFalse(ruleChains.contains(savedRuleChain.getUuidId())); - - restClient.deleteRuleChain(savedRuleChain.getId()); - - } - - @Test - public void testDashboards() throws Exception { - Edge edge = restClient.getTenantEdge("Edge1").get(); - - Dashboard dashboard = new Dashboard(); - dashboard.setTitle("Edge Test Dashboard"); - Dashboard savedDashboard = restClient.saveDashboard(dashboard); - restClient.assignDashboardToEdge(edge.getId(), savedDashboard.getId()); - - Thread.sleep(1000); - Assert.assertTrue(restClient.getEdgeDashboards(edge.getId(), new TimePageLink(2)).getData().stream().allMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - Set dashboards = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DASHBOARD); - Assert.assertEquals(1, dashboards.size()); - Assert.assertTrue(dashboards.contains(savedDashboard.getUuidId())); - - restClient.unassignDashboardFromEdge(edge.getId(), savedDashboard.getId()); - Thread.sleep(1000); - Assert.assertFalse(restClient.getEdgeDashboards(edge.getId(), new TimePageLink(2)).getData().stream().anyMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - dashboards = edgeImitator.getStorage().getEntitiesByType(EdgeEventType.DASHBOARD); - Assert.assertEquals(0, dashboards.size()); - Assert.assertFalse(dashboards.contains(savedDashboard.getUuidId())); - - restClient.deleteDashboard(savedDashboard.getId()); - - } - - @Test - public void testRelations() throws InterruptedException { - Device device = restClient.getTenantDevice("Edge Device 1").get(); - Asset asset = restClient.getTenantAsset("Edge Asset 1").get(); - - EntityRelation relation = new EntityRelation(); - relation.setType("test"); - relation.setFrom(device.getId()); - relation.setTo(asset.getId()); - relation.setTypeGroup(RelationTypeGroup.COMMON); - restClient.saveRelation(relation); - - Thread.sleep(1000); - List relations = edgeImitator.getStorage().getRelations(); - Assert.assertEquals(1, relations.size()); - Assert.assertTrue(relations.contains(relation)); - restClient.deleteRelation(relation.getFrom(), relation.getType(), relation.getTypeGroup(), relation.getTo()); - - Thread.sleep(1000); - relations = edgeImitator.getStorage().getRelations(); - Assert.assertEquals(0, relations.size()); - Assert.assertFalse(relations.contains(relation)); - } - - @Test - public void testAlarms() throws Exception { - Device device = restClient.getTenantDevice("Edge Device 1").get(); - Alarm alarm = new Alarm(); - alarm.setOriginator(device.getId()); - alarm.setStatus(AlarmStatus.ACTIVE_UNACK); - alarm.setType("alarm"); - alarm.setSeverity(AlarmSeverity.CRITICAL); - - Alarm savedAlarm = restClient.saveAlarm(alarm); - AlarmInfo alarmInfo = restClient.getAlarmInfoById(savedAlarm.getId()).get(); - Thread.sleep(1000); - - Assert.assertEquals(1, edgeImitator.getStorage().getAlarms().size()); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().containsKey(alarmInfo.getType())); - Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); - restClient.ackAlarm(savedAlarm.getId()); - - Thread.sleep(1000); - alarmInfo = restClient.getAlarmInfoById(savedAlarm.getId()).get(); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); - Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); - restClient.clearAlarm(savedAlarm.getId()); - - Thread.sleep(1000); - alarmInfo = restClient.getAlarmInfoById(savedAlarm.getId()).get(); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isCleared()); - Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); - - restClient.deleteAlarm(savedAlarm.getId()); - - } - - @Ignore - @Test - public void testTelemetry() throws Exception { - Device device = restClient.getTenantDevice("Edge Device 1").get(); - DeviceCredentials deviceCredentials = restClient.getDeviceCredentialsByDeviceId(device.getId()).get(); - ResponseEntity response = restClient.getRestTemplate() - .postForEntity(HTTPS_URL + "/api/v1/{credentialsId}/telemetry", - "{'test': 25}", - ResponseEntity.class, - deviceCredentials.getCredentialsId()); - Assert.assertEquals(response.getStatusCode(), HttpStatus.OK); - Thread.sleep(1000); - List keys = restClient.getTimeseriesKeys(device.getId()); - List latestTimeseries = restClient.getLatestTimeseries(device.getId(), keys); - Assert.assertEquals(1, latestTimeseries.size()); - TsKvEntry tsKvEntry = latestTimeseries.get(0); - Map telemetry = edgeImitator.getStorage().getLatestTelemetry(); - Assert.assertEquals(1, telemetry.size()); - Assert.assertTrue(telemetry.containsKey(device.getUuidId())); - TransportProtos.PostTelemetryMsg telemetryMsg = telemetry.get(device.getUuidId()); - Assert.assertEquals(1, telemetryMsg.getTsKvListCount()); - TransportProtos.TsKvListProto tsKv = telemetryMsg.getTsKvListList().get(0); - Assert.assertEquals(tsKvEntry.getTs(), tsKv.getTs()); - Assert.assertEquals(1, tsKv.getKvCount()); - TransportProtos.KeyValueProto keyValue = tsKv.getKvList().get(0); - Assert.assertEquals(tsKvEntry.getKey(), keyValue.getKey()); - Assert.assertEquals(tsKvEntry.getValueAsString(), Long.toString(keyValue.getLongV())); - } - - @AfterClass - public static void destroy() throws InterruptedException { - uninstallation(); - edgeImitator.disconnect(); - } - - private static void installation() throws IOException { - Edge edge = new Edge(); - edge.setName("Edge1"); - edge.setType("test"); - edge.setRoutingKey("routing"); - edge.setSecret("secret"); - Edge savedEdge = restClient.saveEdge(edge); - - Device device = new Device(); - device.setName("Edge Device 1"); - device.setType("test"); - Device savedDevice = restClient.saveDevice(device); - restClient.assignDeviceToEdge(savedEdge.getId(), savedDevice.getId()); - - Asset asset = new Asset(); - asset.setName("Edge Asset 1"); - asset.setType("test"); - Asset savedAsset = restClient.saveAsset(asset); - restClient.assignAssetToEdge(savedEdge.getId(), savedAsset.getId()); - - ObjectMapper mapper = new ObjectMapper(); - Class edgeTestClass = EdgeTest.class; - JsonNode configuration = mapper.readTree(edgeTestClass.getClassLoader().getResourceAsStream("RootRuleChain.json")); - RuleChain ruleChain = mapper.treeToValue(configuration.get("ruleChain"), RuleChain.class); - RuleChainMetaData ruleChainMetaData = mapper.treeToValue(configuration.get("metadata"), RuleChainMetaData.class); - RuleChain savedRuleChain = restClient.saveRuleChain(ruleChain); - ruleChainMetaData.setRuleChainId(savedRuleChain.getId()); - restClient.saveRuleChainMetaData(ruleChainMetaData); - restClient.setRootRuleChain(savedRuleChain.getId()); - } - - private static void uninstallation() { - Device device = restClient.getTenantDevice("Edge Device 1").get(); - restClient.deleteDevice(device.getId()); - - Asset asset = restClient.getTenantAsset("Edge Asset 1").get(); - restClient.deleteAsset(asset.getId()); - - Edge edge = restClient.getTenantEdge("Edge1").get(); - restClient.deleteEdge(edge.getId()); - - List ruleChains = restClient.getRuleChains(new TextPageLink(3)).getData(); - RuleChain oldRoot = ruleChains.stream().filter(ruleChain -> ruleChain.getName().equals("Root Rule Chain")).findAny().get(); - RuleChain newRoot = ruleChains.stream().filter(ruleChain -> ruleChain.getName().equals("Test Root Rule Chain")).findAny().get(); - restClient.setRootRuleChain(oldRoot.getId()); - restClient.deleteRuleChain(newRoot.getId()); - } - -} diff --git a/msa/black-box-tests/src/test/resources/RootRuleChain.json b/msa/black-box-tests/src/test/resources/RootRuleChain.json deleted file mode 100644 index 56324e72f5..0000000000 --- a/msa/black-box-tests/src/test/resources/RootRuleChain.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "ruleChain": { - "additionalInfo": null, - "name": "Test Root Rule Chain", - "type": "CORE", - "firstRuleNodeId": null, - "root": false, - "debugMode": false, - "configuration": null - }, - "metadata": { - "firstNodeIndex": 4, - "nodes": [ - { - "additionalInfo": { - "layoutX": 1117, - "layoutY": 156 - }, - "type": "org.thingsboard.rule.engine.edge.TbMsgPushToEdgeNode", - "name": "Push to edge", - "debugMode": false, - "configuration": { - "version": 0 - } - }, - { - "additionalInfo": { - "layoutX": 825, - "layoutY": 407 - }, - "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", - "name": "RPC Call Request", - "debugMode": false, - "configuration": { - "timeoutInSeconds": 60 - } - }, - { - "additionalInfo": { - "layoutX": 826, - "layoutY": 327 - }, - "type": "org.thingsboard.rule.engine.action.TbLogNode", - "name": "Log Other", - "debugMode": false, - "configuration": { - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" - } - }, - { - "additionalInfo": { - "layoutX": 827, - "layoutY": 244 - }, - "type": "org.thingsboard.rule.engine.action.TbLogNode", - "name": "Log RPC from Device", - "debugMode": false, - "configuration": { - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" - } - }, - { - "additionalInfo": { - "layoutX": 347, - "layoutY": 149 - }, - "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", - "name": "Message Type Switch", - "debugMode": false, - "configuration": { - "version": 0 - } - }, - { - "additionalInfo": { - "layoutX": 821, - "layoutY": 72 - }, - "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", - "name": "Save Client Attributes", - "debugMode": false, - "configuration": { - "scope": "CLIENT_SCOPE" - } - }, - { - "additionalInfo": { - "layoutX": 824, - "layoutY": 156 - }, - "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", - "name": "Save Timeseries", - "debugMode": false, - "configuration": { - "defaultTTL": 0 - } - } - ], - "connections": [ - { - "fromIndex": 4, - "toIndex": 1, - "type": "RPC Request to Device" - }, - { - "fromIndex": 4, - "toIndex": 3, - "type": "RPC Request from Device" - }, - { - "fromIndex": 4, - "toIndex": 6, - "type": "Post telemetry" - }, - { - "fromIndex": 4, - "toIndex": 5, - "type": "Post attributes" - }, - { - "fromIndex": 4, - "toIndex": 2, - "type": "Other" - }, - { - "fromIndex": 6, - "toIndex": 0, - "type": "Success" - } - ], - "ruleChainConnections": null - } -} \ No newline at end of file From afacaf25471f144f31575b46b737a04f718b3ce7 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 24 Sep 2020 15:25:38 +0300 Subject: [PATCH 125/156] switched EDGES_RPC_ENABLED to false --- application/src/main/resources/thingsboard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index db83fd700a..bcf3425f53 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -588,7 +588,7 @@ transport: # Edges parameters edges: rpc: - enabled: "${EDGES_RPC_ENABLED:true}" + enabled: "${EDGES_RPC_ENABLED:false}" port: "${EDGES_RPC_PORT:7070}" ssl: # Enable/disable SSL support From 8eda901fee34f0dc834e1e641db3ae5b2278f22c Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 24 Sep 2020 19:03:02 +0300 Subject: [PATCH 126/156] added countDownLatch for saving time --- .../thingsboard/server/edge/BaseEdgeTest.java | 125 +++++++++--------- .../server/edge/imitator/EdgeImitator.java | 1 + .../server/edge/imitator/EdgeStorage.java | 22 ++- 3 files changed, 85 insertions(+), 63 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index 3f5f9ee0e4..303307af25 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -45,12 +45,11 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.edge.imitator.EdgeImitator; -import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.*; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -91,7 +90,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); edgeImitator.connect(); - Thread.sleep(5000); } @After @@ -108,7 +106,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @Test public void test() throws Exception { - testReceivedData(); + testReceivedInitialData(); testDevices(); testAssets(); testRuleChains(); @@ -117,8 +115,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { testAlarms(); } - private void testReceivedData() throws Exception { + private void testReceivedInitialData() throws Exception { log.info("Checking received data"); + waitForMessages(6); // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases + EdgeConfiguration configuration = edgeImitator.getStorage().getConfiguration(); Assert.assertNotNull(configuration); @@ -163,7 +163,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataDevices.getData().contains(savedDevice)); - Thread.sleep(1000); + waitForMessages(1); Set devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); Assert.assertEquals(2, devices.size()); Assert.assertTrue(devices.contains(savedDevice.getUuidId())); @@ -173,7 +173,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataDevices.getData().contains(savedDevice)); - Thread.sleep(1000); + waitForMessages(1); devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); Assert.assertEquals(1, devices.size()); Assert.assertFalse(devices.contains(savedDevice.getUuidId())); @@ -195,7 +195,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataAssets.getData().contains(savedAsset)); - Thread.sleep(1000); + waitForMessages(1); Set assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); Assert.assertEquals(2, assets.size()); Assert.assertTrue(assets.contains(savedAsset.getUuidId())); @@ -205,7 +205,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataAssets.getData().contains(savedAsset)); - Thread.sleep(1000); + waitForMessages(1); assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); Assert.assertEquals(1, assets.size()); Assert.assertFalse(assets.contains(savedAsset.getUuidId())); @@ -227,7 +227,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { TimePageData pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataRuleChain.getData().contains(savedRuleChain)); - Thread.sleep(1000); + waitForMessages(1); Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); Assert.assertEquals(2, ruleChains.size()); Assert.assertTrue(ruleChains.contains(savedRuleChain.getUuidId())); @@ -237,7 +237,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataRuleChain.getData().contains(savedRuleChain)); - Thread.sleep(1000); + waitForMessages(1); ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); Assert.assertEquals(1, ruleChains.size()); Assert.assertFalse(ruleChains.contains(savedRuleChain.getUuidId())); @@ -259,7 +259,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { TimePageData pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataDashboard.getData().stream().allMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - Thread.sleep(1000); + waitForMessages(1); Set dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); Assert.assertEquals(1, dashboards.size()); Assert.assertTrue(dashboards.contains(savedDashboard.getUuidId())); @@ -269,7 +269,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataDashboard.getData().stream().anyMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - Thread.sleep(1000); + waitForMessages(1); dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); Assert.assertEquals(0, dashboards.size()); Assert.assertFalse(dashboards.contains(savedDashboard.getUuidId())); @@ -280,44 +280,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { } - private void installation() throws Exception { - edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); - - Device device = new Device(); - device.setName("Edge Device 1"); - device.setType("test"); - Device savedDevice = doPost("/api/device", device, Device.class); - doPost("/api/edge/" + edge.getId().getId().toString() - + "/device/" + savedDevice.getId().getId().toString(), Device.class); - - Asset asset = new Asset(); - asset.setName("Edge Asset 1"); - asset.setType("test"); - Asset savedAsset = doPost("/api/asset", asset, Asset.class); - doPost("/api/edge/" + edge.getId().getId().toString() - + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); - } - - private void uninstallation() throws Exception { - - TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", - new TypeReference>() {}, new TextPageLink(100)); - for (Device device: pageDataDevices.getData()) { - doDelete("/api/device/" + device.getId().getId().toString()) - .andExpect(status().isOk()); - } - - TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", - new TypeReference>() {}, new TextPageLink(100)); - for (Asset asset: pageDataAssets.getData()) { - doDelete("/api/asset/" + asset.getId().getId().toString()) - .andExpect(status().isOk()); - } - - doDelete("/api/edge/" + edge.getId().getId().toString()) - .andExpect(status().isOk()); - } - private void testRelations() throws Exception { log.info("Testing Relations"); List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", @@ -339,7 +301,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { relation.setTypeGroup(RelationTypeGroup.COMMON); doPost("/api/relation", relation); - Thread.sleep(1000); + waitForMessages(1); List relations = edgeImitator.getStorage().getRelations(); Assert.assertEquals(1, relations.size()); Assert.assertTrue(relations.contains(relation)); @@ -352,7 +314,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { "&toType=" + relation.getTo().getEntityType().name()) .andExpect(status().isOk()); - Thread.sleep(1000); + waitForMessages(1); relations = edgeImitator.getStorage().getRelations(); Assert.assertEquals(0, relations.size()); Assert.assertFalse(relations.contains(relation)); @@ -376,20 +338,20 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Alarm savedAlarm = doPost("/api/alarm", alarm, Alarm.class); AlarmInfo alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); - Thread.sleep(1000); + waitForMessages(1); Assert.assertEquals(1, edgeImitator.getStorage().getAlarms().size()); Assert.assertTrue(edgeImitator.getStorage().getAlarms().containsKey(alarmInfo.getType())); Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack"); - Thread.sleep(1000); + waitForMessages(1); alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear"); - Thread.sleep(1000); + waitForMessages(1); alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isCleared()); @@ -400,4 +362,49 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { log.info("Alarms tested successfully"); } + private void installation() throws Exception { + edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); + + Device device = new Device(); + device.setName("Edge Device 1"); + device.setType("test"); + Device savedDevice = doPost("/api/device", device, Device.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + + Asset asset = new Asset(); + asset.setName("Edge Asset 1"); + asset.setType("test"); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + } + + private void uninstallation() throws Exception { + + TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)); + for (Device device: pageDataDevices.getData()) { + doDelete("/api/device/" + device.getId().getId().toString()) + .andExpect(status().isOk()); + } + + TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)); + for (Asset asset: pageDataAssets.getData()) { + doDelete("/api/asset/" + asset.getId().getId().toString()) + .andExpect(status().isOk()); + } + + doDelete("/api/edge/" + edge.getId().getId().toString()) + .andExpect(status().isOk()); + } + + private void waitForMessages(int messageAmount) throws InterruptedException { + edgeImitator.getStorage().setLatch(new CountDownLatch(messageAmount)); + while (!edgeImitator.getStorage().getLatch().await(1, TimeUnit.SECONDS)) { + log.warn("Waiting for messages.."); + } + } + } diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 9f6d51a601..e91e57e9a6 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -111,6 +111,7 @@ public class EdgeImitator { } private ListenableFuture> processDownlinkMsg(DownlinkMsg downlinkMsg) { + log.info(String.valueOf(downlinkMsg)); List> result = new ArrayList<>(); if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java index a52d1e7f6e..7320b93054 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CountDownLatch; import java.util.stream.Collectors; @Slf4j @@ -45,11 +46,14 @@ public class EdgeStorage { private EdgeConfiguration configuration; + private CountDownLatch latch; + private Map entities; private Map alarms; private List relations; public EdgeStorage() { + latch = new CountDownLatch(0); entities = new HashMap<>(); alarms = new HashMap<>(); relations = new ArrayList<>(); @@ -60,15 +64,19 @@ public class EdgeStorage { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: entities.put(uuid, type); + latch.countDown(); break; case ENTITY_DELETED_RPC_MESSAGE: - entities.remove(uuid); + if (entities.remove(uuid) != null) { + latch.countDown(); + } break; } return Futures.immediateFuture(null); } public ListenableFuture processRelation(RelationUpdateMsg relationMsg) { + boolean result = false; EntityRelation relation = new EntityRelation(); relation.setType(relationMsg.getType()); relation.setTypeGroup(RelationTypeGroup.valueOf(relationMsg.getTypeGroup())); @@ -77,12 +85,15 @@ public class EdgeStorage { switch (relationMsg.getMsgType()) { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: - relations.add(relation); + result = relations.add(relation); break; case ENTITY_DELETED_RPC_MESSAGE: - relations.remove(relation); + result = relations.remove(relation); break; } + if (result) { + latch.countDown(); + } return Futures.immediateFuture(null); } @@ -93,9 +104,12 @@ public class EdgeStorage { case ALARM_ACK_RPC_MESSAGE: case ALARM_CLEAR_RPC_MESSAGE: alarms.put(alarmMsg.getType(), AlarmStatus.valueOf(alarmMsg.getStatus())); + latch.countDown(); break; case ENTITY_DELETED_RPC_MESSAGE: - alarms.remove(alarmMsg.getName()); + if (alarms.remove(alarmMsg.getName()) != null) { + latch.countDown(); + } break; } return Futures.immediateFuture(null); From 199c175396085bfcd851459ef5631af84d627a40 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 24 Sep 2020 19:06:28 +0300 Subject: [PATCH 127/156] deleted logs and wildcard imports --- .../java/org/thingsboard/server/edge/BaseEdgeTest.java | 7 +++++-- .../org/thingsboard/server/edge/imitator/EdgeImitator.java | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index 303307af25..25ad8d7e94 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -45,9 +45,12 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.edge.imitator.EdgeImitator; -import org.thingsboard.server.gen.edge.*; +import org.thingsboard.server.gen.edge.EdgeConfiguration; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index e91e57e9a6..9f6d51a601 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -111,7 +111,6 @@ public class EdgeImitator { } private ListenableFuture> processDownlinkMsg(DownlinkMsg downlinkMsg) { - log.info(String.valueOf(downlinkMsg)); List> result = new ArrayList<>(); if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { From 3f36e15ee6f3064b350b0cc1b52389791adfdc7b Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 24 Sep 2020 19:49:31 +0300 Subject: [PATCH 128/156] last methods --- .../thingsboard/rest/client/RestClient.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index ab04b16b66..4e2f12e8c2 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -2251,6 +2251,53 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { }, params).getBody(); } + public Optional addDefaultEdgeRuleChain(RuleChainId ruleChainId) { + try { + ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/ruleChain/{ruleChainId}/defaultEdge", null, RuleChain.class, ruleChainId.getId()); + return Optional.ofNullable(ruleChain.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Optional removeDefaultEdgeRuleChain(RuleChainId ruleChainId) { + try { + ResponseEntity ruleChain = restTemplate.exchange(baseURL + "/api/ruleChain/{ruleChainId}/defaultEdge", HttpMethod.DELETE, HttpEntity.EMPTY, RuleChain.class, ruleChainId.getId()); + return Optional.ofNullable(ruleChain.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public List getDefaultEdgeRuleChains() { + return restTemplate.exchange(baseURL + "/ruleChain/defaultEdgeRuleChains", + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }).getBody(); + } + + public Optional setDefaultRootEdgeRuleChain(RuleChainId ruleChainId) { + try { + ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/ruleChain/{ruleChainId}/defaultRootEdge", null, RuleChain.class, ruleChainId.getId()); + return Optional.ofNullable(ruleChain.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + public TextPageData getTenantEdges(String type, TextPageLink pageLink) { Map params = new HashMap<>(); params.put("type", type); From fd32ba176175cb4e12b2a13911b4bd57a8a51b95 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 25 Sep 2020 12:04:38 +0300 Subject: [PATCH 129/156] concurrency fixes --- .../thingsboard/server/edge/BaseEdgeTest.java | 55 ++++++++++--------- .../server/edge/imitator/EdgeStorage.java | 9 +++ 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index 25ad8d7e94..be26e64f1a 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -67,9 +67,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { private EdgeImitator edgeImitator; private Edge edge; - @Autowired - RuleChainService ruleChainService; - @Before public void beforeTest() throws Exception { loginSysAdmin(); @@ -88,10 +85,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { tenantAdmin.setLastName("Downs"); tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); - installation(); edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); + // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases + edgeImitator.getStorage().expectMessageAmount(6); edgeImitator.connect(); } @@ -120,7 +118,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { private void testReceivedInitialData() throws Exception { log.info("Checking received data"); - waitForMessages(6); // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases + edgeImitator.getStorage().waitForMessages(); EdgeConfiguration configuration = edgeImitator.getStorage().getConfiguration(); Assert.assertNotNull(configuration); @@ -160,23 +158,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { device.setName("Edge Device 2"); device.setType("test"); Device savedDevice = doPost("/api/device", device, Device.class); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/device/" + savedDevice.getId().getId().toString(), Device.class); TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataDevices.getData().contains(savedDevice)); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); Set devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); Assert.assertEquals(2, devices.size()); Assert.assertTrue(devices.contains(savedDevice.getUuidId())); + edgeImitator.getStorage().expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/device/" + savedDevice.getId().getId().toString(), Device.class); pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataDevices.getData().contains(savedDevice)); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); Assert.assertEquals(1, devices.size()); Assert.assertFalse(devices.contains(savedDevice.getUuidId())); @@ -192,23 +192,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { asset.setName("Edge Asset 2"); asset.setType("test"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataAssets.getData().contains(savedAsset)); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); Set assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); Assert.assertEquals(2, assets.size()); Assert.assertTrue(assets.contains(savedAsset.getUuidId())); + edgeImitator.getStorage().expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataAssets.getData().contains(savedAsset)); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); Assert.assertEquals(1, assets.size()); Assert.assertFalse(assets.contains(savedAsset.getUuidId())); @@ -224,23 +226,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { ruleChain.setName("Edge Test Rule Chain"); ruleChain.setType(RuleChainType.EDGE); RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); TimePageData pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataRuleChain.getData().contains(savedRuleChain)); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); Assert.assertEquals(2, ruleChains.size()); Assert.assertTrue(ruleChains.contains(savedRuleChain.getUuidId())); + edgeImitator.getStorage().expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataRuleChain.getData().contains(savedRuleChain)); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); Assert.assertEquals(1, ruleChains.size()); Assert.assertFalse(ruleChains.contains(savedRuleChain.getUuidId())); @@ -256,23 +260,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Dashboard dashboard = new Dashboard(); dashboard.setTitle("Edge Test Dashboard"); Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); TimePageData pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertTrue(pageDataDashboard.getData().stream().allMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); Set dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); Assert.assertEquals(1, dashboards.size()); Assert.assertTrue(dashboards.contains(savedDashboard.getUuidId())); + edgeImitator.getStorage().expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", new TypeReference>() {}, new TextPageLink(100)); Assert.assertFalse(pageDataDashboard.getData().stream().anyMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); Assert.assertEquals(0, dashboards.size()); Assert.assertFalse(dashboards.contains(savedDashboard.getUuidId())); @@ -302,12 +308,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { relation.setFrom(device.getId()); relation.setTo(asset.getId()); relation.setTypeGroup(RelationTypeGroup.COMMON); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/relation", relation); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); List relations = edgeImitator.getStorage().getRelations(); Assert.assertEquals(1, relations.size()); Assert.assertTrue(relations.contains(relation)); + edgeImitator.getStorage().expectMessageAmount(1); doDelete("/api/relation?" + "fromId=" + relation.getFrom().getId().toString() + "&fromType=" + relation.getFrom().getEntityType().name() + @@ -317,7 +325,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { "&toType=" + relation.getTo().getEntityType().name()) .andExpect(status().isOk()); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); relations = edgeImitator.getStorage().getRelations(); Assert.assertEquals(0, relations.size()); Assert.assertFalse(relations.contains(relation)); @@ -339,22 +347,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { alarm.setType("alarm"); alarm.setSeverity(AlarmSeverity.CRITICAL); + edgeImitator.getStorage().expectMessageAmount(1); Alarm savedAlarm = doPost("/api/alarm", alarm, Alarm.class); AlarmInfo alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); Assert.assertEquals(1, edgeImitator.getStorage().getAlarms().size()); Assert.assertTrue(edgeImitator.getStorage().getAlarms().containsKey(alarmInfo.getType())); Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack"); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + edgeImitator.getStorage().expectMessageAmount(1); doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear"); - waitForMessages(1); + edgeImitator.getStorage().waitForMessages(); alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isCleared()); @@ -402,12 +413,4 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { doDelete("/api/edge/" + edge.getId().getId().toString()) .andExpect(status().isOk()); } - - private void waitForMessages(int messageAmount) throws InterruptedException { - edgeImitator.getStorage().setLatch(new CountDownLatch(messageAmount)); - while (!edgeImitator.getStorage().getLatch().await(1, TimeUnit.SECONDS)) { - log.warn("Waiting for messages.."); - } - } - } diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java index 7320b93054..cadd580f58 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Slf4j @@ -121,4 +122,12 @@ public class EdgeStorage { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet(); } + public void waitForMessages() throws InterruptedException { + latch.await(5, TimeUnit.SECONDS); + } + + public void expectMessageAmount(int messageAmount) { + latch = new CountDownLatch(messageAmount); + } + } From 05a7f3b2de15ff95e8c89718efff3759d3d032c8 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 25 Sep 2020 13:12:30 +0300 Subject: [PATCH 130/156] fixed setRootRuleChain for Edges --- .../src/main/java/org/thingsboard/rest/client/RestClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 4e2f12e8c2..0232bc5216 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -2029,9 +2029,9 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public Optional setRootRuleChain(RuleChainId ruleChainId, EdgeId edgeId) { + public Optional setRootRuleChain(EdgeId edgeId, RuleChainId ruleChainId) { try { - ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/{ruleChainId}/root", null, RuleChain.class, edgeId.getId(), ruleChainId.getId()); + ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/{ruleChainId}/root", null, Edge.class, edgeId.getId(), ruleChainId.getId()); return Optional.ofNullable(ruleChain.getBody()); } catch (HttpClientErrorException exception) { if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { From c39cfe490a3b2f26be55979341401a563944aca2 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 25 Sep 2020 14:19:22 +0300 Subject: [PATCH 131/156] fixed getDefaultEdgeRuleChains method --- .../src/main/java/org/thingsboard/rest/client/RestClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 0232bc5216..904e662e12 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -2278,7 +2278,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } public List getDefaultEdgeRuleChains() { - return restTemplate.exchange(baseURL + "/ruleChain/defaultEdgeRuleChains", + return restTemplate.exchange(baseURL + "/api/ruleChain/defaultEdgeRuleChains", HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference>() { From b67e21604b3744ffcb473872902211b2d712a4aa Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 25 Sep 2020 15:22:03 +0300 Subject: [PATCH 132/156] Added edge license key and cloud endpoint --- .../main/data/upgrade/2.6.0/schema_update.cql | 2 + .../main/data/upgrade/2.6.0/schema_update.sql | 2 + .../ThingsboardSecurityConfiguration.java | 2 +- .../server/controller/EdgeController.java | 21 +++++ .../ThingsboardErrorResponseHandler.java | 13 ++- .../service/edge/rpc/EdgeGrpcService.java | 11 ++- .../service/edge/rpc/EdgeGrpcSession.java | 18 ++-- .../rpc/constructor/AssetMsgConstructor.java | 6 +- .../rpc/constructor/DeviceMsgConstructor.java | 4 + .../constructor/EntityViewMsgConstructor.java | 5 +- .../controller/AbstractControllerTest.java | 2 + .../controller/BaseEdgeControllerTest.java | 3 + .../server/dao/edge/EdgeService.java | 4 + .../server/common/data/edge/Edge.java | 4 + .../data/exception/ThingsboardErrorCode.java | 3 +- .../thingsboard/edge/rpc/EdgeGrpcClient.java | 94 +++++++++---------- .../thingsboard/edge/rpc/EdgeRpcClient.java | 2 + common/edge-api/src/main/proto/edge.proto | 8 +- .../server/dao/edge/EdgeServiceImpl.java | 90 +++++++++++++++++- .../server/dao/model/ModelConstants.java | 2 + .../server/dao/model/nosql/EdgeEntity.java | 16 +++- .../server/dao/model/sql/EdgeEntity.java | 12 +++ .../resources/cassandra/schema-entities.cql | 2 + .../resources/sql/schema-entities-hsql.sql | 2 + .../main/resources/sql/schema-entities.sql | 2 + .../dao/service/BaseDashboardServiceTest.java | 2 + .../dao/service/BaseEdgeServiceTest.java | 2 + ui/src/app/common/utils.service.js | 12 ++- ui/src/app/edge/edge-fieldset.tpl.html | 14 +++ ui/src/app/edge/edge.directive.js | 1 + ui/src/app/locale/locale.constant-de_DE.json | 4 + ui/src/app/locale/locale.constant-en_US.json | 4 + ui/src/app/locale/locale.constant-es_ES.json | 4 + ui/src/app/locale/locale.constant-fr_FR.json | 4 + 34 files changed, 303 insertions(+), 74 deletions(-) diff --git a/application/src/main/data/upgrade/2.6.0/schema_update.cql b/application/src/main/data/upgrade/2.6.0/schema_update.cql index 6ac8f404bd..a6744c52f9 100644 --- a/application/src/main/data/upgrade/2.6.0/schema_update.cql +++ b/application/src/main/data/upgrade/2.6.0/schema_update.cql @@ -57,6 +57,8 @@ CREATE TABLE IF NOT EXISTS thingsboard.edge ( search_text text, routing_key text, secret text, + edge_license_key text, + cloud_endpoint text, configuration text, additional_info text, PRIMARY KEY (id, tenant_id, customer_id, type) diff --git a/application/src/main/data/upgrade/2.6.0/schema_update.sql b/application/src/main/data/upgrade/2.6.0/schema_update.sql index 90660d4026..b3bfd07620 100644 --- a/application/src/main/data/upgrade/2.6.0/schema_update.sql +++ b/application/src/main/data/upgrade/2.6.0/schema_update.sql @@ -25,6 +25,8 @@ CREATE TABLE IF NOT EXISTS edge ( label varchar(255), routing_key varchar(255), secret varchar(255), + edge_license_key varchar(30), + cloud_endpoint varchar(255), search_text varchar(255), tenant_id varchar(31), CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name), diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 683345fe7f..0972d965ad 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -69,7 +69,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login"; public static final String PUBLIC_LOGIN_ENTRY_POINT = "/api/auth/login/public"; public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token"; - protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/static/**", "/api/noauth/**", "/webjars/**"}; + protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/static/**", "/api/noauth/**", "/webjars/**", "/api/license/**"}; public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**"; public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**"; diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 057e4a90bf..4c6be42064 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeSearchQuery; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EdgeId; @@ -408,4 +409,24 @@ public class EdgeController extends BaseController { } } + @RequestMapping(value = "/license/checkInstance", method = RequestMethod.POST) + @ResponseBody + public Object checkInstance(@RequestBody Object request) throws ThingsboardException { + try { + return edgeService.checkInstance(request); + } catch (Exception e) { + throw new ThingsboardException(e, ThingsboardErrorCode.SUBSCRIPTION_VIOLATION); + } + } + + @RequestMapping(value = "/license/activateInstance", params = {"licenseSecret", "releaseDate"}, method = RequestMethod.POST) + @ResponseBody + public Object activateInstance(@RequestParam String licenseSecret, + @RequestParam String releaseDate) throws ThingsboardException { + try { + return edgeService.activateInstance(licenseSecret, releaseDate); + } catch (Exception e) { + throw new ThingsboardException(e, ThingsboardErrorCode.SUBSCRIPTION_VIOLATION); + } + } } diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index e139f9a821..f8026d6278 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -27,6 +27,7 @@ import org.springframework.security.authentication.LockedException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.msg.tools.TbRateLimitsException; @@ -66,7 +67,12 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { response.setContentType(MediaType.APPLICATION_JSON_VALUE); if (exception instanceof ThingsboardException) { - handleThingsboardException((ThingsboardException) exception, response); + ThingsboardException thingsboardException = (ThingsboardException) exception; + if (thingsboardException.getErrorCode() == ThingsboardErrorCode.SUBSCRIPTION_VIOLATION) { + handleSubscriptionException((ThingsboardException) exception, response); + } else { + handleThingsboardException((ThingsboardException) exception, response); + } } else if (exception instanceof TbRateLimitsException) { handleRateLimitException(response, (TbRateLimitsException) exception); } else if (exception instanceof AccessDeniedException) { @@ -126,6 +132,11 @@ public class ThingsboardErrorResponseHandler implements AccessDeniedHandler { ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)); } + private void handleSubscriptionException(ThingsboardException subscriptionException, HttpServletResponse response) throws IOException { + response.setStatus(HttpStatus.FORBIDDEN.value()); + mapper.writeValue(response.getWriter(), + (new ObjectMapper()).readValue(((HttpClientErrorException) subscriptionException.getCause()).getResponseBodyAsByteArray(), Object.class)); + } private void handleAccessDeniedException(HttpServletResponse response) throws IOException { response.setStatus(HttpStatus.FORBIDDEN.value()); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index f6359275ea..89c4c1e1b7 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -145,8 +145,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i executor.submit(() -> { while (!Thread.interrupted()) { try { - for (EdgeGrpcSession session : sessions.values()) { - session.processHandleMessages(); + if (sessions.size() > 0) { + for (EdgeGrpcSession session : sessions.values()) { + session.processHandleMessages(); + } + } else { + log.trace("No sessions available, sleep for the next run"); + try { + Thread.sleep(1000); + } catch (InterruptedException ignore) {} } } catch (Exception e) { log.warn("Failed to process messages handling!", e); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index d56f2b871b..3fb42a40b6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -159,10 +159,10 @@ public final class EdgeGrpcSession implements Closeable { if (ConnectResponseCode.ACCEPTED != responseMsg.getResponseCode()) { outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); } - if (ConnectResponseCode.ACCEPTED == responseMsg.getResponseCode()) { - connected = true; - ctx.getSyncEdgeService().sync(edge); - } + } + if (!connected && requestMsg.getMsgType().equals(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE)) { + connected = true; + ctx.getSyncEdgeService().sync(edge); } if (connected) { if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE) && requestMsg.hasUplinkMsg()) { @@ -182,8 +182,12 @@ public final class EdgeGrpcSession implements Closeable { @Override public void onCompleted() { connected = false; - sessionCloseListener.accept(edge.getId()); - outputStream.onCompleted(); + if (edge != null) { + sessionCloseListener.accept(edge.getId()); + } + try { + outputStream.onCompleted(); + } catch (Exception ignored) {} } }; } @@ -948,6 +952,8 @@ public final class EdgeGrpcSession implements Closeable { .setName(edge.getName()) .setRoutingKey(edge.getRoutingKey()) .setType(edge.getType()) + .setEdgeLicenseKey(edge.getEdgeLicenseKey()) + .setCloudEndpoint(edge.getCloudEndpoint()) .setCloudType("CE") .build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java index 694efcd081..c6eb3d32f4 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java @@ -17,11 +17,10 @@ package org.thingsboard.server.service.edge.rpc.constructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -43,6 +42,9 @@ public class AssetMsgConstructor { builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); } + if (asset.getAdditionalInfo() != null) { + builder.setAdditionalInfo(JacksonUtil.toString(asset.getAdditionalInfo())); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java index 38905d7529..ffc635075d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; @@ -50,6 +51,9 @@ public class DeviceMsgConstructor { builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); } + if (device.getAdditionalInfo() != null) { + builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo())); + } return builder.build(); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java index c19a84cfcb..abe32dec77 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java @@ -19,8 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.EdgeEntityType; import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -54,6 +54,9 @@ public class EntityViewMsgConstructor { builder.setCustomerIdMSB(customerId.getId().getMostSignificantBits()); builder.setCustomerIdLSB(customerId.getId().getLeastSignificantBits()); } + if (entityView.getAdditionalInfo() != null) { + builder.setAdditionalInfo(JacksonUtil.toString(entityView.getAdditionalInfo())); + } return builder.build(); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java index 0b3a86a22e..d44dd867de 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java @@ -510,6 +510,8 @@ public abstract class AbstractControllerTest { edge.setType(type); edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); + edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20)); + edge.setCloudEndpoint("http://localhost:8080"); return edge; } } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index 1f655a2c3c..165f8cecdb 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.controller; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -90,6 +91,8 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { Assert.assertNotNull(savedEdge.getCustomerId()); Assert.assertEquals(NULL_UUID, savedEdge.getCustomerId().getId()); Assert.assertEquals(edge.getName(), savedEdge.getName()); + Assert.assertTrue(StringUtils.isNoneBlank(savedEdge.getEdgeLicenseKey())); + Assert.assertTrue(StringUtils.isNoneBlank(savedEdge.getCloudEndpoint())); savedEdge.setName("My new edge"); doPost("/api/edge", savedEdge, Edge.class); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index f09db3e9e1..e29d5f3307 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -76,4 +76,8 @@ public interface EdgeService { ListenableFuture> findEdgesByTenantIdAndDashboardId(TenantId tenantId, DashboardId dashboardId); ListenableFuture> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId); + + Object checkInstance(Object request); + + Object activateInstance(String licenseSecret, String releaseDate); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java index 56990cff44..699fdf954a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java @@ -45,6 +45,8 @@ public class Edge extends SearchTextBasedWithAdditionalInfo implements H private String label; private String routingKey; private String secret; + private String edgeLicenseKey; + private String cloudEndpoint; private transient JsonNode configuration; public Edge() { @@ -64,6 +66,8 @@ public class Edge extends SearchTextBasedWithAdditionalInfo implements H this.name = edge.getName(); this.routingKey = edge.getRoutingKey(); this.secret = edge.getSecret(); + this.edgeLicenseKey = edge.getEdgeLicenseKey(); + this.cloudEndpoint = edge.getCloudEndpoint(); this.configuration = edge.getConfiguration(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java index 916a50b26a..d28eea57aa 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java @@ -28,7 +28,8 @@ public enum ThingsboardErrorCode { BAD_REQUEST_PARAMS(31), ITEM_NOT_FOUND(32), TOO_MANY_REQUESTS(33), - TOO_MANY_UPDATES(34); + TOO_MANY_UPDATES(34), + SUBSCRIPTION_VIOLATION(40); private int errorCode; diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 57c1cf272e..4c20e97b6a 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -81,7 +81,6 @@ public class EdgeGrpcClient implements EdgeRpcClient { throw new RuntimeException(e); } } - gracefulShutdown(); channel = builder.build(); EdgeRpcServiceGrpc.EdgeRpcServiceStub stub = EdgeRpcServiceGrpc.newStub(channel); log.info("[{}] Sending a connect request to the TB!", edgeKey); @@ -92,53 +91,6 @@ public class EdgeGrpcClient implements EdgeRpcClient { .build()); } - private void gracefulShutdown() { - try { - if (channel != null) { - channel.shutdown().awaitTermination(timeoutSecs, TimeUnit.SECONDS); - } - } catch (InterruptedException e) { - log.debug("Error during shutdown of the previous channel", e); - } - } - - @Override - public void disconnect() throws InterruptedException { - try { - inputStream.onCompleted(); - } catch (Exception e) { - } - if (channel != null) { - channel.shutdown().awaitTermination(timeoutSecs, TimeUnit.SECONDS); - } - } - - @Override - public void sendUplinkMsg(UplinkMsg msg) { - try { - uplinkMsgLock.lock(); - this.inputStream.onNext(RequestMsg.newBuilder() - .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) - .setUplinkMsg(msg) - .build()); - } finally { - uplinkMsgLock.unlock(); - } - } - - @Override - public void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg) { - try { - uplinkMsgLock.lock(); - this.inputStream.onNext(RequestMsg.newBuilder() - .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) - .setDownlinkResponseMsg(downlinkResponseMsg) - .build()); - } finally { - uplinkMsgLock.unlock(); - } - } - private StreamObserver initOutputStream(String edgeKey, Consumer onUplinkResponse, Consumer onEdgeUpdate, @@ -179,8 +131,52 @@ public class EdgeGrpcClient implements EdgeRpcClient { @Override public void onCompleted() { log.debug("[{}] The rpc session was closed!", edgeKey); - onError.accept(new EdgeConnectionException("[" + edgeKey + "] The rpc session was closed!")); } }; } + + @Override + public void disconnect() throws InterruptedException { + if (channel != null) { + channel.shutdown().awaitTermination(timeoutSecs, TimeUnit.SECONDS); + } + } + + @Override + public void sendUplinkMsg(UplinkMsg msg) { + try { + uplinkMsgLock.lock(); + this.inputStream.onNext(RequestMsg.newBuilder() + .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) + .setUplinkMsg(msg) + .build()); + } finally { + uplinkMsgLock.unlock(); + } + } + + @Override + public void sendSyncRequestMsg() { + try { + uplinkMsgLock.lock(); + this.inputStream.onNext(RequestMsg.newBuilder() + .setMsgType(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE) + .build()); + } finally { + uplinkMsgLock.unlock(); + } + } + + @Override + public void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg) { + try { + uplinkMsgLock.lock(); + this.inputStream.onNext(RequestMsg.newBuilder() + .setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE) + .setDownlinkResponseMsg(downlinkResponseMsg) + .build()); + } finally { + uplinkMsgLock.unlock(); + } + } } diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java index c268b2a9e9..a66f941922 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java @@ -34,6 +34,8 @@ public interface EdgeRpcClient { void disconnect() throws InterruptedException; + void sendSyncRequestMsg(); + void sendUplinkMsg(UplinkMsg uplinkMsg); void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg); diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 560522e021..30279ed10d 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -49,6 +49,7 @@ message ResponseMsg { enum RequestMsgType { CONNECT_RPC_MESSAGE = 0; UPLINK_RPC_MESSAGE = 1; + SYNC_REQUEST_RPC_MESSAGE = 2; } message ConnectRequestMsg { @@ -76,7 +77,9 @@ message EdgeConfiguration { string name = 5; string routingKey = 6; string type = 7; - string cloudType = 8; + string edgeLicenseKey = 8; + string cloudEndpoint = 9; + string cloudType = 10; } enum UpdateMsgType { @@ -169,6 +172,7 @@ message DeviceUpdateMsg { string name = 6; string type = 7; string label = 8; + string additionalInfo = 9; } message DeviceCredentialsUpdateMsg { @@ -188,6 +192,7 @@ message AssetUpdateMsg { string name = 6; string type = 7; string label = 8; + string additionalInfo = 9; } message EntityViewUpdateMsg { @@ -201,6 +206,7 @@ message EntityViewUpdateMsg { int64 entityIdMSB = 8; int64 entityIdLSB = 9; EdgeEntityType entityType = 10; + string additionalInfo = 11; } message AlarmUpdateMsg { diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 2a362e6483..55ff78e61d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -20,13 +20,21 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpHost; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import org.springframework.web.client.RestTemplate; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; @@ -48,14 +56,9 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; -import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.customer.CustomerDao; -import org.thingsboard.server.dao.dashboard.DashboardService; -import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.entity.AbstractEntityService; -import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; -import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.service.DataValidator; @@ -65,10 +68,15 @@ import org.thingsboard.server.dao.tenant.TenantDao; import org.thingsboard.server.dao.user.UserService; import javax.annotation.Nullable; +import javax.annotation.PostConstruct; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -89,6 +97,10 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; public static final String INCORRECT_EDGE_ID = "Incorrect edgeId "; + private RestTemplate restTemplate; + + private static final String EDGE_LICENSE_SERVER_ENDPOINT = "https://license.thingsboard.io"; + @Autowired private EdgeDao edgeDao; @@ -110,6 +122,17 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @Autowired private RelationService relationService; + @Value("${edges.rpc.enabled:false}") + private boolean edgesRpcEnabled; + + @PostConstruct + public void init() { + super.init(); + if (edgesRpcEnabled) { + initRestTemplate(); + } + } + @Override public Edge findEdgeById(TenantId tenantId, EdgeId edgeId) { log.trace("Executing findEdgeById [{}]", edgeId); @@ -374,6 +397,12 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic if (StringUtils.isEmpty(edge.getRoutingKey())) { throw new DataValidationException("Edge routing key should be specified!"); } + if (StringUtils.isEmpty(edge.getEdgeLicenseKey())) { + throw new DataValidationException("Edge license key should be specified!"); + } + if (StringUtils.isEmpty(edge.getCloudEndpoint())) { + throw new DataValidationException("Cloud endpoint should be specified!"); + } if (edge.getTenantId() == null) { throw new DataValidationException("Edge should be assigned to tenant!"); } else { @@ -475,4 +504,55 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic }, MoreExecutors.directExecutor()); } + @Override + public Object checkInstance(Object request) { + return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/checkInstance", request, Object.class, new Object[0]); + } + + @Override + public Object activateInstance(String edgeLicenseSecret, String releaseDate) { + Map params = new HashMap(); + params.put("licenseSecret", edgeLicenseSecret); + params.put("releaseDate", releaseDate); + return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/activateInstance?licenseSecret={licenseSecret}&releaseDate={releaseDate}", (Object) null, Object.class, params); + } + + private void initRestTemplate() { + boolean jdkHttpClientEnabled = org.apache.commons.lang3.StringUtils.isNotEmpty(System.getProperty("tb.proxy.jdk")) && System.getProperty("tb.proxy.jdk").equalsIgnoreCase("true"); + boolean systemProxyEnabled = org.apache.commons.lang3.StringUtils.isNotEmpty(System.getProperty("tb.proxy.system")) && System.getProperty("tb.proxy.system").equalsIgnoreCase("true"); + boolean proxyEnabled = org.apache.commons.lang3.StringUtils.isNotEmpty(System.getProperty("tb.proxy.host")) && org.apache.commons.lang3.StringUtils.isNotEmpty(System.getProperty("tb.proxy.port")); + if (jdkHttpClientEnabled) { + log.warn("Going to use plain JDK Http Client!"); + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + if (proxyEnabled) { + log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port")); + factory.setProxy(new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port"))))); + } + + this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory()); + } else { + CloseableHttpClient httpClient; + HttpComponentsClientHttpRequestFactory requestFactory; + if (systemProxyEnabled) { + log.warn("Going to use System Proxy Server!"); + httpClient = HttpClients.createSystem(); + requestFactory = new HttpComponentsClientHttpRequestFactory(); + requestFactory.setHttpClient(httpClient); + this.restTemplate = new RestTemplate(requestFactory); + } else if (proxyEnabled) { + log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port")); + httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).setProxy(new HttpHost(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")), "https")).build(); + requestFactory = new HttpComponentsClientHttpRequestFactory(); + requestFactory.setHttpClient(httpClient); + this.restTemplate = new RestTemplate(requestFactory); + } else { + httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).build(); + requestFactory = new HttpComponentsClientHttpRequestFactory(); + requestFactory.setHttpClient(httpClient); + this.restTemplate = new RestTemplate(requestFactory); + } + } + + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 54a65077c5..688a22675d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -377,6 +377,8 @@ public class ModelConstants { public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key"; public static final String EDGE_SECRET_PROPERTY = "secret"; + public static final String EDGE_LICENSE_KEY_PROPERTY = "edge_license_key"; + public static final String EDGE_CLOUD_ENDPOINT_KEY_PROPERTY = "cloud_endpoint"; /** * Cassandra edge queue constants. diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java index 37e2d821ba..5480a9109f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.model.nosql; import com.datastax.driver.core.utils.UUIDs; -import com.datastax.driver.mapping.annotations.ClusteringColumn; import com.datastax.driver.mapping.annotations.Column; import com.datastax.driver.mapping.annotations.PartitionKey; import com.datastax.driver.mapping.annotations.Table; @@ -32,14 +31,13 @@ import org.thingsboard.server.dao.model.type.JsonCodec; import java.util.UUID; -import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_CUSTOMER_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TENANT_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TYPE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ADDITIONAL_INFO_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CLOUD_ENDPOINT_KEY_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CONFIGURATION_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LABEL_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LICENSE_KEY_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROOT_RULE_CHAIN_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY; @@ -84,6 +82,12 @@ public class EdgeEntity implements SearchTextEntity { @Column(name = EDGE_ROUTING_KEY_PROPERTY) private String routingKey; + @Column(name = EDGE_LICENSE_KEY_PROPERTY) + private String edgeLicenseKey; + + @Column(name = EDGE_CLOUD_ENDPOINT_KEY_PROPERTY) + private String cloudEndpoint; + @Column(name = EDGE_SECRET_PROPERTY) private String secret; @@ -125,6 +129,8 @@ public class EdgeEntity implements SearchTextEntity { this.label = edge.getLabel(); this.routingKey = edge.getRoutingKey(); this.secret = edge.getSecret(); + this.edgeLicenseKey = edge.getEdgeLicenseKey(); + this.cloudEndpoint = edge.getCloudEndpoint(); this.configuration = edge.getConfiguration(); this.additionalInfo = edge.getAdditionalInfo(); } @@ -152,6 +158,8 @@ public class EdgeEntity implements SearchTextEntity { edge.setLabel(label); edge.setRoutingKey(routingKey); edge.setSecret(secret); + edge.setEdgeLicenseKey(edgeLicenseKey); + edge.setCloudEndpoint(cloudEndpoint); edge.setConfiguration(configuration); edge.setAdditionalInfo(additionalInfo); return edge; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java index 6ede11a61f..76bd4f2961 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java @@ -36,9 +36,11 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CLOUD_ENDPOINT_KEY_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LABEL_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LICENSE_KEY_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROOT_RULE_CHAIN_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY; @@ -81,6 +83,12 @@ public class EdgeEntity extends BaseSqlEntity implements SearchTextEntity< @Column(name = EDGE_SECRET_PROPERTY) private String secret; + @Column(name = EDGE_LICENSE_KEY_PROPERTY) + private String edgeLicenseKey; + + @Column(name = EDGE_CLOUD_ENDPOINT_KEY_PROPERTY) + private String cloudEndpoint; + @Type(type = "json") @Column(name = ModelConstants.EDGE_CONFIGURATION_PROPERTY) private JsonNode configuration; @@ -111,6 +119,8 @@ public class EdgeEntity extends BaseSqlEntity implements SearchTextEntity< this.label = edge.getLabel(); this.routingKey = edge.getRoutingKey(); this.secret = edge.getSecret(); + this.edgeLicenseKey = edge.getEdgeLicenseKey(); + this.cloudEndpoint = edge.getCloudEndpoint(); this.configuration = edge.getConfiguration(); this.additionalInfo = edge.getAdditionalInfo(); } @@ -147,6 +157,8 @@ public class EdgeEntity extends BaseSqlEntity implements SearchTextEntity< edge.setLabel(label); edge.setRoutingKey(routingKey); edge.setSecret(secret); + edge.setEdgeLicenseKey(edgeLicenseKey); + edge.setCloudEndpoint(cloudEndpoint); edge.setConfiguration(configuration); edge.setAdditionalInfo(additionalInfo); return edge; diff --git a/dao/src/main/resources/cassandra/schema-entities.cql b/dao/src/main/resources/cassandra/schema-entities.cql index a5518662ae..8ac0ad4956 100644 --- a/dao/src/main/resources/cassandra/schema-entities.cql +++ b/dao/src/main/resources/cassandra/schema-entities.cql @@ -737,6 +737,8 @@ CREATE TABLE IF NOT EXISTS thingsboard.edge ( search_text text, routing_key text, secret text, + edge_license_key text, + cloud_endpoint text, configuration text, additional_info text, PRIMARY KEY (id, tenant_id, customer_id, type) diff --git a/dao/src/main/resources/sql/schema-entities-hsql.sql b/dao/src/main/resources/sql/schema-entities-hsql.sql index 32855d2df3..8aea89a2b4 100644 --- a/dao/src/main/resources/sql/schema-entities-hsql.sql +++ b/dao/src/main/resources/sql/schema-entities-hsql.sql @@ -265,6 +265,8 @@ CREATE TABLE IF NOT EXISTS edge ( label varchar(255), routing_key varchar(255), secret varchar(255), + edge_license_key varchar(30), + cloud_endpoint varchar(255), search_text varchar(255), tenant_id varchar(31), CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name), diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index d1d33ff71f..4ec76cc845 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -265,6 +265,8 @@ CREATE TABLE IF NOT EXISTS edge ( label varchar(255), routing_key varchar(255), secret varchar(255), + edge_license_key varchar(30), + cloud_endpoint varchar(255), search_text varchar(255), tenant_id varchar(31), CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name), diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java index 0854ceaae2..af3b4dd291 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java @@ -358,6 +358,8 @@ public abstract class BaseDashboardServiceTest extends AbstractServiceTest { edge.setType("default"); edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); + edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20)); + edge.setCloudEndpoint("http://localhost:8080"); edge = edgeService.saveEdge(edge); try { dashboardService.assignDashboardToEdge(tenantId, dashboard.getId(), edge.getId()); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java index 7d31ff4236..8e773d2fab 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java @@ -590,6 +590,8 @@ public abstract class BaseEdgeServiceTest extends AbstractServiceTest { edge.setType(type); edge.setSecret(RandomStringUtils.randomAlphanumeric(20)); edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20)); + edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20)); + edge.setCloudEndpoint("http://localhost:8080"); return edge; } diff --git a/ui/src/app/common/utils.service.js b/ui/src/app/common/utils.service.js index d5e4852afd..64610be2f5 100644 --- a/ui/src/app/common/utils.service.js +++ b/ui/src/app/common/utils.service.js @@ -33,7 +33,7 @@ export default angular.module('thingsboard.utils', [thingsboardTypes]) const varsRegex = /\$\{([^}]*)\}/g; /*@ngInject*/ -function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, types) { +function Utils($mdColorPalette, $rootScope, $window, $location, $translate, $q, $timeout, types) { var predefinedFunctions = {}, predefinedFunctionsList = [], @@ -142,6 +142,7 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t guid: guid, cleanCopy: cleanCopy, isLocalUrl: isLocalUrl, + baseUrl: baseUrl, validateDatasources: validateDatasources, createKey: createKey, createAdditionalDataKey: createAdditionalDataKey, @@ -435,6 +436,15 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t } } + function baseUrl() { + var url = $location.protocol() + '://' + $location.host(); + var port = $location.port(); + if (port != 80 && port != 443) { + url += ":" + port; + } + return url; + } + function validateDatasources(datasources) { datasources.forEach(function (datasource) { if (datasource.type === 'device') { diff --git a/ui/src/app/edge/edge-fieldset.tpl.html b/ui/src/app/edge/edge-fieldset.tpl.html index c151c03f10..1595b2aebd 100644 --- a/ui/src/app/edge/edge-fieldset.tpl.html +++ b/ui/src/app/edge/edge-fieldset.tpl.html @@ -83,6 +83,20 @@ + + + +
+
edge.edge-license-key-required
+
+
+ + + +
+
edge.cloud-endpoint-required
+
+
diff --git a/ui/src/app/edge/edge.directive.js b/ui/src/app/edge/edge.directive.js index d96dfa4b4d..98f010e009 100644 --- a/ui/src/app/edge/edge.directive.js +++ b/ui/src/app/edge/edge.directive.js @@ -35,6 +35,7 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD if (!scope.edge.id) { scope.edge.routingKey = utils.guid(''); scope.edge.secret = generateSecret(20); + scope.edge.cloudEndpoint = utils.baseUrl(); } if (scope.edge.customerId && scope.edge.customerId.id !== types.id.nullUid) { scope.isAssignedToCustomer = true; diff --git a/ui/src/app/locale/locale.constant-de_DE.json b/ui/src/app/locale/locale.constant-de_DE.json index 1f9bdbae58..f8a1d887ff 100644 --- a/ui/src/app/locale/locale.constant-de_DE.json +++ b/ui/src/app/locale/locale.constant-de_DE.json @@ -747,6 +747,10 @@ "delete-edges-text": "Vorsicht, nach Bestätigung werden alle ausgewählten Rand entfernt und alle zugehörigen Daten werden nicht wiederhergestellt.", "name": "Name", "name-required": "Name ist erforderlich.", + "edge-license-key": "Edge Lizenzschlüssel", + "edge-license-key-required": "Edge Lizenzschlüssel ist erforderlich.", + "cloud-endpoint": "Cloud-Endpunkt", + "cloud-endpoint-required": "Cloud-Endpunkt ist erforderlich.", "description": "Beschreibung", "events": "Ereignisse", "details": "Details", diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 34ef9c98ef..c77192bffb 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -778,6 +778,10 @@ "delete-edges-text": "Be careful, after the confirmation all selected edges will be removed and all related data will become unrecoverable.", "name": "Name", "name-required": "Name is required.", + "edge-license-key": "Edge License Key", + "edge-license-key-required": "Edge License Key is required.", + "cloud-endpoint": "Cloud Endpoint", + "cloud-endpoint-required": "Cloud Endpoint is required.", "description": "Description", "entity-info": "Entity info", "details": "Details", diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json index de16a8ab99..f8f4e6bbe9 100644 --- a/ui/src/app/locale/locale.constant-es_ES.json +++ b/ui/src/app/locale/locale.constant-es_ES.json @@ -760,6 +760,10 @@ "delete-edges-text": "Tenga cuidado, después de la confirmación se eliminarán todos los bordes seleccionados y todos los datos relacionados se volverán irrecuperables", "name": "Nombre", "name-required": "Se requiere nombre", + "edge-license-key": "Edge Clave de licencia", + "edge-license-key-required": "Se requiere edge clave de licencia", + "cloud-endpoint": "Punto final de la nube", + "cloud-endpoint-required": "Se requiere punto final de la nube", "description": "Descripción", "events": "Eventos", "details": "Detalles", diff --git a/ui/src/app/locale/locale.constant-fr_FR.json b/ui/src/app/locale/locale.constant-fr_FR.json index 444228966f..4058148bbd 100644 --- a/ui/src/app/locale/locale.constant-fr_FR.json +++ b/ui/src/app/locale/locale.constant-fr_FR.json @@ -765,6 +765,10 @@ "delete-edges-text": "Faites attention, après la confirmation, tous les bordures sélectionnés seront supprimés et toutes les données associées deviendront irrécupérables.", "name": "Nom", "name-required": "Le nom de la bordure est requis", + "edge-license-key": "Edge Clé de licence", + "edge-license-key-required": "La edge clé de licence est requise", + "cloud-endpoint": "Clé de licence", + "cloud-endpoint-required": "La clé de licence est requise", "description": "Dispositifs", "events": "Événements", "details": "Détails de l'entité", From f28721cc4779035351659945695bf19cedc0d428 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 25 Sep 2020 16:04:10 +0300 Subject: [PATCH 133/156] Added additional info --- .../server/service/edge/rpc/processor/DeviceProcessor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java index 85ffab4799..0e5b88aa2a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceProcessor.java @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; @@ -131,6 +132,7 @@ public class DeviceProcessor extends BaseProcessor { device.setName(deviceUpdateMsg.getName()); device.setType(deviceUpdateMsg.getType()); device.setLabel(deviceUpdateMsg.getLabel()); + device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); deviceService.saveDevice(device); saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_REQUEST, deviceId, null); @@ -148,6 +150,7 @@ public class DeviceProcessor extends BaseProcessor { device.setName(deviceUpdateMsg.getName()); device.setType(deviceUpdateMsg.getType()); device.setLabel(deviceUpdateMsg.getLabel()); + device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); device = deviceService.saveDevice(device); createDeviceCredentials(device); createRelationFromEdge(tenantId, edge.getId(), device.getId()); From 78a7e6764119dc6af5d12745fa469da6bb2f4944 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 25 Sep 2020 16:42:00 +0300 Subject: [PATCH 134/156] Test fixed --- .../java/org/thingsboard/server/edge/imitator/EdgeImitator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 9f6d51a601..69470a681d 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -75,6 +75,8 @@ public class EdgeImitator { this::onEdgeUpdate, this::onDownlink, this::onClose); + + edgeRpcClient.sendSyncRequestMsg(); } public void disconnect() throws InterruptedException { From 5613baf066dc56ee85709c10d757ce8799c4f425 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 25 Sep 2020 16:52:56 +0300 Subject: [PATCH 135/156] Added correct onComplete in case onError --- .../java/org/thingsboard/edge/rpc/EdgeGrpcClient.java | 10 ++++++++-- .../java/org/thingsboard/edge/rpc/EdgeRpcClient.java | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 4c20e97b6a..88fe402668 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -40,6 +40,7 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg; import javax.net.ssl.SSLException; import java.io.File; import java.net.URISyntaxException; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @@ -107,7 +108,7 @@ public class EdgeGrpcClient implements EdgeRpcClient { } else { log.error("[{}] Failed to establish the connection! Code: {}. Error message: {}.", edgeKey, connectResponseMsg.getResponseCode(), connectResponseMsg.getErrorMsg()); try { - EdgeGrpcClient.this.disconnect(); + EdgeGrpcClient.this.disconnect(true); } catch (InterruptedException e) { log.error("[{}] Got interruption during disconnect!", edgeKey, e); } @@ -136,7 +137,12 @@ public class EdgeGrpcClient implements EdgeRpcClient { } @Override - public void disconnect() throws InterruptedException { + public void disconnect(boolean onError) throws InterruptedException { + if (!onError) { + try { + inputStream.onCompleted(); + } catch (Exception ignored) {} + } if (channel != null) { channel.shutdown().awaitTermination(timeoutSecs, TimeUnit.SECONDS); } diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java index a66f941922..7aa017c3db 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java @@ -32,7 +32,7 @@ public interface EdgeRpcClient { Consumer onDownlink, Consumer onError); - void disconnect() throws InterruptedException; + void disconnect(boolean onError) throws InterruptedException; void sendSyncRequestMsg(); From 8f5fefa0a0cbb72a67da957e4f7a7dde8463cc4a Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 25 Sep 2020 16:59:47 +0300 Subject: [PATCH 136/156] Compilation fix --- .../java/org/thingsboard/server/edge/imitator/EdgeImitator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 69470a681d..e1b54b6f84 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -80,7 +80,7 @@ public class EdgeImitator { } public void disconnect() throws InterruptedException { - edgeRpcClient.disconnect(); + edgeRpcClient.disconnect(false); } private void onUplinkResponse(UplinkResponseMsg msg) { From 7644aa434200059da9b5830b13a8a600900bea4a Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 25 Sep 2020 17:29:33 +0300 Subject: [PATCH 137/156] Added edge update config handler --- .../server/service/edge/rpc/EdgeGrpcSession.java | 14 +++++++------- .../org/thingsboard/edge/rpc/EdgeGrpcClient.java | 3 +++ common/edge-api/src/main/proto/edge.proto | 5 +++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 3fb42a40b6..de68eb6e55 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -83,6 +83,7 @@ import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.EdgeUpdateMsg; import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationRequestMsg; @@ -244,12 +245,11 @@ public final class EdgeGrpcSession implements Closeable { void onConfigurationUpdate(Edge edge) { try { this.edge = edge; - // TODO: voba - push edge configuration update to edge -// sendResponseMsg(org.thingsboard.server.gen.integration.ResponseMsg.newBuilder() -// .setIntegrationUpdateMsg(IntegrationUpdateMsg.newBuilder() -// .setConfiguration(constructIntegrationConfigProto(configuration, defaultConverterProto, downLinkConverterProto)) -// .build()) -// .build()); + EdgeUpdateMsg edgeConfig = EdgeUpdateMsg.newBuilder() + .setConfiguration(constructEdgeConfigProto(edge)).build(); + outputStream.onNext(ResponseMsg.newBuilder() + .setEdgeUpdateMsg(edgeConfig) + .build()); } catch (Exception e) { log.error("Failed to construct proto objects!", e); } @@ -903,7 +903,7 @@ public final class EdgeGrpcSession implements Closeable { } } if (uplinkMsg.getDeviceRpcCallMsgList() != null && !uplinkMsg.getDeviceRpcCallMsgList().isEmpty()) { - for (DeviceRpcCallMsg deviceRpcCallMsg: uplinkMsg.getDeviceRpcCallMsgList()) { + for (DeviceRpcCallMsg deviceRpcCallMsg : uplinkMsg.getDeviceRpcCallMsgList()) { result.add(ctx.getDeviceProcessor().processDeviceRpcCallResponseMsg(edge.getTenantId(), deviceRpcCallMsg)); } } diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 88fe402668..edc1e5bc91 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -114,6 +114,9 @@ public class EdgeGrpcClient implements EdgeRpcClient { } onError.accept(new EdgeConnectionException("Failed to establish the connection! Response code: " + connectResponseMsg.getResponseCode().name())); } + } else if (responseMsg.hasEdgeUpdateMsg()) { + log.debug("[{}] Edge update message received {}", edgeKey, responseMsg.getEdgeUpdateMsg()); + onEdgeUpdate.accept(responseMsg.getEdgeUpdateMsg().getConfiguration()); } else if (responseMsg.hasUplinkResponseMsg()) { log.debug("[{}] Uplink response message received {}", edgeKey, responseMsg.getUplinkResponseMsg()); onUplinkResponse.accept(responseMsg.getUplinkResponseMsg()); diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 30279ed10d..c2ce170401 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -44,6 +44,7 @@ message ResponseMsg { ConnectResponseMsg connectResponseMsg = 1; UplinkResponseMsg uplinkResponseMsg = 2; DownlinkMsg downlinkMsg = 3; + EdgeUpdateMsg edgeUpdateMsg = 4; } enum RequestMsgType { @@ -52,6 +53,10 @@ enum RequestMsgType { SYNC_REQUEST_RPC_MESSAGE = 2; } +message EdgeUpdateMsg { + EdgeConfiguration configuration = 1; +} + message ConnectRequestMsg { string edgeRoutingKey = 1; string edgeSecret = 2; From 02585823fcf3e311998ef701eb88204f86dae2c7 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 28 Sep 2020 11:04:02 +0300 Subject: [PATCH 138/156] Properly hanlde gRPC session timeout --- .../server/service/edge/rpc/EdgeGrpcService.java | 9 +++++++-- application/src/main/resources/thingsboard.yml | 1 + .../java/org/thingsboard/edge/rpc/EdgeGrpcClient.java | 6 +++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index 89c4c1e1b7..85ea93bed3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.io.Resources; import com.google.common.util.concurrent.FutureCallback; import io.grpc.Server; -import io.grpc.ServerBuilder; +import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -49,6 +49,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; @Service @Slf4j @@ -68,6 +69,8 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i private String privateKeyResource; @Value("${edges.state.persistToTelemetry:false}") private boolean persistToTelemetry; + @Value("${edges.rpc.client_max_keep_alive_time_sec}") + private int clientMaxKeepAliveTimeSec; @Autowired private EdgeContextComponent ctx; @@ -82,7 +85,9 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i @PostConstruct public void init() { log.info("Initializing Edge RPC service!"); - ServerBuilder builder = ServerBuilder.forPort(rpcPort).addService(this); + NettyServerBuilder builder = NettyServerBuilder.forPort(rpcPort) + .permitKeepAliveTime(clientMaxKeepAliveTimeSec, TimeUnit.SECONDS) + .addService(this); if (sslEnabled) { try { File certFile = new File(Resources.getResource(certFileResource).toURI()); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index bcf3425f53..4fedc0ce08 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -590,6 +590,7 @@ edges: rpc: enabled: "${EDGES_RPC_ENABLED:false}" port: "${EDGES_RPC_PORT:7070}" + client_max_keep_alive_time_sec: "${EDGES_RPC_CLIENT_MAX_KEEP_ALIVE_TIME_SEC:300}" ssl: # Enable/disable SSL support enabled: "${EDGES_RPC_SSL_ENABLED:false}" diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index edc1e5bc91..6232029a14 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -55,6 +55,8 @@ public class EdgeGrpcClient implements EdgeRpcClient { private int rpcPort; @Value("${cloud.rpc.timeout}") private int timeoutSecs; + @Value("${cloud.rpc.keep_alive_time_sec}") + private int keepAliveTimeSec; @Value("${cloud.rpc.ssl.enabled}") private boolean sslEnabled; @Value("${cloud.rpc.ssl.cert}") @@ -73,7 +75,9 @@ public class EdgeGrpcClient implements EdgeRpcClient { Consumer onEdgeUpdate, Consumer onDownlink, Consumer onError) { - NettyChannelBuilder builder = NettyChannelBuilder.forAddress(rpcHost, rpcPort).usePlaintext(); + NettyChannelBuilder builder = NettyChannelBuilder.forAddress(rpcHost, rpcPort) + .keepAliveTime(keepAliveTimeSec, TimeUnit.SECONDS) + .usePlaintext(); if (sslEnabled) { try { builder.sslContext(GrpcSslContexts.forClient().trustManager(new File(Resources.getResource(certResource).toURI())).build()); From 52c8e1b48f258f0f3060c5b5e244fd9fd609845a Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 28 Sep 2020 17:02:14 +0300 Subject: [PATCH 139/156] fixed attributes saving --- .../thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index f0f5d2418f..5da3df68ae 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -66,7 +66,7 @@ public class TbMsgAttributesNode implements TbNode { if (StringUtils.isEmpty(msg.getMetaData().getValue(SCOPE))) { msg.getMetaData().putValue(SCOPE, config.getScope()); } - ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), config.getScope(), + ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), msg.getMetaData().getValue(SCOPE), new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); } From 9e215251584092941187f587a68a064b48e95cce Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 29 Sep 2020 13:43:35 +0300 Subject: [PATCH 140/156] code coverage for processors and telemetry constructor --- .../thingsboard/server/edge/BaseEdgeTest.java | 284 +++++++++++++++++- .../server/edge/imitator/EdgeImitator.java | 25 ++ .../server/edge/imitator/EdgeStorage.java | 29 +- .../engine/telemetry/TbMsgAttributesNode.java | 2 +- 4 files changed, 326 insertions(+), 14 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index be26e64f1a..084def021c 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -15,7 +15,11 @@ */ package org.thingsboard.server.edge; +import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -24,6 +28,7 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DashboardInfo; +import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; @@ -33,7 +38,11 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; @@ -42,17 +51,24 @@ import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.controller.AbstractControllerTest; -import org.thingsboard.server.dao.rule.RuleChainService; +import org.thingsboard.server.dao.edge.EdgeEventService;; import org.thingsboard.server.edge.imitator.EdgeImitator; +import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.UpdateMsgType; +import org.thingsboard.server.gen.edge.UplinkMsg; +import org.thingsboard.server.gen.transport.TransportProtos; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -67,6 +83,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { private EdgeImitator edgeImitator; private Edge edge; + @Autowired + private EdgeEventService edgeEventService; + @Before public void beforeTest() throws Exception { loginSysAdmin(); @@ -114,6 +133,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { testDashboards(); testRelations(); testAlarms(); + testTimeseries(); + testAttributes(); + testSendMessagesToCloud(); } private void testReceivedInitialData() throws Exception { @@ -376,6 +398,251 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { log.info("Alarms tested successfully"); } + private void testTimeseries() throws Exception { + log.info("Testing timeseries"); + ObjectMapper mapper = new ObjectMapper(); + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertEquals(1, edgeDevices.size()); + Device device = edgeDevices.get(0); + Assert.assertEquals("Edge Device 1", device.getName()); + + String timeseriesData = "{\"data\":{\"temperature\":25},\"ts\":" + System.currentTimeMillis() + "}"; + JsonNode timeseriesEntityData = mapper.readTree(timeseriesData); + EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), ActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); + edgeImitator.getStorage().expectMessageAmount(1); + edgeEventService.saveAsync(edgeEvent1); + edgeImitator.getStorage().waitForMessages(); + + EntityDataProto latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); + Assert.assertNotNull(latestEntityDataMsg); + UUID uuid = new UUID(latestEntityDataMsg.getEntityIdMSB(), latestEntityDataMsg.getEntityIdLSB()); + Assert.assertEquals(device.getId().getId(), uuid); + Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); + Assert.assertTrue(latestEntityDataMsg.hasPostTelemetryMsg()); + + TransportProtos.PostTelemetryMsg postTelemetryMsg = latestEntityDataMsg.getPostTelemetryMsg(); + Assert.assertEquals(1, postTelemetryMsg.getTsKvListCount()); + TransportProtos.TsKvListProto tsKvListProto = postTelemetryMsg.getTsKvList(0); + Assert.assertEquals(timeseriesEntityData.get("ts").asLong(), tsKvListProto.getTs()); + Assert.assertEquals(1, tsKvListProto.getKvCount()); + TransportProtos.KeyValueProto keyValueProto = tsKvListProto.getKv(0); + Assert.assertEquals("temperature", keyValueProto.getKey()); + Assert.assertEquals(25, keyValueProto.getLongV()); + edgeImitator.getStorage().setLatestEntityDataMsg(null); + log.info("Timeseries tested successfully"); + } + + private void testAttributes() throws Exception { + log.info("Testing attributes"); + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertEquals(1, edgeDevices.size()); + Device device = edgeDevices.get(0); + Assert.assertEquals("Edge Device 1", device.getName()); + + String attributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"test\":\"test\"}}"; + JsonNode attributesEntityData = mapper.readTree(attributesData); + EdgeEvent edgeEvent2 = constructEdgeEvent(tenantId, edge.getId(), ActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); + edgeImitator.getStorage().expectMessageAmount(1); + edgeEventService.saveAsync(edgeEvent2); + edgeImitator.getStorage().waitForMessages(); + + EntityDataProto latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); + Assert.assertNotNull(latestEntityDataMsg); + UUID uuid = new UUID(latestEntityDataMsg.getEntityIdMSB(), latestEntityDataMsg.getEntityIdLSB()); + Assert.assertEquals(device.getId().getId(), uuid); + Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); + Assert.assertEquals(attributesEntityData.get("scope").asText(), latestEntityDataMsg.getPostAttributeScope()); + Assert.assertTrue(latestEntityDataMsg.hasPostAttributesMsg()); + + TransportProtos.PostAttributeMsg postAttributeMsg = latestEntityDataMsg.getPostAttributesMsg(); + Assert.assertEquals(1, postAttributeMsg.getKvCount()); + TransportProtos.KeyValueProto keyValueProto = postAttributeMsg.getKv(0); + Assert.assertEquals("test", keyValueProto.getKey()); + Assert.assertEquals("test", keyValueProto.getStringV()); + edgeImitator.getStorage().setLatestEntityDataMsg(null); + log.info("Attributes tested successfully"); + } + + private void testSendMessagesToCloud() throws Exception { + log.info("Sending messages to cloud"); + sendDevice(); + sendAlarm(); + sendTelemetry(); + sendRelation(); + sendDeleteDeviceOnEdge(); + log.info("Messages were sent successfully"); + } + + private void sendDevice() throws Exception { + UUID uuid = UUIDs.timeBased(); + + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + DeviceUpdateMsg.Builder deviceUpdateMsgBuilder = DeviceUpdateMsg.newBuilder(); + deviceUpdateMsgBuilder.setIdMSB(uuid.getMostSignificantBits()); + deviceUpdateMsgBuilder.setIdLSB(uuid.getLeastSignificantBits()); + deviceUpdateMsgBuilder.setName("Edge Device 2"); + deviceUpdateMsgBuilder.setType("test"); + deviceUpdateMsgBuilder.setMsgType(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE); + builder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build()); + edgeImitator.expectResponsesAmount(1); + edgeImitator.sendUplinkMsg(builder.build()); + edgeImitator.waitForResponses(); + + Device device = doGet("/api/device/" + uuid.toString(), Device.class); + Assert.assertNotNull(device); + Assert.assertEquals("Edge Device 2", device.getName()); + } + + private void sendAlarm() throws Exception { + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Optional foundDevice = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 2")).findAny(); + Assert.assertTrue(foundDevice.isPresent()); + Device device = foundDevice.get(); + + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + AlarmUpdateMsg.Builder alarmUpdateMgBuilder = AlarmUpdateMsg.newBuilder(); + alarmUpdateMgBuilder.setName("alarm from edge"); + alarmUpdateMgBuilder.setStatus(AlarmStatus.ACTIVE_UNACK.name()); + alarmUpdateMgBuilder.setSeverity(AlarmSeverity.CRITICAL.name()); + alarmUpdateMgBuilder.setOriginatorName(device.getName()); + alarmUpdateMgBuilder.setOriginatorType(EntityType.DEVICE.name()); + builder.addAlarmUpdateMsg(alarmUpdateMgBuilder.build()); + edgeImitator.expectResponsesAmount(1); + edgeImitator.sendUplinkMsg(builder.build()); + edgeImitator.waitForResponses(); + + + List alarms = doGetTypedWithPageLink("/api/alarm/{entityType}/{entityId}?", + new TypeReference>() {}, + new TextPageLink(100), device.getId().getEntityType().name(), device.getId().getId().toString()) + .getData(); + + for (AlarmInfo alarmInfo: alarms) { + log.info(String.valueOf(alarmInfo)); + } + + Optional foundAlarm = alarms.stream().filter(alarm -> alarm.getType().equals("alarm from edge")).findAny(); + Assert.assertTrue(foundAlarm.isPresent()); + AlarmInfo alarmInfo = foundAlarm.get(); + Assert.assertEquals(device.getId(), alarmInfo.getOriginator()); + Assert.assertEquals(AlarmStatus.ACTIVE_UNACK, alarmInfo.getStatus()); + Assert.assertEquals(AlarmSeverity.CRITICAL, alarmInfo.getSeverity()); + } + + private void sendRelation() throws Exception { + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Optional foundDevice1 = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 1")).findAny(); + Assert.assertTrue(foundDevice1.isPresent()); + Device device1 = foundDevice1.get(); + Optional foundDevice2 = edgeDevices.stream().filter(device2 -> device2.getName().equals("Edge Device 2")).findAny(); + Assert.assertTrue(foundDevice2.isPresent()); + Device device2 = foundDevice2.get(); + + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + RelationUpdateMsg.Builder relationUpdateMsgBuilder = RelationUpdateMsg.newBuilder(); + relationUpdateMsgBuilder.setType("test"); + relationUpdateMsgBuilder.setTypeGroup(RelationTypeGroup.COMMON.name()); + relationUpdateMsgBuilder.setToIdMSB(device1.getId().getId().getMostSignificantBits()); + relationUpdateMsgBuilder.setToIdLSB(device1.getId().getId().getLeastSignificantBits()); + relationUpdateMsgBuilder.setToEntityType(device1.getId().getEntityType().name()); + relationUpdateMsgBuilder.setFromIdMSB(device2.getId().getId().getMostSignificantBits()); + relationUpdateMsgBuilder.setFromIdLSB(device2.getId().getId().getLeastSignificantBits()); + relationUpdateMsgBuilder.setFromEntityType(device2.getId().getEntityType().name()); + relationUpdateMsgBuilder.setAdditionalInfo("{}"); + builder.addRelationUpdateMsg(relationUpdateMsgBuilder.build()); + UplinkMsg msg = builder.build(); + edgeImitator.expectResponsesAmount(1); + edgeImitator.sendUplinkMsg(msg); + edgeImitator.waitForResponses(); + + EntityRelation relation = doGet("/api/relation?" + + "&fromId=" + device2.getId().getId().toString() + + "&fromType=" + device2.getId().getEntityType().name() + + "&relationType=" + "test" + + "&relationTypeGroup=" + RelationTypeGroup.COMMON.name() + + "&toId=" + device1.getId().getId().toString() + + "&toType=" + device1.getId().getEntityType().name(), EntityRelation.class); + Assert.assertNotNull(relation); + } + + private void sendTelemetry() throws Exception { + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Optional foundDevice = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 2")).findAny(); + Assert.assertTrue(foundDevice.isPresent()); + Device device = foundDevice.get(); + + edgeImitator.expectResponsesAmount(2); + + JsonObject data = new JsonObject(); + String timeseriesKey = "key"; + String timeseriesValue = "25"; + data.addProperty(timeseriesKey, timeseriesValue); + UplinkMsg.Builder builder1 = UplinkMsg.newBuilder(); + EntityDataProto.Builder entityDataBuilder = EntityDataProto.newBuilder(); + entityDataBuilder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data, System.currentTimeMillis())); + entityDataBuilder.setEntityType(device.getId().getEntityType().name()); + entityDataBuilder.setEntityIdMSB(device.getUuidId().getMostSignificantBits()); + entityDataBuilder.setEntityIdLSB(device.getUuidId().getLeastSignificantBits()); + builder1.addEntityData(entityDataBuilder.build()); + edgeImitator.sendUplinkMsg(builder1.build()); + + JsonObject attributesData = new JsonObject(); + String attributesKey = "test_attr"; + String attributesValue = "test_value"; + attributesData.addProperty(attributesKey, attributesValue); + UplinkMsg.Builder builder2 = UplinkMsg.newBuilder(); + EntityDataProto.Builder entityDataBuilder2 = EntityDataProto.newBuilder(); + entityDataBuilder2.setEntityType(device.getId().getEntityType().name()); + entityDataBuilder2.setEntityIdMSB(device.getId().getId().getMostSignificantBits()); + entityDataBuilder2.setEntityIdLSB(device.getId().getId().getLeastSignificantBits()); + entityDataBuilder2.setPostAttributesMsg(JsonConverter.convertToAttributesProto(attributesData)); + entityDataBuilder2.setPostAttributeScope(DataConstants.SERVER_SCOPE); + builder2.addEntityData(entityDataBuilder2.build()); + edgeImitator.sendUplinkMsg(builder2.build()); + + edgeImitator.waitForResponses(); + + Thread.sleep(1000); + Map>> timeseries = doGetAsync("/api/plugins/telemetry/DEVICE/" + device.getUuidId() + "/values/timeseries?keys=" + timeseriesKey, Map.class); + Assert.assertTrue(timeseries.containsKey(timeseriesKey)); + Assert.assertEquals(1, timeseries.get(timeseriesKey).size()); + Assert.assertEquals(timeseriesValue, timeseries.get(timeseriesKey).get(0).get("value")); + + List> attributes = doGetAsync("/api/plugins/telemetry/DEVICE/" + device.getId() + "/values/attributes/" + DataConstants.SERVER_SCOPE, List.class); + Assert.assertEquals(1, attributes.size()); + Assert.assertEquals(attributes.get(0).get("key"), attributesKey); + Assert.assertEquals(attributes.get(0).get("value"), attributesValue); + + } + + private void sendDeleteDeviceOnEdge() throws Exception { + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Optional foundDevice = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 2")).findAny(); + Assert.assertTrue(foundDevice.isPresent()); + Device device = foundDevice.get(); + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + DeviceUpdateMsg.Builder deviceDeleteMsgBuilder = DeviceUpdateMsg.newBuilder(); + deviceDeleteMsgBuilder.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE); + deviceDeleteMsgBuilder.setIdMSB(device.getId().getId().getMostSignificantBits()); + deviceDeleteMsgBuilder.setIdLSB(device.getId().getId().getLeastSignificantBits()); + builder.addDeviceUpdateMsg(deviceDeleteMsgBuilder.build()); + edgeImitator.expectResponsesAmount(1); + edgeImitator.sendUplinkMsg(builder.build()); + edgeImitator.waitForResponses(); + device = doGet("/api/device/" + device.getId().getId().toString(), Device.class); + Assert.assertNotNull(device); + edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() { + }, new TextPageLink(100)).getData(); + Assert.assertFalse(edgeDevices.contains(device)); + } + private void installation() throws Exception { edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); @@ -413,4 +680,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { doDelete("/api/edge/" + edge.getId().getId().toString()) .andExpect(status().isOk()); } + + private EdgeEvent constructEdgeEvent(TenantId tenantId, EdgeId edgeId, ActionType edgeEventAction, UUID entityId, EdgeEventType edgeEventType, JsonNode entityBody) { + EdgeEvent edgeEvent = new EdgeEvent(); + edgeEvent.setEdgeId(edgeId); + edgeEvent.setTenantId(tenantId); + edgeEvent.setAction(edgeEventAction.name()); + edgeEvent.setEntityId(entityId); + edgeEvent.setType(edgeEventType); + edgeEvent.setBody(entityBody); + return edgeEvent; + } } diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index e1b54b6f84..90ec80838f 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -32,14 +32,18 @@ import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; +import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; @Slf4j public class EdgeImitator { @@ -49,6 +53,8 @@ public class EdgeImitator { private EdgeRpcClient edgeRpcClient; + private CountDownLatch responsesLatch; + @Getter private EdgeStorage storage; @@ -56,10 +62,12 @@ public class EdgeImitator { public EdgeImitator(String host, int port, String routingKey, String routingSecret) throws NoSuchFieldException, IllegalAccessException { edgeRpcClient = new EdgeGrpcClient(); storage = new EdgeStorage(); + responsesLatch = new CountDownLatch(0); this.routingKey = routingKey; this.routingSecret = routingSecret; setEdgeCredentials("rpcHost", host); setEdgeCredentials("rpcPort", port); + setEdgeCredentials("keepAliveTimeSec", 300); } private void setEdgeCredentials(String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { @@ -83,8 +91,13 @@ public class EdgeImitator { edgeRpcClient.disconnect(false); } + public void sendUplinkMsg(UplinkMsg uplinkMsg) { + edgeRpcClient.sendUplinkMsg(uplinkMsg); + } + private void onUplinkResponse(UplinkResponseMsg msg) { log.info("onUplinkResponse: {}", msg); + responsesLatch.countDown(); } private void onEdgeUpdate(EdgeConfiguration edgeConfiguration) { @@ -144,7 +157,19 @@ public class EdgeImitator { result.add(storage.processAlarm(alarmUpdateMsg)); } } + if (downlinkMsg.getEntityDataList() != null && !downlinkMsg.getEntityDataList().isEmpty()) { + for (EntityDataProto entityData: downlinkMsg.getEntityDataList()) { + result.add(storage.processEntityData(entityData)); + } + } return Futures.allAsList(result); } + public void waitForResponses() throws InterruptedException { responsesLatch.await(5, TimeUnit.SECONDS); + } + + public void expectResponsesAmount(int messageAmount) { + responsesLatch = new CountDownLatch(messageAmount); + } + } diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java index cadd580f58..a8301fda33 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; +import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.RelationUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -47,17 +48,20 @@ public class EdgeStorage { private EdgeConfiguration configuration; - private CountDownLatch latch; + private CountDownLatch messagesLatch; private Map entities; private Map alarms; private List relations; + private EntityDataProto latestEntityDataMsg; + public EdgeStorage() { - latch = new CountDownLatch(0); + messagesLatch = new CountDownLatch(0); entities = new HashMap<>(); alarms = new HashMap<>(); relations = new ArrayList<>(); + latestEntityDataMsg = null; } public ListenableFuture processEntity(UpdateMsgType msgType, EntityType type, UUID uuid) { @@ -65,11 +69,11 @@ public class EdgeStorage { case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: entities.put(uuid, type); - latch.countDown(); + messagesLatch.countDown(); break; case ENTITY_DELETED_RPC_MESSAGE: if (entities.remove(uuid) != null) { - latch.countDown(); + messagesLatch.countDown(); } break; } @@ -93,7 +97,7 @@ public class EdgeStorage { break; } if (result) { - latch.countDown(); + messagesLatch.countDown(); } return Futures.immediateFuture(null); } @@ -105,17 +109,23 @@ public class EdgeStorage { case ALARM_ACK_RPC_MESSAGE: case ALARM_CLEAR_RPC_MESSAGE: alarms.put(alarmMsg.getType(), AlarmStatus.valueOf(alarmMsg.getStatus())); - latch.countDown(); + messagesLatch.countDown(); break; case ENTITY_DELETED_RPC_MESSAGE: if (alarms.remove(alarmMsg.getName()) != null) { - latch.countDown(); + messagesLatch.countDown(); } break; } return Futures.immediateFuture(null); } + public ListenableFuture processEntityData(EntityDataProto entityData) { + latestEntityDataMsg = entityData; + messagesLatch.countDown(); + return Futures.immediateFuture(null); + } + public Set getEntitiesByType(EntityType type) { return entities.entrySet().stream() .filter(entry -> entry.getValue().equals(type)) @@ -123,11 +133,10 @@ public class EdgeStorage { } public void waitForMessages() throws InterruptedException { - latch.await(5, TimeUnit.SECONDS); + messagesLatch.await(5, TimeUnit.SECONDS); } public void expectMessageAmount(int messageAmount) { - latch = new CountDownLatch(messageAmount); + messagesLatch = new CountDownLatch(messageAmount); } - } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index 5da3df68ae..f0f5d2418f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -66,7 +66,7 @@ public class TbMsgAttributesNode implements TbNode { if (StringUtils.isEmpty(msg.getMetaData().getValue(SCOPE))) { msg.getMetaData().putValue(SCOPE, config.getScope()); } - ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), msg.getMetaData().getValue(SCOPE), + ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), config.getScope(), new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); } From 8059274002d401cf9335752dc24454177b4e050b Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 29 Sep 2020 15:24:18 +0300 Subject: [PATCH 141/156] fixed attributes saving --- .../service/edge/rpc/processor/TelemetryProcessor.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java index d5b31cb18c..fe3fd208f6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; @@ -36,9 +37,11 @@ import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKey; +import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.session.SessionMsgType; +import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.edge.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.EntityDataProto; @@ -136,7 +139,9 @@ public class TelemetryProcessor extends BaseProcessor { private ListenableFuture processPostAttributes(TenantId tenantId, EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { SettableFuture futureToSet = SettableFuture.create(); JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); - TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); + Set attributes = JsonConverter.convertToAttributes(json); + attributesService.save(tenantId, entityId, metaData.getValue("scope"), new ArrayList<>(attributes)); + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ATTRIBUTES_UPDATED, entityId, metaData, gson.toJson(json)); tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { @Override public void onSuccess(TbQueueMsgMetadata metadata) { From 64e60de9bc8ce8376ed99c702e97314d2e9248c7 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 29 Sep 2020 17:10:09 +0300 Subject: [PATCH 142/156] processing future + attributes node refactoring --- .../rpc/processor/TelemetryProcessor.java | 27 ++++++++++++++----- .../engine/telemetry/TbMsgAttributesNode.java | 4 +-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java index fe3fd208f6..cc2cb15d4b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java @@ -15,12 +15,14 @@ */ package org.thingsboard.server.service.edge.rpc.processor; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import com.google.gson.Gson; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.stereotype.Component; import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.server.common.data.DataConstants; @@ -140,12 +142,23 @@ public class TelemetryProcessor extends BaseProcessor { SettableFuture futureToSet = SettableFuture.create(); JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); Set attributes = JsonConverter.convertToAttributes(json); - attributesService.save(tenantId, entityId, metaData.getValue("scope"), new ArrayList<>(attributes)); - TbMsg tbMsg = TbMsg.newMsg(DataConstants.ATTRIBUTES_UPDATED, entityId, metaData, gson.toJson(json)); - tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + ListenableFuture> future = attributesService.save(tenantId, entityId, metaData.getValue("scope"), new ArrayList<>(attributes)); + Futures.addCallback(future, new FutureCallback>() { @Override - public void onSuccess(TbQueueMsgMetadata metadata) { - futureToSet.set(null); + public void onSuccess(@Nullable List voids) { + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ATTRIBUTES_UPDATED, entityId, metaData, gson.toJson(json)); + tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't process post attributes [{}]", msg, t); + futureToSet.setException(t); + } + }); } @Override @@ -153,7 +166,7 @@ public class TelemetryProcessor extends BaseProcessor { log.error("Can't process post attributes [{}]", msg, t); futureToSet.setException(t); } - }); + }, dbCallbackExecutorService); return futureToSet; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index f0f5d2418f..5fd06108e4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -63,9 +63,7 @@ public class TbMsgAttributesNode implements TbNode { } String src = msg.getData(); Set attributes = JsonConverter.convertToAttributes(new JsonParser().parse(src)); - if (StringUtils.isEmpty(msg.getMetaData().getValue(SCOPE))) { - msg.getMetaData().putValue(SCOPE, config.getScope()); - } + msg.getMetaData().putValue(SCOPE, config.getScope()); ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), config.getScope(), new ArrayList<>(attributes), new TelemetryNodeCallback(ctx, msg)); } From 20c794884a5d1c0a2fb8290610e192e84994fc63 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 1 Oct 2020 13:55:30 +0300 Subject: [PATCH 143/156] attributes updated/post attributes separation --- .../constructor/EntityDataMsgConstructor.java | 9 +++- .../rpc/processor/TelemetryProcessor.java | 30 +++++++++-- common/edge-api/src/main/proto/edge.proto | 5 +- .../rule/engine/edge/TbMsgPushToEdgeNode.java | 50 +++++++++---------- 4 files changed, 61 insertions(+), 33 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index 0f7fb0523d..5bbea5351f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -18,7 +18,6 @@ package org.thingsboard.server.service.edge.rpc.constructor; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; -import com.google.gson.JsonNull; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -27,6 +26,7 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.gen.edge.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.transport.TransportProtos; import java.util.List; @@ -57,7 +57,12 @@ public class EntityDataMsgConstructor { case ATTRIBUTES_UPDATED: try { JsonObject data = entityData.getAsJsonObject(); - builder.setPostAttributesMsg(JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv"))); + TransportProtos.PostAttributeMsg postAttributeMsg = JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv")); + if (data.has("isPostAttributes") && data.getAsJsonPrimitive("isPostAttributes").getAsBoolean()) { + builder.setPostAttributesMsg(postAttributeMsg); + } else { + builder.setAttributesUpdateMsg(postAttributeMsg); + } builder.setPostAttributeScope(data.getAsJsonPrimitive("scope").getAsString()); } catch (Exception e) { log.warn("Can't convert to attributes proto, entityData [{}]", entityData, e); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java index cc2cb15d4b..da5dc3746f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java @@ -68,13 +68,16 @@ public class TelemetryProcessor extends BaseProcessor { public List> onTelemetryUpdate(TenantId tenantId, EntityDataProto entityData) { List> result = new ArrayList<>(); EntityId entityId = constructEntityId(entityData); - if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg()) && entityId != null) { + if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdateMsg()) && entityId != null) { TbMsgMetaData metaData = constructBaseMsgMetadata(tenantId, entityId); metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE); if (entityData.hasPostAttributesMsg()) { - metaData.putValue("scope", entityData.getPostAttributeScope()); result.add(processPostAttributes(tenantId, entityId, entityData.getPostAttributesMsg(), metaData)); } + if (entityData.hasAttributesUpdateMsg()) { + metaData.putValue("scope", entityData.getPostAttributeScope()); + result.add(processAttributesUpdate(tenantId, entityId, entityData.getAttributesUpdateMsg(), metaData)); + } if (entityData.hasPostTelemetryMsg()) { result.add(processPostTelemetry(tenantId, entityId, entityData.getPostTelemetryMsg(), metaData)); } @@ -139,6 +142,25 @@ public class TelemetryProcessor extends BaseProcessor { } private ListenableFuture processPostAttributes(TenantId tenantId, EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { + SettableFuture futureToSet = SettableFuture.create(); + JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); + TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, metaData, gson.toJson(json)); + tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() { + @Override + public void onSuccess(TbQueueMsgMetadata metadata) { + futureToSet.set(null); + } + + @Override + public void onFailure(Throwable t) { + log.error("Can't process post attributes [{}]", msg, t); + futureToSet.setException(t); + } + }); + return futureToSet; + } + + private ListenableFuture processAttributesUpdate(TenantId tenantId, EntityId entityId, TransportProtos.PostAttributeMsg msg, TbMsgMetaData metaData) { SettableFuture futureToSet = SettableFuture.create(); JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); Set attributes = JsonConverter.convertToAttributes(json); @@ -155,7 +177,7 @@ public class TelemetryProcessor extends BaseProcessor { @Override public void onFailure(Throwable t) { - log.error("Can't process post attributes [{}]", msg, t); + log.error("Can't process attributes update [{}]", msg, t); futureToSet.setException(t); } }); @@ -163,7 +185,7 @@ public class TelemetryProcessor extends BaseProcessor { @Override public void onFailure(Throwable t) { - log.error("Can't process post attributes [{}]", msg, t); + log.error("Can't process attributes update [{}]", msg, t); futureToSet.setException(t); } }, dbCallbackExecutorService); diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index c2ce170401..e5aa03cfa2 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -102,8 +102,9 @@ message EntityDataProto { string entityType = 3; transport.PostTelemetryMsg postTelemetryMsg = 4; transport.PostAttributeMsg postAttributesMsg = 5; - string postAttributeScope = 6; - AttributeDeleteMsg attributeDeleteMsg = 7; + transport.PostAttributeMsg attributesUpdateMsg = 6; + string postAttributeScope = 7; + AttributeDeleteMsg attributeDeleteMsg = 8; // transport.ToDeviceRpcRequestMsg ??? } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 8d00507a7d..b510af10b0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -138,16 +138,37 @@ public class TbMsgPushToEdgeNode implements TbNode { } private EdgeEvent buildEdgeEvent(TbMsg msg, TbContext ctx) throws JsonProcessingException { - if (DataConstants.ALARM.equals(msg.getType())) { + String msgType = msg.getType(); + if (DataConstants.ALARM.equals(msgType)) { return buildEdgeEvent(ctx.getTenantId(), ActionType.ADDED, getUUIDFromMsgData(msg), EdgeEventType.ALARM, null); } else { EdgeEventType edgeEventTypeByEntityType = EdgeUtils.getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType()); if (edgeEventTypeByEntityType == null) { return null; } - ActionType actionType = getActionTypeByMsgType(msg.getType()); - JsonNode entityBody = getEntityBody(actionType, msg.getData(), msg.getMetaData().getData()); - return buildEdgeEvent(ctx.getTenantId(), actionType, msg.getOriginator().getId(), edgeEventTypeByEntityType, entityBody); + ActionType actionType = getActionTypeByMsgType(msgType); + Map entityBody = new HashMap<>(); + Map metadata = msg.getMetaData().getData(); + JsonNode dataJson = json.readTree(msg.getData()); + switch (actionType) { + case ATTRIBUTES_UPDATED: + entityBody.put("kv", dataJson); + entityBody.put("scope", metadata.get("scope")); + if (SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msgType)) { + entityBody.put("isPostAttributes", true); + } + break; + case ATTRIBUTES_DELETED: + List keys = json.treeToValue(dataJson.get("attributes"), List.class); + entityBody.put("keys", keys); + entityBody.put("scope", metadata.get("scope")); + break; + case TIMESERIES_UPDATED: + entityBody.put("data", dataJson); + entityBody.put("ts", metadata.get("ts")); + break; + } + return buildEdgeEvent(ctx.getTenantId(), actionType, msg.getOriginator().getId(), edgeEventTypeByEntityType, json.valueToTree(entityBody)); } } @@ -161,27 +182,6 @@ public class TbMsgPushToEdgeNode implements TbNode { return edgeEvent; } - private JsonNode getEntityBody(ActionType actionType, String data, Map metadata) throws JsonProcessingException { - Map entityBody = new HashMap<>(); - JsonNode dataJson = json.readTree(data); - switch (actionType) { - case ATTRIBUTES_UPDATED: - entityBody.put("kv", dataJson); - entityBody.put("scope", metadata.get("scope")); - break; - case ATTRIBUTES_DELETED: - List keys = json.treeToValue(dataJson.get("attributes"), List.class); - entityBody.put("keys", keys); - entityBody.put("scope", metadata.get("scope")); - break; - case TIMESERIES_UPDATED: - entityBody.put("data", dataJson); - entityBody.put("ts", metadata.get("ts")); - break; - } - return json.valueToTree(entityBody); - } - private UUID getUUIDFromMsgData(TbMsg msg) throws JsonProcessingException { JsonNode data = json.readTree(msg.getData()).get("id"); String id = json.treeToValue(data.get("id"), String.class); From ed4d5a69ddd7be07199a79511c0e4415232437bf Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 1 Oct 2020 16:00:06 +0300 Subject: [PATCH 144/156] fixes --- .../edge/rpc/constructor/EntityDataMsgConstructor.java | 2 +- .../service/edge/rpc/processor/TelemetryProcessor.java | 8 ++++---- common/edge-api/src/main/proto/edge.proto | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index 5bbea5351f..ffa2ada070 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -61,7 +61,7 @@ public class EntityDataMsgConstructor { if (data.has("isPostAttributes") && data.getAsJsonPrimitive("isPostAttributes").getAsBoolean()) { builder.setPostAttributesMsg(postAttributeMsg); } else { - builder.setAttributesUpdateMsg(postAttributeMsg); + builder.setAttributesUpdatedMsg(postAttributeMsg); } builder.setPostAttributeScope(data.getAsJsonPrimitive("scope").getAsString()); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java index da5dc3746f..2fdd5614aa 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryProcessor.java @@ -22,7 +22,6 @@ import com.google.common.util.concurrent.SettableFuture; import com.google.gson.Gson; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; -import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.stereotype.Component; import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.server.common.data.DataConstants; @@ -52,6 +51,7 @@ import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueMsgMetadata; import org.thingsboard.server.queue.util.TbCoreComponent; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -68,15 +68,15 @@ public class TelemetryProcessor extends BaseProcessor { public List> onTelemetryUpdate(TenantId tenantId, EntityDataProto entityData) { List> result = new ArrayList<>(); EntityId entityId = constructEntityId(entityData); - if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdateMsg()) && entityId != null) { + if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdatedMsg()) && entityId != null) { TbMsgMetaData metaData = constructBaseMsgMetadata(tenantId, entityId); metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE); if (entityData.hasPostAttributesMsg()) { result.add(processPostAttributes(tenantId, entityId, entityData.getPostAttributesMsg(), metaData)); } - if (entityData.hasAttributesUpdateMsg()) { + if (entityData.hasAttributesUpdatedMsg()) { metaData.putValue("scope", entityData.getPostAttributeScope()); - result.add(processAttributesUpdate(tenantId, entityId, entityData.getAttributesUpdateMsg(), metaData)); + result.add(processAttributesUpdate(tenantId, entityId, entityData.getAttributesUpdatedMsg(), metaData)); } if (entityData.hasPostTelemetryMsg()) { result.add(processPostTelemetry(tenantId, entityId, entityData.getPostTelemetryMsg(), metaData)); diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index e5aa03cfa2..fd26e1fcd4 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -102,7 +102,7 @@ message EntityDataProto { string entityType = 3; transport.PostTelemetryMsg postTelemetryMsg = 4; transport.PostAttributeMsg postAttributesMsg = 5; - transport.PostAttributeMsg attributesUpdateMsg = 6; + transport.PostAttributeMsg attributesUpdatedMsg = 6; string postAttributeScope = 7; AttributeDeleteMsg attributeDeleteMsg = 8; // transport.ToDeviceRpcRequestMsg ??? From 93363f81bbd9bb41ec0ef382bf480a1d85e7f7f3 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Thu, 1 Oct 2020 20:12:24 +0300 Subject: [PATCH 145/156] sync edge api --- .../server/controller/BaseController.java | 8 ++++++-- .../server/controller/EdgeController.java | 13 +++++++++++++ .../org/thingsboard/rest/client/RestClient.java | 4 ++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index b0f0e0867f..856ee71314 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -104,6 +104,7 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.component.ComponentDiscoveryService; import org.thingsboard.server.service.edge.EdgeNotificationService; +import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.AccessControlService; @@ -202,12 +203,15 @@ public abstract class BaseController { @Autowired protected TbQueueProducerProvider producerProvider; - @Autowired + @Autowired(required = false) protected EdgeService edgeService; - @Autowired + @Autowired(required = false) protected EdgeNotificationService edgeNotificationService; + @Autowired(required = false) + protected SyncEdgeService syncEdgeService; + @Value("${server.log_controller_error_stack_trace}") @Getter private boolean logControllerErrorStackTrace; diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 4c6be42064..e1d7c0aa53 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -26,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; @@ -409,6 +410,18 @@ public class EdgeController extends BaseController { } } + @PreAuthorize("hasAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/edge/sync", method = RequestMethod.POST) + public void syncEdge(@RequestBody EdgeId edgeId) throws ThingsboardException { + try { + edgeId = checkNotNull(edgeId); + Edge edge = checkEdgeId(edgeId, Operation.READ); + syncEdgeService.sync(edge); + } catch (Exception e) { + throw handleException(e); + } + } + @RequestMapping(value = "/license/checkInstance", method = RequestMethod.POST) @ResponseBody public Object checkInstance(@RequestBody Object request) throws ThingsboardException { diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 904e662e12..ee62c0808e 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -2372,6 +2372,10 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { params).getBody(); } + public void syncEdge(EdgeId edgeId) { + restTemplate.postForEntity(baseURL + "/api/edge/sync", edgeId, EdgeId.class); + } + @Deprecated public Optional getAttributes(String accessToken, String clientKeys, String sharedKeys) { Map params = new HashMap<>(); From c9dcbda18dc1c6f5649eb23c5fa13d8d1b1effd4 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 2 Oct 2020 14:21:52 +0300 Subject: [PATCH 146/156] ui side + handle exceptions --- .../server/controller/BaseController.java | 4 ++++ .../server/controller/EdgeController.java | 11 ++++++++--- .../server/service/edge/rpc/EdgeGrpcService.java | 9 +++++++++ ui/src/app/api/edge.service.js | 14 +++++++++++++- ui/src/app/edge/edge-fieldset.tpl.html | 6 ++++++ ui/src/app/edge/edge.directive.js | 13 ++++++++++++- ui/src/app/locale/locale.constant-de_DE.json | 2 ++ ui/src/app/locale/locale.constant-en_US.json | 2 ++ ui/src/app/locale/locale.constant-es_ES.json | 2 ++ ui/src/app/locale/locale.constant-fr_FR.json | 2 ++ 10 files changed, 60 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 856ee71314..582af82f71 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -104,6 +104,7 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.component.ComponentDiscoveryService; import org.thingsboard.server.service.edge.EdgeNotificationService; +import org.thingsboard.server.service.edge.rpc.EdgeGrpcService; import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.security.model.SecurityUser; @@ -212,6 +213,9 @@ public abstract class BaseController { @Autowired(required = false) protected SyncEdgeService syncEdgeService; + @Autowired(required = false) + protected EdgeGrpcService edgeGrpcService; + @Value("${server.log_controller_error_stack_trace}") @Getter private boolean logControllerErrorStackTrace; diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index e1d7c0aa53..be03c034e9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -26,7 +26,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; @@ -47,6 +46,7 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.edge.rpc.EdgeGrpcSession; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; @@ -415,8 +415,13 @@ public class EdgeController extends BaseController { public void syncEdge(@RequestBody EdgeId edgeId) throws ThingsboardException { try { edgeId = checkNotNull(edgeId); - Edge edge = checkEdgeId(edgeId, Operation.READ); - syncEdgeService.sync(edge); + if (isEdgesSupportEnabled()) { + EdgeGrpcSession session = edgeGrpcService.getEdgeGrpcSessionById(edgeId); + Edge edge = session.getEdge(); + syncEdgeService.sync(edge); + } else { + throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL); + } } catch (Exception e) { throw handleException(e); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index 85ea93bed3..936a805ea0 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -146,6 +146,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis()); } + public EdgeGrpcSession getEdgeGrpcSessionById(EdgeId edgeId) { + EdgeGrpcSession session = sessions.get(edgeId); + if (session != null && session.isConnected()) { + return session; + } else { + throw new RuntimeException("Edge is not connected"); + } + } + private void processHandleMessages() { executor.submit(() -> { while (!Thread.interrupted()) { diff --git a/ui/src/app/api/edge.service.js b/ui/src/app/api/edge.service.js index 7814e1d826..528dea960c 100644 --- a/ui/src/app/api/edge.service.js +++ b/ui/src/app/api/edge.service.js @@ -33,7 +33,8 @@ function EdgeService($http, $q, customerService) { unassignEdgeFromCustomer: unassignEdgeFromCustomer, makeEdgePublic: makeEdgePublic, setRootRuleChain: setRootRuleChain, - getEdgeEvents: getEdgeEvents + getEdgeEvents: getEdgeEvents, + syncEdge: syncEdge }; return service; @@ -262,4 +263,15 @@ function EdgeService($http, $q, customerService) { }); return deferred.promise; } + + function syncEdge(edgeId) { + var deferred = $q.defer(); + var url = '/api/edge/sync'; + $http.post(url, edgeId).then(function success(response) { + deferred.resolve(response); + }, function fail(response) { + deferred.reject(response.data); + }); + return deferred.promise; + } } diff --git a/ui/src/app/edge/edge-fieldset.tpl.html b/ui/src/app/edge/edge-fieldset.tpl.html index 1595b2aebd..5811969b6a 100644 --- a/ui/src/app/edge/edge-fieldset.tpl.html +++ b/ui/src/app/edge/edge-fieldset.tpl.html @@ -48,6 +48,12 @@ edge.copy-id + + + edge.sync +
diff --git a/ui/src/app/edge/edge.directive.js b/ui/src/app/edge/edge.directive.js index 98f010e009..04165418e9 100644 --- a/ui/src/app/edge/edge.directive.js +++ b/ui/src/app/edge/edge.directive.js @@ -20,7 +20,7 @@ import edgeFieldsetTemplate from './edge-fieldset.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ -export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, utils, toast, types, customerService) { +export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, utils, toast, types, customerService, edgeService) { var linker = function (scope, element) { var template = $templateCache.get(edgeFieldsetTemplate); element.html(template); @@ -69,6 +69,17 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD toast.showSuccess($translate.instant('edge.id-copied-message'), 750, angular.element(element).parent().parent(), 'bottom left'); }; + scope.onEdgeSync = function (edgeId) { + edgeService.syncEdge(edgeId).then( + function success() { + toast.showSuccess($translate.instant('edge.sync-message'), 750, angular.element(element).parent().parent(), 'bottom left'); + }, + function fail(error) { + toast.showError(error); + } + ); + } + $compile(element.contents())(scope); scope.onEdgeInfoCopied = function(type) { diff --git a/ui/src/app/locale/locale.constant-de_DE.json b/ui/src/app/locale/locale.constant-de_DE.json index f8a1d887ff..582b7b72c2 100644 --- a/ui/src/app/locale/locale.constant-de_DE.json +++ b/ui/src/app/locale/locale.constant-de_DE.json @@ -756,6 +756,8 @@ "details": "Details", "copy-id": "Regelketten-ID kopieren", "id-copied-message": "Regelketten-ID wurde in die Zwischenablage kopiert", + "sync": "Sync Edge", + "sync-message": "Edge wurde synchronisiert", "permissions": "Berechtigungen", "edge-required": "Rand ist erforderlich.", "edge-type": "Randtyp", diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index c77192bffb..412280603c 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -788,6 +788,8 @@ "events": "Events", "copy-id": "Copy Edge Id", "id-copied-message": "Edge Id has been copied to clipboard", + "sync": "Sync Edge", + "sync-message": "Edge has been synchronized", "permissions": "Permissions", "edge-required": "Edge required", "edge-type": "Edge type", diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json index f8f4e6bbe9..3eea48845f 100644 --- a/ui/src/app/locale/locale.constant-es_ES.json +++ b/ui/src/app/locale/locale.constant-es_ES.json @@ -769,6 +769,8 @@ "details": "Detalles", "copy-id": "Copiar ID de borde", "id-copied-message": "El ID de borde se ha copiado al portapapeles", + "sync": "Sinc Edge", + "sync-message": "Edge se ha sincronizado", "permissions": "Permisos", "edge-required": "Edge required", "edge-type": "Type de la bordure", diff --git a/ui/src/app/locale/locale.constant-fr_FR.json b/ui/src/app/locale/locale.constant-fr_FR.json index 4058148bbd..ffd4e05896 100644 --- a/ui/src/app/locale/locale.constant-fr_FR.json +++ b/ui/src/app/locale/locale.constant-fr_FR.json @@ -774,6 +774,8 @@ "details": "Détails de l'entité", "copy-id": "Copier borudre Id", "id-copied-message": "Id de la bordure a été copié dans le presse-papier", + "sync": "Sync Edge", + "sync-message": "Edge a été synchronisé", "permissions": "Autorisations", "edge-required": "Bordure est requise", "edge-type": "Type de la bordure", From 773b856c2547924cc76fb61fec38ecc43056fd21 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 2 Oct 2020 15:34:54 +0300 Subject: [PATCH 147/156] tested attributes updated/post attributes separation --- .../thingsboard/server/edge/BaseEdgeTest.java | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index 084def021c..db7bb48f75 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -19,6 +19,7 @@ import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.junit.After; @@ -441,11 +442,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Device device = edgeDevices.get(0); Assert.assertEquals("Edge Device 1", device.getName()); - String attributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"test\":\"test\"}}"; + String attributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"key\":\"value\"}}"; JsonNode attributesEntityData = mapper.readTree(attributesData); - EdgeEvent edgeEvent2 = constructEdgeEvent(tenantId, edge.getId(), ActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); + EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), ActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); edgeImitator.getStorage().expectMessageAmount(1); - edgeEventService.saveAsync(edgeEvent2); + edgeEventService.saveAsync(edgeEvent1); edgeImitator.getStorage().waitForMessages(); EntityDataProto latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); @@ -454,14 +455,36 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Assert.assertEquals(device.getId().getId(), uuid); Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); Assert.assertEquals(attributesEntityData.get("scope").asText(), latestEntityDataMsg.getPostAttributeScope()); + Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg()); + + TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg(); + Assert.assertEquals(1, attributesUpdatedMsg.getKvCount()); + TransportProtos.KeyValueProto keyValueProto = attributesUpdatedMsg.getKv(0); + Assert.assertEquals("key", keyValueProto.getKey()); + Assert.assertEquals("value", keyValueProto.getStringV()); + edgeImitator.getStorage().setLatestEntityDataMsg(null); + + ((ObjectNode) attributesEntityData).put("isPostAttributes", true); + EdgeEvent edgeEvent2 = constructEdgeEvent(tenantId, edge.getId(), ActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); + edgeImitator.getStorage().expectMessageAmount(1); + edgeEventService.saveAsync(edgeEvent2); + edgeImitator.getStorage().waitForMessages(); + + latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); + Assert.assertNotNull(latestEntityDataMsg); + uuid = new UUID(latestEntityDataMsg.getEntityIdMSB(), latestEntityDataMsg.getEntityIdLSB()); + Assert.assertEquals(device.getId().getId(), uuid); + Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); + Assert.assertEquals(attributesEntityData.get("scope").asText(), latestEntityDataMsg.getPostAttributeScope()); Assert.assertTrue(latestEntityDataMsg.hasPostAttributesMsg()); TransportProtos.PostAttributeMsg postAttributeMsg = latestEntityDataMsg.getPostAttributesMsg(); Assert.assertEquals(1, postAttributeMsg.getKvCount()); - TransportProtos.KeyValueProto keyValueProto = postAttributeMsg.getKv(0); - Assert.assertEquals("test", keyValueProto.getKey()); - Assert.assertEquals("test", keyValueProto.getStringV()); + keyValueProto = postAttributeMsg.getKv(0); + Assert.assertEquals("key", keyValueProto.getKey()); + Assert.assertEquals("value", keyValueProto.getStringV()); edgeImitator.getStorage().setLatestEntityDataMsg(null); + log.info("Attributes tested successfully"); } @@ -600,7 +623,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { entityDataBuilder2.setEntityType(device.getId().getEntityType().name()); entityDataBuilder2.setEntityIdMSB(device.getId().getId().getMostSignificantBits()); entityDataBuilder2.setEntityIdLSB(device.getId().getId().getLeastSignificantBits()); - entityDataBuilder2.setPostAttributesMsg(JsonConverter.convertToAttributesProto(attributesData)); + entityDataBuilder2.setAttributesUpdatedMsg(JsonConverter.convertToAttributesProto(attributesData)); entityDataBuilder2.setPostAttributeScope(DataConstants.SERVER_SCOPE); builder2.addEntityData(entityDataBuilder2.build()); edgeImitator.sendUplinkMsg(builder2.build()); From e09b97100b965343d977300b56794252be96cfd3 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Fri, 2 Oct 2020 19:29:35 +0300 Subject: [PATCH 148/156] tests refactored --- .../thingsboard/server/edge/BaseEdgeTest.java | 430 +++++++++++------- .../server/edge/imitator/EdgeImitator.java | 52 ++- .../server/edge/imitator/EdgeStorage.java | 142 ------ 3 files changed, 299 insertions(+), 325 deletions(-) delete mode 100644 application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index db7bb48f75..c5db7a0e97 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonObject; +import com.google.protobuf.AbstractMessage; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -28,7 +29,6 @@ import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.Dashboard; -import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; @@ -57,10 +57,13 @@ import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.edge.EdgeEventService;; import org.thingsboard.server.edge.imitator.EdgeImitator; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.DashboardUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EntityDataProto; import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.transport.TransportProtos; @@ -68,7 +71,6 @@ import org.thingsboard.server.gen.transport.TransportProtos; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.UUID; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -109,7 +111,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases - edgeImitator.getStorage().expectMessageAmount(6); + edgeImitator.expectMessageAmount(6); edgeImitator.connect(); } @@ -141,105 +143,142 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { private void testReceivedInitialData() throws Exception { log.info("Checking received data"); - edgeImitator.getStorage().waitForMessages(); + edgeImitator.waitForMessages(); - EdgeConfiguration configuration = edgeImitator.getStorage().getConfiguration(); + EdgeConfiguration configuration = edgeImitator.getConfiguration(); Assert.assertNotNull(configuration); - Map entities = edgeImitator.getStorage().getEntities(); - Assert.assertFalse(entities.isEmpty()); - - Set devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); - Assert.assertEquals(1, devices.size()); - TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", - new TypeReference>() {}, new TextPageLink(100)); - for (Device device: pageDataDevices.getData()) { - Assert.assertTrue(devices.contains(device.getUuidId())); - } - - Set assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); - Assert.assertEquals(1, assets.size()); - TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", - new TypeReference>() {}, new TextPageLink(100)); - for (Asset asset: pageDataAssets.getData()) { - Assert.assertTrue(assets.contains(asset.getUuidId())); - } + Optional optionalMsg1 = edgeImitator.findMessageByType(DeviceUpdateMsg.class); + Assert.assertTrue(optionalMsg1.isPresent()); + DeviceUpdateMsg deviceUpdateMsg = optionalMsg1.get(); + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); + UUID deviceUUID = new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()); + Device device = doGet("/api/device/" + deviceUUID.toString(), Device.class); + Assert.assertNotNull(device); + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertTrue(edgeDevices.contains(device)); + + Optional optionalMsg2 = edgeImitator.findMessageByType(AssetUpdateMsg.class); + Assert.assertTrue(optionalMsg2.isPresent()); + AssetUpdateMsg assetUpdateMsg = optionalMsg2.get(); + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, assetUpdateMsg.getMsgType()); + UUID assetUUID = new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB()); + Asset asset = doGet("/api/asset/" + assetUUID.toString(), Asset.class); + Assert.assertNotNull(asset); + List edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertTrue(edgeAssets.contains(asset)); + + Optional optionalMsg3 = edgeImitator.findMessageByType(RuleChainUpdateMsg.class); + Assert.assertTrue(optionalMsg3.isPresent()); + RuleChainUpdateMsg ruleChainUpdateMsg = optionalMsg3.get(); + Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType()); + UUID ruleChainUUID = new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB()); + RuleChain ruleChain = doGet("/api/ruleChain/" + ruleChainUUID.toString(), RuleChain.class); + Assert.assertNotNull(ruleChain); + List edgeRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertTrue(edgeRuleChains.contains(ruleChain)); - Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); - Assert.assertEquals(1, ruleChains.size()); - TimePageData pageDataRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", - new TypeReference>() {}, new TextPageLink(100)); - for (RuleChain ruleChain: pageDataRuleChains.getData()) { - Assert.assertTrue(ruleChains.contains(ruleChain.getUuidId())); - } log.info("Received data checked"); } - private void testDevices() throws Exception { + private void testDevices() throws Exception { log.info("Testing devices"); + Device device = new Device(); device.setName("Edge Device 2"); device.setType("test"); Device savedDevice = doPost("/api/device", device, Device.class); - edgeImitator.getStorage().expectMessageAmount(1); + + edgeImitator.expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/device/" + savedDevice.getId().getId().toString(), Device.class); - - TimePageData pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertTrue(pageDataDevices.getData().contains(savedDevice)); - edgeImitator.getStorage().waitForMessages(); - Set devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); - Assert.assertEquals(2, devices.size()); - Assert.assertTrue(devices.contains(savedDevice.getUuidId())); - - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); + DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); + Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits()); + Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(deviceUpdateMsg.getName(), savedDevice.getName()); + Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType()); + + edgeImitator.expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/device/" + savedDevice.getId().getId().toString(), Device.class); - pageDataDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertFalse(pageDataDevices.getData().contains(savedDevice)); - edgeImitator.getStorage().waitForMessages(); - devices = edgeImitator.getStorage().getEntitiesByType(EntityType.DEVICE); - Assert.assertEquals(1, devices.size()); - Assert.assertFalse(devices.contains(savedDevice.getUuidId())); + edgeImitator.waitForMessages(); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); + deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); + Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits()); + Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits()); + + edgeImitator.expectMessageAmount(1); doDelete("/api/device/" + savedDevice.getId().getId().toString()) .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); + deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); + Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits()); + Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits()); + log.info("Devices tested successfully"); } + private void testAssets() throws Exception { log.info("Testing assets"); Asset asset = new Asset(); asset.setName("Edge Asset 2"); asset.setType("test"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); - edgeImitator.getStorage().expectMessageAmount(1); + + edgeImitator.expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); - - TimePageData pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertTrue(pageDataAssets.getData().contains(savedAsset)); - edgeImitator.getStorage().waitForMessages(); - Set assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); - Assert.assertEquals(2, assets.size()); - Assert.assertTrue(assets.contains(savedAsset.getUuidId())); - - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof AssetUpdateMsg); + AssetUpdateMsg assetUpdateMsg = (AssetUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, assetUpdateMsg.getMsgType()); + Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits()); + Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(assetUpdateMsg.getName(), savedAsset.getName()); + Assert.assertEquals(assetUpdateMsg.getType(), savedAsset.getType()); + + edgeImitator.expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); - pageDataAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertFalse(pageDataAssets.getData().contains(savedAsset)); - edgeImitator.getStorage().waitForMessages(); - assets = edgeImitator.getStorage().getEntitiesByType(EntityType.ASSET); - Assert.assertEquals(1, assets.size()); - Assert.assertFalse(assets.contains(savedAsset.getUuidId())); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof AssetUpdateMsg); + assetUpdateMsg = (AssetUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, assetUpdateMsg.getMsgType()); + Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits()); + Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits()); + edgeImitator.expectMessageAmount(1); doDelete("/api/asset/" + savedAsset.getId().getId().toString()) .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof AssetUpdateMsg); + assetUpdateMsg = (AssetUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, assetUpdateMsg.getMsgType()); + Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits()); + Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits()); + log.info("Assets tested successfully"); } @@ -249,33 +288,45 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { ruleChain.setName("Edge Test Rule Chain"); ruleChain.setType(RuleChainType.EDGE); RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class); - edgeImitator.getStorage().expectMessageAmount(1); + + edgeImitator.expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); + edgeImitator.waitForMessages(); - TimePageData pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertTrue(pageDataRuleChain.getData().contains(savedRuleChain)); - edgeImitator.getStorage().waitForMessages(); - Set ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); - Assert.assertEquals(2, ruleChains.size()); - Assert.assertTrue(ruleChains.contains(savedRuleChain.getUuidId())); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg); + RuleChainUpdateMsg ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType()); + Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits()); + Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(ruleChainUpdateMsg.getName(), savedRuleChain.getName()); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); - pageDataRuleChain = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertFalse(pageDataRuleChain.getData().contains(savedRuleChain)); - edgeImitator.getStorage().waitForMessages(); - ruleChains = edgeImitator.getStorage().getEntitiesByType(EntityType.RULE_CHAIN); - Assert.assertEquals(1, ruleChains.size()); - Assert.assertFalse(ruleChains.contains(savedRuleChain.getUuidId())); + edgeImitator.waitForMessages(); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg); + ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType()); + Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits()); + Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); + + edgeImitator.expectMessageAmount(1); doDelete("/api/ruleChain/" + savedRuleChain.getId().getId().toString()) .andExpect(status().isOk()); - log.info("RuleChains tested successfully"); + edgeImitator.waitForMessages(); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg); + ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType()); + Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits()); + Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); + + log.info("RuleChains tested successfully"); } private void testDashboards() throws Exception { @@ -283,33 +334,45 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Dashboard dashboard = new Dashboard(); dashboard.setTitle("Edge Test Dashboard"); Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class); - edgeImitator.getStorage().expectMessageAmount(1); + + edgeImitator.expectMessageAmount(1); doPost("/api/edge/" + edge.getId().getId().toString() + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); + edgeImitator.waitForMessages(); - TimePageData pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertTrue(pageDataDashboard.getData().stream().allMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - edgeImitator.getStorage().waitForMessages(); - Set dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); - Assert.assertEquals(1, dashboards.size()); - Assert.assertTrue(dashboards.contains(savedDashboard.getUuidId())); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); + DashboardUpdateMsg dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); + Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits()); + Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName()); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); - pageDataDashboard = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/dashboards?", - new TypeReference>() {}, new TextPageLink(100)); - Assert.assertFalse(pageDataDashboard.getData().stream().anyMatch(dashboardInfo -> dashboardInfo.getUuidId().equals(savedDashboard.getUuidId()))); - edgeImitator.getStorage().waitForMessages(); - dashboards = edgeImitator.getStorage().getEntitiesByType(EntityType.DASHBOARD); - Assert.assertEquals(0, dashboards.size()); - Assert.assertFalse(dashboards.contains(savedDashboard.getUuidId())); + edgeImitator.waitForMessages(); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); + dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); + Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits()); + Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); + + edgeImitator.expectMessageAmount(1); doDelete("/api/dashboard/" + savedDashboard.getId().getId().toString()) .andExpect(status().isOk()); - log.info("Dashboards tested successfully"); + edgeImitator.waitForMessages(); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); + dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); + Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits()); + Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); + + log.info("Dashboards tested successfully"); } private void testRelations() throws Exception { @@ -331,14 +394,24 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { relation.setFrom(device.getId()); relation.setTo(asset.getId()); relation.setTypeGroup(RelationTypeGroup.COMMON); - edgeImitator.getStorage().expectMessageAmount(1); - doPost("/api/relation", relation); - edgeImitator.getStorage().waitForMessages(); - List relations = edgeImitator.getStorage().getRelations(); - Assert.assertEquals(1, relations.size()); - Assert.assertTrue(relations.contains(relation)); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); + doPost("/api/relation", relation); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof RelationUpdateMsg); + RelationUpdateMsg relationUpdateMsg = (RelationUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, relationUpdateMsg.getMsgType()); + Assert.assertEquals(relationUpdateMsg.getType(), relation.getType()); + Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getFromIdLSB(), relation.getFrom().getId().getLeastSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name());Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToIdLSB(), relation.getTo().getId().getLeastSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); + Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name()); + + edgeImitator.expectMessageAmount(1); doDelete("/api/relation?" + "fromId=" + relation.getFrom().getId().toString() + "&fromType=" + relation.getFrom().getEntityType().name() + @@ -347,15 +420,23 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { "&toId=" + relation.getTo().getId().toString() + "&toType=" + relation.getTo().getEntityType().name()) .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof RelationUpdateMsg); + relationUpdateMsg = (RelationUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, relationUpdateMsg.getMsgType()); + Assert.assertEquals(relationUpdateMsg.getType(), relation.getType()); + Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getFromIdLSB(), relation.getFrom().getId().getLeastSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name());Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToIdLSB(), relation.getTo().getId().getLeastSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); + Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name()); - edgeImitator.getStorage().waitForMessages(); - relations = edgeImitator.getStorage().getRelations(); - Assert.assertEquals(0, relations.size()); - Assert.assertFalse(relations.contains(relation)); log.info("Relations tested successfully"); } - private void testAlarms() throws Exception { log.info("Testing Alarms"); List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", @@ -370,29 +451,45 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { alarm.setType("alarm"); alarm.setSeverity(AlarmSeverity.CRITICAL); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); Alarm savedAlarm = doPost("/api/alarm", alarm, Alarm.class); - AlarmInfo alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); - edgeImitator.getStorage().waitForMessages(); - - Assert.assertEquals(1, edgeImitator.getStorage().getAlarms().size()); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().containsKey(alarmInfo.getType())); - Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); + AlarmUpdateMsg alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, alarmUpdateMsg.getMsgType()); + Assert.assertEquals(alarmUpdateMsg.getType(), savedAlarm.getType()); + Assert.assertEquals(alarmUpdateMsg.getName(), savedAlarm.getName()); + Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName()); + Assert.assertEquals(alarmUpdateMsg.getStatus(), savedAlarm.getStatus().name()); + Assert.assertEquals(alarmUpdateMsg.getSeverity(), savedAlarm.getSeverity().name()); + + edgeImitator.expectMessageAmount(1); doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack"); - - edgeImitator.getStorage().waitForMessages(); - alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); - Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); + alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ALARM_ACK_RPC_MESSAGE, alarmUpdateMsg.getMsgType()); + Assert.assertEquals(alarmUpdateMsg.getType(), savedAlarm.getType()); + Assert.assertEquals(alarmUpdateMsg.getName(), savedAlarm.getName()); + Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName()); + Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.ACTIVE_ACK.name()); + + edgeImitator.expectMessageAmount(1); doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear"); + edgeImitator.waitForMessages(); - edgeImitator.getStorage().waitForMessages(); - alarmInfo = doGet("/api/alarm/info/" + savedAlarm.getId().getId().toString(), AlarmInfo.class); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isAck()); - Assert.assertTrue(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()).isCleared()); - Assert.assertEquals(edgeImitator.getStorage().getAlarms().get(alarmInfo.getType()), alarmInfo.getStatus()); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); + alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE, alarmUpdateMsg.getMsgType()); + Assert.assertEquals(alarmUpdateMsg.getType(), savedAlarm.getType()); + Assert.assertEquals(alarmUpdateMsg.getName(), savedAlarm.getName()); + Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName()); + Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.CLEARED_ACK.name()); doDelete("/api/alarm/" + savedAlarm.getId().getId().toString()) .andExpect(status().isOk()); @@ -411,15 +508,16 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { String timeseriesData = "{\"data\":{\"temperature\":25},\"ts\":" + System.currentTimeMillis() + "}"; JsonNode timeseriesEntityData = mapper.readTree(timeseriesData); EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), ActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); edgeEventService.saveAsync(edgeEvent1); - edgeImitator.getStorage().waitForMessages(); - - EntityDataProto latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); - Assert.assertNotNull(latestEntityDataMsg); - UUID uuid = new UUID(latestEntityDataMsg.getEntityIdMSB(), latestEntityDataMsg.getEntityIdLSB()); - Assert.assertEquals(device.getId().getId(), uuid); - Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityDataProto); + EntityDataProto latestEntityDataMsg = (EntityDataProto) latestMessage; + Assert.assertEquals(latestEntityDataMsg.getEntityIdMSB(), device.getUuidId().getMostSignificantBits()); + Assert.assertEquals(latestEntityDataMsg.getEntityIdLSB(), device.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(latestEntityDataMsg.getEntityType(), device.getId().getEntityType().name()); Assert.assertTrue(latestEntityDataMsg.hasPostTelemetryMsg()); TransportProtos.PostTelemetryMsg postTelemetryMsg = latestEntityDataMsg.getPostTelemetryMsg(); @@ -430,7 +528,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { TransportProtos.KeyValueProto keyValueProto = tsKvListProto.getKv(0); Assert.assertEquals("temperature", keyValueProto.getKey()); Assert.assertEquals(25, keyValueProto.getLongV()); - edgeImitator.getStorage().setLatestEntityDataMsg(null); log.info("Timeseries tested successfully"); } @@ -445,16 +542,17 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { String attributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"key\":\"value\"}}"; JsonNode attributesEntityData = mapper.readTree(attributesData); EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), ActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); edgeEventService.saveAsync(edgeEvent1); - edgeImitator.getStorage().waitForMessages(); - - EntityDataProto latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); - Assert.assertNotNull(latestEntityDataMsg); - UUID uuid = new UUID(latestEntityDataMsg.getEntityIdMSB(), latestEntityDataMsg.getEntityIdLSB()); - Assert.assertEquals(device.getId().getId(), uuid); - Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); - Assert.assertEquals(attributesEntityData.get("scope").asText(), latestEntityDataMsg.getPostAttributeScope()); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityDataProto); + EntityDataProto latestEntityDataMsg = (EntityDataProto) latestMessage; + Assert.assertEquals(latestEntityDataMsg.getEntityIdMSB(), device.getUuidId().getMostSignificantBits()); + Assert.assertEquals(latestEntityDataMsg.getEntityIdLSB(), device.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(latestEntityDataMsg.getEntityType(), device.getId().getEntityType().name()); + Assert.assertEquals(latestEntityDataMsg.getPostAttributeScope(), attributesEntityData.get("scope").asText()); Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg()); TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg(); @@ -462,28 +560,27 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { TransportProtos.KeyValueProto keyValueProto = attributesUpdatedMsg.getKv(0); Assert.assertEquals("key", keyValueProto.getKey()); Assert.assertEquals("value", keyValueProto.getStringV()); - edgeImitator.getStorage().setLatestEntityDataMsg(null); ((ObjectNode) attributesEntityData).put("isPostAttributes", true); EdgeEvent edgeEvent2 = constructEdgeEvent(tenantId, edge.getId(), ActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); - edgeImitator.getStorage().expectMessageAmount(1); + edgeImitator.expectMessageAmount(1); edgeEventService.saveAsync(edgeEvent2); - edgeImitator.getStorage().waitForMessages(); - - latestEntityDataMsg = edgeImitator.getStorage().getLatestEntityDataMsg(); - Assert.assertNotNull(latestEntityDataMsg); - uuid = new UUID(latestEntityDataMsg.getEntityIdMSB(), latestEntityDataMsg.getEntityIdLSB()); - Assert.assertEquals(device.getId().getId(), uuid); - Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); - Assert.assertEquals(attributesEntityData.get("scope").asText(), latestEntityDataMsg.getPostAttributeScope()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityDataProto); + latestEntityDataMsg = (EntityDataProto) latestMessage; + Assert.assertEquals(latestEntityDataMsg.getEntityIdMSB(), device.getUuidId().getMostSignificantBits()); + Assert.assertEquals(latestEntityDataMsg.getEntityIdLSB(), device.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(latestEntityDataMsg.getEntityType(), device.getId().getEntityType().name()); + Assert.assertEquals(latestEntityDataMsg.getPostAttributeScope(), attributesEntityData.get("scope").asText()); Assert.assertTrue(latestEntityDataMsg.hasPostAttributesMsg()); - TransportProtos.PostAttributeMsg postAttributeMsg = latestEntityDataMsg.getPostAttributesMsg(); - Assert.assertEquals(1, postAttributeMsg.getKvCount()); - keyValueProto = postAttributeMsg.getKv(0); + attributesUpdatedMsg = latestEntityDataMsg.getPostAttributesMsg(); + Assert.assertEquals(1, attributesUpdatedMsg.getKvCount()); + keyValueProto = attributesUpdatedMsg.getKv(0); Assert.assertEquals("key", keyValueProto.getKey()); Assert.assertEquals("value", keyValueProto.getStringV()); - edgeImitator.getStorage().setLatestEntityDataMsg(null); log.info("Attributes tested successfully"); } @@ -542,11 +639,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { new TypeReference>() {}, new TextPageLink(100), device.getId().getEntityType().name(), device.getId().getId().toString()) .getData(); - - for (AlarmInfo alarmInfo: alarms) { - log.info(String.valueOf(alarmInfo)); - } - Optional foundAlarm = alarms.stream().filter(alarm -> alarm.getType().equals("alarm from edge")).findAny(); Assert.assertTrue(foundAlarm.isPresent()); AlarmInfo alarmInfo = foundAlarm.get(); diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 90ec80838f..4cdc7ba84c 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -19,12 +19,12 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import com.google.protobuf.AbstractMessage; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.thingsboard.edge.rpc.EdgeGrpcClient; import org.thingsboard.edge.rpc.EdgeRpcClient; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; @@ -41,7 +41,7 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; -import java.util.UUID; +import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -53,16 +53,19 @@ public class EdgeImitator { private EdgeRpcClient edgeRpcClient; + private CountDownLatch messagesLatch; private CountDownLatch responsesLatch; @Getter - private EdgeStorage storage; - + private EdgeConfiguration configuration; + @Getter + private List downlinkMsgs; public EdgeImitator(String host, int port, String routingKey, String routingSecret) throws NoSuchFieldException, IllegalAccessException { edgeRpcClient = new EdgeGrpcClient(); - storage = new EdgeStorage(); + messagesLatch = new CountDownLatch(0); responsesLatch = new CountDownLatch(0); + downlinkMsgs = new ArrayList<>(); this.routingKey = routingKey; this.routingSecret = routingSecret; setEdgeCredentials("rpcHost", host); @@ -101,7 +104,7 @@ public class EdgeImitator { } private void onEdgeUpdate(EdgeConfiguration edgeConfiguration) { - storage.setConfiguration(edgeConfiguration); + this.configuration = edgeConfiguration; } private void onDownlink(DownlinkMsg downlinkMsg) { @@ -129,47 +132,68 @@ public class EdgeImitator { List> result = new ArrayList<>(); if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { - result.add(storage.processEntity(deviceUpdateMsg.getMsgType(), EntityType.DEVICE, new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()))); + saveDownlinkMsg(deviceUpdateMsg); } } if (downlinkMsg.getAssetUpdateMsgList() != null && !downlinkMsg.getAssetUpdateMsgList().isEmpty()) { for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) { - result.add(storage.processEntity(assetUpdateMsg.getMsgType(), EntityType.ASSET, new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB()))); + saveDownlinkMsg(assetUpdateMsg); } } if (downlinkMsg.getRuleChainUpdateMsgList() != null && !downlinkMsg.getRuleChainUpdateMsgList().isEmpty()) { for (RuleChainUpdateMsg ruleChainUpdateMsg: downlinkMsg.getRuleChainUpdateMsgList()) { - result.add(storage.processEntity(ruleChainUpdateMsg.getMsgType(), EntityType.RULE_CHAIN, new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB()))); + saveDownlinkMsg(ruleChainUpdateMsg); } } if (downlinkMsg.getDashboardUpdateMsgList() != null && !downlinkMsg.getDashboardUpdateMsgList().isEmpty()) { for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) { - result.add(storage.processEntity(dashboardUpdateMsg.getMsgType(), EntityType.DASHBOARD, new UUID(dashboardUpdateMsg.getIdMSB(), dashboardUpdateMsg.getIdLSB()))); + saveDownlinkMsg(dashboardUpdateMsg); } } if (downlinkMsg.getRelationUpdateMsgList() != null && !downlinkMsg.getRelationUpdateMsgList().isEmpty()) { for (RelationUpdateMsg relationUpdateMsg: downlinkMsg.getRelationUpdateMsgList()) { - result.add(storage.processRelation(relationUpdateMsg)); + saveDownlinkMsg(relationUpdateMsg); } } if (downlinkMsg.getAlarmUpdateMsgList() != null && !downlinkMsg.getAlarmUpdateMsgList().isEmpty()) { for (AlarmUpdateMsg alarmUpdateMsg: downlinkMsg.getAlarmUpdateMsgList()) { - result.add(storage.processAlarm(alarmUpdateMsg)); + saveDownlinkMsg(alarmUpdateMsg); } } if (downlinkMsg.getEntityDataList() != null && !downlinkMsg.getEntityDataList().isEmpty()) { for (EntityDataProto entityData: downlinkMsg.getEntityDataList()) { - result.add(storage.processEntityData(entityData)); + saveDownlinkMsg(entityData); } } return Futures.allAsList(result); } - public void waitForResponses() throws InterruptedException { responsesLatch.await(5, TimeUnit.SECONDS); + private ListenableFuture saveDownlinkMsg(AbstractMessage message) { + downlinkMsgs.add(message); + messagesLatch.countDown(); + return Futures.immediateFuture(null); + } + + public void waitForMessages() throws InterruptedException { + messagesLatch.await(5, TimeUnit.SECONDS); + } + + public void expectMessageAmount(int messageAmount) { + messagesLatch = new CountDownLatch(messageAmount); } + public void waitForResponses() throws InterruptedException { responsesLatch.await(5, TimeUnit.SECONDS); } + public void expectResponsesAmount(int messageAmount) { responsesLatch = new CountDownLatch(messageAmount); } + public Optional findMessageByType(Class tClass) { + return (Optional) downlinkMsgs.stream().filter(downlinkMsg -> downlinkMsg.getClass().isAssignableFrom(tClass)).findAny(); + } + + public AbstractMessage getLatestMessage() { + return downlinkMsgs.get(downlinkMsgs.size() - 1); + } + } diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java deleted file mode 100644 index a8301fda33..0000000000 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeStorage.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright © 2016-2020 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.edge.imitator; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.alarm.AlarmStatus; -import org.thingsboard.server.common.data.id.EntityIdFactory; -import org.thingsboard.server.common.data.relation.EntityRelation; -import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.gen.edge.AlarmUpdateMsg; -import org.thingsboard.server.gen.edge.EdgeConfiguration; -import org.thingsboard.server.gen.edge.EntityDataProto; -import org.thingsboard.server.gen.edge.RelationUpdateMsg; -import org.thingsboard.server.gen.edge.UpdateMsgType; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -@Slf4j -@Getter -@Setter -public class EdgeStorage { - - private EdgeConfiguration configuration; - - private CountDownLatch messagesLatch; - - private Map entities; - private Map alarms; - private List relations; - - private EntityDataProto latestEntityDataMsg; - - public EdgeStorage() { - messagesLatch = new CountDownLatch(0); - entities = new HashMap<>(); - alarms = new HashMap<>(); - relations = new ArrayList<>(); - latestEntityDataMsg = null; - } - - public ListenableFuture processEntity(UpdateMsgType msgType, EntityType type, UUID uuid) { - switch (msgType) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - entities.put(uuid, type); - messagesLatch.countDown(); - break; - case ENTITY_DELETED_RPC_MESSAGE: - if (entities.remove(uuid) != null) { - messagesLatch.countDown(); - } - break; - } - return Futures.immediateFuture(null); - } - - public ListenableFuture processRelation(RelationUpdateMsg relationMsg) { - boolean result = false; - EntityRelation relation = new EntityRelation(); - relation.setType(relationMsg.getType()); - relation.setTypeGroup(RelationTypeGroup.valueOf(relationMsg.getTypeGroup())); - relation.setTo(EntityIdFactory.getByTypeAndUuid(relationMsg.getToEntityType(), new UUID(relationMsg.getToIdMSB(), relationMsg.getToIdLSB()))); - relation.setFrom(EntityIdFactory.getByTypeAndUuid(relationMsg.getFromEntityType(), new UUID(relationMsg.getFromIdMSB(), relationMsg.getFromIdLSB()))); - switch (relationMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - result = relations.add(relation); - break; - case ENTITY_DELETED_RPC_MESSAGE: - result = relations.remove(relation); - break; - } - if (result) { - messagesLatch.countDown(); - } - return Futures.immediateFuture(null); - } - - public ListenableFuture processAlarm(AlarmUpdateMsg alarmMsg) { - switch (alarmMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: - case ALARM_ACK_RPC_MESSAGE: - case ALARM_CLEAR_RPC_MESSAGE: - alarms.put(alarmMsg.getType(), AlarmStatus.valueOf(alarmMsg.getStatus())); - messagesLatch.countDown(); - break; - case ENTITY_DELETED_RPC_MESSAGE: - if (alarms.remove(alarmMsg.getName()) != null) { - messagesLatch.countDown(); - } - break; - } - return Futures.immediateFuture(null); - } - - public ListenableFuture processEntityData(EntityDataProto entityData) { - latestEntityDataMsg = entityData; - messagesLatch.countDown(); - return Futures.immediateFuture(null); - } - - public Set getEntitiesByType(EntityType type) { - return entities.entrySet().stream() - .filter(entry -> entry.getValue().equals(type)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet(); - } - - public void waitForMessages() throws InterruptedException { - messagesLatch.await(5, TimeUnit.SECONDS); - } - - public void expectMessageAmount(int messageAmount) { - messagesLatch = new CountDownLatch(messageAmount); - } -} From 898b7570a5b424a9619c5d52845b518bd92e101c Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 5 Oct 2020 11:07:32 +0300 Subject: [PATCH 149/156] fixes --- .../server/edge/imitator/EdgeImitator.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 4cdc7ba84c..64f17d59c9 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -132,37 +132,37 @@ public class EdgeImitator { List> result = new ArrayList<>(); if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { - saveDownlinkMsg(deviceUpdateMsg); + result.add(saveDownlinkMsg(deviceUpdateMsg)); } } if (downlinkMsg.getAssetUpdateMsgList() != null && !downlinkMsg.getAssetUpdateMsgList().isEmpty()) { for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) { - saveDownlinkMsg(assetUpdateMsg); + result.add(saveDownlinkMsg(assetUpdateMsg)); } } if (downlinkMsg.getRuleChainUpdateMsgList() != null && !downlinkMsg.getRuleChainUpdateMsgList().isEmpty()) { for (RuleChainUpdateMsg ruleChainUpdateMsg: downlinkMsg.getRuleChainUpdateMsgList()) { - saveDownlinkMsg(ruleChainUpdateMsg); + result.add(saveDownlinkMsg(ruleChainUpdateMsg)); } } if (downlinkMsg.getDashboardUpdateMsgList() != null && !downlinkMsg.getDashboardUpdateMsgList().isEmpty()) { for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) { - saveDownlinkMsg(dashboardUpdateMsg); + result.add(saveDownlinkMsg(dashboardUpdateMsg)); } } if (downlinkMsg.getRelationUpdateMsgList() != null && !downlinkMsg.getRelationUpdateMsgList().isEmpty()) { for (RelationUpdateMsg relationUpdateMsg: downlinkMsg.getRelationUpdateMsgList()) { - saveDownlinkMsg(relationUpdateMsg); + result.add(saveDownlinkMsg(relationUpdateMsg)); } } if (downlinkMsg.getAlarmUpdateMsgList() != null && !downlinkMsg.getAlarmUpdateMsgList().isEmpty()) { for (AlarmUpdateMsg alarmUpdateMsg: downlinkMsg.getAlarmUpdateMsgList()) { - saveDownlinkMsg(alarmUpdateMsg); + result.add(saveDownlinkMsg(alarmUpdateMsg)); } } if (downlinkMsg.getEntityDataList() != null && !downlinkMsg.getEntityDataList().isEmpty()) { for (EntityDataProto entityData: downlinkMsg.getEntityDataList()) { - saveDownlinkMsg(entityData); + result.add(saveDownlinkMsg(entityData)); } } return Futures.allAsList(result); From 74a69d8a1e26c124ed1ce921ad4536fc32342443 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 5 Oct 2020 12:02:20 +0300 Subject: [PATCH 150/156] test for sync Edge --- .../controller/BaseEdgeControllerTest.java | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index 165f8cecdb..a32754b418 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -23,17 +23,20 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.thingsboard.server.common.data.Customer; -import org.thingsboard.server.common.data.EntitySubtype; -import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.*; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.edge.imitator.EdgeImitator; +import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import java.util.ArrayList; import java.util.Collections; @@ -641,4 +644,54 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { Assert.assertEquals(0, pageData.getData().size()); } + @Test + public void testSyncEdge() throws Exception { + Edge edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); + + Device device = new Device(); + device.setName("Edge Device 1"); + device.setType("test"); + Device savedDevice = doPost("/api/device", device, Device.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/device/" + savedDevice.getId().getId().toString(), Device.class); + + Asset asset = new Asset(); + asset.setName("Edge Asset 1"); + asset.setType("test"); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + + EdgeImitator edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); + // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases + edgeImitator.expectMessageAmount(6); + edgeImitator.connect(); + edgeImitator.waitForMessages(); + + Assert.assertEquals(6, edgeImitator.getDownlinkMsgs().size()); + Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); + Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); + Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); + + edgeImitator.getDownlinkMsgs().clear(); + + edgeImitator.expectMessageAmount(3); + doPost("/api/edge/sync", edge.getId()); + edgeImitator.waitForMessages(); + + Assert.assertEquals(3, edgeImitator.getDownlinkMsgs().size()); + Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); + Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); + Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); + + edgeImitator.disconnect(); + + doDelete("/api/device/" + savedDevice.getId().getId().toString()) + .andExpect(status().isOk()); + doDelete("/api/asset/" + savedAsset.getId().getId().toString()) + .andExpect(status().isOk()); + doDelete("/api/edge/" + edge.getId().getId().toString()) + .andExpect(status().isOk()); + } + } From 8ad8e2d797932157bd82fbb812d49aed1b123633 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 5 Oct 2020 12:04:49 +0300 Subject: [PATCH 151/156] refactored imports --- .../server/controller/BaseEdgeControllerTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index a32754b418..9e1bf1b609 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -23,11 +23,14 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.thingsboard.server.common.data.*; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; From 97d2d661519faa33cfb8c5af5a3b9267e92d0e69 Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 5 Oct 2020 16:53:11 +0300 Subject: [PATCH 152/156] test coverage for Customer, EntityView, WidgetsBundle, WidgetType entities + request messages --- .../controller/BaseEdgeControllerTest.java | 13 +- .../thingsboard/server/edge/BaseEdgeTest.java | 280 +++++++++++++++++- .../server/edge/imitator/EdgeImitator.java | 57 ++++ 3 files changed, 339 insertions(+), 11 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index 9e1bf1b609..d388148325 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -40,6 +40,7 @@ import org.thingsboard.server.edge.imitator.EdgeImitator; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; +import org.thingsboard.server.gen.edge.UserUpdateMsg; import java.util.ArrayList; import java.util.Collections; @@ -666,26 +667,28 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); EdgeImitator edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); - // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases - edgeImitator.expectMessageAmount(6); + // should be 4, but 4 events from sync service + 3 from controller. will be fixed in next releases + edgeImitator.expectMessageAmount(7); edgeImitator.connect(); edgeImitator.waitForMessages(); - Assert.assertEquals(6, edgeImitator.getDownlinkMsgs().size()); + Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size()); Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); + Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent()); edgeImitator.getDownlinkMsgs().clear(); - edgeImitator.expectMessageAmount(3); + edgeImitator.expectMessageAmount(4); doPost("/api/edge/sync", edge.getId()); edgeImitator.waitForMessages(); - Assert.assertEquals(3, edgeImitator.getDownlinkMsgs().size()); + Assert.assertEquals(4, edgeImitator.getDownlinkMsgs().size()); Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); + Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent()); edgeImitator.disconnect(); diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index c5db7a0e97..f3512a7141 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -18,7 +18,6 @@ package org.thingsboard.server.edge; import com.datastax.driver.core.utils.UUIDs; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonObject; import com.google.protobuf.AbstractMessage; @@ -28,10 +27,12 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; @@ -44,7 +45,9 @@ import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -52,20 +55,34 @@ import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.edge.EdgeEventService;; +import org.thingsboard.server.dao.util.mapping.JacksonUtil; import org.thingsboard.server.edge.imitator.EdgeImitator; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; +import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UpdateMsgType; import org.thingsboard.server.gen.edge.UplinkMsg; +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; import org.thingsboard.server.gen.transport.TransportProtos; import java.util.List; @@ -110,8 +127,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { installation(); edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); - // should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases - edgeImitator.expectMessageAmount(6); + // should be 4, but 4 events from sync service + 3 from controller. will be fixed in next releases + edgeImitator.expectMessageAmount(7); edgeImitator.connect(); } @@ -136,6 +153,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { testDashboards(); testRelations(); testAlarms(); + testEntityView(); + testCustomer(); + testWidgetsBundleAndWidgetType(); testTimeseries(); testAttributes(); testSendMessagesToCloud(); @@ -148,6 +168,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { EdgeConfiguration configuration = edgeImitator.getConfiguration(); Assert.assertNotNull(configuration); + UserId userId = edgeImitator.getUserId(); + Assert.assertNotNull(userId); + Optional optionalMsg1 = edgeImitator.findMessageByType(DeviceUpdateMsg.class); Assert.assertTrue(optionalMsg1.isPresent()); DeviceUpdateMsg deviceUpdateMsg = optionalMsg1.get(); @@ -406,7 +429,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Assert.assertEquals(relationUpdateMsg.getType(), relation.getType()); Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); Assert.assertEquals(relationUpdateMsg.getFromIdLSB(), relation.getFrom().getId().getLeastSignificantBits()); - Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name());Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); + Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); + Assert.assertEquals(relationUpdateMsg.getFromIdMSB(), relation.getFrom().getId().getMostSignificantBits()); Assert.assertEquals(relationUpdateMsg.getToIdLSB(), relation.getTo().getId().getLeastSignificantBits()); Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name()); @@ -496,9 +520,179 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { log.info("Alarms tested successfully"); } + private void testEntityView() throws Exception { + log.info("Testing EntityView"); + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Assert.assertEquals(1, edgeDevices.size()); + Device device = edgeDevices.get(0); + Assert.assertEquals("Edge Device 1", device.getName()); + + EntityView entityView = new EntityView(); + entityView.setName("Edge EntityView 1"); + entityView.setType("test"); + entityView.setEntityId(device.getId()); + EntityView savedEntityView = doPost("/api/entityView", entityView, EntityView.class); + + edgeImitator.expectMessageAmount(1); + doPost("/api/edge/" + edge.getId().getId().toString() + + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg); + EntityViewUpdateMsg entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, entityViewUpdateMsg.getMsgType()); + Assert.assertEquals(entityViewUpdateMsg.getType(), savedEntityView.getType()); + Assert.assertEquals(entityViewUpdateMsg.getName(), savedEntityView.getName()); + Assert.assertEquals(entityViewUpdateMsg.getIdMSB(), savedEntityView.getUuidId().getMostSignificantBits()); + Assert.assertEquals(entityViewUpdateMsg.getIdLSB(), savedEntityView.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(entityViewUpdateMsg.getEntityIdMSB(), device.getUuidId().getMostSignificantBits()); + Assert.assertEquals(entityViewUpdateMsg.getEntityIdLSB(), device.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(entityViewUpdateMsg.getEntityType().name(), device.getId().getEntityType().name()); + + edgeImitator.expectMessageAmount(1); + doDelete("/api/edge/" + edge.getId().getId().toString() + + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg); + entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, entityViewUpdateMsg.getMsgType()); + Assert.assertEquals(entityViewUpdateMsg.getIdMSB(), savedEntityView.getUuidId().getMostSignificantBits()); + Assert.assertEquals(entityViewUpdateMsg.getIdLSB(), savedEntityView.getUuidId().getLeastSignificantBits()); + + edgeImitator.expectMessageAmount(1); + doDelete("/api/entityView/" + savedEntityView.getId().getId().toString()) + .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg); + entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, entityViewUpdateMsg.getMsgType()); + Assert.assertEquals(entityViewUpdateMsg.getIdMSB(), savedEntityView.getUuidId().getMostSignificantBits()); + Assert.assertEquals(entityViewUpdateMsg.getIdLSB(), savedEntityView.getUuidId().getLeastSignificantBits()); + + log.info("EntityView tested successfully"); + } + + private void testCustomer() throws Exception { + log.info("Testing Customer"); + + Customer customer = new Customer(); + customer.setTitle("Edge Customer 1"); + Customer savedCustomer = doPost("/api/customer", customer, Customer.class); + + edgeImitator.expectMessageAmount(1); + doPost("/api/customer/" + savedCustomer.getId().getId().toString() + + "/edge/" + edge.getId().getId().toString(), Edge.class); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg); + CustomerUpdateMsg customerUpdateMsg = (CustomerUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, customerUpdateMsg.getMsgType()); + Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits()); + Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(customerUpdateMsg.getTitle(), savedCustomer.getTitle()); + + edgeImitator.expectMessageAmount(1); + doDelete("/api/customer/edge/" + edge.getId().getId().toString(), Edge.class); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg); + customerUpdateMsg = (CustomerUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, customerUpdateMsg.getMsgType()); + Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits()); + Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits()); + + edgeImitator.expectMessageAmount(1); + doDelete("/api/customer/" + savedCustomer.getId().getId().toString()) + .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg); + customerUpdateMsg = (CustomerUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, customerUpdateMsg.getMsgType()); + Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits()); + Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits()); + + log.info("Customer tested successfully"); + } + + private void testWidgetsBundleAndWidgetType() throws Exception { + log.info("Testing WidgetsBundle and WidgetType"); + + WidgetsBundle widgetsBundle = new WidgetsBundle(); + widgetsBundle.setTitle("Test Widget Bundle"); + + edgeImitator.expectMessageAmount(1); + WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof WidgetsBundleUpdateMsg); + WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = (WidgetsBundleUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, widgetsBundleUpdateMsg.getMsgType()); + Assert.assertEquals(widgetsBundleUpdateMsg.getIdMSB(), savedWidgetsBundle.getUuidId().getMostSignificantBits()); + Assert.assertEquals(widgetsBundleUpdateMsg.getIdLSB(), savedWidgetsBundle.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(widgetsBundleUpdateMsg.getAlias(), savedWidgetsBundle.getAlias()); + Assert.assertEquals(widgetsBundleUpdateMsg.getTitle(), savedWidgetsBundle.getTitle()); + + WidgetType widgetType = new WidgetType(); + widgetType.setName("Test Widget Type"); + widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); + ObjectNode descriptor = mapper.createObjectNode(); + descriptor.put("key", "value"); + widgetType.setDescriptor(descriptor); + + edgeImitator.expectMessageAmount(1); + WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof WidgetTypeUpdateMsg); + WidgetTypeUpdateMsg widgetTypeUpdateMsg = (WidgetTypeUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, widgetTypeUpdateMsg.getMsgType()); + Assert.assertEquals(widgetTypeUpdateMsg.getIdMSB(), savedWidgetType.getUuidId().getMostSignificantBits()); + Assert.assertEquals(widgetTypeUpdateMsg.getIdLSB(), savedWidgetType.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(widgetTypeUpdateMsg.getAlias(), savedWidgetType.getAlias()); + Assert.assertEquals(widgetTypeUpdateMsg.getName(), savedWidgetType.getName()); + Assert.assertEquals(JacksonUtil.toJsonNode(widgetTypeUpdateMsg.getDescriptorJson()), savedWidgetType.getDescriptor()); + + edgeImitator.expectMessageAmount(1); + doDelete("/api/widgetType/" + savedWidgetType.getId().getId().toString()) + .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof WidgetTypeUpdateMsg); + widgetTypeUpdateMsg = (WidgetTypeUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, widgetTypeUpdateMsg.getMsgType()); + Assert.assertEquals(widgetTypeUpdateMsg.getIdMSB(), savedWidgetType.getUuidId().getMostSignificantBits()); + Assert.assertEquals(widgetTypeUpdateMsg.getIdLSB(), savedWidgetType.getUuidId().getLeastSignificantBits()); + + edgeImitator.expectMessageAmount(1); + doDelete("/api/widgetsBundle/" + savedWidgetsBundle.getId().getId().toString()) + .andExpect(status().isOk()); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof WidgetsBundleUpdateMsg); + widgetsBundleUpdateMsg = (WidgetsBundleUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, widgetsBundleUpdateMsg.getMsgType()); + Assert.assertEquals(widgetsBundleUpdateMsg.getIdMSB(), savedWidgetsBundle.getUuidId().getMostSignificantBits()); + Assert.assertEquals(widgetsBundleUpdateMsg.getIdLSB(), savedWidgetsBundle.getUuidId().getLeastSignificantBits()); + + log.info("WidgetsBundle and WidgetType tested successfully"); + } + private void testTimeseries() throws Exception { log.info("Testing timeseries"); - ObjectMapper mapper = new ObjectMapper(); List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", new TypeReference>() {}, new TextPageLink(100)).getData(); Assert.assertEquals(1, edgeDevices.size()); @@ -592,6 +786,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { sendTelemetry(); sendRelation(); sendDeleteDeviceOnEdge(); + sendRuleChainMetadataRequest(); + sendUserCredentialsRequest(); + sendDeviceCredentialsRequest(); log.info("Messages were sent successfully"); } @@ -719,7 +916,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { entityDataBuilder2.setPostAttributeScope(DataConstants.SERVER_SCOPE); builder2.addEntityData(entityDataBuilder2.build()); edgeImitator.sendUplinkMsg(builder2.build()); - edgeImitator.waitForResponses(); Thread.sleep(1000); @@ -735,6 +931,78 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { } + private void sendRuleChainMetadataRequest() throws Exception { + RuleChainId edgeRootRuleChainId = edge.getRootRuleChainId(); + + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + RuleChainMetadataRequestMsg.Builder ruleChainMetadataRequestMsgBuilder = RuleChainMetadataRequestMsg.newBuilder(); + ruleChainMetadataRequestMsgBuilder.setRuleChainIdMSB(edgeRootRuleChainId.getId().getMostSignificantBits()); + ruleChainMetadataRequestMsgBuilder.setRuleChainIdLSB(edgeRootRuleChainId.getId().getLeastSignificantBits()); + builder.addRuleChainMetadataRequestMsg(ruleChainMetadataRequestMsgBuilder.build()); + edgeImitator.expectResponsesAmount(1); + edgeImitator.expectMessageAmount(1); + edgeImitator.sendUplinkMsg(builder.build()); + edgeImitator.waitForResponses(); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof RuleChainMetadataUpdateMsg); + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = (RuleChainMetadataUpdateMsg) latestMessage; + Assert.assertEquals(ruleChainMetadataUpdateMsg.getRuleChainIdMSB(), edgeRootRuleChainId.getId().getMostSignificantBits()); + Assert.assertEquals(ruleChainMetadataUpdateMsg.getRuleChainIdLSB(), edgeRootRuleChainId.getId().getLeastSignificantBits()); + } + + private void sendUserCredentialsRequest() throws Exception { + UserId userId = edgeImitator.getUserId(); + + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + UserCredentialsRequestMsg.Builder userCredentialsRequestMsgBuilder = UserCredentialsRequestMsg.newBuilder(); + userCredentialsRequestMsgBuilder.setUserIdMSB(userId.getId().getMostSignificantBits()); + userCredentialsRequestMsgBuilder.setUserIdLSB(userId.getId().getLeastSignificantBits()); + builder.addUserCredentialsRequestMsg(userCredentialsRequestMsgBuilder.build()); + edgeImitator.expectResponsesAmount(1); + edgeImitator.expectMessageAmount(1); + edgeImitator.sendUplinkMsg(builder.build()); + edgeImitator.waitForResponses(); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof UserCredentialsUpdateMsg); + UserCredentialsUpdateMsg userCredentialsUpdateMsg = (UserCredentialsUpdateMsg) latestMessage; + Assert.assertEquals(userCredentialsUpdateMsg.getUserIdMSB(), userId.getId().getMostSignificantBits()); + Assert.assertEquals(userCredentialsUpdateMsg.getUserIdLSB(), userId.getId().getLeastSignificantBits()); + } + + private void sendDeviceCredentialsRequest() throws Exception { + List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", + new TypeReference>() {}, new TextPageLink(100)).getData(); + Optional foundDevice = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 1")).findAny(); + Assert.assertTrue(foundDevice.isPresent()); + Device device = foundDevice.get(); + + DeviceCredentials deviceCredentials = doGet("/api/device/" + device.getId().getId().toString() + "/credentials", DeviceCredentials.class); + + UplinkMsg.Builder builder = UplinkMsg.newBuilder(); + DeviceCredentialsRequestMsg.Builder deviceCredentialsRequestMsgBuilder = DeviceCredentialsRequestMsg.newBuilder(); + deviceCredentialsRequestMsgBuilder.setDeviceIdMSB(device.getUuidId().getMostSignificantBits()); + deviceCredentialsRequestMsgBuilder.setDeviceIdLSB(device.getUuidId().getLeastSignificantBits()); + builder.addDeviceCredentialsRequestMsg(deviceCredentialsRequestMsgBuilder.build()); + + edgeImitator.expectResponsesAmount(1); + edgeImitator.expectMessageAmount(1); + edgeImitator.sendUplinkMsg(builder.build()); + edgeImitator.waitForResponses(); + edgeImitator.waitForMessages(); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DeviceCredentialsUpdateMsg); + DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = (DeviceCredentialsUpdateMsg) latestMessage; + Assert.assertEquals(deviceCredentialsUpdateMsg.getDeviceIdMSB(), device.getUuidId().getMostSignificantBits()); + Assert.assertEquals(deviceCredentialsUpdateMsg.getDeviceIdLSB(), device.getUuidId().getLeastSignificantBits()); + Assert.assertEquals(deviceCredentialsUpdateMsg.getCredentialsType(), deviceCredentials.getCredentialsType().name()); + Assert.assertEquals(deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentials.getCredentialsId()); + } + private void sendDeleteDeviceOnEdge() throws Exception { List edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", new TypeReference>() {}, new TextPageLink(100)).getData(); diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 64f17d59c9..452421f001 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -25,23 +25,33 @@ import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.thingsboard.edge.rpc.EdgeGrpcClient; import org.thingsboard.edge.rpc.EdgeRpcClient; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.DownlinkMsg; import org.thingsboard.server.gen.edge.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.EdgeConfiguration; import org.thingsboard.server.gen.edge.EntityDataProto; +import org.thingsboard.server.gen.edge.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.UplinkMsg; import org.thingsboard.server.gen.edge.UplinkResponseMsg; +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.UserUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; +import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -59,6 +69,8 @@ public class EdgeImitator { @Getter private EdgeConfiguration configuration; @Getter + private UserId userId; + @Getter private List downlinkMsgs; public EdgeImitator(String host, int port, String routingKey, String routingSecret) throws NoSuchFieldException, IllegalAccessException { @@ -107,6 +119,10 @@ public class EdgeImitator { this.configuration = edgeConfiguration; } + private void onUserUpdate(UserUpdateMsg userUpdateMsg) { + this.userId = new UserId(new UUID(userUpdateMsg.getIdMSB(), userUpdateMsg.getIdLSB())); + } + private void onDownlink(DownlinkMsg downlinkMsg) { ListenableFuture> future = processDownlinkMsg(downlinkMsg); Futures.addCallback(future, new FutureCallback>() { @@ -135,6 +151,11 @@ public class EdgeImitator { result.add(saveDownlinkMsg(deviceUpdateMsg)); } } + if (downlinkMsg.getDeviceCredentialsUpdateMsgList() != null && !downlinkMsg.getDeviceCredentialsUpdateMsgList().isEmpty()) { + for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg: downlinkMsg.getDeviceCredentialsUpdateMsgList()) { + result.add(saveDownlinkMsg(deviceCredentialsUpdateMsg)); + } + } if (downlinkMsg.getAssetUpdateMsgList() != null && !downlinkMsg.getAssetUpdateMsgList().isEmpty()) { for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) { result.add(saveDownlinkMsg(assetUpdateMsg)); @@ -145,6 +166,11 @@ public class EdgeImitator { result.add(saveDownlinkMsg(ruleChainUpdateMsg)); } } + if (downlinkMsg.getRuleChainMetadataUpdateMsgList() != null && !downlinkMsg.getRuleChainMetadataUpdateMsgList().isEmpty()) { + for (RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg: downlinkMsg.getRuleChainMetadataUpdateMsgList()) { + result.add(saveDownlinkMsg(ruleChainMetadataUpdateMsg)); + } + } if (downlinkMsg.getDashboardUpdateMsgList() != null && !downlinkMsg.getDashboardUpdateMsgList().isEmpty()) { for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) { result.add(saveDownlinkMsg(dashboardUpdateMsg)); @@ -165,6 +191,37 @@ public class EdgeImitator { result.add(saveDownlinkMsg(entityData)); } } + if (downlinkMsg.getEntityViewUpdateMsgList() != null && !downlinkMsg.getEntityViewUpdateMsgList().isEmpty()) { + for (EntityViewUpdateMsg entityViewUpdateMsg: downlinkMsg.getEntityViewUpdateMsgList()) { + result.add(saveDownlinkMsg(entityViewUpdateMsg)); + } + } + if (downlinkMsg.getCustomerUpdateMsgList() != null && !downlinkMsg.getCustomerUpdateMsgList().isEmpty()) { + for (CustomerUpdateMsg customerUpdateMsg: downlinkMsg.getCustomerUpdateMsgList()) { + result.add(saveDownlinkMsg(customerUpdateMsg)); + } + } + if (downlinkMsg.getWidgetsBundleUpdateMsgList() != null && !downlinkMsg.getWidgetsBundleUpdateMsgList().isEmpty()) { + for (WidgetsBundleUpdateMsg widgetsBundleUpdateMsg: downlinkMsg.getWidgetsBundleUpdateMsgList()) { + result.add(saveDownlinkMsg(widgetsBundleUpdateMsg)); + } + } + if (downlinkMsg.getWidgetTypeUpdateMsgList() != null && !downlinkMsg.getWidgetTypeUpdateMsgList().isEmpty()) { + for (WidgetTypeUpdateMsg widgetTypeUpdateMsg: downlinkMsg.getWidgetTypeUpdateMsgList()) { + result.add(saveDownlinkMsg(widgetTypeUpdateMsg)); + } + } + if (downlinkMsg.getUserUpdateMsgList() != null && !downlinkMsg.getUserUpdateMsgList().isEmpty()) { + for (UserUpdateMsg userUpdateMsg: downlinkMsg.getUserUpdateMsgList()) { + onUserUpdate(userUpdateMsg); + result.add(saveDownlinkMsg(userUpdateMsg)); + } + } + if (downlinkMsg.getUserCredentialsUpdateMsgList() != null && !downlinkMsg.getUserCredentialsUpdateMsgList().isEmpty()) { + for (UserCredentialsUpdateMsg userCredentialsUpdateMsg: downlinkMsg.getUserCredentialsUpdateMsgList()) { + result.add(saveDownlinkMsg(userCredentialsUpdateMsg)); + } + } return Futures.allAsList(result); } From 6081ed1ad063e3ba8f8d4a2867acecb4ea53bd9a Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Mon, 5 Oct 2020 18:15:36 +0300 Subject: [PATCH 153/156] fixed message amount --- .../server/controller/BaseEdgeControllerTest.java | 5 ++--- .../test/java/org/thingsboard/server/edge/BaseEdgeTest.java | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index d388148325..fa7166f561 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -667,12 +667,11 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); EdgeImitator edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); - // should be 4, but 4 events from sync service + 3 from controller. will be fixed in next releases - edgeImitator.expectMessageAmount(7); + edgeImitator.expectMessageAmount(8); edgeImitator.connect(); edgeImitator.waitForMessages(); - Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size()); + Assert.assertEquals(8, edgeImitator.getDownlinkMsgs().size()); Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index f3512a7141..0d765fbf6b 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -127,8 +127,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { installation(); edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); - // should be 4, but 4 events from sync service + 3 from controller. will be fixed in next releases - edgeImitator.expectMessageAmount(7); + // should be less, but events from SyncEdgeService stack with events from controller. will be fixed in next releases + edgeImitator.expectMessageAmount(8); edgeImitator.connect(); } From a7a7cb2ad5b1c2b5140cae090a8f65d60cd9f06c Mon Sep 17 00:00:00 2001 From: Bohdan Smetaniuk Date: Tue, 6 Oct 2020 14:25:07 +0300 Subject: [PATCH 154/156] fixed bug with extra UserCredentialsUpdataMsg --- .../controller/BaseEdgeControllerTest.java | 7 +++++-- .../thingsboard/server/edge/BaseEdgeTest.java | 2 +- .../server/edge/imitator/EdgeImitator.java | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index fa7166f561..16338584af 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -40,6 +40,7 @@ import org.thingsboard.server.edge.imitator.EdgeImitator; import org.thingsboard.server.gen.edge.AssetUpdateMsg; import org.thingsboard.server.gen.edge.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.UserUpdateMsg; import java.util.ArrayList; @@ -667,11 +668,12 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); EdgeImitator edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); - edgeImitator.expectMessageAmount(8); + edgeImitator.ignoreType(UserCredentialsUpdateMsg.class); + edgeImitator.expectMessageAmount(7); edgeImitator.connect(); edgeImitator.waitForMessages(); - Assert.assertEquals(8, edgeImitator.getDownlinkMsgs().size()); + Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size()); Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); @@ -689,6 +691,7 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent()); + edgeImitator.allowIgnoredTypes(); edgeImitator.disconnect(); doDelete("/api/device/" + savedDevice.getId().getId().toString()) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index 0d765fbf6b..7938f06222 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -128,7 +128,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); // should be less, but events from SyncEdgeService stack with events from controller. will be fixed in next releases - edgeImitator.expectMessageAmount(8); + edgeImitator.expectMessageAmount(7); edgeImitator.connect(); } diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 452421f001..3eca5438dd 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -65,6 +65,7 @@ public class EdgeImitator { private CountDownLatch messagesLatch; private CountDownLatch responsesLatch; + private List> ignoredTypes; @Getter private EdgeConfiguration configuration; @@ -78,6 +79,7 @@ public class EdgeImitator { messagesLatch = new CountDownLatch(0); responsesLatch = new CountDownLatch(0); downlinkMsgs = new ArrayList<>(); + ignoredTypes = new ArrayList<>(); this.routingKey = routingKey; this.routingSecret = routingSecret; setEdgeCredentials("rpcHost", host); @@ -226,8 +228,10 @@ public class EdgeImitator { } private ListenableFuture saveDownlinkMsg(AbstractMessage message) { - downlinkMsgs.add(message); - messagesLatch.countDown(); + if (!ignoredTypes.contains(message.getClass())) { + downlinkMsgs.add(message); + messagesLatch.countDown(); + } return Futures.immediateFuture(null); } @@ -253,4 +257,12 @@ public class EdgeImitator { return downlinkMsgs.get(downlinkMsgs.size() - 1); } + public void ignoreType(Class type) { + ignoredTypes.add(type); + } + + public void allowIgnoredTypes() { + ignoredTypes.clear(); + } + } From 160fd94666e831be23f43cb29d55c770e477d354 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 9 Oct 2020 15:47:59 +0300 Subject: [PATCH 155/156] Moved service to base class. Change sync button icon --- .../server/service/security/AccessValidator.java | 2 +- .../org/thingsboard/server/edge/BaseEdgeTest.java | 11 +++++++++++ .../server/dao/asset/BaseAssetService.java | 4 ---- .../server/dao/customer/CustomerServiceImpl.java | 4 ---- .../server/dao/device/DeviceServiceImpl.java | 4 ---- .../server/dao/entity/AbstractEntityService.java | 4 ++++ .../server/dao/entity/BaseEntityService.java | 4 ---- .../server/dao/entityview/EntityViewServiceImpl.java | 7 +------ .../server/dao/rule/BaseRuleChainService.java | 4 ---- .../server/dao/tenant/TenantServiceImpl.java | 5 ----- ui/src/app/edge/edge-fieldset.tpl.html | 2 +- 11 files changed, 18 insertions(+), 33 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java index 79a2050fb5..874f70a77a 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java +++ b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java @@ -103,7 +103,7 @@ public class AccessValidator { @Autowired protected EntityViewService entityViewService; - @Autowired + @Autowired(required = false) protected EdgeService edgeService; @Autowired diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java index 7938f06222..29ce5c81cf 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java @@ -371,6 +371,17 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName()); + edgeImitator.expectMessageAmount(1); + savedDashboard.setTitle("Updated Edge Test Dashboard"); + doPost("/api/dashboard", savedDashboard, Dashboard.class); + edgeImitator.waitForMessages(); + + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); + dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; + Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); + Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName()); + edgeImitator.expectMessageAmount(1); doDelete("/api/edge/" + edge.getId().getId().toString() + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index 3b662186dc..9b36f46f1d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -50,7 +50,6 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.customer.CustomerDao; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DataValidator; @@ -90,9 +89,6 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ @Autowired private CustomerDao customerDao; - @Autowired - private EdgeService edgeService; - @Autowired private CacheManager cacheManager; diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java index 85dcc8ac59..fa7c872399 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceService; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; @@ -77,9 +76,6 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom @Autowired private DashboardService dashboardService; - @Autowired - private EdgeService edgeService; - @Override public Customer findCustomerById(TenantId tenantId, CustomerId customerId) { log.trace("Executing findCustomerById [{}]", customerId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index 87c5b3e496..2c58e50653 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -54,7 +54,6 @@ import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.dao.customer.CustomerDao; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.exception.DataValidationException; @@ -101,9 +100,6 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe @Autowired private DeviceCredentialsService deviceCredentialsService; - @Autowired - private EdgeService edgeService; - @Autowired private CacheManager cacheManager; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java index deb2f75c6e..3e668a95a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.relation.RelationService; @@ -46,6 +47,9 @@ public abstract class AbstractEntityService { @Autowired protected EntityViewService entityViewService; + @Autowired(required = false) + protected EdgeService edgeService; + @Value("${database.entities.type:sql}") private String databaseType; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java index eadba214f9..a17872915a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java @@ -39,7 +39,6 @@ import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceService; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.tenant.TenantService; @@ -79,9 +78,6 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe @Autowired private RuleChainService ruleChainService; - @Autowired - private EdgeService edgeService; - @Override public void deleteEntityRelations(TenantId tenantId, EntityId entityId) { super.deleteEntityRelations(tenantId, entityId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 8729085ded..d7db5b9a20 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -30,7 +30,6 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Customer; -import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; @@ -50,7 +49,6 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.customer.CustomerDao; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DataValidator; @@ -95,9 +93,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti @Autowired private CustomerDao customerDao; - @Autowired - private EdgeService edgeService; - @Autowired private CacheManager cacheManager; @@ -344,7 +339,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti @Override public ListenableFuture> findEntityViewsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, - TimePageLink pageLink) { + TimePageLink pageLink) { log.trace("Executing findEntityViewsByTenantIdAndEdgeId, tenantId [{}], edgeId [{}], pageLink [{}]", tenantId, edgeId, pageLink); validateId(tenantId, INCORRECT_TENANT_ID + tenantId); validateId(edgeId, INCORRECT_EDGE_ID + edgeId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index bd0e30d401..7baa5fc5b7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleNode; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DataValidator; @@ -79,9 +78,6 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Autowired private TenantDao tenantDao; - @Autowired - private EdgeService edgeService; - @Override public RuleChain saveRuleChain(RuleChain ruleChain) { ruleChainValidator.validate(ruleChain, RuleChain::getTenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index c032f8b5de..0e35583ba6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -21,7 +21,6 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; @@ -30,7 +29,6 @@ import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceService; -import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; @@ -79,9 +77,6 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @Autowired private RuleChainService ruleChainService; - @Autowired - private EdgeService edgeService; - @Override public Tenant findTenantById(TenantId tenantId) { log.trace("Executing findTenantById [{}]", tenantId); diff --git a/ui/src/app/edge/edge-fieldset.tpl.html b/ui/src/app/edge/edge-fieldset.tpl.html index 5811969b6a..bf0f09d972 100644 --- a/ui/src/app/edge/edge-fieldset.tpl.html +++ b/ui/src/app/edge/edge-fieldset.tpl.html @@ -51,7 +51,7 @@ - + edge.sync From 0a7d8e864091fc6ea645257f6205ec72e8ba537c Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Fri, 9 Oct 2020 15:50:05 +0300 Subject: [PATCH 156/156] Disconnect client on error --- .../main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java index 6232029a14..650fb89130 100644 --- a/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java +++ b/common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java @@ -133,6 +133,11 @@ public class EdgeGrpcClient implements EdgeRpcClient { @Override public void onError(Throwable t) { log.debug("[{}] The rpc session received an error!", edgeKey, t); + try { + EdgeGrpcClient.this.disconnect(true); + } catch (InterruptedException e) { + log.error("[{}] Got interruption during disconnect!", edgeKey, e); + } onError.accept(new RuntimeException(t)); }