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; }