From 50d96fb49e4402417540afee94ed2d9a54f87f93 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 4 Mar 2021 10:03:09 +0200 Subject: [PATCH 1/9] Version set to 3.3.0-SNAPSHOT --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/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/package.json | 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/package.json | 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-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 40 files changed, 41 insertions(+), 41 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 4d820b0400..1d02f09d16 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 359a2362f9..1f4849cb79 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 3d9699061e..ba30e5bb43 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index ea4d8cb2d8..79b3bc8e26 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index 114b48a65a..06ba4aff3b 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index e5e4eb107c..7568d18ca6 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index 54098babcc..e0b30dd654 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 94cde12d3a..005c210b7b 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index 8fa8cceb2a..cea8ddc0ce 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index c04ff34adb..f229627480 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index 4368aad588..676593804e 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 7d6be1f5ae..96865036d5 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 5f5bcccc62..491adc189e 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 - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index 8999c3ddb7..6f66da5790 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index aea4ed0af7..e1a08cb74d 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard dao diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index cefbdf140b..9af00d44c7 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index 77dcb5992f..75f009880b 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "3.2.2", + "version": "3.3.0", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.js", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 769cbf6d36..a254b1acde 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index f15738fb74..3d7bf3f347 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index df1988c3a0..133b81c79d 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index d35762163c..efb9a709e9 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 890e8b91e8..1285cca0ce 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index cc85b507a9..da0688b545 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index c7352d9821..782b6a228a 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index 37ce157c41..84906e42db 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 1725a7c3c2..3897c31f5e 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "3.2.2", + "version": "3.3.0", "description": "ThingsBoard Web UI Microservice", "main": "server.js", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index 93c7f24e21..85f5db6ce3 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index f956f6f09a..742aa039be 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard netty-mqtt - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index aab4726de1..7e12adff98 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index b8373b351f..e45db432d8 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index 3709498312..d4af78f871 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index fe44acac1f..bb348793c1 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 - 3.2.2-SNAPSHOT + 3.3.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 f435277fcc..31c0c1d824 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 - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index bb0435d434..c7fcf277ea 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index c979a2d2e1..1ede01a491 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index b91c5d9dd0..41ca5683a1 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index b9c651d9c6..28aaeeab39 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index e45116a8e6..794abceddc 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index a0da1f210b..775a685ae8 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "3.2.2", + "version": "3.3.0", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index f06442db25..fb8c809260 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.2-SNAPSHOT + 3.3.0-SNAPSHOT thingsboard org.thingsboard From 6438f6b0eee75fd9216c36532ed8ab1a4407ae97 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 4 Mar 2021 18:32:28 +0200 Subject: [PATCH 2/9] added resource dao --- .../server/controller/ResourceController.java | 82 +++++++++++++++++ .../install/ThingsboardInstallService.java | 7 ++ .../DefaultSystemDataLoaderService.java | 5 ++ .../service/install/InstallScripts.java | 44 +++++++++ .../install/SqlDatabaseUpgradeService.java | 19 ++++ .../install/SystemDataLoaderService.java | 2 + .../server/dao/resource/ResourceService.java | 33 +++++++ .../data/transport/resource/Resource.java | 37 ++++++++ .../data/transport/resource/ResourceType.java | 20 +++++ .../server/dao/model/ModelConstants.java | 9 ++ .../dao/model/sql/ResourceCompositeKey.java | 45 ++++++++++ .../server/dao/model/sql/ResourceEntity.java | 77 ++++++++++++++++ .../dao/resource/BaseResourceService.java | 90 +++++++++++++++++++ .../server/dao/resource/ResourceDao.java | 33 +++++++ .../dao/sql/resource/ResourceDaoImpl.java | 73 +++++++++++++++ .../dao/sql/resource/ResourceRepository.java | 28 ++++++ .../main/resources/sql/schema-entities.sql | 8 ++ 17 files changed, 612 insertions(+) create mode 100644 application/src/main/java/org/thingsboard/server/controller/ResourceController.java create mode 100644 common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceCompositeKey.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java diff --git a/application/src/main/java/org/thingsboard/server/controller/ResourceController.java b/application/src/main/java/org/thingsboard/server/controller/ResourceController.java new file mode 100644 index 0000000000..b09e4e23b2 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/ResourceController.java @@ -0,0 +1,82 @@ +/** + * Copyright © 2016-2021 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.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.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; +import org.thingsboard.server.dao.resource.ResourceService; +import org.thingsboard.server.queue.util.TbCoreComponent; + +import java.util.List; + +@Slf4j +@RestController +@TbCoreComponent +@RequestMapping("/api") +public class ResourceController extends BaseController { + + private final ResourceService resourceService; + + public ResourceController(ResourceService resourceService) { + this.resourceService = resourceService; + } + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/resource", method = RequestMethod.POST) + @ResponseBody + public Resource saveResource(Resource resource) throws ThingsboardException { + try { + resource.setTenantId(getCurrentUser().getTenantId()); + return checkNotNull(resourceService.saveResource(resource)); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/resource", method = RequestMethod.GET) + @ResponseBody + public List getResources(@RequestParam(required = false) boolean system) throws ThingsboardException { + try { + return checkNotNull(resourceService.findByTenantId(system ? TenantId.SYS_TENANT_ID : getCurrentUser().getTenantId())); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE) + @ResponseBody + public boolean deleteResource(@PathVariable("resourceType") ResourceType resourceType, + @PathVariable("resourceId") String resourceId) throws ThingsboardException { + try { + return resourceService.deleteResource(getCurrentUser().getTenantId(), resourceType, resourceId); + } catch (Exception e) { + throw handleException(e); + } + } + +} 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 8b4a5b77a3..63eea2a7fc 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -194,6 +194,12 @@ public class ThingsboardInstallService { log.info("Updating system data..."); systemDataLoaderService.updateSystemWidgets(); break; + case "3.2.2": + log.info("Upgrading ThingsBoard from version 3.2.2 to 3.3.0 ..."); + databaseEntitiesUpgradeService.upgradeDatabase("3.2.2"); + + log.info("Updating system data..."); + break; default: throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion); @@ -226,6 +232,7 @@ public class ThingsboardInstallService { systemDataLoaderService.createAdminSettings(); systemDataLoaderService.loadSystemWidgets(); systemDataLoaderService.createOAuth2Templates(); + systemDataLoaderService.loadSystemLwm2mResources(); // systemDataLoaderService.loadSystemPlugins(); // systemDataLoaderService.loadSystemRules(); diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index 9028fe279e..6f257a367e 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -445,6 +445,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { installScripts.loadSystemWidgets(); } + @Override + public void loadSystemLwm2mResources() throws Exception { + installScripts.loadSystemLwm2mResources(); + } + private User createUser(Authority authority, TenantId tenantId, CustomerId customerId, 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 47f8529c11..5029a520e3 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 @@ -29,10 +29,13 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; +import org.thingsboard.server.dao.resource.ResourceService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; @@ -42,6 +45,7 @@ import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Base64; import java.util.Optional; import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper; @@ -66,8 +70,11 @@ public class InstallScripts { public static final String WIDGET_BUNDLES_DIR = "widget_bundles"; public static final String OAUTH2_CONFIG_TEMPLATES_DIR = "oauth2_config_templates"; public static final String DASHBOARDS_DIR = "dashboards"; + public static final String MODELS_DIR = "models"; + public static final String CREDENTIALS_DIR = "credentials"; public static final String JSON_EXT = ".json"; + public static final String XML_EXT = ".xml"; @Value("${install.data_dir:}") private String dataDir; @@ -87,6 +94,9 @@ public class InstallScripts { @Autowired private OAuth2ConfigTemplateService oAuth2TemplateService; + @Autowired + private ResourceService resourceService; + public Path getTenantRuleChainsDir() { return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR); } @@ -186,6 +196,40 @@ public class InstallScripts { } } + public void loadSystemLwm2mResources() throws Exception { + Path modelsDir = Paths.get(getDataDir(), MODELS_DIR); + try (DirectoryStream dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) { + dirStream.forEach( + path -> { + try { + Resource resource = new Resource(); + resource.setTenantId(TenantId.SYS_TENANT_ID); + resource.setResourceType(ResourceType.LWM2M_MODEL); + resource.setResourceId(path.getFileName().toString()); + resource.setValue(Files.readString(path)); + resourceService.saveResource(resource); + } catch (Exception e) { + log.error("Unable to load lwm2m model [{}]", path.toString()); + throw new RuntimeException("Unable to load lwm2m model", e); + } + } + ); + } + + Path jksPath = Paths.get(getDataDir(), CREDENTIALS_DIR, "serverKeyStore.jks"); + try { + Resource resource = new Resource(); + resource.setTenantId(TenantId.SYS_TENANT_ID); + resource.setResourceType(ResourceType.LWM2M_KEY_STORE); + resource.setResourceId(jksPath.getFileName().toString()); + resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath))); + resourceService.saveResource(resource); + } catch (Exception e) { + log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString()); + throw new RuntimeException("Unable to load l2m2m serverKeyStore", e); + } + } + public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception { Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR); try (DirectoryStream dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) { 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 c3495d960b..a56cc7ca25 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 @@ -434,6 +434,25 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService log.info("Schema updated."); } break; + case "3.2.2": + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { + log.info("Updating schema ..."); + try { + conn.createStatement().execute("CREATE TABLE IF NOT EXISTS resource (" + + " tenant_id uuid NOT NULL," + + " resource_type varchar(32) NOT NULL," + + " resource_id varchar(255) NOT NULL," + + " resource_value varchar," + + " CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)" + + " );"); + + conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3003000;"); + } catch (Exception e) { + log.error("Failed updating schema!!!", e); + } + log.info("Schema updated."); + } + break; default: throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); } diff --git a/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java index 73e2b6ea57..a6f33f476f 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java @@ -33,4 +33,6 @@ public interface SystemDataLoaderService { void deleteSystemWidgetBundle(String bundleAlias) throws Exception; + void loadSystemLwm2mResources() throws Exception; + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java new file mode 100644 index 0000000000..99cf1ef87b --- /dev/null +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java @@ -0,0 +1,33 @@ +/** + * Copyright © 2016-2021 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.dao.resource; + +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; + +import java.util.List; + + +public interface ResourceService { + Resource saveResource(Resource resource); + + Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); + + boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); + + List findByTenantId(TenantId tenantId); +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java new file mode 100644 index 0000000000..c29b704b04 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2016-2021 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.transport.resource; + +import lombok.Data; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.TenantId; + +@Data +public class Resource implements HasTenantId { + private TenantId tenantId; + private ResourceType resourceType; + private String resourceId; + private String value; + + @Override + public String toString() { + return "Resource{" + + "tenantId=" + tenantId + + ", resourceType=" + resourceType + + ", resourceId='" + resourceId + '\'' + + '}'; + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java new file mode 100644 index 0000000000..2e12bbdda2 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java @@ -0,0 +1,20 @@ +/** + * Copyright © 2016-2021 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.transport.resource; + +public enum ResourceType { + LWM2M_MODEL, LWM2M_KEY_STORE +} 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 fc6a2bed25..3f11a4ed00 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 @@ -453,6 +453,15 @@ public class ModelConstants { public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec"; public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec"; + /** + * Resource constants. + */ + public static final String RESOURCE_TABLE_NAME = "resource"; + public static final String RESOURCE_TENANT_ID_COLUMN = TENANT_ID_COLUMN; + public static final String RESOURCE_TYPE_COLUMN = "resource_type"; + public static final String RESOURCE_ID_COLUMN = "resource_id"; + public static final String RESOURCE_VALUE_COLUMN = "resource_value"; + /** * Cassandra attributes and timeseries constants. */ diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceCompositeKey.java new file mode 100644 index 0000000000..828f1f4341 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceCompositeKey.java @@ -0,0 +1,45 @@ +/** + * Copyright © 2016-2021 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.dao.model.sql; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.transport.resource.Resource; + +import javax.persistence.Transient; +import java.io.Serializable; +import java.util.UUID; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class ResourceCompositeKey implements Serializable { + + @Transient + private static final long serialVersionUID = -3789469030818742769L; + + private UUID tenantId; + private String resourceType; + private String resourceId; + + public ResourceCompositeKey(Resource resource) { + this.tenantId = resource.getTenantId().getId(); + this.resourceType = resource.getResourceType().name(); + this.resourceId = resource.getResourceId(); + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceEntity.java new file mode 100644 index 0000000000..a877afa027 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceEntity.java @@ -0,0 +1,77 @@ +/** + * Copyright © 2016-2021 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.dao.model.sql; + +import lombok.Data; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; +import org.thingsboard.server.dao.model.ToData; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.Table; +import java.util.UUID; + +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_ID_COLUMN; +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN; +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TYPE_COLUMN; +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_VALUE_COLUMN; + +@Data +@Entity +@Table(name = RESOURCE_TABLE_NAME) +@IdClass(ResourceCompositeKey.class) +public class ResourceEntity implements ToData { + + @Id + @Column(name = RESOURCE_TENANT_ID_COLUMN, columnDefinition = "uuid") + private UUID tenantId; + + @Id + @Column(name = RESOURCE_TYPE_COLUMN) + private String resourceType; + + @Id + @Column(name = RESOURCE_ID_COLUMN) + private String resourceId; + + @Column(name = RESOURCE_VALUE_COLUMN) + private String value; + + public ResourceEntity() { + } + + public ResourceEntity(Resource resource) { + this.tenantId = resource.getTenantId().getId(); + this.resourceType = resource.getResourceType().name(); + this.resourceId = resource.getResourceId(); + this.value = resource.getValue(); + } + + @Override + public Resource toData() { + Resource resource = new Resource(); + resource.setTenantId(new TenantId(tenantId)); + resource.setResourceType(ResourceType.valueOf(resourceType)); + resource.setResourceId(resourceId); + resource.setValue(value); + return resource; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java new file mode 100644 index 0000000000..84ce22eef1 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java @@ -0,0 +1,90 @@ +/** + * Copyright © 2016-2021 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.dao.resource; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; +import org.thingsboard.server.dao.exception.DataValidationException; + +import java.util.List; + +@Service +@Slf4j +public class BaseResourceService implements ResourceService { + + private final ResourceDao resourceDao; + + public BaseResourceService(ResourceDao resourceDao) { + this.resourceDao = resourceDao; + } + + @Override + public Resource saveResource(Resource resource) { + log.trace("Executing saveResource [{}]", resource); + validate(resource); + return resourceDao.saveResource(resource); + } + + @Override + public Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) { + log.trace("Executing getResource [{}] [{}] [{}]", tenantId, resourceType, resourceId); + validate(tenantId, resourceType, resourceId); + return resourceDao.getResource(tenantId, resourceType, resourceId); + } + + @Override + public boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { + log.trace("Executing deleteResource [{}] [{}] [{}]", tenantId, resourceType, resourceId); + validate(tenantId, resourceType, resourceId); + return resourceDao.deleteResource(tenantId, resourceType, resourceId); + } + + @Override + public List findByTenantId(TenantId tenantId) { + log.trace("Executing findByTenantId [{}]", tenantId); + return resourceDao.findAllByTenantId(tenantId); + } + + protected void validate(Resource resource) { + if (resource == null) { + throw new DataValidationException("Resource should be specified!"); + } + + if (resource.getValue() == null) { + throw new DataValidationException("Resource value should be specified!"); + } + validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId()); + } + + protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) { + if (resourceType == null) { + throw new DataValidationException("Resource type should be specified!"); + } + if (resourceId == null) { + throw new DataValidationException("Resource id should be specified!"); + } + validate(tenantId); + } + + protected void validate(TenantId tenantId) { + if (tenantId == null) { + throw new DataValidationException("Tenant id should be specified!"); + } + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java b/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java new file mode 100644 index 0000000000..f722423412 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java @@ -0,0 +1,33 @@ +/** + * Copyright © 2016-2021 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.dao.resource; + +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; + +import java.util.List; + +public interface ResourceDao { + + Resource saveResource(Resource resource); + + Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); + + boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); + + List findAllByTenantId(TenantId tenantId); +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java new file mode 100644 index 0000000000..b11c14546a --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java @@ -0,0 +1,73 @@ +/** + * Copyright © 2016-2021 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.dao.sql.resource; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; +import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; +import org.thingsboard.server.dao.model.sql.ResourceEntity; +import org.thingsboard.server.dao.resource.ResourceDao; + +import java.util.List; + +@Slf4j +@Component +public class ResourceDaoImpl implements ResourceDao { + + private final ResourceRepository resourceRepository; + + public ResourceDaoImpl(ResourceRepository resourceRepository) { + this.resourceRepository = resourceRepository; + } + + @Override + @Transactional + public Resource saveResource(Resource resource) { + return DaoUtil.getData(resourceRepository.save(new ResourceEntity(resource))); + } + + @Override + public Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) { + ResourceCompositeKey key = new ResourceCompositeKey(); + key.setTenantId(tenantId.getId()); + key.setResourceType(resourceType.name()); + key.setResourceId(resourceId); + + return DaoUtil.getData(resourceRepository.findById(key)); + } + + @Override + @Transactional + public boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { + ResourceCompositeKey key = new ResourceCompositeKey(); + key.setTenantId(tenantId.getId()); + key.setResourceType(resourceType.name()); + key.setResourceId(resourceId); + + resourceRepository.deleteById(key); + return resourceRepository.existsById(key); + } + + @Override + public List findAllByTenantId(TenantId tenantId) { + return DaoUtil.convertDataList(resourceRepository.findAllByTenantId(tenantId)); + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java new file mode 100644 index 0000000000..d2d92b8b55 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2021 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.dao.sql.resource; + +import org.springframework.data.repository.CrudRepository; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; +import org.thingsboard.server.dao.model.sql.ResourceEntity; + +import java.util.List; + +public interface ResourceRepository extends CrudRepository { + + List findAllByTenantId(TenantId tenantId); +} diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 72e00ae85a..3bf5ce29c8 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -447,6 +447,14 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) ); +CREATE TABLE IF NOT EXISTS resource ( + tenant_id uuid NOT NULL, + resource_type varchar(32) NOT NULL, + resource_id varchar(255) NOT NULL, + resource_value varchar, + CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id) +); + CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) LANGUAGE plpgsql AS $$ From bd3185a98fe7049f0f0c02e1e3a0e9585a0ea773 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 5 Mar 2021 17:43:56 +0200 Subject: [PATCH 3/9] added resource support in transport lvl (get resources and "update", "delete" notifications) --- .../server/controller/ResourceController.java | 17 +++--- .../service/install/InstallScripts.java | 5 +- .../service/lwm2m/LwM2MModelsRepository.java | 2 + .../queue/DefaultTbClusterService.java | 29 ++++++++++ .../service/queue/TbClusterService.java | 5 ++ .../transport/DefaultTransportApiService.java | 54 +++++++++++++++++-- .../server/dao/resource/ResourceService.java | 6 ++- .../data/transport/resource/ResourceType.java | 2 +- .../queue/util/TbLwM2mTransportComponent.java | 2 +- common/queue/src/main/proto/queue.proto | 37 +++++++++++++ .../common/transport/TransportService.java | 4 ++ .../service/DefaultTransportService.java | 16 ++++++ .../dao/resource/BaseResourceService.java | 24 +++++---- .../server/dao/resource/ResourceDao.java | 4 +- .../dao/sql/resource/ResourceDaoImpl.java | 10 ++-- .../dao/sql/resource/ResourceRepository.java | 5 +- 16 files changed, 189 insertions(+), 33 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/ResourceController.java b/application/src/main/java/org/thingsboard/server/controller/ResourceController.java index b09e4e23b2..babe444ae7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ResourceController.java @@ -49,8 +49,10 @@ public class ResourceController extends BaseController { @ResponseBody public Resource saveResource(Resource resource) throws ThingsboardException { try { - resource.setTenantId(getCurrentUser().getTenantId()); - return checkNotNull(resourceService.saveResource(resource)); + resource.setTenantId(getTenantId()); + Resource savedResource = checkNotNull(resourceService.saveResource(resource)); + tbClusterService.onResourceChange(savedResource, null); + return savedResource; } catch (Exception e) { throw handleException(e); } @@ -61,7 +63,7 @@ public class ResourceController extends BaseController { @ResponseBody public List getResources(@RequestParam(required = false) boolean system) throws ThingsboardException { try { - return checkNotNull(resourceService.findByTenantId(system ? TenantId.SYS_TENANT_ID : getCurrentUser().getTenantId())); + return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId())); } catch (Exception e) { throw handleException(e); } @@ -70,13 +72,14 @@ public class ResourceController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE) @ResponseBody - public boolean deleteResource(@PathVariable("resourceType") ResourceType resourceType, - @PathVariable("resourceId") String resourceId) throws ThingsboardException { + public void deleteResource(@PathVariable("resourceType") ResourceType resourceType, + @PathVariable("resourceId") String resourceId) throws ThingsboardException { try { - return resourceService.deleteResource(getCurrentUser().getTenantId(), resourceType, resourceId); + Resource resource = checkNotNull(resourceService.getResource(getTenantId(), resourceType, resourceId)); + resourceService.deleteResource(getTenantId(), resourceType, resourceId); + tbClusterService.onResourceDeleted(resource, null); } catch (Exception e) { throw handleException(e); } } - } 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 5029a520e3..2fc832129f 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 @@ -24,7 +24,6 @@ import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.id.CustomerId; 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.oauth2.OAuth2ClientRegistrationTemplate; import org.thingsboard.server.common.data.rule.RuleChain; @@ -206,7 +205,7 @@ public class InstallScripts { resource.setTenantId(TenantId.SYS_TENANT_ID); resource.setResourceType(ResourceType.LWM2M_MODEL); resource.setResourceId(path.getFileName().toString()); - resource.setValue(Files.readString(path)); + resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(path))); resourceService.saveResource(resource); } catch (Exception e) { log.error("Unable to load lwm2m model [{}]", path.toString()); @@ -220,7 +219,7 @@ public class InstallScripts { try { Resource resource = new Resource(); resource.setTenantId(TenantId.SYS_TENANT_ID); - resource.setResourceType(ResourceType.LWM2M_KEY_STORE); + resource.setResourceType(ResourceType.JKS); resource.setResourceId(jksPath.getFileName().toString()); resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath))); resourceService.saveResource(resource); diff --git a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java index 5057893d5c..3db41fff8b 100644 --- a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java @@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; import org.thingsboard.server.dao.service.Validator; +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; import java.math.BigInteger; @@ -61,6 +62,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @Slf4j @Service +@TbLwM2mTransportComponent @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") public class LwM2MModelsRepository { diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java index 133447022b..3405ab28d8 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java @@ -34,6 +34,7 @@ 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.transport.resource.Resource; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.queue.ServiceType; @@ -247,6 +248,34 @@ public class DefaultTbClusterService implements TbClusterService { onEntityDelete(entity.getTenantId(), entity.getId(), entity.getName(), callback); } + @Override + public void onResourceChange(Resource resource, TbQueueCallback callback) { + TenantId tenantId = resource.getTenantId(); + log.trace("[{}][{}][{}] Processing change resource", tenantId, resource.getResourceType(), resource.getResourceId()); + TransportProtos.ResourceUpdateMsg resourceUpdateMsg = TransportProtos.ResourceUpdateMsg.newBuilder() + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) + .setResourceType(resource.getResourceType().name()) + .setResourceId(resource.getResourceId()) + .build(); + ToTransportMsg transportMsg = ToTransportMsg.newBuilder().setResourceUpdateMsg(resourceUpdateMsg).build(); + broadcast(transportMsg, callback); + } + + @Override + public void onResourceDeleted(Resource resource, TbQueueCallback callback) { + TenantId tenantId = resource.getTenantId(); + log.trace("[{}][{}][{}] Processing delete resource", tenantId, resource.getResourceType(), resource.getResourceId()); + TransportProtos.ResourceDeleteMsg resourceUpdateMsg = TransportProtos.ResourceDeleteMsg.newBuilder() + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) + .setResourceType(resource.getResourceType().name()) + .setResourceId(resource.getResourceId()) + .build(); + ToTransportMsg transportMsg = ToTransportMsg.newBuilder().setResourceDeleteMsg(resourceUpdateMsg).build(); + broadcast(transportMsg, callback); + } + public void onEntityChange(TenantId tenantId, EntityId entityid, T entity, TbQueueCallback callback) { String entityName = (entity instanceof HasName) ? ((HasName) entity).getName() : entity.getClass().getName(); log.trace("[{}][{}][{}] Processing [{}] change event", tenantId, entityid.getEntityType(), entityid.getId(), entityName); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java b/application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java index 92401ea9c0..c1cafa3379 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; +import org.thingsboard.server.common.data.transport.resource.Resource; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.gen.transport.TransportProtos; @@ -71,4 +72,8 @@ public interface TbClusterService { void onDeviceChange(Device device, TbQueueCallback callback); void onDeviceDeleted(Device device, TbQueueCallback callback); + + void onResourceChange(Resource resource, TbQueueCallback callback); + + void onResourceDeleted(Resource resource, TbQueueCallback callback); } diff --git a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java index b157e0d0a7..ef6d87e4be 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java @@ -25,6 +25,7 @@ import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -41,6 +42,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; +import org.thingsboard.server.common.data.transport.resource.Resource; +import org.thingsboard.server.common.data.transport.resource.ResourceType; import org.thingsboard.server.common.msg.EncryptionUtil; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; @@ -53,14 +56,15 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException; import org.thingsboard.server.dao.device.provision.ProvisionRequest; import org.thingsboard.server.dao.device.provision.ProvisionResponse; import org.thingsboard.server.dao.relation.RelationService; +import org.thingsboard.server.dao.resource.ResourceService; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; -import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg; +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionResponseStatus; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; @@ -77,11 +81,14 @@ import org.thingsboard.server.service.profile.TbDeviceProfileCache; import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.state.DeviceStateService; +import java.util.Collections; +import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; /** * Created by ashvayka on 05.10.18. @@ -104,6 +111,7 @@ public class DefaultTransportApiService implements TransportApiService { private final TbClusterService tbClusterService; private final DataDecodingEncodingService dataDecodingEncodingService; private final DeviceProvisionService deviceProvisionService; + private final ResourceService resourceService; private final ConcurrentMap deviceCreationLocks = new ConcurrentHashMap<>(); @@ -112,7 +120,7 @@ public class DefaultTransportApiService implements TransportApiService { RelationService relationService, DeviceCredentialsService deviceCredentialsService, DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService, TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService, - DeviceProvisionService deviceProvisionService) { + DeviceProvisionService deviceProvisionService, ResourceService resourceService) { this.deviceProfileCache = deviceProfileCache; this.tenantProfileCache = tenantProfileCache; this.apiUsageStateService = apiUsageStateService; @@ -124,6 +132,7 @@ public class DefaultTransportApiService implements TransportApiService { this.tbClusterService = tbClusterService; this.dataDecodingEncodingService = dataDecodingEncodingService; this.deviceProvisionService = deviceProvisionService; + this.resourceService = resourceService; } @Override @@ -157,6 +166,9 @@ public class DefaultTransportApiService implements TransportApiService { } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); + } else if (transportApiRequestMsg.hasResourcesRequestMsg()) { + return Futures.transform(handle(transportApiRequestMsg.getResourcesRequestMsg()), + value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); } return Futures.transform(getEmptyTransportApiResponseFuture(), value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); @@ -315,9 +327,9 @@ public class DefaultTransportApiService implements TransportApiService { return TransportApiResponseMsg.newBuilder().setProvisionDeviceResponseMsg(TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()).build(); } TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = TransportProtos.ProvisionDeviceResponseMsg.newBuilder() - .setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name())) - .setStatus(status); - switch (deviceCredentials.getCredentialsType()){ + .setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name())) + .setStatus(status); + switch (deviceCredentials.getCredentialsType()) { case ACCESS_TOKEN: provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId()); break; @@ -353,6 +365,38 @@ public class DefaultTransportApiService implements TransportApiService { return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); } + private ListenableFuture handle(GetResourcesRequestMsg requestMsg) { + TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); + TransportProtos.GetResourcesResponseMsg.Builder builder = TransportProtos.GetResourcesResponseMsg.newBuilder(); + String resourceType = requestMsg.getResourceType(); + String resourceId = requestMsg.getResourceId(); + + List resources; + + if (resourceType != null && resourceId != null) { + resources = Collections.singletonList(toProto( + resourceService.getResource(tenantId, ResourceType.valueOf(resourceType), resourceId))); + } else { + resources = resourceService.findResourcesByTenantId(tenantId) + .stream() + .map(this::toProto) + .collect(Collectors.toList()); + } + + builder.addAllResources(resources); + return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourcesResponseMsg(builder).build()); + } + + private TransportProtos.ResourceMsg toProto(Resource resource) { + return TransportProtos.ResourceMsg.newBuilder() + .setTenantIdMSB(resource.getTenantId().getId().getMostSignificantBits()) + .setTenantIdLSB(resource.getTenantId().getId().getLeastSignificantBits()) + .setResourceType(resource.getResourceType().name()) + .setResourceId(resource.getResourceId()) + .setValue(resource.getValue()) + .build(); + } + private ListenableFuture getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> { if (device == null) { diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java index 99cf1ef87b..03b6976de8 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java @@ -27,7 +27,9 @@ public interface ResourceService { Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); - boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); + List findResourcesByTenantId(TenantId tenantId); - List findByTenantId(TenantId tenantId); + void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); + + void deleteResourcesByTenantId(TenantId tenantId); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java index 2e12bbdda2..c43f1997da 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java @@ -16,5 +16,5 @@ package org.thingsboard.server.common.data.transport.resource; public enum ResourceType { - LWM2M_MODEL, LWM2M_KEY_STORE + LWM2M_MODEL, JKS, PKCS_12 } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java b/common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java index 3bc4d494f2..638f9f6fb2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java @@ -21,6 +21,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") +@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") public @interface TbLwM2mTransportComponent { } diff --git a/common/queue/src/main/proto/queue.proto b/common/queue/src/main/proto/queue.proto index d5f440d808..42f6267d42 100644 --- a/common/queue/src/main/proto/queue.proto +++ b/common/queue/src/main/proto/queue.proto @@ -201,6 +201,25 @@ message LwM2MResponseMsg { LwM2MRegistrationResponseMsg registrationMsg = 1; } +message ResourceMsg { + int64 tenantIdMSB = 1; + int64 tenantIdLSB = 2; + string resourceType = 3; + string resourceId = 4; + string value = 5; +} + +message GetResourcesRequestMsg { + int64 tenantIdMSB = 1; + int64 tenantIdLSB = 2; + string resourceType = 3; + string resourceId = 4; +} + +message GetResourcesResponseMsg { + repeated ResourceMsg resources = 1; +} + message ValidateDeviceLwM2MCredentialsRequestMsg { string credentialsId = 1; } @@ -242,6 +261,20 @@ message EntityDeleteMsg { int64 entityIdLSB = 3; } +message ResourceUpdateMsg { + int64 tenantIdMSB = 1; + int64 tenantIdLSB = 2; + string resourceType = 3; + string resourceId = 4; +} + +message ResourceDeleteMsg { + int64 tenantIdMSB = 1; + int64 tenantIdLSB = 2; + string resourceType = 3; + string resourceId = 4; +} + message SessionCloseNotificationProto { string message = 1; } @@ -525,6 +558,7 @@ message TransportApiRequestMsg { ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; + GetResourcesRequestMsg resourcesRequestMsg = 9; } /* Response from ThingsBoard Core Service to Transport Service */ @@ -534,6 +568,7 @@ message TransportApiResponseMsg { GetEntityProfileResponseMsg entityProfileResponseMsg = 3; ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; LwM2MResponseMsg lwM2MResponseMsg = 6; + GetResourcesResponseMsg resourcesResponseMsg = 7; } /* Messages that are handled by ThingsBoard Core Service */ @@ -578,6 +613,8 @@ message ToTransportMsg { EntityDeleteMsg entityDeleteMsg = 9; ProvisionDeviceResponseMsg provisionResponse = 10; ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11; + ResourceUpdateMsg resourceUpdateMsg = 12; + ResourceDeleteMsg resourceDeleteMsg = 13; } message UsageStatsKVProto{ diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java index e642e7f7b2..ab728af00d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java @@ -25,6 +25,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestM import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg; +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; @@ -51,6 +53,8 @@ public interface TransportService { GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg); + GetResourcesResponseMsg getResources(GetResourcesRequestMsg msg); + void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, TransportServiceCallback callback); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index 473eeea42c..ed02f7016c 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -254,6 +254,18 @@ public class DefaultTransportService implements TransportService { } } + @Override + public TransportProtos.GetResourcesResponseMsg getResources(TransportProtos.GetResourcesRequestMsg msg) { + TbProtoQueueMsg protoMsg = + new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setResourcesRequestMsg(msg).build()); + try { + TbProtoQueueMsg response = transportApiRequestTemplate.send(protoMsg).get(); + return response.getValue().getResourcesResponseMsg(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + @Override public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, TransportServiceCallback callback) { @@ -688,6 +700,10 @@ public class DefaultTransportService implements TransportService { } else if (EntityType.DEVICE.equals(entityType)) { rateLimitService.remove(new DeviceId(entityUuid)); } + } else if (toSessionMsg.hasResourceUpdateMsg()) { + //TODO: update resource cache + } else if (toSessionMsg.hasResourceDeleteMsg()) { + //TODO: remove resource from cache } else { //TODO: should we notify the device actor about missed session? log.debug("[{}] Missing session.", sessionId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java index 84ce22eef1..55394c7266 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java @@ -24,6 +24,9 @@ import org.thingsboard.server.dao.exception.DataValidationException; import java.util.List; +import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; +import static org.thingsboard.server.dao.service.Validator.validateId; + @Service @Slf4j public class BaseResourceService implements ResourceService { @@ -49,18 +52,26 @@ public class BaseResourceService implements ResourceService { } @Override - public boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { + public void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { log.trace("Executing deleteResource [{}] [{}] [{}]", tenantId, resourceType, resourceId); validate(tenantId, resourceType, resourceId); - return resourceDao.deleteResource(tenantId, resourceType, resourceId); + resourceDao.deleteResource(tenantId, resourceType, resourceId); } @Override - public List findByTenantId(TenantId tenantId) { + public List findResourcesByTenantId(TenantId tenantId) { log.trace("Executing findByTenantId [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); return resourceDao.findAllByTenantId(tenantId); } + @Override + public void deleteResourcesByTenantId(TenantId tenantId) { + log.trace("Executing deleteDevicesByTenantId, tenantId [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + resourceDao.removeAllByTenantId(tenantId); + } + protected void validate(Resource resource) { if (resource == null) { throw new DataValidationException("Resource should be specified!"); @@ -79,12 +90,7 @@ public class BaseResourceService implements ResourceService { if (resourceId == null) { throw new DataValidationException("Resource id should be specified!"); } - validate(tenantId); + validateId(tenantId, "Incorrect tenantId "); } - protected void validate(TenantId tenantId) { - if (tenantId == null) { - throw new DataValidationException("Tenant id should be specified!"); - } - } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java b/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java index f722423412..a053bc0c74 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java @@ -27,7 +27,9 @@ public interface ResourceDao { Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); - boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); + void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); List findAllByTenantId(TenantId tenantId); + + void removeAllByTenantId(TenantId tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java index b11c14546a..0cf9fce980 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java @@ -56,18 +56,22 @@ public class ResourceDaoImpl implements ResourceDao { @Override @Transactional - public boolean deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { + public void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { ResourceCompositeKey key = new ResourceCompositeKey(); key.setTenantId(tenantId.getId()); key.setResourceType(resourceType.name()); key.setResourceId(resourceId); resourceRepository.deleteById(key); - return resourceRepository.existsById(key); } @Override public List findAllByTenantId(TenantId tenantId) { - return DaoUtil.convertDataList(resourceRepository.findAllByTenantId(tenantId)); + return DaoUtil.convertDataList(resourceRepository.findAllByTenantId(tenantId.getId())); + } + + @Override + public void removeAllByTenantId(TenantId tenantId) { + resourceRepository.removeAllByTenantId(tenantId.getId()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java index d2d92b8b55..65927ce26e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java @@ -21,8 +21,11 @@ import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; import org.thingsboard.server.dao.model.sql.ResourceEntity; import java.util.List; +import java.util.UUID; public interface ResourceRepository extends CrudRepository { - List findAllByTenantId(TenantId tenantId); + List findAllByTenantId(UUID tenantId); + + void removeAllByTenantId(UUID tenantId); } From 616839a23c4accfe6a5e122213fa21d672148f96 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 5 Mar 2021 18:05:47 +0200 Subject: [PATCH 4/9] refactoring --- .../thingsboard/server/service/lwm2m/LwM2MModelsRepository.java | 1 - .../server/common/transport/service/DefaultTransportService.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java index 3db41fff8b..ddadc6c95c 100644 --- a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java @@ -62,7 +62,6 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @Slf4j @Service -@TbLwM2mTransportComponent @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") public class LwM2MModelsRepository { diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index ed02f7016c..b273ee48cf 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -711,6 +711,7 @@ public class DefaultTransportService implements TransportService { } } + public void onProfileUpdate(DeviceProfile deviceProfile) { long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits(); long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits(); From c78bd55df5c866125b156d1841fc58dd41262f69 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 5 Mar 2021 19:10:44 +0200 Subject: [PATCH 5/9] added resource table to hsql schema --- .../thingsboard/server/dao/tenant/TenantServiceImpl.java | 5 +++++ dao/src/main/resources/sql/schema-entities-hsql.sql | 8 ++++++++ dao/src/test/resources/sql/hsql/drop-all-tables.sql | 1 + dao/src/test/resources/sql/psql/drop-all-tables.sql | 3 ++- 4 files changed, 16 insertions(+), 1 deletion(-) 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 12fdd3a57a..3016474f27 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 @@ -35,6 +35,7 @@ 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.resource.ResourceService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; @@ -88,6 +89,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @Autowired private RuleChainService ruleChainService; + @Autowired + private ResourceService resourceService; + @Override public Tenant findTenantById(TenantId tenantId) { log.trace("Executing findTenantById [{}]", tenantId); @@ -140,6 +144,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe userService.deleteTenantAdmins(tenantId); ruleChainService.deleteRuleChainsByTenantId(tenantId); apiUsageStateService.deleteApiUsageStateByTenantId(tenantId); + resourceService.deleteResourcesByTenantId(tenantId); tenantDao.removeById(tenantId, tenantId.getId()); deleteEntityRelations(tenantId, tenantId); } diff --git a/dao/src/main/resources/sql/schema-entities-hsql.sql b/dao/src/main/resources/sql/schema-entities-hsql.sql index ee658f8da4..787f457c6a 100644 --- a/dao/src/main/resources/sql/schema-entities-hsql.sql +++ b/dao/src/main/resources/sql/schema-entities-hsql.sql @@ -420,3 +420,11 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( sms_exec varchar(32), CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) ); + +CREATE TABLE IF NOT EXISTS resource ( + tenant_id uuid NOT NULL, + resource_type varchar(32) NOT NULL, + resource_id varchar(255) NOT NULL, + resource_value varchar, + CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id) +); diff --git a/dao/src/test/resources/sql/hsql/drop-all-tables.sql b/dao/src/test/resources/sql/hsql/drop-all-tables.sql index b5629b0560..a548ceec30 100644 --- a/dao/src/test/resources/sql/hsql/drop-all-tables.sql +++ b/dao/src/test/resources/sql/hsql/drop-all-tables.sql @@ -28,4 +28,5 @@ DROP TABLE IF EXISTS oauth2_client_registration; DROP TABLE IF EXISTS oauth2_client_registration_info; DROP TABLE IF EXISTS oauth2_client_registration_template; DROP TABLE IF EXISTS api_usage_state; +DROP TABLE IF EXISTS resource; DROP FUNCTION IF EXISTS to_uuid; diff --git a/dao/src/test/resources/sql/psql/drop-all-tables.sql b/dao/src/test/resources/sql/psql/drop-all-tables.sql index 34985883d7..333ce03fba 100644 --- a/dao/src/test/resources/sql/psql/drop-all-tables.sql +++ b/dao/src/test/resources/sql/psql/drop-all-tables.sql @@ -28,4 +28,5 @@ DROP TABLE IF EXISTS tb_schema_settings; DROP TABLE IF EXISTS oauth2_client_registration; DROP TABLE IF EXISTS oauth2_client_registration_info; DROP TABLE IF EXISTS oauth2_client_registration_template; -DROP TABLE IF EXISTS api_usage_state; \ No newline at end of file +DROP TABLE IF EXISTS api_usage_state; +DROP TABLE IF EXISTS resource; From 65f4ca58001a3a71fdf7a654b53cd47122f1d44c Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Mon, 8 Mar 2021 00:00:44 +0200 Subject: [PATCH 6/9] Lwm2m: back: add tenantId and repositoryTenant - test --- .../install/SqlDatabaseUpgradeService.java | 1 + .../service/lwm2m/LwM2MModelsRepository.java | 5 +- ...TransportBootstrapServerConfiguration.java | 2 +- .../lwm2m/server/LwM2mTransportHandler.java | 5 +- .../LwM2mTransportServerConfiguration.java | 8 +- .../server/LwM2mTransportServiceImpl.java | 2 + .../server/LwM2mVersionedModelProvider.java | 98 +++++++++++++++++++ .../server/client/LwM2mClientProfile.java | 12 ++- .../lwm2m/utils/LwM2mValueConverterImpl.java | 9 +- .../lwm2m/LwM2MTransportConfigServer.java | 18 ++-- 10 files changed, 140 insertions(+), 20 deletions(-) create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java 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 a56cc7ca25..2525ebd186 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 @@ -447,6 +447,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService " );"); conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3003000;"); + installScripts.loadSystemLwm2mResources(); } catch (Exception e) { log.error("Failed updating schema!!!", e); } diff --git a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java index ddadc6c95c..228562a039 100644 --- a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java @@ -33,7 +33,6 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; import org.thingsboard.server.dao.service.Validator; -import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; import java.math.BigInteger; @@ -102,8 +101,8 @@ public class LwM2MModelsRepository { */ private List getLwm2mObjects(Predicate predicate, String sortProperty, String sortOrder) { List lwM2mObjects = new ArrayList<>(); - List listObjects = (predicate == null) ? this.contextServer.getModelsValue() : - contextServer.getModelsValue().stream() + List listObjects = (predicate == null) ? this.contextServer.getModelsValueCommon() : + contextServer.getModelsValueCommon().stream() .filter(predicate) .collect(Collectors.toList()); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java index 757b91956b..59e1087f21 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java @@ -94,7 +94,7 @@ public class LwM2MTransportBootstrapServerConfiguration { builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); /** Define model provider (Create Models )*/ - builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValue())); + builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon())); /** Create credentials */ this.setServerWithCredentials(builder); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java index a62bdf2a49..9b99403c7c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java @@ -188,8 +188,9 @@ public class LwM2mTransportHandler { return null; } - public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData) { + public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, String tenantId) { LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile(); + lwM2MClientProfile.setTenantId(tenantId); lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject()); lwM2MClientProfile.setPostKeyNameProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).getAsJsonObject()); lwM2MClientProfile.setPostAttributeProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).getAsJsonArray()); @@ -221,7 +222,7 @@ public class LwM2mTransportHandler { ObjectMapper mapper = new ObjectMapper(); String profileStr = mapper.writeValueAsString(profile); JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; - return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson) : null; + return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId().getId().toString()) : null; } catch (IOException e) { log.error("", e); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java index ace2fb4896..5c4b0af2d0 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java @@ -24,7 +24,6 @@ import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.californium.LeshanServerBuilder; import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; import org.eclipse.leshan.server.model.LwM2mModelProvider; -import org.eclipse.leshan.server.model.VersionedModelProvider; import org.eclipse.leshan.server.security.DefaultAuthorizer; import org.eclipse.leshan.server.security.EditableSecurityStore; import org.eclipse.leshan.server.security.SecurityChecker; @@ -32,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import java.math.BigInteger; @@ -77,6 +77,9 @@ public class LwM2mTransportServerConfiguration { @Autowired private EditableSecurityStore securityStore; + @Autowired + private LwM2mClientContext lwM2mClientContext;; + @Bean public LeshanServer getLeshanServer() { log.info("Starting LwM2M transport Server... PostConstruct"); @@ -95,7 +98,8 @@ public class LwM2mTransportServerConfiguration { builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); /** Define model provider (Create Models )*/ - LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValue()); +// LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueCommon()); + LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueServer(), this.lwM2mClientContext); builder.setObjectModelProvider(modelProvider); /** Create credentials */ diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java index 548d750a3f..43bd9d8022 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java @@ -153,6 +153,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { executorRegistered.submit(() -> { try { log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId()); + ((LwM2mVersionedModelProvider)leshanServer.getModelProvider()).setRepository(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelsValueCommon()); +// (((VersionedModelProvider) (leshanServer)).modelProvider).repository; LwM2mClient lwM2MClient = this.lwM2mClientContext.updateInSessionsLwM2MClient(registration); if (lwM2MClient != null) { SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java new file mode 100644 index 0000000000..b426b8fa93 --- /dev/null +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java @@ -0,0 +1,98 @@ +package org.thingsboard.server.transport.lwm2m.server; + +import org.eclipse.leshan.core.model.LwM2mModel; +import org.eclipse.leshan.core.model.LwM2mModelRepository; +import org.eclipse.leshan.core.model.ObjectModel; +import org.eclipse.leshan.core.model.ResourceModel; +import org.eclipse.leshan.server.model.LwM2mModelProvider; +import org.eclipse.leshan.server.registration.Registration; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class LwM2mVersionedModelProvider implements LwM2mModelProvider { + + private LwM2mModelRepository repository; + private Map repositoriesTenant; + private LwM2mClientContext lwM2mClientContext; + + public LwM2mVersionedModelProvider(Collection objectModels, LwM2mClientContext lwM2mClientContext) { + this.repository = new LwM2mModelRepository(objectModels); + this.lwM2mClientContext = lwM2mClientContext; + this.repositoriesTenant = new ConcurrentHashMap<>(); + } + + public LwM2mVersionedModelProvider(LwM2mModelRepository repository, LwM2mClientContext lwM2mClientContext) { + this.repository = repository; + this.lwM2mClientContext = lwM2mClientContext; + this.repositoriesTenant = new ConcurrentHashMap<>(); + } + + public void setRepositoriesTenant (String tenantID, LwM2mModelRepository repositoryTenant) { + this.repositoriesTenant.put(tenantID, repositoryTenant); + } + + public LwM2mModelRepository getRepositoriesTenant (String tenantID) { + return this.repositoriesTenant.get(tenantID); + } + + public void setRepository (Collection objectModels) { + this.repository = new LwM2mModelRepository(objectModels); + } + + public LwM2mModelRepository getRepositoriesCommonTenant (String tenantID) { + LwM2mModelRepository repository = new LwM2mModelRepository(); + + return repository; + } + + @Override + public LwM2mModel getObjectModel(Registration registration) { + return new DynamicModel(registration, this.lwM2mClientContext.getProfile(registration).getTenantId()); + } + + private class DynamicModel implements LwM2mModel { + + private final Registration registration; + private final String tenantId; + + public DynamicModel(Registration registration, String tenantId) { + this.registration = registration; + this.tenantId = tenantId; + } + + @Override + public ResourceModel getResourceModel(int objectId, int resourceId) { + ObjectModel objectModel = getObjectModel(objectId); + if (objectModel != null) + return objectModel.resources.get(resourceId); + else + return null; + } + + @Override + public ObjectModel getObjectModel(int objectId) { + String version = registration.getSupportedVersion(objectId); + if (version != null) { + return repository.getObjectModel(objectId, version); + } + return null; + } + + @Override + public Collection getObjectModels() { + Map supportedObjects = registration.getSupportedObject(); + Collection result = new ArrayList<>(supportedObjects.size()); + for (Map.Entry supportedObject : supportedObjects.entrySet()) { + ObjectModel objectModel = repository.getObjectModel(supportedObject.getKey(), + supportedObject.getValue()); + if (objectModel != null) + result.add(objectModel); + } + return result; + } + } +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java index 810ea253a7..1e2df43b5d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java @@ -22,12 +22,14 @@ import lombok.Data; @Data public class LwM2mClientProfile { + + private String tenantId; /** * {"clientLwM2mSettings": { * clientUpdateValueAfterConnect: false; * } **/ - JsonObject postClientLwM2mSettings; + private JsonObject postClientLwM2mSettings; /** * {"keyName": { @@ -36,22 +38,22 @@ public class LwM2mClientProfile { * "/3/0/2": "serialNumber" * } **/ - JsonObject postKeyNameProfile; + private JsonObject postKeyNameProfile; /** * [ "/2/0/0", "/2/0/1"] */ - JsonArray postAttributeProfile; + private JsonArray postAttributeProfile; /** * [ "/2/0/0", "/2/0/1"] */ - JsonArray postTelemetryProfile; + private JsonArray postTelemetryProfile; /** * [ "/2/0/0", "/2/0/1"] */ - JsonArray postObserveProfile; + private JsonArray postObserveProfile; public LwM2mClientProfile clone() { LwM2mClientProfile lwM2mClientProfile = new LwM2mClientProfile(); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java index 67ce459d9b..136de3eb95 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java @@ -26,6 +26,7 @@ import org.eclipse.leshan.core.util.StringUtils; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; +import java.math.BigInteger; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @@ -130,7 +131,13 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { return String.valueOf(value); case TIME: String DATE_FORMAT = "MMM d, yyyy HH:mm a"; - Long timeValue = ((Date) value).getTime(); + Long timeValue; + try { + timeValue = ((Date) value).getTime(); + } + catch (Exception e){ + timeValue = new BigInteger((byte [])value).longValue(); + } DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); return formatter.format(new Date(timeValue)); default: diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java index 810848a5ca..4f3e0a8c9c 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java @@ -84,7 +84,11 @@ public class LwM2MTransportConfigServer { @Getter @Setter - private List modelsValue; + private List modelsValueCommon; + + @Getter + @Setter + private List modelsValueServer; @Getter @Value("${transport.lwm2m.timeout:}") @@ -188,11 +192,13 @@ public class LwM2MTransportConfigServer { @PostConstruct public void init() { - modelsValue = ObjectLoader.loadDefault(); + modelsValueServer = ObjectLoader.loadDefault(); + modelsValueServer.remove(3); + modelsValueCommon = ObjectLoader.loadDefault(); File path = getPathModels(); if (path.isDirectory()) { try { - modelsValue.addAll(ObjectLoader.loadObjectsFromDir(path)); + modelsValueCommon.addAll(ObjectLoader.loadObjectsFromDir(path)); log.info(" [{}] Models directory is a directory", path.getAbsoluteFile()); } catch (Exception e) { log.error(" [{}] Could not parse the resource definition file", e.toString()); @@ -255,9 +261,9 @@ public class LwM2MTransportConfigServer { public ResourceModel getResourceModel(Registration registration, LwM2mPath pathIds) { String pathLink = "/" + pathIds.getObjectId() + "/" + pathIds.getObjectInstanceId(); return (Arrays.stream(registration.getObjectLinks()).filter(p-> p.getUrl().equals(pathLink)).findFirst().isPresent() && - this.modelsValue.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).size() > 0) && - this.modelsValue.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0).resources.containsKey(pathIds.getResourceId()) ? - this.modelsValue.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0).resources.get(pathIds.getResourceId()) : + this.modelsValueCommon.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).size() > 0) && + this.modelsValueCommon.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0).resources.containsKey(pathIds.getResourceId()) ? + this.modelsValueCommon.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0).resources.get(pathIds.getResourceId()) : null; } From 447bf05b7b9bd3e3d37bc53d42780b613d3a4ea9 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Mon, 8 Mar 2021 19:24:33 +0200 Subject: [PATCH 7/9] Lwm2m: back: add tenantId and repositoryTenant - test2 --- .../server/controller/ResourceController.java | 12 +++++ .../transport/DefaultTransportApiService.java | 7 ++- .../server/dao/resource/ResourceService.java | 2 + .../server/LwM2mTransportContextServer.java | 44 ++++++++++++++++--- .../lwm2m/server/LwM2mTransportHandler.java | 5 ++- .../lwm2m/server/LwM2mTransportRequest.java | 10 +++-- .../LwM2mTransportServerConfiguration.java | 4 ++ .../server/LwM2mVersionedModelProvider.java | 20 ++++++++- .../server/client/LwM2mClientContextImpl.java | 3 +- .../server/client/LwM2mClientProfile.java | 4 +- .../lwm2m/LwM2MTransportConfigServer.java | 4 +- .../dao/resource/BaseResourceService.java | 7 +++ .../server/dao/resource/ResourceDao.java | 2 + .../dao/sql/resource/ResourceDaoImpl.java | 5 +++ .../dao/sql/resource/ResourceRepository.java | 3 +- 15 files changed, 113 insertions(+), 19 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/ResourceController.java b/application/src/main/java/org/thingsboard/server/controller/ResourceController.java index babe444ae7..b1c709a811 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ResourceController.java @@ -69,6 +69,18 @@ public class ResourceController extends BaseController { } } + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/resource/{resourceType}", method = RequestMethod.GET) + @ResponseBody + public List getResources(@RequestParam(required = false) boolean system, + @PathVariable("resourceType") ResourceType resourceType) throws ThingsboardException { + try { + return checkNotNull(resourceService.findResourcesByTenantIdResourceType(system ? TenantId.SYS_TENANT_ID : getTenantId(), resourceType)); + } catch (Exception e) { + throw handleException(e); + } + } + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java index ef6d87e4be..21a96c1bf9 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java @@ -373,9 +373,14 @@ public class DefaultTransportApiService implements TransportApiService { List resources; - if (resourceType != null && resourceId != null) { + if (resourceType != null && resourceId != null && !resourceId.isEmpty()) { resources = Collections.singletonList(toProto( resourceService.getResource(tenantId, ResourceType.valueOf(resourceType), resourceId))); + } else if (resourceType != null && !resourceType.isEmpty()) { + resources = resourceService.findResourcesByTenantIdResourceType(tenantId, ResourceType.valueOf(resourceType)) + .stream() + .map(this::toProto) + .collect(Collectors.toList()); } else { resources = resourceService.findResourcesByTenantId(tenantId) .stream() diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java index 03b6976de8..e88b276d1c 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java @@ -29,6 +29,8 @@ public interface ResourceService { List findResourcesByTenantId(TenantId tenantId); + List findResourcesByTenantIdResourceType(TenantId tenantId, ResourceType resourceType); + void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); void deleteResourcesByTenantId(TenantId tenantId); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java index 062c0f1148..3dd73ae620 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java @@ -34,16 +34,25 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.ObjectModel; import org.springframework.stereotype.Component; import org.thingsboard.server.common.transport.TransportContext; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.common.transport.adaptor.AdaptorException; import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; -import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg; +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesResponseMsg; +import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; +import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; +import java.util.List; +import java.util.UUID; + import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; @Slf4j @@ -56,6 +65,8 @@ public class LwM2mTransportContextServer extends TransportContext { private final TransportService transportService; + private List modelsValueServer; + @Getter private final LwM2MJsonAdaptor adaptor; @@ -89,14 +100,14 @@ public class LwM2mTransportContextServer extends TransportContext { }; } - public void sentParametersOnThingsboard(JsonElement msg, String topicName, TransportProtos.SessionInfoProto sessionInfo) { + public void sentParametersOnThingsboard(JsonElement msg, String topicName, SessionInfoProto sessionInfo) { try { if (topicName.equals(LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) { - TransportProtos.PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg); + PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg); TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(postAttributeMsg); transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSentAttrTelemetry(call)); } else if (topicName.equals(LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC)) { - TransportProtos.PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg); + PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg); TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(postTelemetryMsg); transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSentAttrTelemetry(call)); } @@ -115,8 +126,8 @@ public class LwM2mTransportContextServer extends TransportContext { /** * @return - sessionInfo after access connect client */ - public TransportProtos.SessionInfoProto getValidateSessionInfo(TransportProtos.ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { - return TransportProtos.SessionInfoProto.newBuilder() + public SessionInfoProto getValidateSessionInfo(ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { + return SessionInfoProto.newBuilder() .setNodeId(this.getNodeId()) .setSessionIdMSB(mostSignificantBits) .setSessionIdLSB(leastSignificantBits) @@ -131,4 +142,25 @@ public class LwM2mTransportContextServer extends TransportContext { .build(); } + + + + /** + * ResourcesRequestMsg + * + * @param resourceType + * @return + */ + public GetResourcesResponseMsg getResourceTenant (UUID tenantId, String resourceType) { + + GetResourcesResponseMsg responseMsg = + this.getTransportService() + .getResources(GetResourcesRequestMsg.newBuilder() + .setResourceType(resourceType) + .setTenantIdLSB(tenantId.getLeastSignificantBits()) + .setTenantIdMSB(tenantId.getMostSignificantBits()) + .build()); + return responseMsg; + } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java index 9b99403c7c..150fe9b5d0 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java @@ -45,6 +45,7 @@ import java.util.Arrays; import java.util.Date; import java.util.LinkedList; import java.util.Optional; +import java.util.UUID; @Slf4j //@Component("LwM2MTransportHandler") @@ -188,7 +189,7 @@ public class LwM2mTransportHandler { return null; } - public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, String tenantId) { + public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, UUID tenantId) { LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile(); lwM2MClientProfile.setTenantId(tenantId); lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject()); @@ -222,7 +223,7 @@ public class LwM2mTransportHandler { ObjectMapper mapper = new ObjectMapper(); String profileStr = mapper.writeValueAsString(profile); JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; - return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId().getId().toString()) : null; + return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId().getId()) : null; } catch (IOException e) { log.error("", e); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java index b05c79d6db..fc14b9c080 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java @@ -47,7 +47,6 @@ import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.core.util.NamedThreadFactory; import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.registration.Registration; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; @@ -88,13 +87,16 @@ public class LwM2mTransportRequest { private final LeshanServer leshanServer; - @Autowired - private LwM2mTransportServiceImpl serviceImpl; +// @Autowired +// private LwM2mTransportServiceImpl serviceImpl; - public LwM2mTransportRequest(LwM2mTransportContextServer context, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer) { + private final LwM2mTransportServiceImpl serviceImpl; + + public LwM2mTransportRequest(LwM2mTransportContextServer context, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) { this.context = context; this.lwM2mClientContext = lwM2mClientContext; this.leshanServer = leshanServer; + this.serviceImpl = serviceImpl; } @PostConstruct diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java index 5c4b0af2d0..56cf6b5c2e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java @@ -30,6 +30,9 @@ import org.eclipse.leshan.server.security.SecurityChecker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.ResourceType; +import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; @@ -98,6 +101,7 @@ public class LwM2mTransportServerConfiguration { builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); /** Define model provider (Create Models )*/ + TransportProtos.GetResourcesResponseMsg responseMsg= this.context.getResourceTenant(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); // LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueCommon()); LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueServer(), this.lwM2mClientContext); builder.setObjectModelProvider(modelProvider); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java index b426b8fa93..64e9f67199 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2021 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.transport.lwm2m.server; import org.eclipse.leshan.core.model.LwM2mModel; @@ -11,6 +26,7 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -57,9 +73,9 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { private class DynamicModel implements LwM2mModel { private final Registration registration; - private final String tenantId; + private final UUID tenantId; - public DynamicModel(Registration registration, String tenantId) { + public DynamicModel(Registration registration, UUID tenantId) { this.registration = registration; this.tenantId = tenantId; } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index b965c99611..b41e7cfdaa 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.transport.lwm2m.server.client; -import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.EditableSecurityStore; import org.springframework.stereotype.Service; @@ -105,6 +104,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { /** * Add new LwM2MClient to session + * * @param identity- * @return SecurityInfo. If error - SecurityInfoError * and log: @@ -168,4 +168,5 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { } return false; } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java index 1e2df43b5d..dcda2cc62b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java @@ -20,10 +20,12 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Data; +import java.util.UUID; + @Data public class LwM2mClientProfile { - private String tenantId; + private UUID tenantId; /** * {"clientLwM2mSettings": { * clientUpdateValueAfterConnect: false; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java index 4f3e0a8c9c..4e57e61190 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java @@ -47,7 +47,6 @@ import java.util.stream.Collectors; @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") public class LwM2MTransportConfigServer { - @Getter private String MODEL_PATH_DEFAULT = "models"; @@ -190,6 +189,8 @@ public class LwM2MTransportConfigServer { @Value("${transport.lwm2m.server.secure.alias:}") private String serverAlias; + + @PostConstruct public void init() { modelsValueServer = ObjectLoader.loadDefault(); @@ -276,4 +277,5 @@ public class LwM2MTransportConfigServer { ResourceModel resource = this.getResourceModel(registration, pathIds); return (resource == null) ? ResourceModel.Operations.NONE : resource.operations; } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java index 55394c7266..c33c1b1b7e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java @@ -65,6 +65,13 @@ public class BaseResourceService implements ResourceService { return resourceDao.findAllByTenantId(tenantId); } + @Override + public List findResourcesByTenantIdResourceType(TenantId tenantId, ResourceType resourceType) { + log.trace("Executing findByTenantId [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + return resourceDao.findAllByTenantIdResourceType(tenantId, resourceType); + } + @Override public void deleteResourcesByTenantId(TenantId tenantId) { log.trace("Executing deleteDevicesByTenantId, tenantId [{}]", tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java b/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java index a053bc0c74..defca18533 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java @@ -31,5 +31,7 @@ public interface ResourceDao { List findAllByTenantId(TenantId tenantId); + List findAllByTenantIdResourceType(TenantId tenantId, ResourceType resourceType); + void removeAllByTenantId(TenantId tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java index 0cf9fce980..e1137562da 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java @@ -70,6 +70,11 @@ public class ResourceDaoImpl implements ResourceDao { return DaoUtil.convertDataList(resourceRepository.findAllByTenantId(tenantId.getId())); } + @Override + public List findAllByTenantIdResourceType(TenantId tenantId, ResourceType resourceType) { + return DaoUtil.convertDataList(resourceRepository.findAllByTenantIdAndResourceType(tenantId.getId(), resourceType.name())); + } + @Override public void removeAllByTenantId(TenantId tenantId) { resourceRepository.removeAllByTenantId(tenantId.getId()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java index 65927ce26e..49cc71b972 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.sql.resource; import org.springframework.data.repository.CrudRepository; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; import org.thingsboard.server.dao.model.sql.ResourceEntity; @@ -27,5 +26,7 @@ public interface ResourceRepository extends CrudRepository findAllByTenantId(UUID tenantId); + List findAllByTenantIdAndResourceType(UUID tenantId, String resourceType); + void removeAllByTenantId(UUID tenantId); } From d8ea6ac37d568bb31be72fa4115e15e1691d2789 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 9 Mar 2021 11:08:51 +0200 Subject: [PATCH 8/9] Lwm2m: back: add tenantId and repositoryTenant - test3 --- .../server/LwM2mTransportContextServer.java | 38 ++++++++++++++++++- .../LwM2mTransportServerConfiguration.java | 3 +- .../server/LwM2mTransportServiceImpl.java | 7 +++- .../common/transport/TransportService.java | 5 ++- .../service/DefaultTransportService.java | 12 +++++- 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java index 3dd73ae620..bc7737aebb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java @@ -52,6 +52,8 @@ import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; import java.util.List; import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; @@ -152,7 +154,7 @@ public class LwM2mTransportContextServer extends TransportContext { * @return */ public GetResourcesResponseMsg getResourceTenant (UUID tenantId, String resourceType) { - + CountDownLatch latch = new CountDownLatch(1); GetResourcesResponseMsg responseMsg = this.getTransportService() .getResources(GetResourcesRequestMsg.newBuilder() @@ -160,7 +162,41 @@ public class LwM2mTransportContextServer extends TransportContext { .setTenantIdLSB(tenantId.getLeastSignificantBits()) .setTenantIdMSB(tenantId.getMostSignificantBits()) .build()); + latch.countDown(); + try { + latch.await(this.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + log.error("Failed to await credentials!", e); + } + return responseMsg; } + public GetResourcesResponseMsg getResourceTenantProcess (UUID tenantId, String resourceType) { + CountDownLatch latch = new CountDownLatch(2); + final GetResourcesResponseMsg[] responseMsg = {null}; + this.getTransportService().process(GetResourcesRequestMsg.newBuilder() + .setResourceType(resourceType) + .setTenantIdLSB(tenantId.getLeastSignificantBits()) + .setTenantIdMSB(tenantId.getMostSignificantBits()) + .build(), + new TransportServiceCallback<>() { + @Override + public void onSuccess(GetResourcesResponseMsg msg) { responseMsg[0] = msg; + latch.countDown(); + } + + @Override + public void onError(Throwable e) { + log.trace("[{}] [{}] Failed to process credentials ", tenantId, e); + latch.countDown(); + } + }); + try { + latch.await(this.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + log.error("Failed to await credentials!", e); + } + return responseMsg[0]; + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java index 56cf6b5c2e..df29c435bd 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java @@ -101,7 +101,8 @@ public class LwM2mTransportServerConfiguration { builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); /** Define model provider (Create Models )*/ - TransportProtos.GetResourcesResponseMsg responseMsg= this.context.getResourceTenant(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); + TransportProtos.GetResourcesResponseMsg responseMsg= this.context.getResourceTenantProcess(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); +// TransportProtos.GetResourcesResponseMsg responseMsg= this.context.getResourceTenant(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); // LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueCommon()); LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueServer(), this.lwM2mClientContext); builder.setObjectModelProvider(modelProvider); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java index 43bd9d8022..0032946302 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java @@ -40,6 +40,8 @@ import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.transport.resource.ResourceType; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.adaptor.AdaptorException; import org.thingsboard.server.common.transport.adaptor.JsonConverter; @@ -154,7 +156,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { try { log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId()); ((LwM2mVersionedModelProvider)leshanServer.getModelProvider()).setRepository(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelsValueCommon()); -// (((VersionedModelProvider) (leshanServer)).modelProvider).repository; + TransportProtos.GetResourcesResponseMsg responseMsg= this.lwM2mTransportContextServer.getResourceTenantProcess(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); +// TransportProtos.GetResourcesResponseMsg responseMsg= this.lwM2mTransportContextServer.getResourceTenant(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); + + // (((VersionedModelProvider) (leshanServer)).modelProvider).repository; LwM2mClient lwM2MClient = this.lwM2mClientContext.updateInSessionsLwM2MClient(registration); if (lwM2MClient != null) { SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java index ab728af00d..cce43b3995 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java @@ -75,8 +75,9 @@ public interface TransportService { void onProfileUpdate(DeviceProfile deviceProfile); - void process(LwM2MRequestMsg msg, - TransportServiceCallback callback); + void process(LwM2MRequestMsg msg, TransportServiceCallback callback); + + void process(GetResourcesRequestMsg msg, TransportServiceCallback callback); void process(SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback callback); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index b273ee48cf..1f1d6c6c26 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -61,7 +61,6 @@ import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; -import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; @@ -266,6 +265,16 @@ public class DefaultTransportService implements TransportService { } } + @Override + public void process(TransportProtos.GetResourcesRequestMsg msg, TransportServiceCallback callback) { + log.trace("Processing msg: {}", msg); + TbProtoQueueMsg protoMsg = + new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setResourcesRequestMsg(msg).build()); + AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), + response -> callback.onSuccess(response.getValue().getResourcesResponseMsg()), callback::onError, transportCallbackExecutor); + } + + @Override public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, TransportServiceCallback callback) { @@ -292,6 +301,7 @@ public class DefaultTransportService implements TransportService { response -> callback.onSuccess(response.getValue().getValidateCredResponseMsg()), callback::onError, transportCallbackExecutor); } + @Override public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceX509CertRequestMsg msg, TransportServiceCallback callback) { log.trace("Processing msg: {}", msg); TbProtoQueueMsg protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateX509CertRequestMsg(msg).build()); From 648e8ec262ee4aea594aa438d4d2b651f09bed80 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 12 Mar 2021 17:53:03 +0200 Subject: [PATCH 9/9] lwm2m: add Lwm2m provider for models --- .../service/install/InstallScripts.java | 91 ++++++++++---- ...TransportBootstrapServerConfiguration.java | 3 +- .../server/LwM2mTransportContextServer.java | 87 ++++---------- .../lwm2m/server/LwM2mTransportHandler.java | 6 +- .../lwm2m/server/LwM2mTransportRequest.java | 4 +- .../LwM2mTransportServerConfiguration.java | 30 ++--- .../server/LwM2mTransportServiceImpl.java | 20 ---- .../server/LwM2mVersionedModelProvider.java | 112 +++++++++++------- .../server/client/LwM2mClientContextImpl.java | 1 - .../server/client/LwM2mClientProfile.java | 5 +- .../lwm2m/utils/LwM2mValueConverterImpl.java | 5 + .../lwm2m/LwM2MTransportConfigServer.java | 37 +----- pom.xml | 6 +- 13 files changed, 189 insertions(+), 218 deletions(-) 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 4cb4fbd059..f9ef8e03e1 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 @@ -17,6 +17,10 @@ package org.thingsboard.server.service.install; import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.DDFFileParser; +import org.eclipse.leshan.core.model.DefaultDDFFileValidator; +import org.eclipse.leshan.core.model.InvalidDDFFileException; +import org.eclipse.leshan.core.model.ObjectModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -39,6 +43,8 @@ import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; +import java.io.ByteArrayInputStream; +import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; @@ -196,37 +202,70 @@ public class InstallScripts { } public void loadSystemLwm2mResources() throws Exception { +// Path modelsDir = Paths.get("/home/nick/Igor_project/thingsboard_ce_3_2_docker/thingsboard/common/transport/lwm2m/src/main/resources/models/"); Path modelsDir = Paths.get(getDataDir(), MODELS_DIR); - try (DirectoryStream dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) { - dirStream.forEach( - path -> { - try { - Resource resource = new Resource(); - resource.setTenantId(TenantId.SYS_TENANT_ID); - resource.setResourceType(ResourceType.LWM2M_MODEL); - resource.setResourceId(path.getFileName().toString()); - resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(path))); - resourceService.saveResource(resource); - } catch (Exception e) { - log.error("Unable to load lwm2m model [{}]", path.toString()); - throw new RuntimeException("Unable to load lwm2m model", e); + if (Files.isDirectory(modelsDir)) { + try (DirectoryStream dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) { + dirStream.forEach( + path -> { + try { + byte[] fileBytes = Files.readAllBytes(path); + String key = getObjectModelLwm2mValid(fileBytes, path.getFileName().toString(), new DefaultDDFFileValidator()); + if (key != null) { + Resource resource = new Resource(); + resource.setTenantId(TenantId.SYS_TENANT_ID); + resource.setResourceType(ResourceType.LWM2M_MODEL); + resource.setResourceId(key); + resource.setValue(Base64.getEncoder().encodeToString(fileBytes)); + resourceService.saveResource(resource); + } + } catch (Exception e) { + log.error("Unable to load lwm2m model [{}]", path.toString()); + throw new RuntimeException("Unable to load lwm2m model", e); + } } - } - ); + ); + } } Path jksPath = Paths.get(getDataDir(), CREDENTIALS_DIR, "serverKeyStore.jks"); - try { - Resource resource = new Resource(); - resource.setTenantId(TenantId.SYS_TENANT_ID); - resource.setResourceType(ResourceType.JKS); - resource.setResourceId(jksPath.getFileName().toString()); - resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath))); - resourceService.saveResource(resource); - } catch (Exception e) { - log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString()); - throw new RuntimeException("Unable to load l2m2m serverKeyStore", e); - } + try { + Resource resource = new Resource(); + resource.setTenantId(TenantId.SYS_TENANT_ID); + resource.setResourceType(ResourceType.JKS); + resource.setResourceId(jksPath.getFileName().toString()); + resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath))); + resourceService.saveResource(resource); + } catch (Exception e) { + log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString()); + throw new RuntimeException("Unable to load l2m2m serverKeyStore", e); + } + } + + private String getObjectModelLwm2mValid(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) { + try { + DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator); + ObjectModel objectModel = ddfFileParser.parseEx(new ByteArrayInputStream(xmlByte), streamName).get(0); + return objectModel.id + "##" + objectModel.getVersion(); + } catch (IOException | InvalidDDFFileException e) { + log.error("Could not parse the XML file [{}]", streamName, e); + return null; + } + + } + + private void removeFile(Path modelsDir, String nameFile, byte[] fileBytes) { + String path = "/home/nick/Igor_project/thingsboard_ce_3_2_docker/thingsboard/common/transport/lwm2m/src/main/resources/models/"; + File file = new File(path + nameFile); + if (!file.isDirectory()) { + try { + Files.write(Paths.get(path + "server/" + nameFile), fileBytes); + file.delete(); + } catch (IOException e) { + e.printStackTrace(); + } + + } } public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java index 59e1087f21..e531de3628 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java @@ -17,7 +17,6 @@ package org.thingsboard.server.transport.lwm2m.bootstrap; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; -import org.eclipse.leshan.core.model.StaticModel; import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.server.bootstrap.BootstrapSessionManager; import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer; @@ -94,7 +93,7 @@ public class LwM2MTransportBootstrapServerConfiguration { builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); /** Define model provider (Create Models )*/ - builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon())); +// builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon())); /** Create credentials */ this.setServerWithCredentials(builder); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java index 92db005094..2fffd17a4c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java @@ -16,13 +16,13 @@ package org.thingsboard.server.transport.lwm2m.server; /** * 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. @@ -34,9 +34,13 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.DDFFileParser; +import org.eclipse.leshan.core.model.DefaultDDFFileValidator; +import org.eclipse.leshan.core.model.InvalidDDFFileException; import org.eclipse.leshan.core.model.ObjectModel; import org.springframework.stereotype.Component; import org.thingsboard.server.common.transport.TransportContext; +import org.thingsboard.server.common.transport.TransportResourceCache; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.common.transport.adaptor.AdaptorException; @@ -48,7 +52,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCreden import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; -import java.util.List; +import java.io.ByteArrayInputStream; +import java.io.IOException; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; @@ -62,14 +67,16 @@ public class LwM2mTransportContextServer extends TransportContext { private final TransportService transportService; - private List modelsValueServer; + private final TransportResourceCache transportResourceCache; + @Getter private final LwM2MJsonAdaptor adaptor; - public LwM2mTransportContextServer(LwM2MTransportConfigServer lwM2MTransportConfigServer, TransportService transportService, LwM2MJsonAdaptor adaptor) { + public LwM2mTransportContextServer(LwM2MTransportConfigServer lwM2MTransportConfigServer, TransportService transportService, TransportResourceCache transportResourceCache, LwM2MJsonAdaptor adaptor) { this.lwM2MTransportConfigServer = lwM2MTransportConfigServer; this.transportService = transportService; + this.transportResourceCache = transportResourceCache; this.adaptor = adaptor; } @@ -77,6 +84,10 @@ public class LwM2mTransportContextServer extends TransportContext { return this.lwM2MTransportConfigServer; } + public TransportResourceCache getTransportResourceCache() { + return this.transportResourceCache; + } + /** * Sent to Thingsboard Attribute || Telemetry * @@ -139,59 +150,13 @@ public class LwM2mTransportContextServer extends TransportContext { .build(); } - - - -// /** -// * ResourcesRequestMsg -// * -// * @param resourceType -// * @return -// */ -// public GetResourcesResponseMsg getResourceTenant (UUID tenantId, String resourceType) { -// CountDownLatch latch = new CountDownLatch(1); -// GetResourcesResponseMsg responseMsg = -// this.getTransportService() -// .getResources(GetResourcesRequestMsg.newBuilder() -// .setResourceType(resourceType) -// .setTenantIdLSB(tenantId.getLeastSignificantBits()) -// .setTenantIdMSB(tenantId.getMostSignificantBits()) -// .build()); -// latch.countDown(); -// try { -// latch.await(this.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); -// } catch (InterruptedException e) { -// log.error("Failed to await credentials!", e); -// } -// -// return responseMsg; -// } - -// public GetResourcesResponseMsg getResourceTenantProcess (UUID tenantId, String resourceType) { -// CountDownLatch latch = new CountDownLatch(2); -// final GetResourcesResponseMsg[] responseMsg = {null}; -// this.getTransportService().process(GetResourcesRequestMsg.newBuilder() -// .setResourceType(resourceType) -// .setTenantIdLSB(tenantId.getLeastSignificantBits()) -// .setTenantIdMSB(tenantId.getMostSignificantBits()) -// .build(), -// new TransportServiceCallback<>() { -// @Override -// public void onSuccess(GetResourcesResponseMsg msg) { responseMsg[0] = msg; -// latch.countDown(); -// } -// -// @Override -// public void onError(Throwable e) { -// log.trace("[{}] [{}] Failed to process credentials ", tenantId, e); -// latch.countDown(); -// } -// }); -// try { -// latch.await(this.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); -// } catch (InterruptedException e) { -// log.error("Failed to await credentials!", e); -// } -// return responseMsg[0]; -// } + public ObjectModel parseFromXmlToObjectModel(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) { + try { + DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator); + return ddfFileParser.parseEx(new ByteArrayInputStream(xmlByte), streamName).get(0); + } catch (IOException | InvalidDDFFileException e) { + log.error("Could not parse the XML file [{}]", streamName, e); + return null; + } + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java index 150fe9b5d0..5b6ec23a6e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java @@ -35,6 +35,7 @@ import org.eclipse.leshan.server.californium.LeshanServerBuilder; import org.nustaq.serialization.FSTConfiguration; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; @@ -45,7 +46,6 @@ import java.util.Arrays; import java.util.Date; import java.util.LinkedList; import java.util.Optional; -import java.util.UUID; @Slf4j //@Component("LwM2MTransportHandler") @@ -189,7 +189,7 @@ public class LwM2mTransportHandler { return null; } - public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, UUID tenantId) { + public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, TenantId tenantId) { LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile(); lwM2MClientProfile.setTenantId(tenantId); lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject()); @@ -223,7 +223,7 @@ public class LwM2mTransportHandler { ObjectMapper mapper = new ObjectMapper(); String profileStr = mapper.writeValueAsString(profile); JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; - return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId().getId()) : null; + return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null; } catch (IOException e) { log.error("", e); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java index fc14b9c080..fa7f0d68b8 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java @@ -87,9 +87,6 @@ public class LwM2mTransportRequest { private final LeshanServer leshanServer; -// @Autowired -// private LwM2mTransportServiceImpl serviceImpl; - private final LwM2mTransportServiceImpl serviceImpl; public LwM2mTransportRequest(LwM2mTransportContextServer context, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) { @@ -232,6 +229,7 @@ public class LwM2mTransportRequest { private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) { LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); leshanServer.send(registration, request, timeoutInMs, (ResponseCallback) response -> { + if (!lwM2MClient.isInit()) { lwM2MClient.initValue(this.serviceImpl, request.getPath().toString()); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java index 7fa417b145..0af20b3e51 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java @@ -27,7 +27,6 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.security.DefaultAuthorizer; import org.eclipse.leshan.server.security.EditableSecurityStore; import org.eclipse.leshan.server.security.SecurityChecker; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; @@ -61,24 +60,23 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_W import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; @Slf4j -@Component("LwM2MTransportServerConfiguration") +@Component @TbLwM2mTransportComponent public class LwM2mTransportServerConfiguration { private PublicKey publicKey; private PrivateKey privateKey; private boolean pskMode = false; + private final LwM2mTransportContextServer context; + private final CaliforniumRegistrationStore registrationStore; + private final EditableSecurityStore securityStore; + private final LwM2mClientContext lwM2mClientContext; - @Autowired - private LwM2mTransportContextServer context; - - @Autowired - private CaliforniumRegistrationStore registrationStore; - - @Autowired - private EditableSecurityStore securityStore; - - @Autowired - private LwM2mClientContext lwM2mClientContext;; + public LwM2mTransportServerConfiguration(LwM2mTransportContextServer context, CaliforniumRegistrationStore registrationStore, EditableSecurityStore securityStore, LwM2mClientContext lwM2mClientContext) { + this.context = context; + this.registrationStore = registrationStore; + this.securityStore = securityStore; + this.lwM2mClientContext = lwM2mClientContext; + } @Bean public LeshanServer getLeshanServer() { @@ -98,10 +96,8 @@ public class LwM2mTransportServerConfiguration { builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); /** Define model provider (Create Models )*/ -// TransportProtos.GetResourcesResponseMsg responseMsg= this.context.getResourceTenantProcess(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); -// TransportProtos.GetResourcesResponseMsg responseMsg= this.context.getResourceTenant(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); -// LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueCommon()); - LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValueServer(), this.lwM2mClientContext); + LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.context); + this.context.getLwM2MTransportConfigServer().setModelProvider(modelProvider); builder.setObjectModelProvider(modelProvider); /** Create credentials */ diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java index df469d5a96..1af4e8bfd8 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java @@ -153,11 +153,6 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { executorRegistered.submit(() -> { try { log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId()); - ((LwM2mVersionedModelProvider)leshanServer.getModelProvider()).setRepository(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelsValueCommon()); -// TransportProtos.GetResourcesResponseMsg responseMsg= this.lwM2mTransportContextServer.getResourceTenantProcess(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); -// TransportProtos.GetResourcesResponseMsg responseMsg= this.lwM2mTransportContextServer.getResourceTenant(TenantId.SYS_TENANT_ID.getId(), ResourceType.LWM2M_MODEL.name()); - - // (((VersionedModelProvider) (leshanServer)).modelProvider).repository; LwM2mClient lwM2MClient = this.lwM2mClientContext.updateInSessionsLwM2MClient(registration); if (lwM2MClient != null) { SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); @@ -657,21 +652,6 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { return (clientInstances.size() > 0) ? clientInstances : null; } -// /** -// * get AttrName/TelemetryName with value from Client -// * -// * @param registration - -// * @return - JsonObject, format: {name: value}} -// */ -// private JsonObject getAttributeClient(Registration registration) { -// if (registration.getAdditionalRegistrationAttributes().size() > 0) { -// JsonObject resNameValues = new JsonObject(); -// registration.getAdditionalRegistrationAttributes().forEach(resNameValues::addProperty); -// return resNameValues; -// } -// return null; -// } - /** * @param attributes - new JsonObject * @param telemetry - new JsonObject diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java index 64e9f67199..503af176af 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java @@ -15,100 +15,122 @@ */ package org.thingsboard.server.transport.lwm2m.server; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.DefaultDDFFileValidator; import org.eclipse.leshan.core.model.LwM2mModel; -import org.eclipse.leshan.core.model.LwM2mModelRepository; import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.registration.Registration; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import java.util.ArrayList; +import java.util.Base64; import java.util.Collection; +import java.util.Iterator; import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -public class LwM2mVersionedModelProvider implements LwM2mModelProvider { +import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; - private LwM2mModelRepository repository; - private Map repositoriesTenant; - private LwM2mClientContext lwM2mClientContext; +@Slf4j +public class LwM2mVersionedModelProvider implements LwM2mModelProvider { - public LwM2mVersionedModelProvider(Collection objectModels, LwM2mClientContext lwM2mClientContext) { - this.repository = new LwM2mModelRepository(objectModels); - this.lwM2mClientContext = lwM2mClientContext; - this.repositoriesTenant = new ConcurrentHashMap<>(); - } + /** + * int objectId + * String version ("1.01") + * Key = objectId + "##" + version + * Value = TenantId + */ + private final LwM2mClientContext lwM2mClientContext; + private final LwM2mTransportContextServer lwM2mTransportContextServer; - public LwM2mVersionedModelProvider(LwM2mModelRepository repository, LwM2mClientContext lwM2mClientContext) { - this.repository = repository; + public LwM2mVersionedModelProvider(LwM2mClientContext lwM2mClientContext, LwM2mTransportContextServer lwM2mTransportContextServer) { this.lwM2mClientContext = lwM2mClientContext; - this.repositoriesTenant = new ConcurrentHashMap<>(); + this.lwM2mTransportContextServer = lwM2mTransportContextServer; } - - public void setRepositoriesTenant (String tenantID, LwM2mModelRepository repositoryTenant) { - this.repositoriesTenant.put(tenantID, repositoryTenant); + private String getIdVer(ObjectModel objectModel) { + return objectModel.id + "##" + ((objectModel.getVersion() == null || objectModel.getVersion().isEmpty()) ? ObjectModel.DEFAULT_VERSION : objectModel.getVersion()); } - public LwM2mModelRepository getRepositoriesTenant (String tenantID) { - return this.repositoriesTenant.get(tenantID); - } - - public void setRepository (Collection objectModels) { - this.repository = new LwM2mModelRepository(objectModels); - } - - public LwM2mModelRepository getRepositoriesCommonTenant (String tenantID) { - LwM2mModelRepository repository = new LwM2mModelRepository(); - - return repository; + private String getIdVer(Integer objectId, String version) { + return objectId != null ? objectId + "##" + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; } + /** + * Update repository if need + * + * @param registration + * @return + */ @Override public LwM2mModel getObjectModel(Registration registration) { - return new DynamicModel(registration, this.lwM2mClientContext.getProfile(registration).getTenantId()); + return new DynamicModel(registration + ); } private class DynamicModel implements LwM2mModel { private final Registration registration; - private final UUID tenantId; + private final TenantId tenantId; - public DynamicModel(Registration registration, UUID tenantId) { + public DynamicModel(Registration registration) { this.registration = registration; - this.tenantId = tenantId; + this.tenantId = lwM2mClientContext.getProfile(registration).getTenantId(); } @Override public ResourceModel getResourceModel(int objectId, int resourceId) { - ObjectModel objectModel = getObjectModel(objectId); - if (objectModel != null) - return objectModel.resources.get(resourceId); - else + try { + ObjectModel objectModel = getObjectModel(objectId); + if (objectModel != null) + return objectModel.resources.get(resourceId); + else + return null; + } catch (Exception e) { + log.error("", e); return null; + } } @Override public ObjectModel getObjectModel(int objectId) { String version = registration.getSupportedVersion(objectId); if (version != null) { - return repository.getObjectModel(objectId, version); + return this.getObjectModelDynamic(objectId, version); } return null; } @Override public Collection getObjectModels() { - Map supportedObjects = registration.getSupportedObject(); - Collection result = new ArrayList<>(supportedObjects.size()); - for (Map.Entry supportedObject : supportedObjects.entrySet()) { - ObjectModel objectModel = repository.getObjectModel(supportedObject.getKey(), - supportedObject.getValue()); - if (objectModel != null) + Map supportedObjects = this.registration.getSupportedObject(); + Collection result = new ArrayList(supportedObjects.size()); + Iterator i$ = supportedObjects.entrySet().iterator(); + + while (i$.hasNext()) { + Map.Entry supportedObject = (Map.Entry) i$.next(); + ObjectModel objectModel = this.getObjectModelDynamic((Integer) supportedObject.getKey(), (String) supportedObject.getValue()); + if (objectModel != null) { result.add(objectModel); + } } return result; } + + private ObjectModel getObjectModelDynamic(Integer objectId, String version) { + String key = getIdVer(objectId, version); + String xmlB64 = lwM2mTransportContextServer.getTransportResourceCache().get( + this.tenantId, + LWM2M_MODEL, + key). + getValue(); + return xmlB64 != null && !xmlB64.isEmpty() ? + lwM2mTransportContextServer.parseFromXmlToObjectModel( + Base64.getDecoder().decode(xmlB64), + key + ".xml", + new DefaultDDFFileValidator()) : + null; + } } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index b41e7cfdaa..d30628a43f 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -168,5 +168,4 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { } return false; } - } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java index dcda2cc62b..8285c9bc8b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java @@ -19,13 +19,12 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Data; - -import java.util.UUID; +import org.thingsboard.server.common.data.id.TenantId; @Data public class LwM2mClientProfile { - private UUID tenantId; + private TenantId tenantId; /** * {"clientLwM2mSettings": { * clientUpdateValueAfterConnect: false; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java index 136de3eb95..85283749dc 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java @@ -31,6 +31,8 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; +import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; + @Slf4j public class LwM2mValueConverterImpl implements LwM2mValueConverter { @@ -52,6 +54,9 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { /** expected type */ return value; } + if (currentType == null) { + currentType = OPAQUE; + } switch (expectedType) { case INTEGER: diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java index 4e57e61190..1208ace313 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java @@ -18,10 +18,10 @@ package org.thingsboard.server.common.transport.lwm2m; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.eclipse.leshan.core.model.ObjectLoader; import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mPath; +import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.registration.Registration; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -38,9 +38,7 @@ import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; @Slf4j @Component @@ -87,7 +85,7 @@ public class LwM2MTransportConfigServer { @Getter @Setter - private List modelsValueServer; + private LwM2mModelProvider modelProvider; @Getter @Value("${transport.lwm2m.timeout:}") @@ -189,35 +187,11 @@ public class LwM2MTransportConfigServer { @Value("${transport.lwm2m.server.secure.alias:}") private String serverAlias; - - @PostConstruct public void init() { - modelsValueServer = ObjectLoader.loadDefault(); - modelsValueServer.remove(3); - modelsValueCommon = ObjectLoader.loadDefault(); - File path = getPathModels(); - if (path.isDirectory()) { - try { - modelsValueCommon.addAll(ObjectLoader.loadObjectsFromDir(path)); - log.info(" [{}] Models directory is a directory", path.getAbsoluteFile()); - } catch (Exception e) { - log.error(" [{}] Could not parse the resource definition file", e.toString()); - } - } else { - log.error(" [{}] Read Models", path.getAbsoluteFile()); - } this.getInKeyStore(); } - private File getPathModels() { - Path pathModels = (modelPathFile != null && !modelPathFile.isEmpty()) ? Paths.get(modelPathFile) : - (new File(Paths.get(getBaseDirPath(), PATH_DATA, MODEL_PATH_DEFAULT).toUri()).isDirectory()) ? - Paths.get(getBaseDirPath(), PATH_DATA, MODEL_PATH_DEFAULT) : - Paths.get(getBaseDirPath(), APP_DIR, TRANSPORT_DIR, LWM2M_DIR, SRC_DIR, MAIN_DIR, RESOURCES_DIR, MODEL_PATH_DEFAULT); - return (pathModels != null) ? new File(pathModels.toUri()) : null; - } - private KeyStore getInKeyStore() { try { if (keyStoreValue != null && keyStoreValue.size() > 0) @@ -260,12 +234,7 @@ public class LwM2MTransportConfigServer { } public ResourceModel getResourceModel(Registration registration, LwM2mPath pathIds) { - String pathLink = "/" + pathIds.getObjectId() + "/" + pathIds.getObjectInstanceId(); - return (Arrays.stream(registration.getObjectLinks()).filter(p-> p.getUrl().equals(pathLink)).findFirst().isPresent() && - this.modelsValueCommon.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).size() > 0) && - this.modelsValueCommon.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0).resources.containsKey(pathIds.getResourceId()) ? - this.modelsValueCommon.stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0).resources.get(pathIds.getResourceId()) : - null; + return this.modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); } public ResourceModel.Type getResourceModelType(Registration registration, LwM2mPath pathIds) { diff --git a/pom.xml b/pom.xml index 7e12adff98..4f8c7d3790 100755 --- a/pom.xml +++ b/pom.xml @@ -66,9 +66,9 @@ 2.12.1 2.2.6 2.6.1 - 1.3.0 - 1.3.0 - 1.3.0 + 1.3.1 + 1.3.1 + 1.3.1 2.6.2 2.3.30 1.6.2